운영 중인 앱의 스프링 부트 프로젝트가EC2
서버에서 종료한 적이 없는데 자꾸 종료되는 일이 발생했다. 프로젝트의 오류 로그도 없고 EC2
도 인스턴스 상태 검사 오류가 발생한 적이 없었다. 원인이 무엇인가 확인해보니 OOM(Out Of Memory) killer
의 대상이 되서 프로젝트가 종료된 것이다.
OOM killer
의 작동 방식을 알 수 있다. EC2
서버가 메모리가 부족한 상황이 오면 OOM killer
가 OOM Scoring
을 통해 가장 나쁜 점수를 가진 프로세스를 종료한다. 블로그를 참고하면 메모리를 많이 차지하는 프로세스가 나쁜 점수를 받아 죽을 수 있는데 현재 EC2
서버에서 스프링 부트 프로젝트가 많은 메모리를 차지한다. 그래서 OOM killer
의 대상이 된 것이다. 그러나 스프링 부트 프로젝트는 앱의 백엔드를 담당하는 프로세스이기 때문에 OOM killer
의 대상이 되면 안된다. 그러므로 아래의 방법을 통해 OOM killer
의 대상에서 제외한다. 일단 OOM killer
로 종료된 것인지 확인해보겠다.dmesg | grep -E -i -B100 'killed process'
위의 명령으로 종료된 프로세스의 목록을 확인해보았다.
[52*2*5.*54*91] Out of memory: Killed process 30264 (java) total-vm:2858720kB, anon-rss:255412kB, file-rss:0kB, shmem-rss:0kB, UID:0 pgtables:916kB oom_score_adj:0
로그를 확인해보니 Java
프로세스가 종료되었다.
cat /var/log/kern.log
위의 명령으로 Java
프로세스가 언제 종료되었는지 확인해보았다.
Mar 8 11:32:12 ip-172-31-10-193 kernel: [52*2*5.*54*35] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/user.slice,task=java,pid=30264,uid=0
Mar 8 11:32:12 ip-172-31-10-193 kernel: [52*2*5.*54*91] Out of memory: Killed process 30264 (java) total-vm:2858720kB, anon-rss:255412kB, file-rss:0kB, shmem-rss:0kB, UID:0 pgtables:916kB oom_score_adj:0
Mar 8 11:32:12 ip-172-31-10-193 kernel: [52*2*5.*93*89] oom_reaper: reaped process 30264 (java), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
상황을 확인해보니 UTC기준 3월 8일 11:30분쯤에 OOM Killer
가 스프링 부트 프로젝트를 종료했고 EC2
모니터링 로그에 UTC기준 3월 8일 11:30분쯤에 CPU
사용률이 30%까지 올라갔다.
CPU
사용량이 급증하는 과정에서 EC2
서버의 메모리가 부족해졌고 그래서 OOM killer
가 스프링 부트 프로젝트를 종료한 것이었다. 시스템이 멈추는 것을 막기 위해 OOM killer
는 종료할 수 없게 되어있다. 그러나 스프링 부트 프로젝트는 위에서 말했듯이 OOM killer
의 대상이 되면 안되므로 아래의 방법으로 회피한다.
$ echo -17 > /proc/<pid>/oom_adj
OOM killer
를 끌 수는 없지만 OOM killer
의 OOM scoring
대상에서 벗어나는 것은 가능하다. 위의 명령으로 oom_adj
값을 -17로 설정하는 것이다. -17 값은 OOM_DISABLE의 상수 값입니다. 위의 명령으로는 권한 문제가 발생해서 실제로는 아래의 명령을 적용하였다.
$ sudo bash -c "echo '-17' | tee /proc/<pid>/oom_adj"