Kubernetes 성능 모니터링: 최적화를 위한 도구와 기술
유용한 메트릭, Prometheus, Grafana, kubectl 및 실용적인 리소스 튜닝 습관을 통해 Kubernetes 성능을 모니터링합니다.
Kubernetes 성능 모니터링: 최적화를 위한 도구와 기술
Kubernetes 성능 모니터링은 단순히 CPU 차트를 보는 것이 아닙니다. 클러스터의 평균 CPU가 낮아도 사용자는 느린 요청을 경험할 수 있습니다. 파드는 하루 대부분 충분한 메모리를 가지고 있어도 배치 작업 중에 종료될 수 있습니다. 노드는 디스크 압력이 파드를 축출하기 시작할 때까지 정상으로 보일 수 있습니다. 좋은 모니터링은 클러스터 신호를 사람들이 실제로 관심을 가지는 경험, 즉 서비스가 빠르고, 가용성이 높으며, 예측 가능한지와 연결합니다.
첫 번째 실수는 질문 대신 도구로 시작하는 것입니다. Prometheus, Grafana, metrics-server, kube-state-metrics 및 클라우드 모니터링 플랫폼은 모두 유용하지만, 무엇이 중요한지는 결정하지 않습니다. 워크로드를 이해함으로써 여러분이 결정합니다. 공개 API는 지연 시간과 오류에 관심을 가집니다. 큐 워커는 백로그와 처리 속도에 관심을 가집니다. 야간 작업은 완료 시간과 실패한 파드에 관심을 가집니다. 데이터베이스와 유사한 워크로드는 디스크 지연 시간과 메모리 압력에 관심을 가집니다.
빠른 확인을 위해 kubectl top은 여전히 유용합니다:
kubectl top nodes
kubectl top pods -A
kubectl top pod -n production api-7d9c8f7b9d-2x4mq --containers
이 명령어는 metrics-server에 의존합니다. 최근 CPU 및 메모리 사용량을 제공하지만 전체 기록은 아닙니다. 문제 해결 중에 사용하고, 유일한 모니터링 시스템으로 사용하지 마십시오. 파드가 10분 전에 메모리 부족으로 재시작된 경우 kubectl top은 이를 유발한 스파이크를 보여주지 않을 수 있습니다.
Prometheus는 시계열 데이터를 스크래핑하고 Kubernetes 서비스 디스커버리와 잘 작동하기 때문에 Kubernetes 메트릭의 공통 기반입니다. 일반적인 설정에서 메트릭은 여러 곳에서 수집됩니다. kubelet은 컨테이너 및 파드 리소스 메트릭을 노출합니다. kubelet에 통합된 cAdvisor는 컨테이너 CPU, 메모리, 파일시스템 및 네트워크 데이터를 제공합니다. node-exporter는 호스트 수준 메트릭을 보고합니다. kube-state-metrics는 Kubernetes 객체 상태를 메트릭으로 변환합니다: 원하는 레플리카, 사용 가능한 레플리카, 파드 단계, 노드 조건 등.
Grafana는 이러한 메트릭을 대시보드로 전환합니다. 좋은 대시보드는 게이지의 벽이 아닙니다. 특정 질문에 빠르게 답변할 수 있어야 합니다: 어떤 서비스가 느린지, 어떤 파드가 제한되고 있는지, 어떤 노드가 압력을 받고 있는지, 어떤 Deployment가 롤아웃에 실패하고 있는지, 오토스케일링이 따라잡고 있는지.
애플리케이션 계층에서 시작하십시오. 사용자 대상 서비스의 경우 가장 중요한 신호는 요청 속도, 오류 속도 및 지연 시간입니다. SLO가 있다면 그래프로 표시하십시오. 파드 CPU 차트는 체크아웃이 실패하고 있는지 알려주지 않습니다. 애플리케이션 메트릭이 알려줍니다. Prometheus 클라이언트 라이브러리, OpenTelemetry 또는 플랫폼에서 이미 사용하는 모니터링 시스템으로 서비스를 계측하십시오. Kubernetes 메트릭은 서비스가 왜 비정상인지 설명합니다; 애플리케이션 메트릭은 비정상임을 알려줍니다.
그런 다음 애플리케이션 증상을 파드 리소스에 연결하십시오. CPU 사용량은 Kubernetes에서 잘못 읽기 쉽습니다. CPU 제한이 있는 컨테이너는 평균 CPU가 극적으로 보이지 않더라도 제한될 수 있습니다. 제한은 컨테이너가 스케줄링 기간 내에 제한이 허용하는 것보다 더 많은 CPU 시간을 사용하려고 할 때 발생합니다. 지연 시간에 민감한 앱의 경우 무작위로 보이는 느린 요청을 유발할 수 있습니다.
제한에 대한 유용한 PromQL 쿼리는 다음과 같습니다:
rate(container_cpu_cfs_throttled_periods_total{namespace="production", container!=""}[5m])
값이 상승하면 컨테이너가 제한되고 있음을 의미합니다. CPU 사용량 및 요청 지연 시간과 함께 확인하십시오. 지연 시간 스파이크가 제한과 일치하면 CPU 제한을 높이거나 제거하고, 레플리카를 늘리거나, 코드 경로를 최적화하는 것을 고려하십시오. 일부 팀은 CPU 요청을 설정하지만 지연 시간에 민감한 서비스에 대해 CPU 제한을 피하고, 대신 요청, 오토스케일링 및 노드 용량 제어에 의존합니다. 이는 합리적일 수 있지만, 시끄러운 워크로드가 다른 워크로드를 굶주리지 않도록 클러스터 수준의 규율이 필요합니다.
메모리는 다르게 동작합니다. CPU는 제한될 수 있습니다; 메모리는 같은 방식으로 느려질 수 없습니다. 컨테이너가 메모리 제한을 초과하면 OOMKilled될 수 있습니다. 재시작 이유를 찾으십시오:
kubectl describe pod -n production api-7d9c8f7b9d-2x4mq
kubectl get pod -n production api-7d9c8f7b9d-2x4mq -o jsonpath='{.status.containerStatuses[*].lastState}'
Prometheus에서 작업 세트 메모리를 관찰하고 제한과 비교하십시오:
container_memory_working_set_bytes{namespace="production", container!=""}
조용한 한 시간만 보고 메모리를 튜닝하지 마십시오. 피크 트래픽, 배치 윈도우, 배포 및 가비지 컬렉션 동작을 살펴보십시오. Java, Go, Node.js 및 Python 서비스는 서로 다른 메모리 프로필을 가지고 있습니다. 정상 트래픽 중에 넉넉해 보이는 제한이 시작 중, 캐시 워밍업 또는 큰 요청 중에는 너무 빡빡할 수 있습니다.
리소스 요청은 스케줄러가 파드를 배치하는 데 사용하기 때문에 중요합니다. 요청이 너무 낮으면 Kubernetes는 동일한 노드에 너무 많은 바쁜 파드를 패킹할 수 있습니다. 모든 것이 효율적으로 보이다가 해당 파드들이 동시에 바빠지면 문제가 발생합니다. 요청이 너무 높으면 클러스터는 용량을 낭비하고 오토스케일링이 필요 이상으로 노드를 추가할 수 있습니다. 최상의 요청은 일반적으로 관찰된 사용량에 여유분을 더한 값이며, 다른 서비스에서 복사한 값이 아닙니다.
Vertical Pod Autoscaler는 과거 사용량에서 요청을 추천하여 도움을 줄 수 있습니다. 많은 팀이 먼저 권장 모드로 VPA를 실행합니다. 자동 업데이트는 구성 및 워크로드 유형에 따라 파드를 재시작할 수 있기 때문입니다. 추천을 입력으로 취급하고 법칙으로 취급하지 마십시오. 드물지만 중요한 스파이크가 있는 서비스는 평균 기록이 제안하는 것보다 더 많은 여유분이 필요할 수 있습니다.
Horizontal Pod Autoscaler는 더 많은 레플리카가 실제로 처리량을 향상시킬 때 유용합니다. 상태 비저장 웹 서비스와 부하를 공유할 수 있는 워커에 잘 작동합니다. 단일 스레드 병목, 데이터베이스 잠금 또는 이미 포화된 다운스트림 종속성을 해결하지는 않습니다.
기본 HPA는 다음과 같을 수 있습니다:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
HPA 동작을 모니터링하고 레플리카 수만 보지 마십시오. 지속적으로 확장 및 축소되면 안정화 윈도우, 대상 또는 메트릭을 조정하십시오. maxReplicas에 도달하고 지연 시간이 여전히 나쁘면 문제는 용량, 코드 또는 종속성일 수 있습니다. 파드가 명백히 과부하된 상태에서 확장되지 않으면 메트릭 가용성과 요청이 설정되었는지 확인하십시오. CPU 사용률 대상은 CPU 요청에 따라 달라집니다; 누락되거나 비현실적인 요청은 오토스케일링을 오해하게 만들 수 있습니다.
노드 상태는 다음 계층입니다. 한 노드의 여러 서비스에 걸쳐 나타나는 파드 문제는 일반적으로 노드 문제입니다. CPU 포화, 부하 평균, 사용 가능한 메모리, 디스크 압력, inode 사용량, 파일시스템 지연 시간, 네트워크 오류 및 kubelet 상태를 관찰하십시오. MemoryPressure, DiskPressure 및 PIDPressure와 같은 노드 조건은 대시보드와 알림에 표시되어야 합니다.
노드가 의심스러울 때 kubectl describe node를 사용하십시오:
kubectl describe node worker-12
조건, 할당된 리소스, 이벤트 및 노드에 스케줄링된 파드를 확인하십시오. 노드는 제한, 요청 또는 실제 사용량에 의해 초과 할당될 수 있습니다. 할당된 리소스 섹션은 스케줄링 가정이 현실과 일치하는지 확인하는 데 도움이 됩니다.
애플리케이션 파드가 정상으로 보이더라도 컨트롤 플레인 모니터링은 중요합니다. API 서버 지연 시간은 배포, 오토스케일링 및 컨트롤러를 느리게 할 수 있습니다. etcd 지연 시간 또는 디스크 문제는 전체 클러스터를 느리게 만들 수 있습니다. Controller Manager 및 Scheduler 문제는 파드 배치 또는 조정을 지연시킬 수 있습니다. 관리형 Kubernetes에서는 모든 컨트롤 플레인 구성 요소를 볼 수 없지만, 클라우드 제공자는 일반적으로 일부 상태 및 API 지연 시간 메트릭을 노출합니다.
이벤트는 인시던트 중에 유용하지만 장기 메트릭 저장소는 아닙니다. 그럼에도 불구하고 방금 무슨 일이 일어났는지 설명하는 경우가 많습니다:
kubectl get events -A --sort-by=.lastTimestamp
실패한 스케줄링, 이미지 풀 오류, 프로브 실패, 축출 및 백오프 메시지를 찾으십시오. 이벤트는 시끄러울 수 있으므로 필요에 따라 네임스페이스 또는 관련 객체로 필터링하십시오.
프로브는 신중한 모니터링이 필요합니다. 너무 공격적인 Liveness 프로브는 느리지만 회복 중인 앱을 재시작하여 인시던트를 악화시킬 수 있습니다. 올바르게 실패하는 Readiness 프로브는 잘못된 파드를 서비스에서 제거하여 사용자를 보호할 수 있습니다. 프로브 실패를 추적하고 CPU 제한, GC 일시 중지, 다운스트림 시간 초과 및 배포와 상관 관계를 분석하십시오.
스토리지 중심 워크로드의 경우 컨테이너 CPU 및 메모리만으로는 충분하지 않습니다. 영구 볼륨 지연 시간, 디스크 처리량, 큐 깊이 및 파일시스템 포화 상태를 관찰하십시오. 느린 스토리지를 기다리는 파드는 차단되어 낮은 CPU를 보일 수 있습니다. 데이터베이스 또는 큐가 Kubernetes에서 실행되는 경우 스토리지 메트릭은 인프라 trivia가 아닌 애플리케이션 성능의 일부입니다.
실용적인 문제 해결 경로는 넓게 시작하여 좁혀집니다. 첫째, 사용자 대상 증상을 확인하십시오: 지연 시간, 오류, 실패한 작업 또는 백로그. 둘째, 범위를 식별하십시오: 하나의 파드, 하나의 Deployment, 하나의 노드, 하나의 네임스페이스 또는 전체 클러스터. 셋째, 최근 변경 사항을 확인하십시오: 배포, 구성 업데이트, 오토스케일러 활동, 노드 로테이션 또는 트래픽 스파이크. 넷째, 파드 리소스 동작을 검사하십시오: CPU 제한, 메모리 압력, 재시작 및 프로브 실패. 다섯째, 노드 및 종속성 상태를 검사하십시오.
알림은 무해한 소음에 사람들을 깨우지 않아야 합니다. 먼저 사용자 영향에 대해 알리십시오: 높은 오류율, 높은 지연 시간, 놓친 작업 마감, 증가하는 큐 연령. 그런 다음 강력한 선행 지표에 대해 알리십시오: 빈번한 OOMKill, 지연 시간에 민감한 서비스의 지속적인 CPU 제한, 원하는 레플리카 미만의 사용 불가능한 파드, 노드 압력, 지속적인 대기 중인 파드, 서비스 메트릭이 나쁜 상태에서 최대 레플리카에 고정된 HPA.
목표는 완벽한 활용률이 아닙니다. 하루 종일 95% 리소스 사용률로 실행되는 클러스터는 하나의 노드가 실패하고 파드를 재스케줄링할 공간이 없을 때까지 효율적으로 보일 수 있습니다. 롤아웃, 재시도, 트래픽 버스트 및 실패를 위한 용량을 남겨두십시오. 최적화는 인시던트를 작게 유지하는 버퍼를 제거하지 않고 낭비를 줄여야 합니다.
좋은 Kubernetes 성능 모니터링은 실용적으로 느껴집니다. 대시보드를 열고 스무 개의 탭을 뒤지지 않고 서비스 상태, 파드 상태, 노드 상태 및 스케일링 동작을 볼 수 있습니다. 속도 저하가 코드, 리소스 제한, 노드 압력, 스토리지, 네트워크 또는 컨트롤 플레인인지 답할 수 있습니다. 그리고 요청, 제한 또는 오토스케일링을 변경할 때 변경 사항이 도움이 되었는지 추측 대신 확인할 수 있습니다.
네임스페이스 수준 보기는 많은 팀이 클러스터를 공유할 때 유용합니다. 단일 팀은 자신의 Deployment만 볼 경우 노드 수준 포화가 오는 것을 보지 못할 수 있습니다. 플랫폼 팀은 네임스페이스 CPU 및 메모리 요청, 실제 사용량, 파드 수, 재시작 및 제한을 보여주는 대시보드를 노출해야 합니다. 이렇게 하면 용량 대화가 덜 감정적이 됩니다. 팀이 "너무 많이" 사용한다고 말하는 대신 요청 추세, 피크 사용량 및 낭비를 보여줄 수 있습니다.
비용 최적화는 안정성 신호 이후에 와야 하며 그 전에 와서는 안 됩니다. 서비스가 요청을 튜닝한 적이 없다면 쉬운 절감 효과를 찾을 수 있습니다. 그러나 요청을 공격적으로 줄이면 스케줄링 압력과 시끄러운 이웃 문제를 만들 수 있습니다. 좋은 프로세스는 한 번에 하나의 워크로드 클래스를 변경하고, 지연 시간과 재시작을 관찰하며, 롤백 노트를 남깁니다. 리소스 튜닝을 프로덕션 코드처럼 취급하십시오: 작은 변경, 측정된 결과.
배포 자체가 성능 인시던트를 만들 수 있습니다. 한 번에 너무 많은 파드를 교체하는 롤아웃은 콜드 캐시, 연결 풀 또는 다운스트림 서비스를 과부하시킬 수 있습니다. 배포 중 롤아웃 기간, 사용 불가능한 레플리카 및 애플리케이션 지연 시간을 관찰하십시오. 서비스가 시작 중에 어떻게 동작하는지에 따라 maxSurge와 maxUnavailable을 튜닝하십시오. 워밍업이 느린 서비스는 정상 상태 성능이 괜찮더라도 보수적인 롤아웃이 필요할 수 있습니다.
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
이 설정이 보편적으로 최선은 아니지만 트레이드오프를 보여줍니다: 느린 롤아웃, 용량 감소에 대한 더 많은 보호. 즉시 시작되는 상태 비저장 서비스의 경우 더 빠른 롤아웃을 선택할 수 있습니다. 캐시를 워밍업하고 많은 다운스트림 연결을 여는 JVM 서비스의 경우 느린 것이 더 안전할 수 있습니다.
메트릭의 카디널리티를 주시하십시오. Kubernetes 레이블은 유혹적이지만, 파드 UID, 요청 ID 또는 사용자 ID와 같은 높은 카디널리티 레이블은 Prometheus를 비싸고 느리게 만들 수 있습니다. 집계에 도움이 되는 레이블을 사용하십시오: 네임스페이스, 워크로드, 파드, 컨테이너, 노드, 상태 코드, 경로 패턴. 모든 사용자 또는 모든 요청에 대해 새로운 시계열을 생성하는 레이블은 피하십시오. 모니터링이 클러스터 성능을 해치는 것이 되어서는 안 됩니다.
로그와 트레이스가 그림을 완성합니다. 메트릭은 지연 시간이 증가했음을 알려줍니다; 트레이스는 어떤 다운스트림 호출이 느려졌는지 보여줄 수 있습니다; 로그는 정확한 오류 또는 시간 초과를 보여줄 수 있습니다. OpenTelemetry는 일반적으로 이러한 신호를 연결하는 데 사용되지만, 도구보다 상관 관계가 중요합니다. 일관된 서비스 이름, 네임스페이스, 버전 및 추적 ID를 사용하여 알림에서 관련 로그로 추측 없이 이동할 수 있습니다.
배치 및 워커 시스템의 경우 파드 CPU만 보지 말고 백로그 연령을 관찰하십시오. 큐 워커는 파드 수준에서 정상이지만 들어오는 작업이 처리 용량을 초과하여 뒤쳐질 수 있습니다. 가장 오래된 메시지 연령, 분당 완료된 작업, 재시도 및 데드 레터 수와 같은 메트릭은 종종 컨테이너 사용률보다 더 중요합니다. CPU가 잘못된 신호일 때 HPA는 사용자 정의 또는 외부 메트릭에서 확장할 수 있습니다.
인시던트 후 대시보드를 검토하십시오. 대응자가 동일한 질문에 답하기 위해 다섯 개의 수동 명령을 실행해야 했다면, 그 질문은 대시보드 또는 런북에 속합니다. 모니터링은 사용을 통해 개선됩니다. 목표는 모든 실패를 예측하는 것이 아닙니다; 다음 조사를 더 짧게 만들고 한 사람의 기억에 덜 의존하게 만드는 것입니다.