← 스터디 홈
9편 · 약 12분

관측성(로깅·메트릭)

관측할 수 없는 시스템은 운영할 수 없다

컨테이너는 수십 개에서 수백 개가 동시에 뜨고 죽는다. SSH로 직접 들어가 tail -f 하던 시절의 방식은 통하지 않는다. 쿠버네티스 관측성은 세 가지 신호로 요약된다.

신호정의도구 예시
메트릭(Metrics)시간축 위의 수치 — CPU, 메모리, 요청 수Prometheus + Grafana
로그(Logs)이벤트 텍스트 스트림Loki + Grafana Alloy
트레이스(Traces)요청이 서비스 사이를 이동한 경로Tempo + OpenTelemetry

이 글에서는 실무에서 가장 먼저 구축하는 메트릭로그 파이프라인을 집중적으로 다룬다.

메트릭 파이프라인 — Prometheus

스크레이핑(Scraping) 모델

Prometheus는 Pull 방식이다. 각 타깃이 /metrics HTTP 엔드포인트를 열어두면 Prometheus가 주기적(기본 15초)으로 당겨온다. Push 방식과 달리 타깃이 Prometheus 주소를 몰라도 되고, 수집 실패를 수집 측에서 감지할 수 있다.

세 계층의 메트릭 수집

쿠버네티스 환경에서 Prometheus는 세 계층을 동시에 관찰한다.

  1. 노드 레벨 — Node Exporter (DaemonSet): 각 노드의 CPU, 메모리, 디스크, 네트워크 지표
  2. 쿠버네티스 오브젝트 레벨 — kube-state-metrics (Deployment): Deployment 복제본 수, Pod 상태, PVC 용량 같은 API 오브젝트 기반 지표. 실제 사용량이 아닌 선언된 상태를 측정한다는 점이 핵심이다
  3. 애플리케이션 레벨 — Prometheus 클라이언트 라이브러리: 앱이 직접 HTTP RPS, 레이턴시 히스토그램, 비즈니스 카운터 등을 /metrics로 노출

주요 PromQL 패턴

# Pod의 CPU 사용률 (컨테이너별, 5분 평균)
rate(container_cpu_usage_seconds_total[5m])

# Deployment 복제본 중 사용 불가 수
kube_deployment_status_replicas_unavailable{deployment="api-server"}

# 노드 메모리 사용률 %
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100

kube-state-metrics vs metrics-server: metrics-server는 HPA·VPA가 현재 사용량을 읽기 위한 경량 어댑터고, kube-state-metrics는 오브젝트의 선언 상태를 측정한다. 두 도구는 역할이 다르므로 둘 다 필요하다.

Alertmanager — 알림 라우팅

Prometheus는 규칙(PrometheusRule)으로 임계치를 평가하고, 발화(fire)된 알림을 Alertmanager에 넘긴다. Alertmanager는 중복 억제(deduplication), 침묵(silencing), 그룹화, Slack/PagerDuty 라우팅을 담당한다.

# PrometheusRule 예시
- alert: PodCrashLooping
  expr: rate(kube_pod_container_status_restarts_total[15m]) > 0
  for: 5m
  labels:
    severity: critical
  annotations:
    summary: "Pod {{ $labels.pod }} 재시작 반복 중"

로그 파이프라인 — Loki

Kubernetes 로그의 흐름

컨테이너는 stdout/stderr에 로그를 쓴다. kubelet이 이를 노드의 /var/log/pods/ 경로에 파일로 쓰고, 로그 에이전트가 그 파일을 수집해 중앙 저장소로 전송한다.

2026년 3월, Promtail은 공식 EOL(End-of-Life)을 맞았다. Grafana는 통합 에이전트 Grafana Alloy로 전환을 권고한다. Alloy는 로그 수집뿐 아니라 메트릭 스크레이핑, 트레이스 전송도 단일 파이프라인으로 처리한다.

Loki의 핵심 설계 원칙

ELK(Elasticsearch, Logstash, Kibana) 스택과 달리 Loki는 로그 내용을 인덱싱하지 않는다. 레이블(namespace, pod, container)만 인덱싱하고 로그 텍스트는 압축 청크로 저장한다. 덕분에 운영 비용이 크게 낮고, Prometheus와 동일한 레이블 체계를 공유해 메트릭-로그 연동이 자연스럽다.

# api-server pod의 최근 에러 로그
{namespace="production", pod=~"api-server-.*"} |= "ERROR"

# HTTP 500 응답을 status 코드로 집계 (메트릭 변환)
sum(rate({job="nginx"}[5m] | json | status="500")) by (path)

전체 관측성 스택 아키텍처

Worker Node App Container stdout / stderr → /var/log/pods/ Node Exporter CPU·메모리·디스크 /metrics Grafana Alloy DaemonSet: 로그 수집 → Loki 전송 kube-state-metrics 오브젝트 상태 /metrics 수집 레이어 Prometheus 15초 주기 Pull TSDB 저장 PrometheusRule 평가 Loki 레이블만 인덱싱 로그 텍스트 압축 저장 Alertmanager 알림 라우팅·중복 억제 Grafana 메트릭 대시보드 로그 탐색 (Explore) 알림 시각화 DataSource: Prometheus + Loki Slack / PagerDuty Alertmanager 라우팅 대상 severity 별 분기 주요 메트릭 지표 kube_pod_status_phase — Pod 상태별 수 (Running/Pending/Failed) container_memory_working_set_bytes — 실제 메모리 사용량 (OOMKill 기준) kube_deployment_status_replicas_unavailable — 사용 불가 복제본 수 node_filesystem_avail_bytes — 노드 디스크 여유 공간 rate(container_cpu_usage_seconds_total[5m]) — CPU 사용률 kube_pod_container_status_restarts_total — 재시작 횟수
Kubernetes 관측성 파이프라인 전체 구조

kube-prometheus-stack — 한 번에 설치

운영 수준의 Prometheus + Grafana + Alertmanager를 가장 빠르게 구성하는 방법은 kube-prometheus-stack Helm 차트다.

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install kube-prom prometheus-community/kube-prometheus-stack \
  --namespace monitoring --create-namespace \
  --set grafana.adminPassword=changeme

차트 한 번으로 Node Exporter DaemonSet, kube-state-metrics, Prometheus Operator, Grafana, Alertmanager가 모두 설치되고, 기본 대시보드와 알림 규칙도 포함된다.

실전 관측성 가이드라인

  1. 기본 4가지 골든 시그널부터 시작한다: 레이턴시, 트래픽, 에러율, 포화도(Saturation). 처음부터 수백 개 메트릭을 수집하면 신호 대 잡음비가 낮아진다.
  2. 로그에 구조화 포맷(JSON)을 사용한다: kubectl logs로 봐도 읽기 쉽고, Loki에서 | json 파서로 필드 추출이 가능하다.
  3. 메트릭 보존 기간을 설정한다: 기본 15일은 용량 예측에 충분하지 않을 수 있다. Thanos나 Mimir를 추가해 장기 보존과 고가용성을 확보한다.
  4. Alertmanager routing tree를 단순하게 유지한다: 라우팅이 복잡해질수록 알림이 어디로 가는지 추적하기 어렵다. severity: critical / warning 두 단계로 시작한다.
  5. SLO(Service Level Objective) 기반 알림을 우선한다: CPU 80% 같은 임계치 알림보다 "에러율 0.1% 초과" 또는 "P99 레이턴시 1초 초과" 같은 사용자 체감 기반 알림이 실제 장애에 더 잘 반응한다.

References

  • https://prometheus.io/docs/introduction/overview/
  • https://grafana.com/docs/loki/latest/get-started/overview/
  • https://grafana.com/docs/alloy/latest/
  • https://unixarena.com/2025/06/prometheus-in-kubernetes-building-production-grade-monitoring-systems.html/
  • https://spacelift.io/blog/kube-state-metrics
  • https://last9.io/blog/kube-state-metrics/
  • https://adminjournal.substack.com/p/building-a-kubernetes-observability
  • https://www.improving.com/thoughts/end-to-end-observability-with-prometheus-grafana-loki-opentelemetry-tempo/
  • https://medium.com/@muppedaanvesh/a-hands-on-guide-to-kubernetes-monitoring-metrics-and-logging-with-grafana-loki-%EF%B8%8F-010c12f0ffb6