Design Kubernetes - HA(High Availability)

2026. 1. 6. 16:04·CKA

프로덕션에서 “마스터(컨트롤 플레인) 노드 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로 조회/수정/배포가 불가
  • 클러스터 상태 변화 반영 불가
    • 노드 장애 감지 후 파드 재배치
    • 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
'CKA' 카테고리의 다른 글
  • Deploy k8s
  • Design Kubernetes - HA of ETCD
  • Design Kubernetes - Choosing Infrastructure
  • Design Kubernetes
5jyan5
5jyan5
  • 5jyan5
    jyan
    5jyan5
  • 전체
    오늘
    어제
    • 분류 전체보기 (242)
      • 김영한의 스프링 핵심 원리(기본편) (8)
      • 김영한의 스프링 핵심 원리 - 고급편 (11)
      • 김영한의 스프링 MVC 1편 (1)
      • 김영한의 스프링 DB 1편 (3)
      • 김영한의 스프링 MVC 2편 (3)
      • 김영한의 ORM 표준 JPA 프로그래밍(기본편) (9)
      • 김영한의 스프링 부트와 JPA 활용2 (2)
      • 김영한의 실전 자바 - 중급 1편 (1)
      • 김영한의 실전 자바 - 고급 1편 (9)
      • 김영한의 실전 자바 - 고급 2편 (9)
      • Readable Code: 읽기 좋은 코드를 작성.. (2)
      • 김영한의 실전 자바 - 고급 3편 (9)
      • CKA (118)
      • 개발 (37)
      • 경제 (4)
      • 리뷰 (1)
      • 정보 (2)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      페치 조인
      JPQL
      @args
      requset scope
      reentarantlock
      락
      조회 성능 최적화
      김영한
      Target
      @discriminatorvalue
      버퍼
      @within
      Thread
      양방향 맵핑
      typequery
      고급
      빈 후처리기
      프록시
      WAS
      jpq
      cglib
      jdk 동적 프록시
      단방향 맵핑
      @discriminatorcolumn
      자바
      log trace
      스레드
      gesingleresult
      프록시 팩토리
      hibernate5module
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.2
    5jyan5
    Design Kubernetes - HA(High Availability)
    상단으로

    티스토리툴바