init: 폴더구조 설계 및 인프라 설계

This commit is contained in:
DongHyeonka
2026-07-24 14:31:53 +09:00
parent 34ad612281
commit f9c463f87a
1839 changed files with 323096 additions and 1 deletions
@@ -0,0 +1,219 @@
# 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[].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 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 대상, `/admin``9000` 외부 비공개.
- 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 금지.