프로덕션에서 “마스터(컨트롤 플레인) 노드 1대”는 대표적인 SPOF(Single Point of Failure)입니다. 워커 노드가 살아있더라도, 컨트롤 플레인이 내려가면 클러스터는 “현재 돌아가는 건 계속 돌지만, 고치거나 확장하거나 복구하는 능력”을 잃습니다. 이 글은 그 이유와, HA에서 무엇을 어떻게 이중화해야 하는지(특히 API Server / Scheduler / Controller Manager / etcd)를 정리합니다.
1) 마스터 노드를 잃으면 실제로 무슨 일이 일어날까?
1.1 “지금 실행 중인 앱”은 당장 멈추지 않을 수 있다
컨트롤 플레인이 내려가도, 워커 노드와 그 위의 컨테이너/파드가 살아있다면 기존 트래픽은 한동안 정상 처리될 수 있습니다.
- kubelet은 워커에서 계속 컨테이너를 실행합니다.
- Service(ClusterIP/NodePort/LoadBalancer)의 데이터플레인(kube-proxy/iptables/ipvs, CNI)은 워커에서 계속 동작합니다.
- 그래서 “이미 떠 있는 파드”가 정상이라면 사용자 요청은 계속 들어갑니다.
1.2 하지만 “복구/변경/스케줄링”은 멈춘다
컨트롤 플레인은 상태 관찰과 조치(reconciliation)의 중심입니다. 마스터(컨트롤 플레인)가 죽으면 아래가 막힙니다.
- 파드 장애 시 자동 복구가 안 됨
- 예: 파드가 크래시났는데 Deployment/ReplicaSet이 새 파드를 만들고 스케줄링해야 함
- 그런데 controller-manager/scheduler가 동작하지 않으면 재생성이 안 됩니다.
- kubectl / API 기반 운영 불가
- kube-apiserver가 없으면
kubectl로 조회/수정/배포가 불가
- kube-apiserver가 없으면
- 클러스터 상태 변화 반영 불가
- 노드 장애 감지 후 파드 재배치
- HPA/VPA 같은 자동 스케일링
- 새 워크로드 배포/롤링 업데이트
- 엔드포인트 갱신 등 컨트롤 플레인 관여 영역
정리하면: 데이터플레인(트래픽 처리)은 잠시 유지될 수 있지만, 컨트롤플레인(상태 관리/복구/운영)은 정지합니다. 그래서 프로덕션에서는 컨트롤 플레인 HA가 필수에 가깝습니다.
2) HA의 목표: “컨트롤 플레인과 etcd까지” SPOF 제거
HA(고가용성) 구성은 “어떤 컴포넌트 하나가 죽어도 서비스 전체가 멈추지 않도록” 중복(redundancy) 을 두는 것입니다.
- 워커 노드: 이미 ReplicaSet/Deployment로 파드 복제
- 애플리케이션: 다중 replica + Service로 분산
- 컨트롤 플레인(이번 글의 초점):
- kube-apiserver
- kube-controller-manager
- kube-scheduler
- etcd
3) 멀티 마스터(멀티 컨트롤 플레인)에서 각 컴포넌트는 어떻게 동작하나?
3.1 kube-apiserver: Active-Active로 여러 개 동시에 떠도 된다
kube-apiserver는 “요청을 받아 처리하는 서버”입니다. 같은 클러스터에 API Server 인스턴스가 여러 개 있어도 문제 없습니다.
- 여러 API Server가 동시에 요청을 처리할 수 있습니다(Active-Active).
kubeconfig는 어디를 가리켜야 할까? → “로드밸런서”
여러 마스터의 API Server(기본 포트 6443) 앞에 L4/L7 로드밸런서를 두고, 클라이언트(kubectl, 컨트롤러들, 워커 kubelet 등)는 LB 주소를 바라보게 하는 게 일반적입니다.
예: kubeconfig에서 클러스터 endpoint를 LB로 지정
clusters:
- cluster:
server: https://k8s-api.example.com:6443
certificate-authority-data: ...
name: prod-ha
contexts:
- context:
cluster: prod-ha
user: admin
name: admin@prod-ha
current-context: admin@prod-ha
(예시) HAProxy로 API Server LB 구성
frontend k8s_api
bind *:6443
mode tcp
default_backend k8s_api_backend
backend k8s_api_backend
mode tcp
balance roundrobin
option tcp-check
server cp1 10.0.0.11:6443 check
server cp2 10.0.0.12:6443 check
server cp3 10.0.0.13:6443 check
3.2 controller-manager / scheduler: Active-Standby(리더 선출)로 “1개만” 동작해야 한다
controller-manager와 scheduler는 “클러스터 상태를 감시하고 조치하는” 컴포넌트입니다.
- controller-manager: ReplicaSet/Node/Endpoint 등 수많은 컨트롤러 루프 실행
- scheduler: Pending 파드를 적절한 노드에 배치
이 둘이 Active-Active로 동시에 조치하면 문제가 생깁니다.
- 같은 파드에 대해 중복 생성/중복 스케줄링 등 “중복 액션”이 발생할 수 있음
그래서 멀티 마스터에서는 일반적으로:
- 여러 인스턴스를 띄우되
- 리더(leader) 1개만 활성(Active)
- 나머지는 대기(Standby)
리더 선출(Leader Election)은 어떻게 되나?
리더 선출은 Kubernetes 내부 리소스(요즘은 주로 Lease)에 “누가 리더인지”를 기록하고, 갱신 경쟁을 통해 결정됩니다.
주요 플래그(스크립트에서 언급된 개념을 정확한 옵션명으로 정리):
--leader-elect=true(기본적으로 켜져 있는 경우가 많음)--leader-elect-lease-duration=15s(리더가 락을 갖는 기간)--leader-elect-renew-deadline=10s(리더가 이 안에 갱신 못 하면 리더 자격 상실)--leader-elect-retry-period=2s(팔로워가 리더가 되기 위해 재시도하는 주기)
값 자체를 외우는 게 목표는 아니고, “리더가 주기적으로 Lease를 갱신하고, 갱신이 끊기면 다른 인스턴스가 리더를 승격한다”는 흐름이 핵심입니다.
리더가 누구인지 확인하는 kubectl 예시
클러스터/버전에 따라 이름이 약간 다를 수 있지만, 보통 kube-system 네임스페이스에 Lease가 있습니다.
kubectl -n kube-system get lease | egrep 'kube-scheduler|kube-controller-manager'
kubectl -n kube-system describe lease kube-controller-manager
kubectl -n kube-system describe lease kube-scheduler
여기서 HolderIdentity 같은 필드로 현재 리더가 어느 노드(어느 인스턴스)인지 확인할 수 있습니다.
4) etcd HA: “컨트롤 플레인 이중화의 핵심 병목/핵심 리스크”
etcd는 Kubernetes의 “상태 저장소”입니다. 컨트롤 플레인 HA는 결국 etcd HA로 이어집니다.
4.1 두 가지 대표 토폴로지
(1) Stacked Control Plane (스택드 토폴로지)
- 각 컨트롤 플레인 노드에 etcd 멤버 + 컨트롤 플레인 컴포넌트를 같이 둠
- 장점: 노드 수가 적고 구성/운영이 단순
- 단점: 컨트롤 플레인 노드 1대 장애 시 etcd 멤버도 같이 손실
- 장애 도메인이 커짐(“한 노드 죽으면 두 레이어가 함께 영향”)
(2) External etcd (외부 etcd 토폴로지)
- etcd를 컨트롤 플레인과 분리된 전용 노드 집합으로 운영
- 장점: 컨트롤 플레인 노드 장애가 etcd에 직접 타격을 덜 줌(리스크 분리)
- 단점: 노드 수/구성/운영 난이도 증가(네트워크, 인증서, 백업/복구 등 복잡)
4.2 API Server는 etcd를 “리스트로” 바라본다
중요 포인트:
- etcd와 직접 통신하는 컨트롤 플레인 컴포넌트는 kube-apiserver
- etcd는 분산 시스템이므로, API Server는 etcd 엔드포인트를 여러 개 알고 있어야 하고(리스트),
- 그 중 살아있는 멤버로 읽기/쓰기를 수행합니다.
(개념 예시) API Server가 etcd endpoint를 여러 개 갖는 형태:
# kube-apiserver manifest의 일부(개념)
- --etcd-servers=https://10.0.0.21:2379,https://10.0.0.22:2379,https://10.0.0.23:2379
- --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
- --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
- --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
5) HA 구성 그림을 현실적으로 잡아보기
스크립트의 결론은 “기존 1마스터에서 HA를 위해 마스터를 늘리고, API Server 앞에 LB를 둔다”는 것입니다. 예시로는:
- 컨트롤 플레인 2대 + 워커 2대 + LB 1대 = 총 5노드
다만 프로덕션 관점에서는 보통:
- 컨트롤 플레인 3대(odd number) 를 더 흔히 권장합니다(리더 선출뿐 아니라 etcd 쿼럼 관점에서도 유리).
- 워커는 서비스 규모에 따라 N대
(가장 흔한 형태 중 하나)
- LB 1
- Control Plane 3
- Worker N
- (토폴로지에 따라) External etcd 3 또는 stacked etcd(컨트롤 플레인에 포함)
6) 실무 감각 정리: “HA에서 진짜 중요한 체크포인트”
- API Server는 Active-Active → LB로 분산, kubeconfig/노드들이 LB를 바라보게
- Controller Manager / Scheduler는 Active-Standby → leader election(Lease)로 1개만 활성
- etcd는 데이터의 근원 → stacked vs external 토폴로지 선택이 HA 리스크를 크게 좌우
- 컨트롤 플레인이 죽어도 “당장” 서비스가 살아 보일 수 있지만
- 장애 복구/스케일/배포/운영이 불가능해지고
- 시간이 지날수록 실제 장애로 이어질 확률이 올라감
'CKA' 카테고리의 다른 글
| Deploy k8s (0) | 2026.01.06 |
|---|---|
| Design Kubernetes - HA of ETCD (0) | 2026.01.06 |
| Design Kubernetes - Choosing Infrastructure (0) | 2026.01.06 |
| Design Kubernetes (0) | 2026.01.06 |
| Network - 정리(2) (0) | 2026.01.05 |