쿠버네티스 HA 클러스터

단일 컨트롤 플레인은 구성이 간단하지만 해당 노드가 멈추면 API 서버도 함께 멈춥니다. 운영 환경에서는 컨트롤 플레인을 홀수 개로 두고, 앞단의 로드밸런서 주소를 모든 노드가 공통 API 엔드포인트로 사용하게 구성할 수 있습니다.

이 글은 컨트롤 플레인 3대와 워커 3대, HAProxy 1대를 사용하는 stacked etcd 구성을 기준으로 합니다. 각 컨트롤 플레인에 etcd 멤버가 함께 배치되는 방식입니다.

쿠버네티스 HA 클러스터 개요

구성 예시

역할주소
control-plane-1~310.10.10.11~13
worker-1~310.10.10.21~23
HAProxy10.10.10.10:6443
Pod CIDR10.244.0.0/16

모든 노드에 같은 주 버전의 kubeadm·kubelet과 정상 동작하는 컨테이너 런타임이 설치돼 있어야 합니다. 로드밸런서는 각 API 서버의 TCP 6443 포트에 접근할 수 있어야 합니다.

HAProxy 설정

HAProxy 노드의 /etc/haproxy/haproxy.cfg에 API 서버용 프런트엔드와 백엔드를 추가합니다.

frontend kubernetes-api
    bind 10.10.10.10:6443
    mode tcp
    option tcplog
    default_backend kubernetes-control-planes

backend kubernetes-control-planes
    mode tcp
    balance roundrobin
    option tcp-check
    server cp1 10.10.10.11:6443 check
    server cp2 10.10.10.12:6443 check
    server cp3 10.10.10.13:6443 check
haproxy -c -f /etc/haproxy/haproxy.cfg
systemctl restart haproxy
nc -zv -w 2 10.10.10.10 6443

API 서버를 올리기 전에는 Connection refused가 나올 수 있습니다. timeout이면 HAProxy와 컨트롤 플레인 사이의 방화벽·라우팅부터 확인해야 합니다.

첫 컨트롤 플레인 초기화

첫 노드에서 공통 엔드포인트와 Pod CIDR을 지정합니다.

sudo kubeadm init \
  --control-plane-endpoint "10.10.10.10:6443" \
  --pod-network-cidr "10.244.0.0/16" \
  --upload-certs

--upload-certs는 다른 컨트롤 플레인이 인증서를 내려받을 수 있게 암호화해 임시 Secret에 올립니다. 출력되는 certificate-key는 민감정보이며 기본적으로 2시간 후 만료되므로 안전하게 보관하고 바로 조인하는 편이 좋습니다.

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

사용할 CNI를 설치합니다. Flannel을 사용한다면 위 Pod CIDR과 맞춰야 합니다.

kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

나머지 노드 조인

추가 컨트롤 플레인은 --control-plane과 인증서 키가 포함된 명령으로 한 대씩 조인합니다.

sudo kubeadm join 10.10.10.10:6443 \
  --token [TOKEN] \
  --discovery-token-ca-cert-hash sha256:[HASH] \
  --control-plane \
  --certificate-key [CERTIFICATE_KEY]

워커는 --control-plane--certificate-key 없이 조인합니다. 명령을 잃어버렸다면 기존 컨트롤 플레인에서 다시 만들 수 있습니다.

kubeadm token create --print-join-command
sudo kubeadm init phase upload-certs --upload-certs

장애 전환 확인

구축 완료만 확인하고 끝내면 HA 구성이 실제로 동작하는지 알 수 없습니다.

kubectl get nodes -o wide
kubectl -n kube-system get pods -o wide
kubectl -n kube-system rollout restart deployment coredns

컨트롤 플레인 한 대의 kubelet을 잠시 중지한 상태에서도 로드밸런서 주소를 통한 kubectl get nodes가 되는지 확인합니다. etcd는 투표 정족수가 필요하므로 세 멤버 중 두 멤버를 동시에 중단하면 안 됩니다. 스냅샷 절차는 ETCD 백업과 복원에서 이어집니다.

참고: kubeadm 고가용성 클러스터 공식 문서