본문으로 건너뛰기

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