운영 비용, Autoscaling, Auto Healing 등의 k8s가 갖는 장점으로 인해 점차 기존의 인프라 시스템에서 쿠버네티스 환경으로 옮겨가고 있는 추세이다. 

이에 따라 기존의 미들웨어 영역에서 서비스 문제를 분석하기 위해 수행했던 몇몇 사항들에 대한 새로운 방법에 대한 고찰이 필요해졌다. 

그 방법엔 여러가지가 있지만  그 중 Heapdump 분석에 대해 알아보고자 한다. 

 

쿠버네티스는 orchestrators로서 컨테이너들을 일일히 배포하고 운영하는 역할을 수행한다. 서비스에 문제가 있는 것을 스스로 감지하며,(물론 정책을 부여하지만) 정책에 따라 컨테이너를 autoscaling시키거나, 재배포 하는 방안을 통해 문제 상황에서 서비스의 중단 없이 빠르게 서비스가 제공될 수 있도록 관리해준다. 서비스를 제공하던 컨테이너에 문제가 생길 시, 대개의 경우 바로 restart가 일어나는데..

어떤 문제가 발생했는지 알기 위해 JVM Heapdump를 남겨보고싶었다. 

 

그럼 이런 쿠버네티스 환경에서 JVM의 Heapdump는 어떻게 남길까? 에 대한 테스트 내용이다. 


1) OOM을 유발하는 jar 파일을 생성한다. 

jar파일에 사용한 코드는 다음과 같다. 


2) Dockerfile 수정 

기존의 Dockerfile에 1)의 jar 파일을 사용할 수 있도록 수정한다.

 


3) Deployment.yaml 수정 

Pod 내 dump를 남기는 방안으로 empty volume을 활용하였으며, empty volume을 pod에 붙이기 위해 Deployment.yaml을 수정한다. 

 


4) Docker 배포

Docker Build -> Docker image 생성 -> Docker Hub 또는 개인이 사용하는 이미지 리포지토리에 Docker image push -> Pod 배포 단계를 진행한다. 

Docker 빌드 및 배포가 정상적으로 수행되었다면, 아래와 같이 Pod 의 정보를 확인 할 수 있다. (뒤의 sttageway-core-it200188b866은 namespace명이다)


5) 컨테이너에 접속하여 프로세스 정상 기동 확인 

Pod가 정상적으로 배포되었다면 컨테이너에 접속하여 jar파일을 통해 javㅋa 프로세스가 정상적으로 기동되었는지 확인한다. 

  • 컨테이너 접속 

  • java 프로세스 확인 

  • OOM 유발 테스트 전 정상 Pod Memory 확인 


6) OOM 테스트 수행 

OOM을 유발하여 dumps 디렉토리에 heapdump가 남겨지는지 확인한다.

  • OOM 발생 

 

  • OOM 발생시 Pod Memory 확인 

기존 Pod의 Memory limit이 1200Mi였던 것을 고려했을 때 (아래 참고), OOM으로 인해 Pod가 사용하는 메모리가 request memory 값을 넘어 limit에 근접하였고, 

이로 인해 Pod의 autoscaling이 일어난 것을 유추할 수 있다. 

  • OOM 테스트 이후 Pod Memory 확인 

다시 Scale in 이후 Pod의 개수가 1개로 유지되었다. 

(참고) 테스트 중인 pod의 limit/request 할당값은 다음과 같다. 

 resources:
  limits:
    cpu: 1000m
    memory: 1200Mi
  requests:
    cpu: 100m
    memory: 640Mi

7) Heapdump 확인

JVM 옵션을 통해(XX:HeapdumpPath=/dumps) 지정한 디렉토리로 이동하여 dump를 확인한다.

 


8) Volume Mount 여부 확인 

위 OOM 테스트에서는 OOM으로 인한 heapdump만 떨어졌을 뿐 프로세스가 재시작되지는 않았다. 

하지만 원래 Pod의 경우 컨테이너의 프로세스(pid=1)가 죽으면 Pod가 재시작된다. 

이 경우 dump를 떨어뜨리기 위해 붙였던 volume과 그 내부의 파일들이 계속 유지되는지 확인이 필요하였다. 

따라서 직접 java 프로세스를 kill 하고 Pod의 상태를 확인해보았다. 

기존 Pod가 재시작되면서 autoscaling 정책에 의해 새로운 Pod가 생성되었다. 

기존 Pod는 동일한 Name을 가지고 재시작되었으며, Restarts count가 1로 증가한 것을 확인 할 수 있다. 

  • java 프로세스 kill 후 pod memory 확인 

기존 Pod가 재시작되면서 limit에 가깝게 메모리를 사용하였다.

  • 동일한 Name으로 재생성된 Pod에 접속하여 dump가 존재하는지 확인 

재생성 전에 남겼던 heapdump 파일이 남아있는 것을 보아 동일한 이름으로 재시작된 Pod는 voulme을 그대로 가지고 있는 것을 알 수 있다. 

  • autoscaling으로 인해 생긴 Pod의 volume 확인 

autoscaling으로 인해 새로 생긴 Pod에도 접속하여 확인해본 결과, 해당 볼륨과 디렉토리는 가지고 있지만, 새로 생성되면서 이전의 dump 파일은 없는 것으로 확인했다.