본문 바로가기
스터디/Cloud & k8s

[k8s] Container 환경에서 JVM GC (Garbage Collection) 확인하기

by zoodi 2023. 8. 25.
728x90

JDK11의 GC는 무조건 G1GC일까?

JDK11의 GC 알고리즘을 일반적으로 G1GC를 사용한다고 알려져있는데요, JDK11을 사용한다고 무조건 G1GC 알고리즘을 사용하는 것이 아니었습니다..!

 

명령어로 GC 확인

어떤 GC를 사용하는지는 아래 명령어를 통해 확인가능합니다.

> java -XX:+PrintCommandLineFlags -version

 

pinpoint로 GC 확인

pinpoint에서도 확인 가능합니다.

 

pinpoint를 확인해보니  Serial GC 알고리즘을 사용하고있네요.

 

 

GC 종류

  • Serial GC
    • 가장 단순한 방식의 GC
    • 싱글스레드로 동작
    • 느리고 그만큼 stop the world 시간이 다른 GC에 비해 길다
    • 보통 실무에서 사용하는 경우가 없음 (디바이스 성능이 안좋아서 cpu 코어가 1개인 경우에만 사용)
  • G1GC
    • Java9의 디폴트 GC
    • 현재 GC 중 stop the world 시간이 가장 짧음
    • Heap을 Region이라는 일정한 부분으로 나눠서 메모리 관리
    • 전체 Heap에 대해서 탐색하지 않고 부분적으로 Region 단위로 탐색하여 각각의 Region에만 GC가 발생

왜 SERIAL GC를 사용하고있을까?

Java9 부터 default GC로 G1GC를 사용합니다.

그런데 왜 위 컨테이너 환경에서 확인했을 때 JDK11을 사용하는데 GC 알고리즘 타입으로 Serial을 사용하고있었을까요?

그 원인을 찾다가 cpu 코어 수에 따라 사용하는 GC 알고리즘이 달라진다는 것을 알았습니다.

 

  • RedHat 문서
JAVA 11GC IN CONTAINER
For Java 11+ it's also useful to know which GC is being used, and you can display this information via -Xlog:gc=info. For example, when container limits allow only a single CPU to be active, the Serial GC will be selected. If more than one CPU is active and sufficient memory (at least 2GB) is allocated to the container, the G1 GC will be selected in Java 11 and later versions:

link: https://developers.redhat.com/articles/2022/04/19/java-17-whats-new-openjdks-container-awareness#tuning_defaults_for_containers

 

Container 환경에서는 CPU Core를 2개 이상 사용하면서 메모리가 2G 이상이여야 G1GC가 채택되는 것이었습니다.

 

아래와 같이 컨테이너 환경을 설정하고 있었는데요.

resources:
  limits:
    nginx:
      cpu: 0.5
      memory: 0.5Gi
      ephemeralStorage: 8Gi
    was:
      cpu: 1
      memory: 1Gi
      ephemeralStorage: 8Gi
    promtail:
      cpu: 0.5
      memory: 0.5Gi
      ephemeralStorage: 1Gi
    prometheus:
      cpu: "500m"
      memory: "256Mi"
      ephemeralStorage: 1Gi

위 코드를 살펴보면 was의 cpu와 memory를 각각 1개, 1G로 설정하였습니다.

 

추가로 너무 낮은 cpu로 설정할경우 문제가 생길 수 있다고합니다.

  • 노드들이 초과할당(overcommited)된 상태가 될 수 있음
  • 평상시에는 문제가 없다가 cpu 자원을 많이 사용하게 되는 경우 각 어플리케이션들은 초기에 요청한 자원만큼만 사용할 수 있어 cpu throttle이 발생
  • 나중엔 어플리케이션 지연 발생

코드 변경

따라서 아래와 같이 코드를 수정하였습니다.

resources:
  limits:
    nginx:
      cpu: 0.5
      memory: 0.5Gi
      ephemeralStorage: 8Gi
    was:
      cpu: 2
      memory: 2Gi
      ephemeralStorage: 8Gi

 

resource limit에 맞추어 hpa  기준도 변경하였습니다.

//AS-IS
hpa:
  was:
    cpu: 0.7 # resource limit 1
    memory: 0.9Gi # resource limit 1Gi



//TO-BE
hpa:
  was:
    cpu: 1.4 # resource limit 2
    memory: 1.8Gi # resource limit 2Gi

 

CPU CORE수에 따른 GC Type

CPU 코어 수에 따라 GC 알고리즘이 달라진다는 것을 알았습니다.

SerialGC와 G1GC 외에도 다양한 GC 알고리즘을 채택하여 사용하고있습니다.

 

대부분의 범용 마이크로 서비스 애플리케이션의 경우 병렬 GC로 시작합니다.

만약 시작할 코어 수를 모르는 경우 2개의 cpu 코어를 선택하는 것이 좋습니다.

 

참고

https://coffeewhale.com/kubernetes/mistake/2020/11/29/mistake-10/

https://dgle.dev/container-gc/

https://learn.microsoft.com/ko-kr/azure/developer/java/containers/overview

https://coffeewhale.com/kubernetes/mistake/2020/11/29/mistake-10/

728x90

댓글