← 스터디 홈
7편 · 약 10분

헬스체크와 롤아웃 전략

Pod는 "떴다"와 "정상"을 구별해야 한다

컨테이너가 시작됐다고 해서 요청을 받아도 되는 상태인 것은 아니다. JVM 예열, 캐시 웜업, DB 커넥션 풀 초기화가 끝나야 비로소 트래픽을 허용할 수 있다. 반대로 이미 떠 있는 컨테이너가 데드락에 빠져 아무것도 못 하는 상태일 수도 있다. 쿠버네티스는 이 두 문제를 세 가지 프로브(Probe)로 해결한다.

세 가지 프로브

Liveness Probe — "살아 있는가?"

앱이 데드락·무한루프·메모리 누수 등으로 응답 불능이 되면 kubelet이 컨테이너를 재시작한다.

핵심 규칙: Liveness Probe는 외부 의존성을 절대 확인하지 않는다. DB가 다운됐을 때 Liveness가 실패하면, 멀쩡한 Pod들이 줄줄이 재시작되어 장애가 증폭된다.

Readiness Probe — "트래픽을 받을 준비가 됐는가?"

실패하면 해당 Pod를 Service의 엔드포인트에서 제거한다. Pod는 죽지 않는다. 준비가 되면 엔드포인트에 다시 추가된다. 롤링 업데이트 중 신규 Pod의 안전을 보장하는 핵심이다.

Startup Probe — "초기화가 끝났는가?"

Startup Probe가 성공할 때까지 Liveness/Readiness Probe를 아예 실행하지 않는다. 시작이 느린 앱(레거시 Java, 대용량 모델 로딩 등)을 위해 설계됐다.

컨테이너 시작 Startup Probe
성공할 때까지 반복
↓ 성공 Liveness Probe
실패 → 재시작
Readiness Probe
실패 → 엔드포인트 제거
세 프로브의 시간 흐름과 역할

프로브 메커니즘

메커니즘설명
httpGet지정 경로에 HTTP GET 요청; 2xx–3xx이면 성공
exec컨테이너 내 명령어 실행; 종료 코드 0이면 성공
tcpSocketTCP 포트 연결 시도; 연결되면 성공
grpcgRPC Health Checking Protocol v1 호출 (Kubernetes 1.24+)

공통 파라미터

파라미터기본값설명
initialDelaySeconds0컨테이너 시작 후 첫 프로브까지 대기 시간
periodSeconds10프로브 실행 주기(초)
timeoutSeconds1프로브 응답 대기 시간(초); 초과 시 실패로 간주
failureThreshold3연속 실패 횟수; 이 값 초과 시 Fail 판정
successThreshold1연속 성공 횟수; Readiness는 1 이상으로 설정 가능

Startup Probe 설정 예: failureThreshold: 30, periodSeconds: 10 → 최대 300초(5분) 동안 초기화를 기다린다.

startupProbe:
  httpGet:
    path: /healthz
    port: 8080
  failureThreshold: 30
  periodSeconds: 10
livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  periodSeconds: 15
  failureThreshold: 3
readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  periodSeconds: 5
  failureThreshold: 3

/healthz/ready분리하는 것이 중요하다. /healthz는 앱 자체만 확인하고, /ready는 DB 연결·캐시 준비 등 서비스 가능 여부를 확인한다.

롤아웃 전략

쿠버네티스 Deployment는 두 가지 업데이트 전략을 제공한다.

RollingUpdate (기본값)

구버전 Pod를 점진적으로 교체한다. 두 버전이 동시에 트래픽을 받는 순간이 생긴다. API 하위 호환성을 유지해야 한다.

strategy:
  type: RollingUpdate
  rollingUpdate:
    maxSurge: 25%        # 희망 복제본 수를 초과해 임시 생성할 수 있는 Pod 최대치
    maxUnavailable: 25%  # 업데이트 중 사용 불가 상태로 둘 수 있는 Pod 최대치
  • maxSurge: 0, maxUnavailable: 1 → 하나씩 교체, 추가 노드 없이 진행 (리소스 절약형)
  • maxSurge: 1, maxUnavailable: 0 → 먼저 새 Pod를 띄우고 나서 구 Pod를 내린다 (무중단 보장형)

새 Pod가 Readiness Probe를 통과해야 구 Pod가 내려가기 때문에, Readiness Probe가 없으면 롤아웃이 안전을 보장하지 못한다.

Recreate

구 Pod를 모두 내린 뒤 새 Pod를 띄운다. 단순하지만 다운타임이 발생한다. 두 버전이 동시에 뜨면 안 되는 앱(예: 싱글톤 잠금, DB 스키마 마이그레이션 직후)에 사용한다.

strategy:
  type: Recreate

롤아웃 흐름 한눈에 보기

구 버전 Pod (v1) v1 ✓ v1 ✓ v1 종료↓ 신 버전 Pod (v2) v2 초기화… v2 Ready✓ v2 Ready✓ Readiness 통과 후 v1 교체 ① v2 Pod 생성 → Readiness Probe 실행 중 (트래픽 차단) ② Readiness 성공 → 엔드포인트 추가, v1 Pod 종료 시작 ③ 반복 → 모든 v1이 v2로 교체 완료
RollingUpdate 중 Readiness Probe 역할

안티패턴 정리

실수결과
Liveness에서 DB 연결 확인DB 장애 시 Pod 재시작 폭풍
/healthz/ready를 동일 엔드포인트로 사용초기화 중인 Pod에 트래픽이 유입됨
initialDelaySeconds를 너무 길게 설정실제 장애를 늦게 감지
Startup Probe 없이 긴 initialDelaySeconds이미 죽은 컨테이너를 오래 방치
Readiness Probe 없이 RollingUpdate준비 안 된 Pod에 트래픽 유입 가능

References

  • https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/
  • https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
  • https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
  • https://oneuptime.com/blog/post/2026-02-09-health-checks-liveness-vs-readiness/view
  • https://oneuptime.com/blog/post/2026-02-09-rolling-update-maxsurge-maxunavailable/view
  • https://www.bluematador.com/blog/kubernetes-deployments-rolling-update-configuration
  • https://spacelift.io/blog/kubernetes-liveness-probe
  • https://octopus.com/devops/kubernetes-deployments/kubernetes-deployment-strategies/