Skip to content
hello tis
Go back

[26.09.15] 알툴즈 AI API의 OOM kill과 정상 종료 과정 구분하기

알툴즈 AI API의 JVM 메모리 장애에서는 Heap 사용량이 정상인데 RSS가 증가해 OOM kill과 재시작이 반복됐습니다. 서버가 다시 요청을 받을 수 있어도 종료 전에 받은 요청의 처리 완료까지 보장되지는 않습니다. 종료 원인과 요청의 처리 상태를 구분해 대응할 필요가 있습니다.

Pod 교체 중 요청을 마무리하도록 종료 시간 배분하기

롤링 업데이트로 새 Pod를 준비해도 기존 Pod가 처리 중인 요청은 새 Pod로 옮겨지지 않습니다. 기존 Pod에서 요청을 마무리할 수 있도록 종료 유예 시간이 필요합니다.

Pod 삭제에 따른 트래픽 경로 변경과 종료 처리는 함께 진행됩니다. 경로 변경이 반영되기 전에는 기존 Pod로 새 요청이 들어올 수 있으므로, 새 요청의 유입을 멈추는 시간과 처리 중인 요청을 마무리하는 시간을 구분해야 합니다.

JVM의 종료 훅은 JVM이 종료될 때 실행하는 스레드입니다. Spring은 종료 훅에서 컨텍스트를 닫으며, graceful shutdown이 켜져 있으면 설정된 종료 대기 시간을 한도로 처리 중인 요청의 완료를 대기합니다.

종료 유예 시간 30초, preStop 실행 시간 10초 조건

Pod 삭제 시 kubelet과 컨테이너 런타임, JVM, Spring의 종료 순서와 시간 초과 분기

종료 유예 시간은 preStop 실행 전부터 계산됩니다. preStop의 대기가 길어질수록 JVM이 처리 중인 요청과 자원 정리를 완료할 시간은 줄어듭니다. 따라서 트래픽 경로 변경을 기다리는 시간과 JVM의 종료 시간을 같은 유예 시간 안에서 배분해야 합니다.

종료 유예 시간 30초 중 preStop이 10초를 사용하는 경우

공통 시간축에서 preStop 실행과 JVM 종료, 컨테이너 런타임의 대기에 사용할 수 있는 시간

강제 종료로 응답을 받지 못한 요청의 복구 방식 결정하기

커널이 JVM을 OOM kill하면 SIGKILL로 강제 종료하므로, 종료 훅을 실행할 수 없습니다. graceful shutdown으로 처리 중인 요청을 마무리하거나 @PreDestroy로 자원을 정리할 기회가 사라집니다.

종료 코드만으로는 종료 원인과 요청 완료 여부를 확정할 수 없습니다. OpenJDK는 종료 훅을 거친 뒤에도 143으로 종료할 수 있습니다. 137은 종료 유예 시간 초과와 OOM kill에서 모두 나타날 수 있으므로, 종료 사유와 메모리 상태를 함께 확인해야 합니다.

종료 상황종료 신호종료 훅과 요청 처리함께 확인할 기록
Pod 교체 중 유예 시간 안에 종료SIGTERMgraceful shutdown 설정 시 처리 완료 대기143과 배포 이력
종료 유예 시간 초과SIGTERM 이후 SIGKILL처리 중인 요청과 종료 훅 강제 중단137과 종료 유예 시간 초과 기록
커널의 OOM killSIGKILL종료 훅 실행 불가137, reason: OOMKilled, 메모리 상태

종료 원인을 확인해도 개별 요청의 처리 결과까지 알 수는 없습니다. 응답이 없어도 이미 처리 완료 상태일 수 있습니다. 처리 결과를 모른 채 재시도하면 같은 요청이 중복 실행될 수 있으므로, 요청 식별자로 완료 기록과 외부 처리 상태를 대조해야 합니다.

처리 기록은 프로세스가 종료된 뒤에도 조회할 수 있어야 합니다. 같은 요청 식별자를 보내는 것만으로 중복 실행이 방지되지는 않으므로, 서버의 상태 변경과 외부 처리까지 중복 실행을 방지할 수 있는 요청으로 자동 재시도를 한정할 필요가 있습니다.

완료 기록과 외부 처리 상태, 중복 실행 방지 가능 여부에 따른 요청 복구 분기

확인한 상태필요한 대응
처리 완료요청 식별자와 요청 내용이 일치하는 기존 결과를 반환해야 합니다.
외부 처리 진행 중대기 한도를 넘겨도 실패로 단정하지 않고 외부 처리 상태를 다시 확인해야 합니다.
처리 결과 불명처리 기록과 외부 처리 결과를 대조할 경로가 없거나, 대조 후에도 처리 결과를 확정할 수 없으면 수동으로 확인해야 합니다.
외부 처리가 없고 중복 실행 방지 가능재시도 가능한 오류와 횟수, 대기 시간을 제한해야 합니다.
중복 실행 방지 불가이미 반영된 변경과 재시도로 추가될 변경을 구분해 복구 방법을 결정해야 합니다.

Share this post:

Previous Post
사내 버셀 구축 - 2단계: 보안 피드백 반영
Next Post
[26.09.14] 챌린지 API의 장시간 동작 검증을 위한 30시간 Soak Test 진행하기