livenessProbe:
httpGet: { path: /healthz, port: 8080 }
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet: { path: /ready, port: 8080 }
periodSeconds: 5
startupProbe:
httpGet: { path: /healthz, port: 8080 }
failureThreshold: 30
periodSeconds: 10 # 최대 300초까지 기동을 기다린다
- liveness — 실패하면 '컨테이너를 재시작' 한다
- 재시작으로 나아질 문제만 넣는다 (데드락 · 무한 루프)
- readiness — 실패하면 '엔드포인트에서 뺀다' (재시작하지 않는다)
- 의존 자원 확인은 여기에
- startup — 통과할 때까지 liveness·readiness 를 유예한다
- 기동이 느린 애플리케이션에 필수
가장 흔한 사고 — liveness 에 DB 확인
DB 장애 → 모든 파드의 liveness 실패 → 전부 재시작
- 재시작해도 DB 는 여전히 죽어 있다
- CrashLoopBackOff 무한 루프
원래 3초 순단이었을 일이 수 분짜리 장애가 된다 게다가 재시작 중에는 로그도 끊긴다
규칙 — liveness 는 '자기 자신' 만 본다
- 공통 의존은 readiness 에, 그것도 필수 의존만
readiness 도 깊게 만들면 위험하다
readiness 에 DB 를 넣으면
- DB 가 흔들릴 때 모든 파드가 동시에 NotReady 가 된다
- 트래픽 받을 곳이 없어진다 (503)
- 복구 후에도 한꺼번에 붙어 DB 를 또 무너뜨린다
필수 의존(없으면 아무것도 못 함)만 넣고, 선택 의존은 기능 축소로 대응한다
프로브 종류
-
httpGet — 2xx·3xx 면 성공. 가장 흔하다
-
tcpSocket — 포트가 열려 있으면 성공. HTTP 가 아닌 것에
-
exec — 명령의 종료 코드 0 이면 성공. 비용이 가장 크다
-
grpc — gRPC 헬스 체크 프로토콜
-
exec 프로브는 매번 프로세스를 띄운다
- 주기가 짧고 파드가 많으면 노드 부하가 된다
프로브가 부하가 되는 경우
파드 1,000개 × readiness 5초 주기 = 초당 200회 헬스체크
- exec 프로브면 매번 프로세스를 띄운다 → 노드 부하
- 헬스체크가 DB 를 찌르면 DB 부하가 된다
- 액세스 로그의 대부분이 헬스체크가 된다
대응
- 헬스 엔드포인트는 가볍게 (계산·외부 호출 없이)
- 주기를 필요 이상으로 짧게 두지 않는다
- 앞단에서 헬스체크 경로의 로그를 끈다
값을 정하는 감각
- readiness — 주기 5~10초 · failureThreshold 3
- 15~30초 안에 트래픽에서 빠진다
- liveness — 주기 10~30초 · failureThreshold 3
- 성급하게 재시작하지 않도록 readiness 보다 느슨하게
- startup — failureThreshold × periodSeconds 가 최대 기동 허용 시간
- 가장 느린 기동보다 넉넉하게
liveness 를 readiness 보다 촘촘하게 두면 일시적 지연에 재시작이 걸려 상황이 악화된다
면접 함정
- ❌ "liveness와 readiness는 비슷하다" → 실패 시 조치가 재시작이냐 트래픽 제외냐로 완전히 다르다.
- ❌ "initialDelaySeconds로 기동을 기다리면 된다" → 기동 시간이 들쭉날쭉하면 깨진다. startupProbe를 쓴다.