Kubernetes 환경에서 sample-batch
시스템은 Java 기반의 Spring Batch Job을 실행하고 있으며, 안정적인 종료 처리가 매우 중요합니다. 특히 다음과 같은 요구사항을 만족해야 합니다:
SIGTERM
수신 시 Whatap 등 모니터링 에이전트가 전송을 마무리할 시간 확보- 리소스가 부족하거나 컨테이너 runtime이 멈춘(hang) 상황에서도 Job이 명확히 종료될 것
- Spring Context 내부에서 종료 시 리소스 정리를 할 수 있을 것
이를 위해 다음 설정 및 코드 전략을 활용했습니다:
핵심 설정
yaml복사편집activeDeadlineSeconds: 180
terminationGracePeriodSeconds: 10
- 180초가 지나면 종료 신호 전송
- 이후 10초간 graceful shutdown 기회 부여 (
SIGTERM
) - 이후 종료되지 않으면
SIGKILL
전송
코드 전략 요약
1. Shutdown Hook에서 Whatap 처리 및 Thread 정리
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
// Spring Context 수동 종료
if (ctx.isActive()) ctx.close();
// 모니터링 대기 시간
Thread.sleep(10000);
// 커스텀 스레드 그룹 interrupt
for (Thread t : Thread.getAllStackTraces().keySet()) {
if (t.getThreadGroup().getName().equals("batch-thread-group")) t.interrupt();
}
}));
2. ContextClosedEventListener에서 Job 및 스케줄러 강제 정지
@Component
public class ContextClosedEventListener implements ApplicationListener<ContextClosedEvent> {
@Override
public void onApplicationEvent(ContextClosedEvent event) {
// 스케줄러 종료
scheduler.shutdown();
// 실행 중인 Job 강제 중단
jobOperator.stop(executionId);
// 스레드 interrupt
interruptBatchThreads();
}
}
container runtime hang 이슈란?
Kubernetes가 SIGTERM
을 보냈음에도 Pod이 Terminating
상태에서 수분간 멈춰있는 경우, container runtime (예: containerd)이 중단되었거나 응답을 못하는 상태일 수 있습니다.
- 디스크 IO 병목
- 컨테이너 상태를 알 수 없는 zombie 상태
- containerd <-> kubelet 통신 실패
이런 경우에는 kubelet 로그 분석, 디스크/메모리/CPU 자원 확인이 필요합니다.
결론
Spring Batch를 Kubernetes 위에서 운영할 때는 단순히 activeDeadlineSeconds
설정만으로는 충분하지 않습니다.
shutdown hook, graceful shutdown을 위한 ContextClosedEvent
, 그리고 container runtime hang에 대한 이해까지 함께 갖추면 안정적이고 모니터링 가능한 종료 환경을 구축할 수 있습니다.