[DevOps] K8S Resource 최적화 사례

안녕하세요? 정리하는 개발자 워니즈입니다. 이번시간에는 k8s의 리소스 최적화 사례에 대해서 정리를 해보려고 하빈다. 필자가 근무하는 프로젝트에서는 k8s를 직접 구축하여 사용하고 있습니다.

그런데, Worker Node에서 CPU Request가 초과했다는 메트릭을 식별했고, 배포간에는 pod가 pending이 되는 현상까지 식별했습니다.

pod pending

무엇인가 문제가 생긴것임에는 틀림이 없어, 확인하여 조치하기로 했습니다.

1. k8s에서의 Request와 Limit이란?

필자가 운영하는 k8s에서는 수십개의 pod들이 MSA의 형태로 운영되고 있습니다. 1개의 pod에는 설정할수 있는 CPU와 Memory의 값이 있는데요. 이부분이 최적의 조건으로 설정이 된것이 아니라 최대한 크게 지정되었고, 지속적으로 어플리케이션이 생겨남에 따라 복제가 되어 관리가 되질 않았습니다.

  • Request : 컨테이너에 필요한 최소 리소스양을 정의 -> pod가 스케쥴링 되는 방식에 영향
  • Limit : 컨테이너가 사용할 수 있는 최대 리소스 양을 정의
  • CPU: Unless your app is specifically designed to take advantage of multiple cores (scientific computing and some databases come to mind), it is usually a best practice to keep the CPU request at ‘1’ or below, and run more replicas to scale it out. This gives the system more flexibility and reliability.
  • Memory : Mbyte 단위

그동안 Request와 Limit의 기준이 모호하게 설정되어있습니다.

resources:  
    requests:    
        cpu: 5
        memory: 10Gi
    limits:    
        cpu: 5
        memory: 10Gi

실제 예시로 위와 같이 CPU를 5 core를 사용하도록 설정이 된 부분도 있었습니다. 여기서 replica가 4개만 설정되어도 20 core Resource를 사용하도록 강제하는 것입니다.

Qos Classes of k8s PODs

  • 서비스 품질(Qos)는 스케쥴러가 pod의 스케쥴링 및 제거 우선순위를 결정하는데 사용하는 kubernetes 개념입니다.

kubernetes QoS

  • 종료 우선순위 : Base Effort > Burstable > Guaranteed
    • 예를들어, Node에 메모리가 부족하게 되면, 종료를 하여 메모리를 확보

2. k8s 리소스 최적화 방안

최적화가 어려운것은 정답이 없다는 것입니다. 필자가 운영하는 어플리케이션 마다의 비지니스도 다르고, 각자가 사용하는 리소스 소모량도 분명히 차이가 있었습니다.

우선 지난 1년간 수집된 Metric기반으로 데이터를 분석하기로 했습니다. 평균적으로 사용하는 양을 구했고 아래와 같이 CPU에 대한 사용률은 거의 없고, Memory 위주로 사용하는 것을 식별했습니다.

Namespace POD Name CPU Memory CPU optimization Memory Optimization
test-biz test-biz-custody-7b757d6664-8nl5q 9m 927Mi 500m 2Gi
test-biz test-biz-custody-d77bffb45-nh929 4m 68Mi 500m 2Gi
test-biz test-biz-gateway-5b8cc784b-bl58p 16m 695Mi 500m 2Gi
test-biz test-biz-internal-gateway-65f489f884-t58br 16m 681Mi 500m 2Gi
test-biz test-biz-member-6799f5c5d5-7k42h 7m 869Mi 500m 2Gi
test-game test-game-5d4f9c64ff-twc6f 5m 67Mi 500m 2Gi
test-market test-market-bff-54559c789-mn8ql 4m 68Mi 500m 2Gi

다음과 같은 기준에 의거하여 공통적인 Spec을 산정했습니다.

  • CPU 기준
    • .5 core 공통 적용
    • 구글에서 가이드하는 문서를 따름.
  • Memory 기준
    • 1Gi 미만 : 2Gi
    • 1Gi 이상 2Gi 미만 : 3Gi
    • 2Gi 이상 3Gi 미만 : 4Gi
    • 3Gi 이상 : 5Gi

3. 최적화 진행한 맞이한 문제들

위에서 정한 Spec을 기준으로 수십개의 어플리케이션들을 전체적으로 재정의했고, 개발환경에 배포를 수행했습니다. 그런데 쉽게 될줄만 알았던 것이 문제에 봉착했었습니다.

어플리케이션 기동을 위한 최소한의 CPU

어플리케이션이 최초 기동 시 여러가지 자원들을 생성하고 연결(DB, Kafka, Redis 등)과정을 수립하는데 있어 CPU 소모가 이전보다 더 발생을 하게 됩니다. 즉, 위와 같은 그래프 패턴을 보이게 되는데 평상시에 대한 체크만 수행을 했고, Start할때 최소한의 필요한 양을 산정하지 못했습니다.

확인을 해본결과 1 Core를 넘지 않는 것을 확인하고, 공통 Spec으로 1 Core로 수정하기로 했습니다.

JVM사용을 위한 최소한의 Memory

위에서 선정한 Memory의 최적화는 컨테이너에 대한 Java 메모리 할당을 참고했습니다. 이 곳에서 설명하길 아래와 같이 되어있습니다.

항상 컨테이너에 최소 25% 더 많은 메모리를 할당해야 합니다(예: ‘-m’). 힙 크기 값보다. -Xmx 값을 2GB로 구성한 다음 컨테이너의 메모리 크기를 2.5GB 이상으로 구성했다고 가정합니다.

힙 공간 외에도 애플리케이션에는 Java 스레드, 가비지 컬렉션, 메타 공간, 기본 메모리, 소켓 버퍼를 위한 공간이 필요합니다. 이러한 모든 구성 요소에는 할당된 힙 크기를 초과하는 추가 메모리가 필요합니다

예를들어 pod가 2.5Gi가 할당되고 JVM에 2Gi가 할당 됐을 때 최적의 모범사례라고 할 수 있습니다.

그래서 다음과 같이 JVM 스펙을 산청했습니다.

  • pod 2.5Gi -> jvm 2Gi
  • pod 3.5Gi -> jvm 3Gi
  • pod 4.5Gi -> jvm 3Gi
  • pod 5.5Gi -> jvm 4Gi

위의 기준으로 설정하여 특별히 Java Process에 문제가 발생을 하지 않도록 구성했습니다.

4. 결과

AS-IS

master를 제외한 나머지 worker node들의 사용률이 아래와 같았고, 평균을 내면 위처럼 CPU가 대략 75%정도를 사용하고있었습니다.

Host Name Allocatable CPU CPU Requested Memory Requested
worker001 7900m 7455m (94%) 11552310Ki (35%)
worker002 7900m 7445m (94%) 12559926Ki (38%)
worker003 7900m 7445m (94%) 13084214Ki (40%)
Worker004 7900m 7445m (94%) 8566396928 (25%)

TO-BE

절반정도로 CPU 요청량이 감소했으며, 어플리케이션 성능상에도 특별한 문제가 발생을 하지도 않았습니다.

5. 마치며…

최적화라는 것은 정답이 없기에 더더욱 어려운 것 같습니다. 이번의 최적화 작업을 진행하면서, 상황마다의 최적화 할 수 있는 요소들이 다양하다는 것을 느끼게 되었고, 확실히 데이터(Metric)기반으로 최적화를 진행하다보니 개발팀을 설득하기도 수월했다고 생각이 됩니다.

무수히 많은 어플리케이션들이 Cluster를 공유하면서 사용하다보니 자원이 많이 부족해질 수 있었던 상황인데 최적화를 통해서 쾌적환 환경을 제공할 수 있게 되어 굉장히 뿌듯했던 것 같습니다.

6. 참조

Medium.com에서 보기

https://blog.kubecost.com/blog/requests-and-limits/

Kubernetes Resource Request와 Limit의 이해

Medium.com에서 보기

https://kubesphere.io/blogs/understand-requests-and-limits-in-kubernetes/

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다