Infra

Kubernetes 무중단 배포를 위한 preStop 훅과 Grace Period 설정

mindol 2026. 1. 11. 17:39

Kubernetes에서 파드 종료 시 에러가 발생하는 이유 

쿠버네티스를 운영하다 보면 종종 의문스러운 상황을 마주합니다. 기존 파드를 종료하고 새 파드를 배포했을 뿐인데, 간헐적으로 5xx 에러가 발생하거나 롤링 업데이트 도중 사용자가 에러 페이지를 보게 되는 경우죠.

 

이번 글에서는 도대체 왜 이런 다운타임이 발생하는지 그 원인을 파헤쳐보고, preStop 훅을 활용해 이를 우아하게(Graceful) 해결하는 방법을 단계별로 알아보겠습니다.


파드가 죽을 때 무슨 일이 벌어지나?

파드 삭제 명령(kubectl delete pod 또는 kubectl drain)이 내려지면, Kubernetes는 두 가지 작업을 동시에 시작합니다:

작업 담당 컴포넌트 하는 일
파드 종료 Kubelet 컨테이너에 종료 신호(SIGTERM) 전송
트래픽 차단 Endpoint Controller, kube-proxy 서비스 목록에서 파드 IP 제거, iptables 갱신

 

여기서 핵심은 "동시에" 입니다. 순차적으로 "트래픽 먼저 끊고 → 파드 종료"가 아닙니다.


문제의 원인: Race Condition

두 작업이 동시에 시작되지만, 완료 시간이 다릅니다.

파드 종료:     ████░░░░░░  (빠름, 1~2초)
트래픽 차단:   ████████░░  (느림, 5~10초)

 

파드는 이미 죽었는데, 로드밸런서는 아직 그 사실을 모릅니다.

 

결과적으로:

  1. 로드밸런서가 죽은 파드로 요청을 보냄
  2. Connection refused 또는 502/504 에러 발생
  3. 사용자가 에러 페이지를 봄

이게 바로 배포할 때마다 간헐적으로 에러가 튀는 이유입니다.

 


해결책: preStop 훅으로 종료 지연하기

아이디어는 간단합니다. 파드가 죽기 전에 잠깐 기다리게 해서, 로드밸런서가 파드를 목록에서 뺄 시간을 주면 됩니다.

 

이걸 구현하는 게 preStop 훅입니다.

lifecycle:
  preStop:
    exec:
      command: ["sh", "-c", "sleep 10"]

이제 어떻게 동작하나?

  1. 파드 삭제 요청이 들어옴
  2. preStop 훅 실행 → 10초간 대기 (이 동안 파드는 살아있고, 요청도 처리함)
  3. 그 10초 동안 Endpoint Controller가 서비스 목록에서 파드 제거 (새 트래픽 차단) & 삭제 대상 파드는 기존에 수행중인 작업을 마무리
  4. 새로운 사용자는 에러 없이 다른 파드로 연결되며, 기존 사용자는 정상적으로 처리된 응답을 받음

핵심: 파드가 서비스 목록에서 빠질 때까지 살아있는 상태로 버티는 것입니다.

 

전체 종료 흐름

 

[삭제 요청] ─┬─→ Endpoint 제거 시작 (비동기)
             │
             ├─→ preStop 훅 실행 (sleep 10초)
             │
             └─→ Grace Period 카운트다운 시작 (기본 30초)
                      │
                      ▼
              [preStop 완료]
                      │
                      ▼
              [SIGTERM 전송] → 앱 종료 시작
                      │
                      ▼
              [앱 정상 종료] 또는 [Grace Period 초과 시 SIGKILL]

 

 

설정 예시

apiVersion: v1
kind: Pod
metadata:
  name: my-app
spec:
  terminationGracePeriodSeconds: 60  # 넉넉하게
  containers:
  - name: my-app
    image: nginx
    lifecycle:
      preStop:
        exec:
          command: ["sh", "-c", "sleep 10"]

terminationGracePeriodSeconds 계산법

terminationGracePeriodSeconds > preStop 시간 + 앱 종료 시간

 

Grace Period 안에 preStop 훅 실행과 앱 종료가 모두 완료되어야 합니다. 시간이 부족하면 SIGKILL로 강제 종료되어 데이터 유실이나 연결 끊김이 발생할 수 있습니다.

 

예시 계산:

항목 시간
preStop (sleep) 10초
앱 종료 (연결 정리, 버퍼 플러시 등) 15초
합계 25초
권장 설정 40~60초

 

여유 시간을 두는 이유:

  • 네트워크 지연으로 Endpoint 제거가 늦어질 수 있음
  • 앱이 처리 중인 요청을 마무리하는 데 예상보다 오래 걸릴 수 있음
  • 예외 상황에서도 graceful shutdown이 보장되어야 함

 

마무리

 

정리하면:

  1. 문제: 파드 종료와 트래픽 차단이 동시에 일어나서 race condition 발생
  2. 원인: 트래픽 차단이 파드 종료보다 느림
  3. 해결: preStop 훅으로 파드 종료를 지연시켜 로드밸런서 갱신 시간 확보
  4. 주의: terminationGracePeriodSeconds를 충분히 길게 설정

참고 문서