5.3 신호 상관관계
PostgreSQL metric만 보면 database 내부에서 나타난 결과는 알 수 있지만, 원인이 host인지 application인지 구분하기 어렵습니다. 같은 시간축에 service, pool, PostgreSQL, OS, Kubernetes, trace를 놓고 가설을 검증합니다.
공통 label
서로 다른 exporter가 같은 대상을 가리키도록 label 체계를 맞춥니다.
| 계층 | 권장 label |
|---|---|
| 공통 | environment, region, cluster |
| PostgreSQL | instance, datname, role |
| Kubernetes | namespace, pod, node |
| 애플리케이션 | service, version |
PostgreSQL Pod가 재생성될 때 Pod 이름과 database cluster identity를 분리해야 장기 graph가 끊기지 않습니다.
Linux와 node_exporter
Database 지연과 함께 확인할 대표 지표입니다.
# CPU 사용률
1 - avg by (instance) (
rate(node_cpu_seconds_total{mode="idle"}[5m])
)
# Disk read/write latency 근사
rate(node_disk_read_time_seconds_total[5m])
/
rate(node_disk_reads_completed_total[5m])
읽기 작업이 없는 구간의 평균 latency는 정의되지 않은 값으로 남깁니다.
# Memory available ratio
node_memory_MemAvailable_bytes
/
node_memory_MemTotal_bytes
CPU utilization만으로 saturation을 판단하지 않습니다. run queue, pressure stall information, cgroup throttling을 함께 봅니다. Disk도 utilization 100% 여부보다 request latency와 queue, PostgreSQL I/O timing을 같이 확인합니다.
Kubernetes와 container
Pod 환경에서는 request/limit과 실제 사용량을 연결합니다.
container_cpu_usage_seconds_totalcontainer_cpu_cfs_throttled_seconds_totalcontainer_memory_working_set_byteskube_pod_container_status_restarts_total- PVC 사용량과 node volume latency
PostgreSQL CPU가 host 전체로는 여유 있어 보여도 container limit에 걸려 throttling될 수 있습니다. OOMKilled 재시작은 PostgreSQL log보다 Kubernetes Pod status에서 먼저 드러나는 경우가 많습니다.
Application과 connection pool
다음 metric이 없으면 database connection 문제의 절반만 보게 됩니다.
- active/idle pool connection
- acquire wait duration
- acquire timeout count
- query request rate와 error rate
- transaction duration
PostgreSQL backend가 max_connections에 가깝지 않아도 특정 application pool 하나가 고갈될 수 있습니다. 반대로 pool은 여유 있지만 database에서 lock wait가 길어져 connection 반환이 늦어질 수도 있습니다.
OpenTelemetry trace
Trace의 database span은 느린 사용자 요청이 실제로 SQL에서 시간을 썼는지 보여 줍니다. 공통 attribute는 다음과 같습니다.
db.system.name=postgresql- database namespace
- server address와 port
- operation name
- error status
SQL 원문 전체를 span attribute로 무조건 넣지 않습니다. 개인정보, secret, 큰 payload를 제거하고 parameterized statement나 operation 수준으로 제한합니다.
상관관계 예시
| 함께 나타난 변화 | 우선 가설 | 다음 확인 |
|---|---|---|
| API latency↑, pool wait↑, DB connection 고정 | connection 반환 지연 | 긴 transaction/lock wait |
| DB read time↑, node disk latency↑ | storage 병목 | volume/filesystem/checkpoint |
| Pod CPU throttling↑, query latency↑ | CPU limit 부족 | request/limit/node 여유 |
| replica lag↑, WAL rate↑ | apply 처리량 부족 | replay 상태/disk/long query |
pg_up↓, node 정상 | 인증/TLS/DB availability | exporter log/pg_isready |
상관관계는 원인 증명이 아닙니다. 시간 순서와 원본 상태를 확인하고, 변경 또는 재현으로 가설을 검증합니다.
참고: node_exporter, Kubernetes observability, OpenTelemetry database spans