쿠버네티스 시스템 컴포넌트 메트릭

쿠버네티스 시스템 컴포넌트 메트릭 (Metrics For Kubernetes System Components)

시스템 컴포넌트 메트릭은 그 안에서 무슨 일이 일어나고 있는지 더 잘 볼 수 있게 해줘요. 메트릭은 특히 대시보드와 알림을 만드는 데 유용해요.

쿠버네티스 컴포넌트는 Prometheus 형식으로 메트릭을 내보내요. 이 형식은 사람과 머신 모두 읽을 수 있도록 설계된 구조화된 평문이에요.

출처: 문서

본문

쿠버네티스의 메트릭

대부분의 경우 메트릭은 HTTP 서버의 /metrics 엔드포인트에서 사용할 수 있어요. 기본으로 엔드포인트를 노출하지 않는 컴포넌트는 --bind-address 플래그로 활성화할 수 있어요.

이런 컴포넌트의 예시:

프로덕션 환경에서는 Prometheus Server나 다른 메트릭 스크레이퍼를 구성해 이 메트릭을 주기적으로 수집하고 일종의 시계열 데이터베이스에서 사용할 수 있게 만들 수 있어요.

kubelet/metrics/cadvisor, /metrics/resource, /metrics/probes 엔드포인트에서도 메트릭을 노출해요. 이 메트릭들은 같은 수명주기를 가지지 않아요.

클러스터가 RBAC를 사용한다면 메트릭을 읽으려면 /metrics 에 접근을 허용하는 ClusterRole을 가진 사용자·그룹·ServiceAccount를 통한 인가가 필요해요. 예:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus
rules:
  - nonResourceURLs:
      - "/metrics"
    verbs:
      - get

메트릭 수명주기

Alpha 메트릭 → Beta 메트릭 → Stable 메트릭 → Deprecated 메트릭 → Hidden 메트릭 → Deleted 메트릭

Alpha 메트릭은 안정성 보장이 없어요. 이 메트릭은 언제든 수정되거나 삭제될 수 있어요.

Beta 메트릭은 stable 메트릭보다 더 느슨한 API 계약을 지켜요. Beta 메트릭은 수명 동안 라벨을 제거할 수 없지만, 베타 단계에서 라벨을 추가할 수는 있어요.

Stable 메트릭은 변경되지 않음을 보장해요. 이는 다음을 의미해요:

  • 사용 중단 서명이 없는 stable 메트릭은 삭제되거나 이름이 바뀌지 않을 거예요
  • stable 메트릭의 유형은 수정되지 않을 거예요

Deprecated 메트릭은 삭제 예정이지만 여전히 사용할 수 있어요. 이 메트릭에는 어떤 버전에서 사용 중단됐는지에 대한 애노테이션이 포함돼요.

예를 들어:

Hidden 메트릭은 더 이상 스크레이핑을 위해 게시되지 않지만 여전히 사용할 수 있어요. Deprecated 메트릭은 안정성 수준에 따라 일정 기간 후 hidden 메트릭이 돼요:

  • STABLE 메트릭은 최소 3개 릴리스 또는 9개월 중 더 긴 기간 후 hidden이 돼요.
  • BETA 메트릭은 최소 1개 릴리스 또는 4개월 중 더 긴 기간 후 hidden이 돼요.
  • ALPHA 메트릭은 사용 중단된 같은 릴리스에서 hidden 또는 제거될 수 있어요.

Hidden 메트릭을 사용하려면 활성화해야 해요. 자세한 내용은 Hidden 메트릭 표시 섹션을 참고해요.

Deleted 메트릭은 더 이상 게시되지 않고 사용할 수 없어요.

Hidden 메트릭 표시

위에서 설명했듯이 관리자는 특정 바이너리의 명령줄 플래그로 hidden 메트릭을 활성화할 수 있어요. 이것은 지난 릴리스에서 사용 중단된 메트릭의 마이그레이션을 놓친 관리자를 위한 탈출구(escape hatch)로 사용하기 위한 것이에요.

show-hidden-metrics-for-version 플래그는 해당 릴리스에서 사용 중단된 메트릭을 표시하려는 버전을 받아요. 버전은 x.y로 표현되며, 여기서 x는 major 버전, y는 minor 버전이에요. 메트릭이 patch 릴리스에서 사용 중단될 수 있더라도 patch 버전은 필요하지 않아요. 그 이유는 메트릭 사용 중단 정책이 minor 릴리스에 대해 실행되기 때문이에요.

이 플래그는 이전 minor 버전만 값으로 받을 수 있어요. 이전 릴리스에 숨겨진 모든 메트릭을 표시하려면 show-hidden-metrics-for-version 플래그를 이전 버전으로 설정할 수 있어요. 너무 오래된 버전을 사용하는 것은 메트릭 사용 중단 정책을 위반하므로 허용되지 않아요.

예를 들어 메트릭 A1.29 에서 사용 중단됐다고 가정해 봐요. 메트릭 A 가 hidden이 되는 버전은 그 안정성 수준에 따라 달라져요:

  • 메트릭 AALPHA라면 1.29 에서 hidden될 수 있어요.
  • 메트릭 ABETA라면 최소 1.30 에서 hidden될 거예요. 1.30 으로 업그레이드하면서 여전히 A 가 필요하다면 명령줄 플래그 --show-hidden-metrics-for-version=1.29 를 사용해야 해요.
  • 메트릭 ASTABLE이라면 최소 1.32 에서 hidden될 거예요. 1.32 로 업그레이드하면서 여전히 A 가 필요하다면 명령줄 플래그 --show-hidden-metrics-for-version=1.31 를 사용해야 해요.

컴포넌트 메트릭

kube-controller-manager 메트릭

컨트롤러 매니저 메트릭은 컨트롤러 매니저의 성능과 건강에 대한 중요한 통찰을 제공해요. 이 메트릭에는 go_routine 수 같은 일반적인 Go 언어 런타임 메트릭과 etcd 요청 지연 시간이나 클러스터의 건강을 가늠하는 데 사용할 수 있는 Cloudprovider (AWS, GCE, OpenStack) API 지연 시간 같은 컨트롤러 특정 메트릭이 포함돼요.

쿠버네티스 1.7부터 GCE, AWS, Vsphere, OpenStack의 저장 작업에 대한 자세한 Cloudprovider 메트릭을 사용할 수 있어요. 이 메트릭은 영구 볼륨 작업의 건강을 모니터링하는 데 사용할 수 있어요.

예를 들어 GCE의 경우 이 메트릭은 다음과 같이 불러요:

cloudprovider_gce_api_request_duration_seconds { request = "instance_list"}
cloudprovider_gce_api_request_duration_seconds { request = "disk_insert"}
cloudprovider_gce_api_request_duration_seconds { request = "disk_delete"}
cloudprovider_gce_api_request_duration_seconds { request = "attach_disk"}
cloudprovider_gce_api_request_duration_seconds { request = "detach_disk"}
cloudprovider_gce_api_request_duration_seconds { request = "list_disk"}

kube-scheduler 메트릭

스케줄러는 모든 실행 중인 파드의 요청된 리소스와 원하는 한도를 보고하는 선택적 메트릭을 노출해요. 이 메트릭은 용량 계획 대시보드를 만들고, 현재·과거 스케줄링 한도를 평가하며, 리소스 부족으로 스케줄할 수 없는 워크로드를 빠르게 식별하고, 실제 사용량을 파드의 요청과 비교하는 데 사용할 수 있어요.

kube-scheduler는 각 파드에 대해 구성된 리소스 요청과 한도를 식별해요. 요청이나 한도가 0이 아니면 kube-scheduler는 메트릭 시계열을 보고해요. 시계열은 다음으로 라벨링돼요:

  • namespace
  • pod name
  • 파드가 스케줄된 노드 또는 아직 스케줄되지 않았다면 빈 문자열
  • priority
  • 그 파드에 할당된 스케줄러
  • 리소스 이름(예: cpu)
  • 리소스 단위(알려진 경우, 예: cores)

파드가 완료에 도달하면(restartPolicyNever 또는 OnFailure 이고 Succeeded 또는 Failed 파드 단계에 있거나, 삭제되어 모든 컨테이너가 종료 상태인 경우) 시리즈는 더 이상 보고되지 않아요. 스케줄러가 이제 실행할 다른 파드를 스케줄할 수 있기 때문이에요. 두 메트릭은 kube_pod_resource_requestkube_pod_resource_limit 이라고 해요.

메트릭은 HTTP 엔드포인트 /metrics/resources 에 노출돼요. 이것은 /metrics/resources 엔드포인트에 대한 인가가 필요하며, 보통 /metrics/resources non-resource URL에 대해 get 동사를 가진 ClusterRole로 부여돼요.

쿠버네티스 1.21에서는 이 alpha 안정성 메트릭을 노출하려면 --show-hidden-metrics-for-version=1.20 플래그를 사용해야 해요.

kubelet Pressure Stall Information (PSI) 메트릭

이는 쿠버네티스의 stable 기능이며 버전 v1.36부터 stable입니다. 처음에는 v1.33 릴리스에서 사용할 수 있었어요. 이 기능이나 동작은 더 이상 비활성화하거나 옵트아웃할 수 없어요(잠겨 있음). 관련 기능 게이트에 값을 명시적으로 설정하면 쿠버네티스는 그 값을 무시하지만 오류를 보고하지 않아요.

커널에 PSI가 활성화되어 있으면(버전 4.20 이상) kubelet은 CPU, 메모리, I/O 사용에 대한 Pressure Stall Information (PSI)을 수집해요. 정보는 노드·파드·컨테이너 수준에서 수집돼요.

Prometheus 메트릭: /metrics/cadvisor 엔드포인트에 총 정지 시간(초)을 나타내는 누적 카운터(총계)로 노출돼요. 메트릭은 이 엔드포인트에 다음 이름으로 노출돼요:

container_pressure_cpu_stalled_seconds_total
container_pressure_cpu_waiting_seconds_total
container_pressure_memory_stalled_seconds_total
container_pressure_memory_waiting_seconds_total
container_pressure_io_stalled_seconds_total
container_pressure_io_waiting_seconds_total

요약 API(Summary API): /stats/summary 엔드포인트에 노출되어 누적 totals 와 이동 평균(avg10, avg60, avg300)을 JSON 형식으로 제공해요. 이 평균들은 해당 10초, 60초, 5분 간격 동안 작업이 리소스에서 정지된 시간의 백분율을 나타내요.

이 메트릭들은 /proc/pressure/ 의 노드 파일을 통해 네이티브로도 내보내져요. cpu, memory, io는 다음 형식이에요:

some avg10=0.00 avg60=0.00 avg300=0.00 total=0
full avg10=0.00 avg60=0.00 avg300=0.00 total=0

이 메트릭들을 어떻게 함께 해석할 수 있을까요? 요약 API의 다음 쿼리를 예로 들어 봐요: kubectl get --raw "/api/v1/nodes/$(kubectl get nodes -o jsonpath='{.items[0].metadata.name}')/proxy/stats/summary" | jq '.pods[].containers[] | select(.name=="<CONTAINER_NAME>") | {name, cpu: .cpu.psi, memory: .memory.psi, io: .io.psi}'. 이는 정보를 다음과 같은 json 형식으로 반환해요.

{
  "name": "<CONTAINER_NAME>",
  "cpu": {
    "full": {
      "total": 0,
      "avg10": 0,
      "avg60": 0,
      "avg300": 0
    },
    "some": {
      "total": 35232438,
      "avg10": 0.74,
      "avg60": 0.52,
      "avg300": 0.21,
    },  
  },
  "memory": {
    "full": {
      "total": 539105,
      "avg10": 0,
      "avg60": 0,
      "avg300": 0
    },
    "some": {
      "total": 658164,
      "avg10": 0.01,
      "avg60": 0.01,
      "avg300": 0.00,
    },
    }
  },
  "io": {
    "full": {
      "total": 33190987,
      "avg10": 0.31,
      "avg60": 0.22,
      "avg300": 0.05,
    },
    "some": {
      "total": 40809937,
      "avg10": 0.52,
      "avg60": 0.45,
      "avg300": 0.12,
    }
  }
}

간단한 스파이크 시나리오가 있어요. cpu.some avg100.74 는 지난 10초 동안 이 컨테이너의 최소 한 작업이 시간의 0.74%(0.0074초 또는 74밀리초) 동안 CPU에서 정지됐다는 것을 나타내요. 같은 리소스에서 avg10 (0.74)이 avg300 (0.21)보다 현저히 높기 때문에, 이는 지속적인 장기 병목이 아닌 최근의 리소스 경합 급증을 시사해요. 지속적으로 모니터링하고 avg300 메트릭도 함께 증가하면 더 심각하고 지속적인 문제로 진단할 수 있어요!

추가로 이 예시에서 cpu.some 은 압력을 보이는 반면 cpu.full 은 0.00으로 남아 있는 것을 주목해요. 이는 일부 프로세스가 CPU 시간을 기다리며 지연됐지만 컨테이너 전체는 여전히 진행되고 있었다는 것을 알려줘요. 0이 아닌 full 값은 모든 비유휴 작업이 동시에 정지됐다는 것을 나타내며 훨씬 더 큰 문제예요.

total 값 35232438은 사람이 읽기엔 덜 친숙하지만 마이크로초 단위의 누적 정지 시간을 나타내며, 평균에는 나타나지 않을 수 있는 지연 시간 급증 감지를 허용해요. 이것은 또한 Prometheus 같은 모니터링 시스템이 특정 시간 창에 걸친 정확한 증가율을 계산하는 데 유용해요.

마지막으로, 낮은 Memory Pressure와 함께 높은 I/O Pressure를 관찰하면 애플리케이션이 사용 가능한 RAM 부족으로 실패하는 것이 아니라 디스크 처리량을 기다리고 있음을 나타낼 수 있어요. 노드가 메모리에서 과도하게 커밋되지 않았으며, 디스크 소비에 대해 다른 진단을 조사할 수 있어요.

PSI 메트릭은 모든 cgroup의 모든 수준에서 실시간 리소스 경합을 모니터링하는 더 강력한 방법을 열어주며, 시스템 전체에 걸쳐 워크로드를 동적으로 처리할 기회를 제공해요. PSI 메트릭에 대해 더 읽으려면 PSI 메트릭 이해하기를 참고해요.

요구 사항

Pressure Stall Information은 다음을 요구해요:

메트릭 비활성화

명령줄 플래그 --disabled-metrics 로 메트릭을 명시적으로 끌 수 있어요. 예를 들어 메트릭이 성능 문제를 일으키는 경우에 원할 수 있어요. 입력은 비활성화된 메트릭 목록(즉 --disabled-metrics=metric1,metric2)이에요.

메트릭 카디널리티 강제

무한 차원의 메트릭은 계측된 컴포넌트에서 메모리 문제를 일으킬 수 있어요. 리소스 사용을 제한하려면 --allow-metric-labels 명령줄 옵션을 사용해 메트릭에 대한 라벨 값의 허용 목록을 동적으로 구성할 수 있어요.

alpha 단계에서 플래그는 메트릭 라벨 허용 목록으로 일련의 매핑만 받을 수 있어요. 각 매핑은 <metric_name>,<label_name>=<allowed_labels> 형식이며, 여기서 <allowed_labels> 는 허용 가능한 라벨 이름의 쉼표로 구분된 목록이에요.

전체 형식은 다음과 같아요:

--allow-metric-labels <metric_name>,<label_name>='<allow_value1>, <allow_value2>...', <metric_name2>,<label_name>='<allow_value1>, <allow_value2>...', ...

예시:

--allow-metric-labels number_count_metric,odd_number='1,3,5', number_count_metric,even_number='2,4,6', date_gauge_metric,weekend='Saturday,Sunday'

CLI에서 이를 지정하는 것 외에도 구성 파일 안에서도 할 수 있어요. 컴포넌트에 --allow-metric-labels-manifest 명령줄 인자로 그 구성 파일의 경로를 지정할 수 있어요. 다음은 그 구성 파일 내용의 예시예요:

"metric1,label2": "v1,v2,v3"
"metric2,label1": "v1,v2,v3"

추가로 cardinality_enforcement_unexpected_categorizations_total 메타 메트릭은 카디널리티 강제 동안 예상치 못한 분류의 수를 기록해요. 즉 허용 목록 제약과 관련해 허용되지 않는 라벨 값이 발견될 때마다요.

더 알아보기 (Learn more)