Chapter 14

쿠버네티스 모니터링

  • 14.1 metrics-server
  • 14.2 kube-state-metrics
  • 14.3 node-exporter
  • 14.4 프로메테우스(Prometheus)
  • 14.5 그라파나(Grafana)

클러스터를 운영하면서 "지금 CPU 얼마나 쓰고 있지?", "파드가 몇 개 Running이지?", "노드 디스크가 부족하진 않나?" 같은 질문에 답하려면 모니터링 체계가 필수야.

metrics-server는 쿠버네티스에서 **실시간 리소스 사용량(CPU, 메모리)**을 수집하는 가벼운 컴포넌트야:

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

설치하면 kubectl top 명령어를 사용할 수 있어:

kubectl top nodes           # 노드별 CPU/메모리 사용량
kubectl top pods            # 파드별 CPU/메모리 사용량
kubectl top pods -n kube-system  # 특정 네임스페이스

metrics-server가 하는 일은 각 노드의 kubelet에서 주기적으로(기본 15초) 메트릭을 수집하고, 수집한 메트릭을 메모리에 저장한 뒤(디스크에 저장하지 않아), Metrics API(/apis/metrics.k8s.io)를 통해 제공하는 거야. 11장에서 다룬 **HPA(Horizontal Pod Autoscaler)**가 동작하려면 metrics-server가 반드시 설치되어 있어야 해. HPA가 스케일링 결정을 내리려면 현재 CPU/메모리 사용량을 알아야 하니까.

metrics-server의 한계는 현재 시점의 메트릭만 제공한다는 거야. 과거 데이터를 저장하지 않으니까, 히스토리 조회나 트렌드 분석이 안 돼. 이건 프로메테우스의 영역이지.

kube-state-metrics는 metrics-server와 이름이 비슷하지만 역할이 완전히 달라. metrics-server가 실제 리소스 사용량(CPU 몇 %, 메모리 몇 MB)을 보여준다면, kube-state-metrics는 쿠버네티스 오브젝트의 상태 정보(파드가 몇 개 Running인지, 디플로이먼트의 replicas가 원하는 수와 일치하는지)를 제공해.

kube-state-metrics가 제공하는 메트릭 예시를 보면:

  • kube_pod_status_phase: 파드의 상태 (Pending, Running, Failed 등)
  • kube_deployment_spec_replicas: 디플로이먼트의 원하는 레플리카 수
  • kube_deployment_status_replicas_available: 실제 가용한 레플리카 수
  • kube_node_status_condition: 노드의 상태 (Ready, DiskPressure 등)
  • kube_pod_container_status_restarts_total: 컨테이너 재시작 횟수
kubectl apply -f https://github.com/kubernetes/kube-state-metrics/releases/latest/download/kube-state-metrics.yaml

kube-state-metrics는 프로메테우스와 조합해서 사용하는 게 일반적이야. "파드가 CrashLoopBackOff에 빠졌을 때 알림을 보내기" 같은 알림 규칙을 설정할 수 있지.

node-exporter노드(서버)의 하드웨어 및 OS 수준 메트릭을 수집하는 프로메테우스 공식 익스포터야. CPU 사용률(코어별, 모드별), 메모리 사용량(총량, 사용량, 캐시, 버퍼), 디스크 I/O(읽기/쓰기 바이트, IOPS), 네트워크 트래픽(인터페이스별 송수신), 파일시스템 사용량, 시스템 로드를 수집하지.

node-exporter는 데몬셋으로 배포해. 모든 노드에 하나씩 떠야 하니까:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
spec:
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      hostNetwork: true
      hostPID: true
      containers:
        - name: node-exporter
          image: prom/node-exporter:latest
          ports:
            - containerPort: 9100
          volumeMounts:
            - name: proc
              mountPath: /host/proc
              readOnly: true
            - name: sys
              mountPath: /host/sys
              readOnly: true
      volumes:
        - name: proc
          hostPath:
            path: /proc
        - name: sys
          hostPath:
            path: /sys

hostNetwork: true로 호스트 네트워크를 사용하고, /proc/sys를 마운트해서 노드의 시스템 정보에 접근해. 각 노드의 9100 포트에서 프로메테우스 형식의 메트릭을 노출하지.

프로메테우스는 CNCF 졸업 프로젝트이자 쿠버네티스 모니터링의 사실상 표준이야. 핵심 아키텍처를 보면:

  • Pull 방식: 프로메테우스가 타겟(node-exporter, kube-state-metrics, 애플리케이션 등)에서 메트릭을 주기적으로 긁어와(scrape). Push 방식이 아니야.
  • 시계열 데이터베이스(TSDB): 수집한 메트릭을 시계열로 저장해. 과거 데이터를 쿼리할 수 있지.
  • PromQL: 프로메테우스 전용 쿼리 언어야. 강력한 집계와 필터링을 지원해.
  • Alertmanager: 알림 규칙에 따라 Slack, PagerDuty, 이메일 등으로 알림을 발송하지.

쿠버네티스에 프로메테우스를 설치하는 가장 쉬운 방법은 kube-prometheus-stack Helm 차트야:

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/kube-prometheus-stack

이 한 줄로 Prometheus, Alertmanager, Grafana, node-exporter, kube-state-metrics가 모두 설치돼.

프로메테우스의 강점 중 하나는 쿠버네티스와의 서비스 디스커버리 통합이야. 파드가 생성/삭제될 때 자동으로 타겟을 추가/제거하지. 파드에 어노테이션을 붙여서 프로메테우스가 스크래핑하도록 설정할 수 있어:

metadata:
  annotations:
    prometheus.io/scrape: "true"
    prometheus.io/port: "8080"
    prometheus.io/path: "/metrics"

PromQL 예시를 보면:

# 최근 5분간 평균 CPU 사용률
rate(node_cpu_seconds_total{mode!="idle"}[5m])

# 파드별 메모리 사용량 (상위 10개)
topk(10, container_memory_usage_bytes{namespace="default"})

# 디플로이먼트의 가용 레플리카가 원하는 수보다 적은 경우
kube_deployment_status_replicas_available < kube_deployment_spec_replicas

알림 규칙도 설정할 수 있어:

groups:
  - name: kubernetes-alerts
    rules:
      - alert: PodCrashLooping
        expr: rate(kube_pod_container_status_restarts_total[15m]) > 0
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "파드가 반복적으로 재시작되고 있습니다"

프로메테우스가 메트릭을 수집하고 저장한다면, 그라파나는 그 데이터를 시각화하는 도구야. 대시보드를 만들어서 클러스터 상태를 한눈에 볼 수 있지.

kube-prometheus-stack으로 설치하면 그라파나에 기본 대시보드가 포함되어 있어:

  • Kubernetes / Compute Resources / Cluster: 클러스터 전체 CPU/메모리 사용량
  • Kubernetes / Compute Resources / Namespace (Pods): 네임스페이스별 파드 리소스 사용량
  • Kubernetes / Compute Resources / Node (Pods): 노드별 리소스 현황
  • Node Exporter / Nodes: 노드의 시스템 메트릭 (CPU, 메모리, 디스크, 네트워크)

그라파나 대시보드는 JSON으로 내보내기/가져오기가 가능해서, 한 번 만든 대시보드를 팀 전체에 공유하거나 다른 클러스터에 적용할 수 있어. Grafana Dashboard 커뮤니티에서 다른 사람이 만든 대시보드를 ID로 임포트할 수도 있지.

그라파나에서 알림을 직접 설정할 수도 있지만, 프로메테우스의 Alertmanager를 사용하는 게 더 일반적이야. Alertmanager가 알림 그룹화, 중복 제거, 라우팅(심각도에 따라 다른 채널로) 같은 고급 기능을 제공하니까.

전체 모니터링 스택을 정리하면:

node-exporter  → (노드 메트릭)       → Prometheus → Grafana
kube-state-metrics → (오브젝트 상태)  → Prometheus → Grafana
metrics-server → (kubectl top, HPA)
애플리케이션   → (/metrics 엔드포인트) → Prometheus → Grafana
                                     → Alertmanager → Slack/PagerDuty

정리

14장 읽고 기억할 거 네 가지:

  1. metrics-server는 실시간 CPU/메모리, kube-state-metrics는 오브젝트 상태를 수집한다. 역할이 다르니 둘 다 필요함.
  2. node-exporter는 노드의 하드웨어/OS 메트릭을 수집한다. 데몬셋으로 모든 노드에 배포.
  3. 프로메테우스는 Pull 방식으로 메트릭을 수집하고, PromQL로 쿼리한다. kube-prometheus-stack 하나면 전체 모니터링 스택을 한 번에 설치할 수 있다.
  4. 그라파나로 프로메테우스 데이터를 시각화한다. 기본 제공 대시보드로 시작하고, 필요에 따라 커스텀 대시보드를 만들 수 있다.