[7. HA 컨트롤플레인]
출제 비중: 매우 낮음. 관련 문제 없음. 시험은 개념 + join 명령 수준.
1. 왜 HA가 필요한가
CP가 1대면 그 노드가 죽을 때 kubectl, 스케줄링, 스케일링이 전부 멈춘다.
이미 떠 있는 Pod은 살아 있지만 관리가 안 된다.
CP를 여러 대로 늘리면 한 대가 죽어도 나머지가 이어받는다.
2. etcd를 어디에 둘까
Stacked (kubeadm 기본값, 실무 대부분)
구조 : CP 노드마다 etcd가 같이 뜸
장점 : 서버 수가 적고 구성이 간단함
단점 : CP 한 대가 죽으면 etcd 멤버도 같이 빠짐
External
구조 : etcd를 별도 서버에 따로 둠
장점 : CP 장애와 etcd 장애가 분리됨
단점 : 서버가 최소 6대로 늘고 관리가 복잡함
실무 kubeadm 클러스터는 대부분 Stacked 3대.
3. 쿼럼
etcd 대수 쿼럼 버틸 수 있는 장애
1 1 0
3 2 1
4 3 1
5 3 2
4대는 3대와 버티는 수가 같아서 이득이 없다. 그래서 홀수로 둔다.
4. 로드밸런서가 왜 필수인가
kubelet, kubectl, 컨트롤러는 모두 apiserver 주소 "하나"를
kubeconfig에 적어두고 쓴다.
CP1 주소를 직접 적으면 CP1이 죽을 때 같이 끊긴다.
그래서 앞에 LB를 두고 모두가 LB 주소를 보게 한다.
kubelet / kubectl --> LB :6443 --+--> CP1 apiserver
+--> CP2 apiserver
+--> CP3 apiserver
5. kubeadm 명령
첫 CP (LB 주소를 엔드포인트로, 인증서를 클러스터에 업로드)
kubeadm init --control-plane-endpoint=lb:6443 --upload-certs
추가 CP (--control-plane 과 --certificate-key 가 붙음)
kubeadm join lb:6443 --token ... --discovery-token-ca-cert-hash sha256:... \
--control-plane --certificate-key <key>
worker (위 두 옵션이 없음)
kubeadm join lb:6443 --token ... --discovery-token-ca-cert-hash sha256:...
--upload-certs 가 필요한 이유
CP들은 CA 같은 인증서를 공유해야 한다.
이 옵션이 인증서를 암호화해서 클러스터에 올리고,
추가 CP는 --certificate-key 로 풀어서 받아간다.
6. 함정
- --control-plane-endpoint 는 init 때만 정할 수 있다.
CP 1대로 시작해도 나중을 위해 처음부터 LB 주소로 만드는 게 정석.
- certificate-key 는 2시간 뒤 만료된다.
늦게 추가하면 kubeadm init phase upload-certs --upload-certs 로 새로 발급.
- worker join 에 --control-plane 을 붙이면 그 노드가 CP로 들어간다.
기억할 것: 추가 CP join 명령과 worker join 명령의 차이.
7. Q&A
Q1. External etcd 구성은 왜 최소 6대인가? 백업 서버를 두는 건가?
백업이 아니라 역할이 다른 서버 두 묶음이다.
- CP 서버 3대 : apiserver, scheduler, controller-manager 실행
- etcd 서버 3대 : etcd 전용. 셋이 모여 하나의 etcd 클러스터를 이룸
- etcd도 쿼럼이 필요해서 따로 떼어내도 최소 3대. 그래서 3 + 3 = 6대.
- CP와 etcd는 1:1 짝이 아니다. apiserver 3개가 etcd 3대 전체에 접속한다.
CP1 apiserver --+ +-- etcd1
CP2 apiserver --+------->+-- etcd2 (셋이 하나의 etcd 클러스터)
CP3 apiserver --+ +-- etcd3
- 복제는 백업이 아니다. 실수로 지운 데이터도 그대로 복제되므로
snapshot 백업은 별도로 해야 한다.
Q2. etcd도 Redis 클러스터처럼 해시로 데이터를 쪼개나?
쪼개지 않는다. 모든 멤버가 전체 데이터를 가진다.
항목 Redis 클러스터 etcd
데이터 분배 해시 슬롯으로 분할 분할 없음. 전원 전체 복사본
쓰기 슬롯 담당 master 리더 1대
복제 비동기 과반수 저장 후 성공 응답
장애 시 유실 가능 유실 없음
대수 증가 용량/처리량 증가 증가 없음. 쓰기가 느려짐
- Raft 합의 알고리즘 사용. 투표로 리더 선출, 리더 장애 시 자동 재선출.
- 목적은 용량이 아니라 정확성. 쿠버네티스 상태는 수 GB 수준이라 한 대에 다 들어간다.
그래서 3대 또는 5대로 둔다.
Q3. LB는 어느 CP에 올라가 있나?
쿠버네티스가 LB를 만들어 주지 않는다. 직접 준비해야 한다.
- 클라우드 LB : 클라우드 관리형 (AWS NLB 등)
- 별도 LB 서버 : CP와 다른 VM 2대에 HAProxy + keepalived (온프레미스)
- CP 위에 올림 : kube-vip 를 CP마다 static pod 로 실행 (서버 절약)
- LB가 1대면 그게 새로운 단일 장애점. 그래서 2대 + VIP 로 구성.
- VIP = 떠다니는 IP. LB1이 죽으면 LB2가 같은 IP를 가져간다.
클라이언트는 IP 하나만 알면 된다. keepalived, kube-vip 가 IP 넘기기를 한다.
Q4. join 명령의 token, ca-cert-hash, certificate-key 는 어디서 나오나?
첫 CP에서 kubeadm init 을 실행하면 마지막에 join 명령이 통째로 출력된다.
그걸 복사해서 새 노드에 붙여 넣는 것이 전부다.
Your Kubernetes control-plane has initialized successfully!
...
You can now join any number of control-plane nodes by running:
kubeadm join lb:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:1234...cdef \
--control-plane --certificate-key 5678...90ab
Then you can join any number of worker nodes by running:
kubeadm join lb:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:1234...cdef
새 노드와 클러스터는 처음 만나는 사이라 서로가 진짜인지 확인해야 한다.
token 클러스터가 새 노드를 확인. 입장용 임시 비밀번호. 24시간 만료
ca-cert-hash 새 노드가 클러스터를 확인. CA 지문 대조. CA 교체 전까지 유효
certificate-key 추가 CP 전용. 업로드된 공유 인증서를 푸는 열쇠. 2시간 만료
- certificate-key 는 CP끼리 CA를 공유하기 위한 값이라 worker join 에는 없다.
출력을 잃어버렸거나 만료됐을 때 (첫 CP에서 실행)
kubeadm token create --print-join-command
-> worker join 명령 한 줄 전체를 출력
kubeadm init phase upload-certs --upload-certs
-> 추가 CP용 certificate-key 재발급
추가 CP는 첫 번째 출력 뒤에
--control-plane --certificate-key <두 번째 출력 키>
를 붙인다.
시험: worker 추가 문제면
CP에서 --print-join-command 실행 -> 출력 복사 -> worker에 ssh 후 붙여 넣기