서버가 죽었는데 로드밸런서가 계속 트래픽을 보내면 요청이 실패한다. 서버를 배포하기 위해 내릴 때 기존 요청을 처리 중인 연결을 강제로 끊으면 사용자 입장에서 오류가 난다. 헬스체크와 Connection Draining은 이 두 문제를 해결한다.

Health Check

로드밸런서는 주기적으로 각 서버에 헬스체크 요청을 보낸다. 응답이 정상이면 트래픽을 보내고, 비정상이면 해당 서버를 타깃 그룹에서 제외한다.

ALB 헬스체크 설정:
  프로토콜: HTTP
  경로: /health
  포트: 8080
  정상 임계값: 연속 2번 성공
  비정상 임계값: 연속 3번 실패
  타임아웃: 5초
  간격: 30초

서버가 연속 3번 실패하면 Unhealthy로 표시되고 트래픽이 끊긴다. 이후 다시 연속 2번 성공하면 트래픽이 재개된다.

헬스체크 엔드포인트 설계

단순히 HTTP 200을 반환하는 것 이상으로 설계하는 것이 좋다.

// 얕은 헬스체크: 프로세스가 살아있는지만 확인
GET /health  200 OK

// 깊은 헬스체크: DB, 캐시 연결까지 확인
GET /health/ready
{
  "status": "ok",
  "db": "connected",
  "cache": "connected"
}

로드밸런서 헬스체크는 얕은 체크가 맞다. DB 연결을 확인하는 깊은 체크를 로드밸런서에 연결하면, DB가 잠깐 느려질 때 모든 서버가 Unhealthy로 빠지는 사태가 생긴다.

깊은 헬스체크는 k8s의 Readiness/Liveness Probe처럼 파드 레벨에서 별도로 관리하는 것이 맞다. 로드밸런서 헬스체크 경로(/health)는 프로세스 기동 확인 수준으로 단순하게 유지한다.

배포 시 활용

새 버전을 배포할 때:

  1. 새 인스턴스/파드 기동 시작
  2. 헬스체크 통과할 때까지 대기 (Healthy 상태 진입)
  3. 로드밸런서가 트래픽 전송 시작
  4. 이전 버전 서버 제거 시작 (Connection Draining)

헬스체크가 통과하지 않으면 배포가 중단된다. 잘못된 버전이 트래픽을 받기 전에 차단된다.

Connection Draining (Deregistration Delay)

서버를 타깃 그룹에서 제거할 때, 이미 처리 중인 연결을 강제로 끊으면 오류가 발생한다. Connection Draining은 제거 신호를 받은 서버에 새 연결은 보내지 않고, 기존 연결은 설정된 시간 동안 자연스럽게 완료되길 기다리는 메커니즘이다.

배포 시 흐름:
1. 서버를 타깃 그룹에서 deregister 요청
2. 로드밸런서: 이 서버로 새 연결 전송 중단
3. 기존 진행 중인 요청은 계속 처리
4. Deregistration Delay (기본 300초) 동안 기다림
5. 딜레이 이내에 모든 연결 종료되면 즉시 제거
   딜레이 초과하면 강제 종료 후 제거
6. 서버 셧다운
AWS ALB 설정:
  Deregistration Delay: 300초 (기본값, 0~3600 사이 설정 가능)

딜레이 값 설정

API 서버처럼 요청 처리 시간이 짧은 경우 30~60초면 충분하다. 배치 처리나 파일 업로드처럼 오래 걸리는 요청이 있으면 더 길게 설정한다.

배포 파이프라인 타임아웃과 맞춰야 한다. Deregistration Delay가 300초인데 배포 스텝 타임아웃이 120초면, 딜레이가 끝나기 전에 파이프라인이 실패한다.

EKS에서는 파드 종료 전에 로드밸런서에서 제거되는 타이밍을 맞추는 것이 중요하다. preStop 훅에 sleep을 넣어 로드밸런서 deregistration이 완료될 때까지 기다리는 패턴이 흔하다.

lifecycle:
  preStop:
    exec:
      command: ["/bin/sh", "-c", "sleep 10"]   # deregistration 완료 대기

트레이드오프

헬스체크 간격을 짧게 하면 장애 감지가 빠르지만 서버 부하가 늘고, 헬스체크 트래픽 비용도 증가한다. 간격을 길게 하면 장애 감지가 느려진다. 비정상 임계값을 낮추면 일시적인 느린 응답에도 Unhealthy로 빠질 수 있다. 서비스 특성에 맞는 값을 튜닝해야 한다.

Connection Draining 시간이 길면 배포 속도가 느려진다. 서버 10대를 순차적으로 교체하면서 각각 300초를 기다리면 배포에 50분이 걸린다. 딜레이를 짧게 하거나, 병렬로 여러 서버를 동시에 교체하는 방식을 조합해 배포 시간을 조정한다.