Files
project-infra/docs/standards/infra/observability-health.md
T

9.4 KiB
Raw Blame History

observability / health 기준

목적

이 문서는 1000+ 서비스가 공통으로 따르는 observability 기준선이다. metrics 수집 경로, golden signal 정의, 로그 포맷 / 수집 stack, trace 수집(OTel), health endpoint 외부 비공개 원칙, cardinality 가드를 한 파일에 고정한다.

공식 / 업계 근거

  • Google SRE Book (Ch.6): Four Golden Signals = Latency, Traffic, Errors, Saturation. 운영 대시보드의 기본 구성 원칙.
  • RED method (Tom Wilkie, Weaveworks): request-driven service에 대해 Rate, Errors, Duration.
  • USE method (Brendan Gregg): resource에 대해 Utilization, Saturation, Errors.
  • kube-prometheus-stack: Prometheus Operator를 통한 ServiceMonitor / PodMonitor CRD가 primary scrape path.
  • Prometheus annotation fallback: prometheus.io/scrape: "true" 등은 Operator가 없을 때만 사용.
  • OpenTelemetry: OTLP protocol + OTel Collector (Deployment gateway + DaemonSet agent) 가 표준.
  • Log shipping canonical stacks: Loki + Grafana Alloy (또는 Promtail) / Fluent Bit → OpenSearch. 한 플랫폼에서 둘 이상 섞지 않는다.
  • kubectl events (1.27+ stable) — 기존 kubectl get events보다 sort/watch 기본 제공.
  • metrics-server: HPA/VPA와 kubectl top 을 위한 최소 resource metric. full metrics와 분리.

기본 규칙

1. Four Golden Signals를 모든 서비스 대시보드의 골격으로

각 traffic-facing service는 최소 4개 signal을 노출한다.

  • Latency: request_duration_seconds histogram (p50/p95/p99).
  • Traffic: requests_per_second by method/status.
  • Errors: error_rate (5xx / 전체).
  • Saturation: resource utilization (CPU / memory / connection pool / queue depth).

SLO / alert / dashboard가 이 4개에서 시작한다.

2. RED는 request-driven, USE는 resource에 쓴다

  • HTTP / gRPC 서비스 → RED.
  • Node / disk / CPU / DB pool → USE.
  • 두 방법론을 동시에 활용 가능 (golden signal은 양쪽 합집합).

3. ServiceMonitor / PodMonitor 를 primary scrape path로

kube-prometheus-stack을 운영하는 플랫폼에서는 ServiceMonitor CRD가 표준이다.

  • selector.matchLabels 로 대상 Service 매칭.
  • namespaceSelector 명시 (암묵적 전체 허용 금지).
  • endpoints[].portnamed port, 숫자 port 금지.
  • interval (기본 30s), scrapeTimeout (interval < interval) 명시.
  • scheme (http/https) 명시.
  • bearerTokenSecret / tlsConfig 로 인증 scrape.
  • relabelings 로 label 위생 (pod_template_hash drop 등).

Pod에 직접 연결되는 경우 (Service가 없는 워크로드) PodMonitor 사용.

4. Annotation-based scrape 는 fallback

prometheus.io/scrape: "true" 계열 annotation은 Prometheus가 Operator 없이 kubernetes_sd_configs로 직접 discover하는 방식이다. ServiceMonitor 대비 label relabel / auth / tls 제어가 약하다.

  • kube-prometheus-stack이 있는 환경: 사용 금지, ServiceMonitor 통일.
  • legacy / 교체 진행 중인 플랫폼: 전환 기간 동안만 사용.

지원 annotation:

  • prometheus.io/scrape: "true"
  • prometheus.io/port: "8081"
  • prometheus.io/path: "/metrics"
  • prometheus.io/scheme: "http"

5. metrics port는 외부 비공개, NetworkPolicy로 scraper만 허용

  • /metrics 는 절대 Ingress 경로에 노출하지 않는다.
  • metrics port는 별도 containerPort (ex: 8081, 9000).
  • NetworkPolicy로 monitoring namespace의 prometheus pod만 해당 port에 ingress 허용.

6. Cardinality는 label 설계 단계에서 가드

Prometheus TSDB에서 각 label value 조합 = 새 time series. cardinality 폭발은 쿼리 OOM / storage 폭증의 가장 흔한 원인.

금지 label:

  • user_id, tenant_id (높은 기수) — 대신 top-N aggregation 또는 별도 logging.
  • path (path에 UUID / numeric ID 포함) — template된 route로 바꾼다 (/users/:id).
  • url 전체, request_id, trace_id, session_id.
  • timestamp, epoch value.

허용 label 예:

  • method (GET/POST/…), status_code (bucketed 2xx/4xx/5xx가 더 안전), route (template).

규칙: 한 metric당 series 수 ≤ 10,000 목표. 10만 넘어가면 review.

7. Histogram 을 p99 표현 기본값으로

  • summary는 aggregatable 하지 않다 (서비스 간 p99 합산 불가).
  • histogram_quantile() 를 위한 _bucket + _count + _sum 를 쓴다.
  • bucket boundary는 SLO에 맞춰 튜닝 (le: 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10).

8. 로그는 JSON structured, stdout/stderr 로만

application log는 JSON one-line per record, stdout/stderr로 출력. PVC / hostPath / 컨테이너 내부 file 금지.

필수 field:

  • timestamp (ISO 8601 RFC3339, UTC).
  • level (DEBUG/INFO/WARN/ERROR).
  • service (= app.kubernetes.io/name).
  • trace_id, span_id (OTel에서 주입).
  • message.
  • error (object with type, message, stacktrace when level=ERROR).
  • optional: user_id (hashed), request_id, http_status.

9. 로그 수집 stack은 한 플랫폼당 하나

canonical choice:

  • Loki + Grafana Alloy (권장): 낮은 storage cost, Grafana 통합.
  • Fluent Bit → OpenSearch/Elasticsearch: full-text search 중심, 높은 storage cost.

플랫폼 하나에서 둘 다 운영하지 않는다. AI agent가 매니페스트 생성할 때 플랫폼 선택을 context에서 받아 일관되게 적용한다.

node-level: DaemonSet으로 agent 배포 → tail /var/log/containers/*.log.

10. 민감정보는 로그 금지 + 자동 masking

금지:

  • access/refresh token, bearer, API key.
  • DB password, connection string의 password 부분.
  • Vault secret value.
  • full Authorization header.
  • PII (email, phone, SSN 등) 원문.

구현:

  • logging framework의 structured field 에서만 쓰고 toString() 흐름 차단.
  • 중앙 수집 파이프라인에 redaction filter 추가.
  • 의심스러운 pattern은 debug 로그에서도 masking.

11. OpenTelemetry / OTLP를 trace / metrics 통로로

  • 애플리케이션: OTel SDK로 계측, OTLP (gRPC 4317 또는 HTTP 4318) 로 export.
  • 수집: OTel Collector DaemonSet (agent)OTel Collector Deployment (gateway) → backend (Tempo / Jaeger / New Relic / Datadog).
  • gateway에서 sampling / tail-based sampling / PII scrubbing 적용.
  • app은 cluster 내부 agent endpoint만 알면 됨 (localhost:4317 → DaemonSet).

12. health / metrics / admin endpoint 는 외부 비공개 기본값

외부 비공개 대상:

  • /health, /health/*, /actuator/*.
  • /metrics.
  • /admin, /internal, /debug.
  • Keycloak management port 9000.
  • Vault /sys/* endpoint.

외부 공개는 명시적 review 필요.

13. probe는 health endpoint 와 목적을 구분

  • probe용 endpoint는 shallow, 빠른 응답.
  • 운영자 점검용 deep health는 별도 endpoint (ex: /ops/deep-health), 인증 필요.
  • Prometheus 가 /metrics 를 스크레이프하더라도 probe가 /metrics 를 쓰지 않는다 (cost 문제).

14. kubectl events 를 기본 event 조회 수단으로 (1.27+)

Kubernetes 1.27+ 부터 kubectl events 가 stable.

  • kubectl events -A --watch — cluster-wide live view.
  • kubectl events -n <ns> --for pod/<name> — 특정 오브젝트.
  • kubectl events --types=Warning — 경고만.

kubectl get events 대비 sort-by-timestamp 기본, watch 안정적.

15. 알림 기준: Golden Signal 에 SLO 를 먼저 정의

  • availability SLO: 99.9% / 99.95% 등.
  • latency SLO: p99 < 500ms.
  • error budget: (1 - SLO) × 기간.
  • alert는 burn rate 기준 (1h/6h fast burn + 6h/3d slow burn 이중 창).

단순 "CPU > 80%" alert 는 actionable 하지 않다 (saturation은 dashboard용, 알림은 SLO 기반).

16. 워크로드별 기본 권장안

auth-server (Spring Boot)

  • metrics: micrometer + prometheus registry, /actuator/prometheus.
  • ServiceMonitor with named port metrics (8081).
  • tracing: OTel Java agent, OTLP to DaemonSet.
  • logging: logback JSON encoder → stdout.

keycloak

  • metrics: management port 9000 /metrics.
  • ServiceMonitor 대상, /admin9000 외부 비공개.
  • event metric cardinality는 event_type level 까지만, user / session ID 금지.

vault

  • /sys/metrics?format=prometheus (token 필요) → ServiceMonitor with bearerTokenSecret.
  • /sys/health 는 sealed/standby 구분해서 alert 룰 따로.

minio

  • /minio/v2/metrics/cluster + /node + /bucket.
  • bucket metric은 bucket 수 폭증 시 cardinality 주의.

db (PostgreSQL / MySQL)

  • postgres_exporter / mysqld_exporter sidecar 또는 별도 Deployment.
  • USE method (connection pool saturation, lock wait).

ingress-controller

  • RED + upstream response time.
  • path label은 반드시 template 화.

프로젝트 기준 요약

  • Four Golden Signals를 dashboard 골격으로, RED/USE를 세부 방법론으로.
  • ServiceMonitor / PodMonitor 를 primary scrape, annotation은 fallback.
  • metrics port는 NetworkPolicy로 monitoring namespace만 허용.
  • Cardinality는 label 설계에서 가드 (user_id / raw path / timestamp 금지).
  • 로그는 JSON structured stdout, trace_id/span_id 포함.
  • log shipping stack은 플랫폼당 하나 (Loki+Alloy 또는 Fluent Bit→OpenSearch).
  • 로그에 민감정보 금지, 중앙 파이프라인 redaction.
  • OpenTelemetry DaemonSet agent + Deployment gateway.
  • health / metrics / admin endpoint 외부 비공개.
  • kubectl events 를 기본 event 조회 수단으로 (1.27+).
  • alert는 SLO burn rate 기반, CPU% 같은 단순 threshold 금지.