이 가이드의 1부에 설명된 바와 같이, 쿠버네티스는 애플리케이션를 실행하는 데 필요한 소프트웨어를 구성하는 컨테이너들을 관리하기 위한 일상적인 운영 작업을 자동화합니다. 쿠버네티스는 애플리케이션 배포를 위해 내장된 명령을 사용해, 애플리케이션에 변경 사항을 롤아웃하고, 변화하는 요구에 맞게 애플리케이션을 확장하며, 애플리케이션을 모니터링하는 등 다양한 작업을 수행합니다. 쿠버네티스는 컨테이너를 실행 위치에 상관 없이 오케스트레이션하기 때문에, 여러 클라우드 환경에 배포하고 인프라 플랫폼 간에 쉽게 마이그레이션할 수 있습니다. 간단히 말해, 쿠버네티스는 애플리케이션을 보다 쉽게 관리할 수 있게 해줍니다.

쿠버네티스 시스템을 올바르게 설정하면 시간과 비용을 절약할 수 있습니다. 그러나 쿠버네티스 클러스터를 설정하는 것은 까다로울 수 있습니다. 설정이 적절하지 않으면 애플리케이션의 가용성, 성능, 복원성에 문제가 생기고 과도한 비용이 지출될 수 있습니다. 쿠버네티스 가이드 2부는 현재 작업 중이거나 앞으로 작업하게 될 클러스터에 적절한 파라미터를 균형 있게 설정하는 데 도움을 줄 것입니다. 요청과 제한, CPU 사용률 측정, 쿠버네티스 리소스 할당을 최적화하는 방법에 대해 살펴보겠습니다.

쿠버네티스 CPU와 메모리 요청 및 제한에 대한 비용, 성능, 안정성 다이어그램

요청 및 제한에 맞게 워크로드를 적정 크기로 조정하는 방법

이상적인 환경에서라면, 쿠버네티스 파드가 요청된 만큼만 리소스를 사용하겠지만, 실제 환경에서는 리소스의 사용량을 예측할 수 없습니다. 리소스가 제한된 노드에 대규모 애플리케이션이 있는 경우, 노드의 CPU나 메모리가 부족해져 문제가 발생할 수 있습니다. 어느 정도 경력이 있는 엔지니어라면, 아키텍처의 문제는 곧 한밤중에 오가는 수많은 메시지와 매출 손실로 연결된다는 것을 잘 알 것입니다.

반대로 CPU와 메모리에 너무 많은 리소스가 할당되면, 노드를 위해 비축해둔 리소스가 사용되지 않아 낭비가 발생하고, 사용률이 요청된 수치보다 낮으면 유휴 비용이 발생합니다. 기술 스택을 설계하고 설정할 때, 목표는 특정 워크로드의 기술 사양을 충족하는 가장 저렴한 리소스를 사용하는 것입니다.

리소스 사용을 최적화하여 워크로드를 적정 규모로 조정하려면 시스템의 사용 이력과 워크로드 패턴을 파악하는 것이 중요합니다. 이러한 정보를 바탕으로 합리적인 비용 절감 결정을 내릴 수 있습니다. 예를 들어 평균 CPU 사용률이 40%에 불과하고 지난 2년 동안 트래픽이 가장 높은 날에 CPU 사용률이 60%에 불과했다고 가정해 보겠습니다. 처음에 컴퓨팅 수준을 너무 높게 프로비저닝한 것입니다. 간단하게 설정을 변경해 활용도가 낮은 컴퓨팅 리소스를 줄이면 비용을 크게 절감할 수 있습니다.

배포에 정확한 리소스 요청과 제한 값을 적용하면, 과소 사용과 높은 클러스터 비용을 야기하는 오버프로비저닝을 방지하고, 필요한 것보다 적은 리소스를 프로비저닝하여 메모리 부족(OOM) 이벤트 같은 여러 오류가 발생하는 상황을 피할 수 있습니다.

쿠버네티스는 요청과 제한을 사용하여 CPU와 메모리 같은 리소스를 제어합니다.

쿠버네티스 제한 및 요청 다이어그램

요청은 컨테이너가 확보할 수 있도록 보장된 리소스입니다. 컨테이너가 리소스를 요청하는 경우, 쿠버네티스 스케줄러는 컨테이너가 이 리소스를 수용할 수 있는 노드에 배치되도록 합니다.

제한은 컨테이너가 할당량보다 높은 값을 사용하지 않도록 합니다.

컨테이너당 요청 및 제한을 설정할 수 있습니다. 파드의 각 컨테이너에는 고유한 제한 및 요청 값이 있을 수 있지만, 파드 또는 네임스페이스 수준에서 제한 및 요청 값을 설정할 수도 있습니다.

메모리 할당 및 사용률

메모리 리소스는 바이트 단위로 정의됩니다. 메모리를 일반 정수 또는 고정 소수점 정수로 표현하고, 접미사 E, P, T, G, M, K, Ei, Pi, Ti, Gi, Mi, Ki 중 하나를 사용할 수 있습니다. 예를 들어, 다음과 같은 값은 거의 동일합니다.

128974848, 129e6, 129M, 123Mi

메모리는 압축할 수 있는 리소스가 아니며, 메모리를 조절할 방법이 없습니다. 메모리 제한을 초과하는 컨테이너는 중단됩니다.

파드당 메모리 제한 및 메모리 사용률

설정이 되면, 메모리 제한은 노드가 컨테이너에 할당할 최대 메모리 양을 나타냅니다. 다음은 메모리 제한을 쿼리하는 NRQL의 예입니다.

뉴렐릭 메트릭을 대상으로 하는 NRQL:

SELECT latest(cpuUsedCores/cpuLimitCores) FROM K8sContainerSample FACET podName TIMESERIES SINCE 1 day ago 

프로메테우스 메트릭을 대상으로 하는 NRQL:

SELECT rate(sum(container_cpu_usage_seconds_total), 1 SECONDS) FROM Metric SINCE 1 MINUTES AGO UNTIL NOW FACET pod TIMESERIES LIMIT 20

매니페스트에 제한을 포함하지 않고 전체적으로 설정된 기본값이 없는 경우, 파드는 노드의 사용 가능한 메모리 전체를 사용할 수 있습니다. 노드가 초과 할당될 수 있습니다. 이 경우 노드에서 실행 중인 모든 파드에 대한 제한 합계가 해당 노드의 할당 가능한 총 메모리보다 클 수 있습니다. 이를 위해서는 파드의 특정 요청이 제한 미만이어야 합니다. 할당이 해당 요청을 충족하는 한, 노드의 큐블릿(kubelet)은 요청한 것보다 리소스를 더 많이 사용하는 파드의 리소스 할당량을 줄입니다.

메모리는 압축할 수 없는 리소스이므로 정해진 제한과 관련해 파드의 실제 메모리 사용량을 추적하는 것이 특히 중요합니다. 다른말로 하면, 파드가 정의된 제한보다 많은 메모리를 사용하는 경우 큐블릿은 메모리 할당을 조절할 수 없으므로 해당 파드에서 실행되는 프로세스를 대신 종료한다는 의미입니다. 이 경우 파드는 OOMKilled 상태를 표시합니다.

파드의 메모리 사용량을 설정된 제한값과 비교하면, 메모리 부족(OOM)으로 인해 파드가 종료될 위험이 있는지, 그리고 설정된 제한이 타당한지 알 수 있습니다. 파드의 제한이 표준 메모리 사용량에 너무 가까워지면, 예기치 않은 스파이크로 인해 파드가 종료될 수 있습니다. 하지만 파드의 제한을 일반적인 사용량보다 크게 설정하지 않는 것이 좋습니다. 그렇지 않으면 결정 예약이 올바르게 이행되지 않을 수 있기 때문입니다.

예를 들어, 메모리 요청이 1GiB(기비바이트)이고 제한이 4GiB인 파드는 할당 가능한 메모리가 2GiB인 노드에서 예약될 수 있습니다. (해당 요청을 충족하기에 충분한 양입니다.) 그러나 갑자기 파드에 3GiB의 메모리가 필요해지면, 값이 메모리 제한보다 훨씬 낮아도 파드가 종료됩니다.

쿠버네티스 파드 메모리 제한 예시 다이어그램

노드당 메모리 요청 및 할당 가능한 메모리

메모리 요청은 노드의 큐블릿이 컨테이너에 할당하는 최소 메모리 양입니다.

요청이 제공되지 않으면, 컨테이너 제한에 대한 값이 기본값이 됩니다. (또한 설정되지 않은 경우 노드의 모든 메모리가 될 수 있습니다.) 할당 가능한 메모리는 파드에서 사용할 수 있는 노드의 메모리 양을 반영합니다. 전체 용량에서 OS 및 쿠버네티스 시스템 프로세스에 필요한 메모리 요구 사항을 차감하여 리소스에 대한 사용자 파드와 경쟁하지 않도록 합니다.

노드 메모리 용량은 정적 값이지만, 할당 가능한 메모리(파드에 사용할 수 있는 컴퓨팅 리소스 양)는 그렇지 않습니다. 용량 계획에서는 각 노드의 할당 가능한 메모리와 비교하여 각 노드의 파드 메모리 요청 합계를 지속적으로 파악하는 것이 중요합니다. 이러한 메트릭은 노드의 용량이 모든 현재 파드의 메모리 요구 사항을 충족하기에 충분한지, 그리고 쿠버네티스 스케줄러가 새 파드를 노드에 할당할 수 있는지 여부를 알려줍니다. 노드에 할당 가능한 메모리와 노드 용량 간의 차이점에 대한 보다 자세한 내용은 쿠버네티스 문서의 시스템 데몬용 컴퓨팅 리소스 비축을 참조하십시오. 

쿠버네티스 스케줄러는 여러 레벨의 기준을 사용하여 특정 노드에 파드를 배치할 수 있는지 결정합니다. 결정 요인 중 하나는 노드에서 실행 중인 모든 파드와 새 파드의 요청 합계를 충족하기에 충분한 할당 가능한 메모리가 노드에 있는지 여부입니다. 프로세스 기준 예약에 대한 보다 자세한 내용은 쿠버네티스 스케줄러 문서의 노드 선택 섹션을 참조하십시오.

또한, 메모리 요청과 용량 메트릭을 비교하면 클러스터 전반에서 실행할 파드 수를 시작 및 실행할 때 발생하는 문제를 진단하는 데 도움이 됩니다. 클러스터의 현재 파드 수가 원하는 파드 수보다 훨씬 적은 경우, 이러한 메트릭은 노드에 새 파드를 호스팅할 수 있는 리소스 용량이 부족하다는 것을 보여줍니다. 이 문제에 대한 간단한 해결 방법 중 하나는 클러스터에 더 많은 노드를 프로비저닝하는 것입니다.

CPU 사용률 측정 방법

CPU 코어 1개는 1000m(1,000millipu 또는 1,000millicores)에 해당합니다. 컨테이너를 실행하는 데 하나의 완전한 코어가 필요한 경우, 값을 1000m 또는 1로 설정합니다. 컨테이너에서 코어의 4분의 1이 필요한 경우, 값을 250m로 설정합니다 .

CPU는 압축 가능한 리소스입니다. 컨테이너가 CPU 제한에 도달하기 시작하면, 임계값이 조절됩니다. CPU가 제한되면 성능이 저하되지만 종료되지는 않습니다.

클러스터 성능에 대한 중요한 인사이트를 얻으려면 다음 두 가지를 추적해야 합니다.

  • 설정된 요청 및 제한과 비교하여 파드가 사용하는 CPU 양 추적
  • 노드 수준에서 CPU 사용률 추적

파드가 CPU 제한을 초과한 경우와 마찬가지로 노드 수준에서 사용 가능한 CPU가 부족하면 노드가 각 파드에 할당되는 CPU 양을 제한할 수 있습니다.

파드당 제한과 요청에 비교해 실제 사용률을 측정하면 이러한 사용률이 적절하게 설정되었는지, 파드가 제대로 실행하기에 충분한 CPU를 요청하고 있는지를 파악하는 데 도움이 됩니다. 또는 CPU 사용량이 예상보다 지속적으로 높으면 파드의 문제를 식별해 해결해야 할 수도 있습니다.

다음은 노드당 CPU 요청 및 할당 가능한 CPU를 보여 주는 NRQL 쿼리입니다. 클러스터에서 사용해 보시기 바랍니다.

SELECT
filter(sum(`node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate`), where true) /
filter(sum(kube_pod_container_resource_requests), WHERE (resource = 'cpu') and job = 'kube-state-metrics') * 100 as 'CPU Request Commitment'
FROM Metric FACET node since 1 minute ago

다음은 파드당 CPU 요청 및 할당 가능한 CPU를 보여 주는 NRQL 쿼리입니다. 클러스터에서 사용해 보시기 바랍니다.

SELECT sum(`node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate`) / filter(sum(kube_pod_container_resource_limits), WHERE (resource = 'cpu') and job = 'kube-state-metrics') * 100 as 'CPU Limit Commitment' FROM Metric FACET pod since 1 minute ago

쿠버네티스 리소스 할당을 최적화하는 방법

리소스 할당을 최적화하려면 파드 사양, 리소스 할당량 및 제한 범위를 정의해야 합니다.

파드 사양 정의

다음은 리소스에 대한 일반적인 파드 사양입니다.

쿠버네티스 파드 사양 정의 예시 스크린샷

파드의 각 컨테이너는 자체적으로 요청과 제한을 설정할 수 있으며 모두 부가적으로 적용됩니다. 이 예시에서 파드의 총 메모리 요청은 64MiB이고 총 제한은 128MiB입니다. CPU에 대한 요청을 최대 노드의 코어 수 이상으로 정하면 파드가 예약되지 않습니다. 애플리케이션이 멀티 코어를 활용하도록 특별히 설계되지 않은 경우, 일반적으로 CPU 요청을 1 미만으로 유지하고 복제본을 활용해 수평으로 확장하는 것이 좋습니다.

리소스 할당량 정의

개발자는 가드레일 없이 쿠버네티스에서 실행되는 애플리케이션에 원하는 양의 리소스를 할당할 수 있습니다. 여러 팀이 고정된 수의 노드가 있는 클러스터를 공유하는 경우 이는 문제가 됩니다. 쿠버네티스는 관리자가 ResourceQuotas를 사용하여 네임스페이스에서 리소스 사용에 대한 한계값을 설정할 수 있도록 합니다 .

 

쿠버네티스 리소스 할당량 정의 예시 스크린샷

이 파일을 네임스페이스에 적용하면 네임스페이스의 모든 컨테이너에 대해 다음 요구 사항이 설정됩니다.

  • 모든 CPU 요청의 합계는 0.5개 코어보다 클 수 없음
  • 모든 CPU 제한의 합계는 0.8코어보다 클 수 없음
  • 모든 메모리 요청의 합계는 200MiB를 초과할 수 없음
  • 모든 메모리 제한의 합계는 500MiB를 초과할 수 없음

이는 4MiB 요청이 있는 50개의 컨테이너, 40MiB 요청이 있는 5개의 컨테이너 또는 200MiB 요청이 있는 1개의 컨테이너를 사용할 수 있다는 의미입니다.

제한 범위 정의

네임스페이스에 대한 LimitRange를 생성할 수도 있습니다. 네임스페이스 전체를 보는 대신 개별 컨테이너에 LimitRange를 적용하는 것입니다.

다음은 LimitRange의 예입니다.

쿠버네티스의 LimitRange 예시 스크린샷

기본 섹션은 파드의 컨테이너에 대한 기본 제한을 설정합니다. LimitRange의 값을 사용하면, 자체적으로 범위를 설정하는 모든 컨테이너에 기본값이 할당됩니다.

defaultRequest 섹션에서는 파드의 컨테이너에 대한 기본 요청을 설정합니다. LimitRange의 값을 사용하면, 자체적으로 범위를 설정하는 모든 컨테이너에 기본값이 할당됩니다.

max 섹션은 파드의 컨테이너가 설정할 수 있는 최대 한계를 설정합니다. 컨테이너에 설정된 기본 섹션 및 제한은 이 값보다 클 수 없습니다. 한 가지 유의해야 할 점은, 최대값이 설정되어 있고 기본값이 아닌 경우 이러한 값을 직접 설정하지 않은 컨테이너는 최대값이 한계로 할당된다는 것입니다.

min 섹션은 파드의 컨테이너가 설정할 수 있는 최소 요청값을 설정합니다.defaultRequest섹션과 컨테이너에 설정된 요청값은 이 값보다 낮을 수 없습니다. 참고 사항: 이 값이 설정되어 있고 defaultRequest가 설정되어 있지 않으면, min 값이 defaultRequest 값이 됩니다.

결론

1부에서는 쿠버네티스의 기본 사항과 모니터링이 필요한 이유를 살펴보았으며, 2부에서는 쿠버네티스 아키텍처에 대해 자세히 알아보았습니다. 이제 몇 가지 방법을 직접 사용해 보시기 바랍니다.

쿠버네티스 인프라 효율성을 시각화하는 데 도움을 주는 툴과 프레임워크들이 점점 늘어나고 있습니다. 그 중 두 가지를 살펴보면,

  • Kubecost는 쿠버네티스를 사용하는 팀에 실시간 비용에 대한 가시성과 인사이트를 제공하여 클라우드 비용을 지속적으로 절감할 수 있도록 지원합니다.
  • Open Cost는 공급업체에 구애 받지 않는 오픈 소스 프로젝트로 인프라 및 컨테이너 비용을 실시간으로 측정하고 할당할 수 있도록 합니다. (뉴렐릭은 창립 멤버로 기여했습니다.)