9.4 KiB
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/PodMonitorCRD가 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_secondshistogram (p50/p95/p99). - Traffic:
requests_per_secondby 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[].port는 named 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 withtype,message,stacktracewhen 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 대상,
/admin과9000외부 비공개. - event metric cardinality는
event_typelevel 까지만, user / session ID 금지.
vault
/sys/metrics?format=prometheus(token 필요) → ServiceMonitor withbearerTokenSecret./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 금지.