본문으로 건너뛰기
개발 머꼬
개발 노트인프라·운영
hohyeon.dev15

헬스체크가 있는데도 트래픽이 아직 준비 안 된 인스턴스로 간 이유

  • #DevOps
  • #Engineering Note
  • #Kubernetes

문제 발생

새 버전을 배포하는 동안, 아직 초기화 중(DB 연결 풀 준비, 캐시 워밍업 등)인 인스턴스로 실제 요청이 라우팅되어 일시적으로 에러가 늘어나는 현상이 반복됐습니다. 헬스체크는 분명 설정돼 있었습니다.

원인 분석

헬스체크에는 서로 다른 두 가지 질문이 섞여 있는 경우가 많습니다.

  1. Liveness(생존 확인): "이 프로세스가 죽었나, 살아있나?" — 데드락에 빠지거나 응답 자체를 못 하는 상태인지만 확인합니다. 실패하면 오케스트레이터(Kubernetes 등)가 컨테이너를 재시작합니다.
  2. Readiness(준비 확인): "이 인스턴스가 지금 당장 실제 트래픽을 받을 준비가 됐나?" — DB 연결, 캐시 로딩, 다운스트림 서비스 연결 등이 다 끝났는지 확인합니다. 실패하면 로드밸런서가 그 인스턴스를 트래픽 대상에서 잠시 제외하지만, 재시작하지는 않습니다.

두 개를 하나의 엔드포인트(/health)로 합쳐서 "프로세스가 응답만 하면 OK"로 판정하면, 프로세스는 떠 있지만 아직 DB 연결이 안 끝난 상태에서도 healthy로 보고되어 트래픽이 라우팅됩니다 — 정확히 이번 문제의 원인입니다.

해결 방안

  1. Liveness와 Readiness를 별도 엔드포인트로 분리합니다.
GET /health/live   -> 프로세스가 요청을 처리할 수 있는 상태인지만 확인 (가볍게)
GET /health/ready  -> DB, 캐시, 필수 다운스트림 연결까지 전부 확인
  1. 배포 오케스트레이터(Kubernetes라면 livenessProbe/readinessProbe)에 각각 연결합니다. Readiness가 실패하는 동안은 재시작하지 않고 그저 트래픽에서 제외되도록 설정합니다.
  2. Liveness 체크는 가볍게 만듭니다 — 이 체크 안에서 DB 쿼리 같은 무거운 작업을 하면, DB가 잠깐 느려졌을 때 애플리케이션 자체는 멀쩡한데도 liveness가 실패해 불필요한 재시작이 연쇄적으로 일어날 수 있습니다(재시작 폭풍).
  3. Readiness 체크는 애플리케이션이 실제로 의존하는 리소스를 반영해야 합니다 — 캐시 워밍업이 끝나기 전에 받으면 안 되는 트래픽이 있다면 그 상태도 readiness 판정에 포함시킵니다.
  4. 초기 시작 시간이 원래 긴 애플리케이션(대용량 캐시 로딩 등)이라면, liveness probe에 initialDelaySeconds나 startup probe를 별도로 설정해 아직 시작 중인 상태를 죽은 것으로 오판하지 않도록 합니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.