본문으로 건너뛰기

5.3 신호 상관관계

PostgreSQL metric만 보면 database 내부에서 나타난 결과는 알 수 있지만, 원인이 host인지 application인지 구분하기 어렵습니다. 같은 시간축에 service, pool, PostgreSQL, OS, Kubernetes, trace를 놓고 가설을 검증합니다.

Service/Pool/PostgreSQL/Container/Host 신호를 같은 시간축과 공통 Label로 연결한 계층

공통 label

서로 다른 exporter가 같은 대상을 가리키도록 label 체계를 맞춥니다.

계층권장 label
공통environment, region, cluster
PostgreSQLinstance, datname, role
Kubernetesnamespace, 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_total
  • container_cpu_cfs_throttled_seconds_total
  • container_memory_working_set_bytes
  • kube_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 availabilityexporter log/pg_isready

상관관계는 원인 증명이 아닙니다. 시간 순서와 원본 상태를 확인하고, 변경 또는 재현으로 가설을 검증합니다.

참고: node_exporter, Kubernetes observability, OpenTelemetry database spans