
Node.js 컨테이너, 왜 깔끔하게 안 죽을까? (feat. Graceful shutdown)
두줄요약
Node.js 컨테이너 종료 지연을 PID 1, 시그널 전파, 이벤트 루프 관점에서 분석했습니다. dumb-init과 셧다운 훅, Kubernetes Grace Period의 역할 분담을 적용했습니다.
문제 상황
- Kubernetes 배포 중 SIGTERM 수신 뒤 배치 컨슈머가 종료되지 않고 SIGKILL까지 지속되는 현상
Promise.race기반 2분 타임아웃 이후에도 배치가 완료될 때까지 Pod가 살아 있는 상황
원인 분석
- PID 1의 시그널 처리 특성, 자식 프로세스 시그널 전파와 좀비 프로세스 정리 책임의 결합
- 타임아웃에서 반환된 뒤에도 취소되지 않은 배치 비동기 작업과 타이머가 이벤트 루프에 잔존
해결 방법
dumb-init을 PID 1로 설정해 시그널 전파와 좀비 프로세스 정리 위임- NestJS 셧다운 훅에서 실행 중인 배치 완료를 대기하고 애플리케이션 타임아웃 설정
- 앱 타임아웃보다 긴 Kubernetes
terminationGracePeriodSeconds설정
트레이드오프
AbortController기반 강제 중단 대신 이미 시작된 배치 완료 보장 선택- 루프별 중단 확인 코드 복잡도와 DB 트랜잭션 정합성 위험 회피


