세 개의 컨트롤 플레인 VM은 나쁜 밤을 버틸 세 번의 기회처럼 보입니다. 하지만 그렇지 않으며, 이 두 믿음 사이의 거리가 깔끔한 세 노드 설계를 한 건물이 전력을 잃으면 쓰기 수용을 멈추는 클러스터로 바꿉니다. 사이트 사이의 VPN 링크는 머신을 서로 도달 가능하게 만들고 문제를 고치는 대신 숨깁니다. 투표는 etcd 구성원마다 세어지며, 그 구성원 중 둘은 여전히 하나의 스위치, 하나의 UPS, 하나의 업링크 뒤에 앉을 수 있습니다.

세 개의 컨트롤 플레인 노드, 하나의 장애 도메인

kubectl get nodes 를 실행하면 컨트롤 플레인 항목이 세 개 보이고 클러스터를 고가용성으로 기록합니다. 그 수는 스케줄 가능한 용량을 설명하며 생존성은 아닙니다. 외부 etcd 없이 유지되는 kubeadm에서는 각 컨트롤 플레인 노드가 구성원도 호스팅하므로 세 노드가 실제로 세 투표자를 줍니다. 그 투표자들이 독립적으로 실패하는지는 노드 목록이 답할 수 없는 별개의 질문입니다.

하나의 하이퍼바이저에 두 VM, 하나의 전원 공급에 두 랙, 하나의 ISP에서 두 업링크: 각 쌍은 두 호스트 이름을 쓴 하나의 도메인입니다. 배치를 적고 각 투표자가 무엇을 공유하는지 표시하세요 — 하이퍼바이저, PDU, 랙 상단 스위치, 스토리지 배열, NAT 장치, VPN 집선기. 그다음 종이에서 공유 객체를 하나씩 빼고 남은 투표를 다시 세세요. 실패한 호스트 하나로 투표자 둘을 잃는 클러스터는 처음부터 단일 투표자 클러스터였습니다; 아무도 아직 그 질문을 하지 않았을 뿐입니다.

두 사이트 분할이 견딜 수 있는 것과 없는 것

세 투표자를 두 사이트에 둘과 하나로 배치하면 다른 사이트가 사라질 때 더 큰 쪽은 쿼럼을 유지하고 단일 투표자 쪽은 결코 유지하지 못합니다. 그 비대칭은 산수이며 조정이 아닙니다. 정확히 두 개의 독립 사이트에 퍼진 다수결 기반 etcd 클러스터는 "어느 한 사이트를 잃고도 계속 커밋하라"는 시험을 통과하지 못합니다 — 양쪽이 동시에 과반수를 보유해야 하기 때문입니다.

아래 표는 어떤 장애를 실제로 샀는지 가장 빨리 보는 방법입니다. 각 행을 이렇게 읽으세요: 오늘 밤 이 행 전체가 사라지면 살아남은 쪽이 여전히 쓰기를 커밋할 수 있습니까?

What disappearsVoters leftWrites still commit
Site B, holding voter 32 of 3Yes
Site A, holding voters 1 and 21 of 3No
One hypervisor carrying any two voters1 of 3No
The inter-site VPN only2 of 3 on one sideOnly on the majority side

터널이 결코 투표를 더하지 않는 이유

VPN은 구성원이 아니라 전송입니다. 먼 투표자를 도달 가능하게 만들고 분할을 느린 타임아웃처럼 보이는 것으로 바꿀 수 있지만, 쿼럼에 대한 기여는 그게 전부입니다. 더하는 것은 비용입니다 — 모든 커밋이 링크를 건너야 하고 etcd는 raft 로그를 건드리는 쓰기에서 그 왕복을 지불합니다. 흔들리는 경로는 복제를 재시도와 선거로 바꿉니다.

분할은 사람들이 마법을 기대하는 곳이므로 정확하게 말해야 합니다. 링크가 끊길 때 옛 리더가 단일 투표자 쪽에 앉아 있다면 그쪽은 커밋할 수 없고 선거 타임아웃이 끝나면 리더는 물러납니다 — 반면 두 투표자 쪽은 대체자를 선출합니다. etcd의 장애 모드 안내서 는 동작을 분명히 설명합니다: 다수 쪽에서는 서비스가 계속되고, 고립된 쪽에는 두 번째 쓰기 가능한 클러스터가 없습니다.

어떤 중단을 살지 결정하세요

둘 더하기 하나는 사이트 A가 주 사이트이고 그것을 잃으면 누군가 조치할 때까지 컨트롤 플레인 쓰기를 잃는다는 것을 받아들일 때 정당한 설계입니다. 이를 결함으로 만드는 것은 그 결정을 암묵적으로 남기는 것입니다. 런북에 적으세요: 컨트롤 플레인이 어느 사이트에서 살아남는지, 다른 사이트가 03:00에 꺼질 때 운영자가 무엇을 하는지.

요구가 대신 "어느 사이트든 실패해도 된다"라면 배치는 각 사이트에서 과반수를 유지해야 하고, 두 사이트에 세 투표자로는 그럴 수 없습니다. 진정으로 독립적인 세 번째 도메인을 추가하거나 — 다른 제공자의 작은 리전은 그곳으로 가는 경로가 안정적이면 됩니다 — 별도 etcd를 가진 두 클러스터로 나뉘어 그 분할의 운영 비용을 받아들이거나 해야 합니다. 어떤 증인 지름길도 이것을 피하지 못합니다: etcd에는 경량 중재자 구성원이 없으므로 세 번째 투표자는 자체 디스크, 메모리, 네트워크 요구를 가진 완전한 구성원입니다. 다이어그램에 "증인"이라 적힌 상자를 그린다고 증인이 생기지 않습니다.

쿼럼은 서비스와 같지 않습니다

etcd 쿼럼은 API 서버가 쓰기를 받아들일 수 있게 유지하며, 유지하는 것은 그뿐입니다. 로드 밸런서 상태 검사, 인그레스, 터널을 통한 CNI 도달성, 볼륨 연결 영역, 애플리케이션 복제는 각각 자신의 답이 필요합니다. 클러스터는 깨끗한 과반수를 유지하고도 사용자에게 유용한 것을 전혀 제공하지 못할 수 있습니다.

그다음 있다고 믿는 구성원 구성을 확인하세요, 다이어그램은 흘러가기 때문입니다:

kubectl -n kube-system get pods -l component=etcd -o wide
kubectl get endpoints kube-apiserver -n default
etcdctl member list -w table

구성원 목록을 배치 도면과 비교하세요. 두 구성원이 같은 호스트나 같은 랙으로 해석되면 클러스터가 아니라 도면이 잘못된 것이며, 잘못된 토폴로지 주변에서 크기를 바꾸는 것은 같은 중단의 더 비싼 판을 살 뿐입니다.

어떤 세 투표자 설계든 승인하기 전에 네 가지 질문에 답하세요: 몇 투표자가 함께 전력을 잃는지, 어느 사이트 손실이 여전히 과반수를 남기는지, 터널이 끊길 때 리더가 어디에 있는지, 살아남은 사이트가 아직 무엇을 할 수 있는지. 그중 하나라도 "확실하지 않다"면 클러스터는 아직 고가용성이 아닙니다. 그것은 운이 좋았던 세 대의 머신입니다.

관련 글