쿠버네티스 온프레미스에 설치하기(with Proxmox)

ka8main.png

쿠버네티스 클러스터를 직접 구성하는 도구

kubeadm

  • 쿠버네티스에서 공식 제공하는 클러스터 생성/관리 도구

kubespray

  • 쿠버네티스 클러스터를 배포하는 오픈소스 프로젝트
  • 다양한 형식으로 쿠버네티스 클러스터 구성가능
  • 온프레미스에서 상용 서비스 클러스터 운영시 유용
  • 다양한 CNI 제공

CNI(Container Network Interface)

  • Container간 통신을 지원하는 VxLAN, Pod Network라고도 부름
  • 다양한 종류의 플러그인이 존재
    • flannel, calico, weavenet 등이 있다.
    • 본 포스팅에서는 weavenet 샤용

💡CNI란?

  • CNCF(Cloud Native Computing Foundation)의 프로젝트 중 하나인 CNI는 컨테이너 간의 네트워킹을 제어할 수 있는 플러그인을 만들기 위한 표준이다.
  • 다양한 형태의 컨테이너 런타임과 오케스트레이터 사이의 네트워크 계층을 구현하는 방식이 다양하게 분리되어 각자만의 방식으로 발전하게 되는 것을 방지하고 공통된 인터페이스를 제공하기 만들어졌다.

💡CNI vs Docker Network

  • 표준화: CNI는 다양한 컨테이너 런타임 및 오케스트레이터 간의 표준 네트워킹 인터페이스를 제공하는 것을 목표로 하는 반면, Docker 네트워크는 주로 Docker 컨테이너 환경 내에서의 네트워킹을 관리하는 데 중점을 둠.
  • 유연성 및 확장성: CNI는 플러그인 기반으로 다양한 네트워크 솔루션과의 통합이 용이하지만, Docker 네트워크는 Docker 환경 내에서 제공되는 네트워크 드라이버에 의존함.
  • 사용 사례: CNI는 Kubernetes와 같은 복잡한 오케스트레이션 환경에서 주로 사용되며, Docker 네트워크는 독립적인 Docker 컨테이너 환경에서 주로 사용됨.

쿠버네티스 클러스터 구성

control plane(master node)

  • 워커 노드들의 상태를 관리하고 제어
  • single master
  • multi master(3, 5개의 master nodes)

worker node

  • 도커 플랫폼을 통해 컨테이너를 동작하며 실제 서비스 제공

1. Proxmox 가상머신 생성

a1.png

💡운영체제로는 Ubuntu 22.04를 사용했다. 각 노드에는 2 sockets, 4 cores(8 vCPU), 16GB RAM, 64GiB 디스크 용량을 할당했다.

MasterNode역할을 할 가상노드 1개와 WorkerNode역할을 할 가상노드 2개를 생성했다. 추후 확장가능성을 고려하여 초기화되어있는 Default노드도 하나 복제하였다. K8S & containerd 조합으로 클러스터를 구축할 것이기 때문에, 따로 Proxmox에서 제공하는 LXC는 사용하지 않을 것이다.

번외: 포트포워딩 및 ssh 구성

공유기 포트포워딩 a2.png

~/.ssh/config 설정
a3.png

2. 도커 설치

  1. 시스템 업데이트

먼저, 패키지 목록을 업데이트하고 시스템을 최신 상태로 유지해야 한다.

sudo apt update
sudo apt upgrade -y
  1. Docker 설치를 위한 필수 패키지 설치

Docker를 설치하기 전에 몇 가지 필수 패키지를 설치해야 한다.

sudo apt install apt-transport-https ca-certificates curl software-properties-common -y
  1. Docker 공식 GPG 키 추가

Docker 패키지를 검증할 수 있도록 공식 GPG 키를 추가한다.

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
  1. Docker APT 저장소 추가

Docker 패키지를 설치할 수 있도록 Docker APT 저장소를 추가한다.

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  1. Docker 설치

패키지 목록을 다시 업데이트한 후, Docker를 설치한다.

sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io -y
  1. Docker 서비스 확인 및 시작

Docker가 올바르게 설치되었는지 확인하고, Docker 서비스를 시작한다. 재부팅 시, 자동으로 시작되도록 한다.

sudo systemctl status docker
sudo systemctl enable docker
sudo systemctl start docker
  1. 설치가 잘 되었는지 확인

임시 컨테이너 hello-world를 통해 도커가 잘 작동하는지 확인한다.

docker --version
docker run hello-world

모든 가상 노드에 설치가 되어야 한다. 설치한 후 복제하는 것을 추천한다.

2.5 containerd만 설치(권장)

시스템 업데이트 및 의존성 설치

sudo apt update && sudo apt upgrade -y
sudo apt install -y apt-transport-https ca-certificates curl gnupg lsb-release

containerd 설치

sudo apt install -y containerd

containerd 설정

sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd

3. 쿠버네티스 설치

  1. 스왑메모리 (영구)비활성화하기

kubeadm을 안정적으로 설치하기 위해선 2GB이상의 메모리, 2개 이상의 CPU, SWAP 메모리 비활성화가 필요하다.

sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
minseoky@masternode:~$ systemctl list-unit-files --type swap
UNIT FILE     STATE     VENDOR PRESET
swap.img.swap generated -

1 unit files listed.
minseoky@masternode:~$ systemctl mask swap.img.swap
  1. 저장소 추가
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt update
  1. 방화벽 설정하기

어차피 앞단에서 방화벽이 막아줄테니 내부 방화벽을 끈다는 얘기가 있는데, 내부에서 위협이 발생하면 어떡하나 싶어서 일단 제대로 방화벽 설정을 하도록 하겠다.

먼저 방화벽 설정을 편하게 하도록 ufw를 설치한다.

sudo apt install ufw -y

ssh 연결을 허용하고, 기본옵션으로 모든 인바운드 차단, 모든 아웃바운드 허용한다.

sudo ufw allow ssh
sudo ufw default deny incoming
sudo ufw default allow outgoing

쿠버네티스 운용에 필요한 노드들을 켜준다.

마스터 노드

sudo ufw allow 6443/tcp       # Kubernetes API 서버
sudo ufw allow 2379:2380/tcp  # etcd 서버 클라이언트 API
sudo ufw allow 10250/tcp      # Kubelet API
sudo ufw allow 10251/tcp      # kube-scheduler
sudo ufw allow 10252/tcp      # kube-controller-manager

# Weave Net 포트
sudo ufw allow 6783/tcp
sudo ufw allow 6783/udp
sudo ufw allow 6784/udp

# (선택사항) Kubernetes 대시보드가 8001 포트를 사용하는 경우
sudo ufw allow 8001/tcp

워커 노드

sudo ufw allow 10250/tcp        # Kubelet API
sudo ufw allow 30000:32767/tcp  # NodePort 서비스 범위

# Weave Net 포트
sudo ufw allow 6783/tcp
sudo ufw allow 6783/udp
sudo ufw allow 6784/udp

그리고 방화벽 설정을 재부팅 시 유지하도록 한다.

sudo ufw enable
sudo ufw status
  1. kubeadm, kubelet, kubectl 설치하기
  • Kubeadm: 클러스터 초기 설정 및 구축을 위한 부트스트랩 도구
  • Kubelet: 데몬으로, 각 노드에서 실행되는 Kubenetes 에이전트, Kubelet은 마스터 노드의 지시에 따라 컨테이너를 실행하고 관리한다.
  • Kubectl: 클러스터 관리를 위한 명령줄 도구, 클러스터의 상태를 조회하고 리소스를 관리할 수 있다.
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

마스터 노드

kubelet kubeadm kubectl을 설치한다.

sudo modprobe overlay
sudo modprobe br_netfilter
sudo tee /etc/modules-load.d/k8s.conf <<EOF
overlay
br_netfilter
EOF

sudo tee /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF

sudo sysctl --system

워커 노드

워커 노드에는 kubectl을 설치하지 않아도 된다.

sudo apt install -y kubelet kubeadm
sudo apt-mark hold kubelet kubeadm

4. 쿠버네티스 설정

마스터노드 초기화

sudo kubeadm init --pod-network-cidr=10.32.0.0/12 --cri-socket=/run/containerd/containerd.sock

로컬 kubeconfig 설정

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

kubeadm init 명령어를 실행하면,

  1. 프리플라이트 체크: 시스템의 여러 측면을 검사하여 클러스터 초기화가 성공할 수 있도록 보장한다.
  2. 쿠버네티스 컴포넌트 설치: API 서버, 컨트롤러 매니저, 스케줄러, etcd 등 클러스터를 운영하는 데 필요한 주요 컴포넌트를 설치하고 구성한다.
  3. TLS 인증서 생성: 클러스터 내 통신을 안전하게 하기 위한 TLS 인증서를 생성하고 배포한다.
  4. etcd 데이터베이스 설정: etcd는 쿠버네티스의 데이터 저장소로 사용되며, kubeadm init은 이 데이터베이스를 설정한다.
  5. 관리자 구성을 생성: 클러스터 관리자 계정과 관련된 설정 파일을 생성하여 kubectl을 통해 클러스터를 관리할 수 있도록 한다.
API 서버, 컨트롤러 매니저, 스케줄러, etcd
  1. API 서버 (kube-apiserver)
    • 중앙 관리 인터페이스: Kubernetes의 중앙 관리 컴포넌트로, 클러스터의 상태를 관리하고 조작할 수 있는 유일한 구성 요소이다.
    • REST API: 클러스터 내 모든 요청은 API 서버를 통해 처리되며, 클러스터와 상호작용하기 위한 REST API를 제공한다.
    • 인증 및 인가: 클라이언트 요청의 인증과 인가를 처리하고, 역할 기반 접근 제어(RBAC)를 통해 접근 권한을 관리한다.
    • 상태 관리: etcd와 통신하여 클러스터의 상태를 저장하고 조회한다.
  2. 컨트롤러 매니저 (kube-controller-manager)
    • 컨트롤러 관리: 여러 개의 컨트롤러를 포함하고 있으며, 각 컨트롤러는 클러스터의 특정 측면을 관리한다.
    • 노드 컨트롤러: 노드의 상태를 모니터링하고, 노드가 다운되면 대체 노드를 할당한다.
    • 레플리케이션 컨트롤러: 원하는 수의 파드를 유지하도록 관리한다.
    • 엔드포인트 컨트롤러: 서비스와 파드 간의 엔드포인트를 업데이트한다.
    • 서비스 어카운트 및 토큰 컨트롤러: 서비스 어카운트를 생성하고 API 접근 토큰을 관리한다.
  3. 스케줄러 (kube-scheduler)
    • 파드 할당: 새로 생성된 파드를 적절한 노드에 할당한다.
    • 리소스 사용 최적화: 클러스터의 리소스를 최적화하여 파드의 실행을 관리한다. CPU, 메모리 등의 리소스 요구 사항을 고려하여 파드를 배치한다.
    • 스케줄링 정책: 사용자 정의 스케줄링 정책을 적용하여 파드의 배치를 조정할 수 있다.
  4. etcd
    • 분산 키-값 저장소: 클러스터의 모든 상태 정보를 저장하는 분산 키-값 데이터베이스이다.
    • 데이터 저장: 클러스터의 설정 정보, 스케줄링 정보, 상태 정보 등을 저장한다.
    • 데이터 일관성: 강력한 일관성을 보장하며, 클러스터의 모든 노드가 동일한 상태 정보를 공유할 수 있도록 한다.
    • 백업 및 복구: 클러스터의 상태를 백업하고 복구할 수 있도록 지원한다.

추후 조인을 위해 kubeadm init에서 나온 토큰 값 및 인증서 기억하기

kubeadm join {your_ip}:6443 --token uayyf9.eakzqdiskzg73zl7 \
	--discovery-token-ca-cert-hash sha256:07dc89ef2b3e2b043a3c058b089aca497a8a8e1c980b1c81cfda973f2abb0d87 --cri-socket=unix:///run/containerd/containerd.sock

쿠버네티스 클러스터 접근을 위한 설정파일 생성

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

CNI 플러그인 설치(Weavenet)

kubectl apply -f https://github.com/weaveworks/weave/releases/download/v2.8.1/weave-daemonset-k8s-1.11.yaml

a4.png CNI 플로그인 설치가 완료되면 위와 같이 STATUS가 Ready로 변한다.

kubelet 재실행

sudo systemctl restart kubelet

클러스터에 워커노드 조인

kubeadm join {your_ip}:6443 --token {your_token} \
	--discovery-token-ca-cert-hash sha256:{your_cert} --cri-socket=/run/containerd/containerd.sock

a5.png 조인에 성공하면 위같은 메세지가 나온다.

그 후 마스터 노드에서 노드를 확인해보면… a6.png

Docker vs. containerd

k8s버전 1.20부터 Dockershim 지원이 중단됨에 따라 k8s의 CRI에 도커를 연결하는 것이 불가능해졌다. k8s가 도커 지원을 중단(deprecated)하면서 좀 더 경량화된 containerd가 주류가 되었다. 본 포스트에서는 docker를 설치했으나, docker의 기본 컨테이너 런타임으로 containerd가 포함되어있기 때문에 따로 containerd를 설치할 필요는 없다. 원한다면 본 포스팅에서 도커 설치 대신 containerd만 설치해도 된다.