Keepalived와 HAProxy를 사용한 HA K8s 클러스터
Source: Dev.to
번역을 진행하려면 실제 본문 텍스트가 필요합니다.
해당 글의 내용을 복사해서 제공해 주시면, 마크다운 형식과 코드 블록, URL은 그대로 유지하면서 한국어로 번역해 드리겠습니다.
Source: …
개요
스택형 HA 클러스터는 etcd가 제공하는 분산 데이터 저장소 클러스터가 kubeadm으로 관리되는 노드들로 구성된 클러스터 위에 겹쳐진 토폴로지를 말합니다. 이 클러스터는 컨트롤 플레인 컴포넌트를 실행하는 노드들로 구성됩니다.
각 컨트롤 플레인 노드는 kube‑apiserver, kube‑scheduler, kube‑controller‑manager 인스턴스를 실행합니다. kube‑apiserver는 로드 밸런서를 통해 워커 노드에 노출됩니다.
각 컨트롤 플레인 노드는 로컬 etcd 멤버를 생성하며, 이 etcd 멤버는 동일한 노드의 kube‑apiserver와만 통신합니다. 로컬 kube‑controller‑manager와 kube‑scheduler 인스턴스도 마찬가지입니다.
이 토폴로지는 컨트롤 플레인과 etcd 멤버를 같은 노드에 결합합니다. 외부 etcd 노드가 있는 클러스터보다 설정이 간단하고 복제 관리도 더 쉬워집니다.
3노드 스택형 클러스터에서 일어나는 일
각 컨트롤 플레인 노드는 다음을 실행합니다:
- etcd 멤버
- kube‑apiserver, scheduler, controller‑manager
따라서 구성은 다음과 같습니다:
- 3개의 etcd 멤버 → 쿼럼 = 2
- 3개의 API 서버 → 로드밸런싱 (1개가 다운돼도 처리 가능)
노드 하나가 실패하면 여전히 다음을 유지합니다:
- 2개의 etcd 멤버 → 쿼럼 유지
- 2개의 컨트롤 플레인 인스턴스 → 여전히 사용 가능
이는 kubeadm이 배포하는 기본 토폴로지입니다. kubeadm init 및 kubeadm join --control-plane을 사용할 때 컨트롤 플레인 노드에 로컬 etcd 멤버가 자동으로 생성됩니다.
전제 조건: 이 문서는 클러스터 부트스트래핑 과정을 자세히 다루지 않으므로, 이전에 kubeadm으로 클러스터를 부트스트랩한 경험이 있다고 가정합니다.
Source:
머신 설정하기
HAProxy + Keepalived를 사용해 3개의 마스터 노드와 가상 IP(VIP)를 갖는 Kubernetes 고가용성(HA) 환경을 구축하려면 다음과 같은 구조화된 접근 방식을 따르세요.
마스터
- 10.238.40.162
- 10.238.40.163
- 10.238.40.164
VIP: 10.238.40.166
모든 마스터에 HAProxy와 Keepalived 설치
sudo apt update
sudo apt install -y haproxy keepalived
HAProxy 설정
세 대의 마스터 노드 모두에서 /etc/haproxy/haproxy.cfg 파일을 편집합니다:
global
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
option httplog
option dontlognull
frontend kubernetes-apiserver
bind *:8443
mode tcp
option tcplog
default_backend kubernetes-apiserver
backend kubernetes-apiserver
mode tcp
balance roundrobin
option tcp-check
server master1 10.238.40.162:6443 check fall 3 rise 2
server master2 10.238.40.163:6443 check fall 3 rise 2
server master3 10.238.40.164:6443 check fall 3 rise 2
Keepalived 설정
한 번에 하나의 노드만 VIP를 “소유”하게 되며(Keepalived가 관리), 설정 파일은 모든 노드에 존재합니다.
각 마스터 노드에서 /etc/keepalived/keepalived.conf 파일을 편집합니다.
주의: 각 노드의 priority 값을 아래 표와 같이 조정하세요.
| 노드 | Priority | 역할 |
|---|---|---|
| Master1 | 110 | MASTER |
| Master2 | 100 | BACKUP |
| Master3 | 90 | BACKUP |
global_defs {
router_id LVS_DEVEL
script_user root
enable_script_security
}
vrrp_script chk_haproxy {
script "/bin/curl -f http://localhost:6443/healthz || exit 1"
interval 2
weight -2
fall 3
rise 2
}
vrrp_instance VI_1 {
state MASTER
interface enp19s0
virtual_router_id 51
priority 110 # 위 표에 따라 노드별로 변경
advert_int 1
authentication {
auth_type PASS
auth_pass k8s-ha-cluster
}
virtual_ipaddress {
10.238.40.166/24
}
track_script {
chk_haproxy
}
}
서비스 재시작
sudo systemctl restart haproxy keepalived
sudo systemctl enable haproxy keepalived
VIP 확인
ip addr show | grep 10.238.40.166

서비스 상태 확인
sudo systemctl status haproxy
sudo systemctl status keepalived
클러스터 부트스트랩
첫 번째 마스터 노드에 kubeadm-config.yaml 파일을 생성합니다.
VIP를 control‑plane 엔드포인트로 사용하고 apiServer.certSANs에 포함시킵니다.
중요:
InitConfiguration의advertiseAddress필드를 각 마스터 노드의 IP 주소에 맞게 변경하십시오.
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: v1.32.6
apiServer:
certSANs:
- "10.238.40.166" # VIP
- "127.0.0.1" # localhost
- "0.0.0.0" # wildcard
- "10.96.0.1" # Kubernetes service IP
- "10.238.40.162"
- "10.238.40.163"
- "10.238.40.164"
extraArgs:
# (add any extra arguments you need here)
일반적인 kubeadm init / kubeadm join 절차를 진행하되, VIP(10.238.40.166)를 control‑plane 엔드포인트로 지정합니다.
Source: …
kubeadm 구성
horization-mode: Node,RBAC
certificatesDir: /etc/kubernetes/pki
clusterName: pcai
controlPlaneEndpoint: "10.238.40.166:8443"
controllerManager:
extraArgs:
bind-address: 0.0.0.0
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: registry.k8s.io
networking:
dnsDomain: cluster.local
podSubnet: "172.20.0.0/16"
serviceSubnet: "172.30.0.0/16"
scheduler:
extraArgs:
bind-address: 0.0.0.0
---
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: "10.238.40.162"
bindPort: 6443
nodeRegistration:
criSocket: unix:///var/run/containerd/containerd.sock
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
클러스터 초기화
kubeadm init --upload-certs --config kubeadm-config.yaml -v=5
참고: 출력 결과를 저장하세요! 여기에는 컨트롤 플레인 및 워커 노드용 조인 명령이 포함됩니다.
kubectl 접근 설정
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
네트워킹 솔루션 설치 (Calico)
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml
네트워킹 파드가 준비될 때까지 대기
kubectl wait --for=condition=ready pod -l k8s-app=calico-node -n kube-system --timeout=300s
추가 컨트롤 플레인 노드 조인
다른 마스터 노드에서 ( kubeadm init 출력에 있는) 컨트롤 플레인 조인 명령을 실행합니다:
kubeadm join 10.238.40.166:8443 --token \
--discovery-token-ca-cert-hash sha256: \
--control-plane --certificate-key
참고: 인증서 키는 2시간만 유효합니다. 만료될 경우 새 키를 생성하세요:
kubeadm init phase upload-certs --upload-certs
검증 및 상태 확인
모든 노드가 준비되었는지 확인
kubectl get nodes -o wide
control‑plane 구성 요소 확인
kubectl get pods -n kube-system
etcd 클러스터 상태 확인
kubectl exec -n kube-system etcd- -- etcdctl \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
member list
VIP 장애 조치 테스트
# VIP를 보유한 마스터 노드에서 keepalived 중지
sudo systemctl stop keepalived
# VIP가 다른 노드로 이동했는지 확인
ip addr show | grep 10.238.40.166
# VIP를 통한 API 접근 테스트
curl -k https://10.238.40.166:8443/healthz
# keepalived 재시작
sudo systemctl start keepalived
결론
축하합니다! HAProxy와 Keepalived를 사용한 스택형 etcd 토폴로지를 통해 고가용성 Kubernetes 클러스터를 성공적으로 배포했습니다. 이 설정은 다음과 같은 장점을 제공합니다:
주요 이점
- 고가용성: 단일 장애 지점 없이 자동 페일오버
- 로드 분산: HAProxy를 통해 모든 API 서버에 트래픽이 고르게 분산
- 자동 복구: Keepalived가 몇 초 안에 VIP 페일오버를 처리
- 단순화된 아키텍처: 외부 etcd 대비 스택형 토폴로지가 복잡성을 감소
클러스터 기능
이 3‑마스터 노드 구성에서는:
- 1개의 노드 장애를 견디면서도 클러스터 전체 기능 유지
- 3개 중 2개의 멤버가 남아 etcd 쿼럼 유지
- 남은 정상 마스터를 통해 API 요청 지속 제공
- VIP를 정상 작동 중인 노드로 자동 페일오버
