Kubernetes에서 파드 종료 시 에러가 발생하는 이유
쿠버네티스를 운영하다 보면 종종 의문스러운 상황을 마주합니다. 기존 파드를 종료하고 새 파드를 배포했을 뿐인데, 간헐적으로 5xx 에러가 발생하거나 롤링 업데이트 도중 사용자가 에러 페이지를 보게 되는 경우죠.
이번 글에서는 도대체 왜 이런 다운타임이 발생하는지 그 원인을 파헤쳐보고, preStop 훅을 활용해 이를 우아하게(Graceful) 해결하는 방법을 단계별로 알아보겠습니다.
파드가 죽을 때 무슨 일이 벌어지나?
파드 삭제 명령(kubectl delete pod 또는 kubectl drain)이 내려지면, Kubernetes는 두 가지 작업을 동시에 시작합니다:
| 작업 | 담당 컴포넌트 | 하는 일 |
|---|---|---|
| 파드 종료 | Kubelet | 컨테이너에 종료 신호(SIGTERM) 전송 |
| 트래픽 차단 | Endpoint Controller, kube-proxy | 서비스 목록에서 파드 IP 제거, iptables 갱신 |
여기서 핵심은 "동시에" 입니다. 순차적으로 "트래픽 먼저 끊고 → 파드 종료"가 아닙니다.
문제의 원인: Race Condition
두 작업이 동시에 시작되지만, 완료 시간이 다릅니다.
파드 종료: ████░░░░░░ (빠름, 1~2초)
트래픽 차단: ████████░░ (느림, 5~10초)
파드는 이미 죽었는데, 로드밸런서는 아직 그 사실을 모릅니다.
결과적으로:
- 로드밸런서가 죽은 파드로 요청을 보냄
- Connection refused 또는 502/504 에러 발생
- 사용자가 에러 페이지를 봄
이게 바로 배포할 때마다 간헐적으로 에러가 튀는 이유입니다.
해결책: preStop 훅으로 종료 지연하기
아이디어는 간단합니다. 파드가 죽기 전에 잠깐 기다리게 해서, 로드밸런서가 파드를 목록에서 뺄 시간을 주면 됩니다.
이걸 구현하는 게 preStop 훅입니다.
lifecycle:
preStop:
exec:
command: ["sh", "-c", "sleep 10"]
이제 어떻게 동작하나?
- 파드 삭제 요청이 들어옴
- preStop 훅 실행 → 10초간 대기 (이 동안 파드는 살아있고, 요청도 처리함)
- 그 10초 동안 Endpoint Controller가 서비스 목록에서 파드 제거 (새 트래픽 차단) & 삭제 대상 파드는 기존에 수행중인 작업을 마무리
- 새로운 사용자는 에러 없이 다른 파드로 연결되며, 기존 사용자는 정상적으로 처리된 응답을 받음
핵심: 파드가 서비스 목록에서 빠질 때까지 살아있는 상태로 버티는 것입니다.
전체 종료 흐름

[삭제 요청] ─┬─→ 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이 보장되어야 함
마무리
정리하면:
- 문제: 파드 종료와 트래픽 차단이 동시에 일어나서 race condition 발생
- 원인: 트래픽 차단이 파드 종료보다 느림
- 해결: preStop 훅으로 파드 종료를 지연시켜 로드밸런서 갱신 시간 확보
- 주의:
terminationGracePeriodSeconds를 충분히 길게 설정