Pod가 갑자기 사라진다고? 🚨 Kubernetes Graceful Shutdown 완전 정복
by gasbugs2026. 4. 3.
반응형
Scale-in 할 때마다 클라이언트가 에러를 받는다면, 그건 설계의 문제가 아니라 종료 전략의 문제다.
종료 직전 모든 작업을 완료하고 안전하게 마무리하는 Graceful Shutdown의 서사 — 혼돈 속에서도 질서 있게 정리하고 떠나는 선원의 마음.
🎯 이 글에서 다루는 것
Pod가 종료될 때 실행 중인 요청에 무슨 일이 생기는지
SIGTERM과 Graceful Shutdown의 동작 원리
terminationGracePeriodSeconds 설정으로 종료를 안전하게 만드는 방법
preStop Hook 활용법
MSA 환경에서 권장하는 타임아웃 전략
📌 도입 / 배경
Kubernetes의 HPA(Horizontal Pod Autoscaler)는 트래픽이 줄면 Pod 수를 자동으로 줄여준다. 이건 아주 훌륭한 기능이다.
근데 여기서 현실적인 문제가 생긴다.
"Pod가 줄어드는 순간, 그 Pod에서 처리 중이던 요청은 어떻게 되는 걸까?"
아무 처리를 하지 않으면 아래처럼 된다.
HPA가 Pod를 종료하기로 결정
Pod 안에서 API 요청을 열심히 처리하는 중
Pod가 강제로 SIGKILL을 받고 즉시 사라짐
클라이언트는 응답도 못 받고 TCP 연결이 끊김
클라이언트는 timeout까지 기다리다가 Connection reset 또는 502/504 에러 수신
이 글에서는 이 문제를 Graceful Shutdown(우아한 종료) 전략으로 해결하는 방법을 다룬다.
🔍 Kubernetes Pod 종료 흐름 이해하기
Pod가 삭제될 때 Kubernetes는 아래 순서로 동작한다.
1. kubectl delete pod / HPA scale-in 명령
2. Pod 상태 → Terminating
3. Endpoint에서 해당 Pod IP 제거 (더 이상 새 요청을 받지 않음)
4. Container에 SIGTERM 신호 전송
5. terminationGracePeriodSeconds 동안 대기 (기본 30초)
6. 기간 내 종료 안 되면 SIGKILL로 강제 종료
여기서 핵심은 3번과 4번이 동시에 발생하지 않는다는 점이다.
kube-proxy와 Ingress Controller가 Endpoint 변경을 감지하는 데 수 초의 전파 지연(propagation delay) 이 있다. 즉, SIGTERM을 받은 순간에도 새 요청이 들어올 수 있다는 뜻이다.
가장 근본적인 해결책이다. 애플리케이션이 SIGTERM을 받으면 즉시 죽지 말고, 처리 중인 요청을 마저 끝낸 뒤 종료하도록 만든다.
애플리케이션 레벨 처리 (Node.js 예시)
const server = app.listen(3000);
process.on('SIGTERM', () => {
console.log('SIGTERM received. Closing server gracefully...');
// 새 연결은 받지 않고, 기존 연결 처리 완료 대기
server.close(() => {
console.log('All connections closed. Exiting.');
process.exit(0);
});
// 안전장치: 25초 후 강제 종료 (gracePeriod보다 짧게)
setTimeout(() => {
console.error('Forced exit after timeout');
process.exit(1);
}, 25000);
});
Java Spring Boot 예시
Spring Boot 2.3 이상에서는 설정 한 줄로 Graceful Shutdown을 활성화할 수 있다.