10.1 모니터링
CloudNativePG는 각 PostgreSQL 인스턴스 안에 metrics exporter를 함께 띄운다. 이 exporter는 인스턴스에 접속해 상태를 SQL로 조회하고, 그 결과를 Prometheus가 이해하는 텍스트 포맷으로 HTTP에 노출한다. 관찰의 큰 그림은 단순하다. 각 Pod가 metrics를 내놓으면 Prometheus가 주기적으로 긁어(scrape) 저장하고, Grafana가 그 저장소를 읽어 대시보드로 그린다.
flowchart TD
subgraph POD["PostgreSQL Pod"]
PG["postgres"]
EXP["metrics exporter<br/>:9187/metrics"]
PG -->|SQL 조회| EXP
end
PM["PodMonitor"]
PROM["Prometheus"]
GRAF["Grafana"]
PM -->|scrape 대상 등록| PROM
PROM -->|scrape| EXP
GRAF -->|query| PROM
classDef node fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
class PG,EXP,PM,PROM,GRAF node
metrics endpoint
인스턴스마다 metrics는 9187 포트의 /metrics 경로에 노출된다. exporter는 cnpg_metrics_exporter라는 role로 쿼리를 실행하며, 이 role은 pg_monitor 권한을 물려받아 통계 뷰를 읽을 수 있다.
가장 빠르게 눈으로 확인하는 방법은 port-forward다.
kubectl port-forward cluster-example-1 9187:9187
# 다른 터미널에서
curl -s localhost:9187/metrics | headPod 안에서 직접 확인하려면 Pod IP로 붙는다.
POD_IP=$(kubectl get pod cluster-example-1 -o jsonpath='{.status.podIP}')
kubectl exec -ti curl -- curl -s ${POD_IP}:9187/metrics.spec.monitoring.metricsQueriesTTL을 0으로 둔다. 캐시 효율은 cache_hits·cache_misses metrics로 확인할 수 있다.PodMonitor로 Prometheus에 연결
Prometheus Operator를 쓴다면, PodMonitor 리소스를 만들어 “이 label을 가진 Pod들의 metrics 포트를 긁어라"라고 선언한다. Prometheus는 이 선언을 읽어 scrape 대상에 자동으로 등록한다.
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: cluster-example
spec:
selector:
matchLabels:
cnpg.io/cluster: cluster-example
podMetricsEndpoints:
- port: metrics.spec.monitoring.enablePodMonitor: true로 Operator가 PodMonitor를 대신 만들게 했지만, 이 필드는 deprecated다. 위처럼 PodMonitor를 직접 만드는 방식을 권장한다.기본 제공 metrics
Operator는 cnpg-default-monitoring이라는 ConfigMap을 설치해 두고, 여기에 담긴 기본 쿼리를 모든 클러스터에 적용한다. 대표적인 것들만 추리면 다음과 같다.
| metric | 의미 |
|---|---|
cnpg_collector_up | 인스턴스가 살아 있는지 여부 |
cnpg_collector_pg_wal | WAL 파일 개수·크기 |
cnpg_collector_sync_replicas | synchronous replica 현황 |
cnpg_collector_nodes_used | 인스턴스가 퍼져 있는 노드 수 |
cnpg_collector_postgres_version | PostgreSQL 버전 정보 |
기본 metrics가 불필요하면 클러스터 단위로 .spec.monitoring.disableDefaultQueries: true를 주거나, Operator 설정에서 MONITORING_QUERIES_CONFIGMAP을 빈 문자열로 두어 전역에서 끌 수 있다.
custom query
기본 metrics로 부족하면 직접 쿼리를 정의해 새 metric을 만든다. 쿼리는 ConfigMap이나 Secret에 담고, 클러스터에서 이를 참조한다.
spec:
monitoring:
customQueriesConfigMap:
- name: example-monitoring
key: custom-queriescnpg.io/reload: "" label을 붙여 두면 내용이 바뀔 때 자동으로 다시 읽힌다.쿼리 하나의 구조는 아래와 같다. query가 실제 SQL이고, metrics의 각 항목이 결과 컬럼을 어떤 종류의 metric으로 내보낼지 지정한다.
pg_replication:
query: "SELECT CASE WHEN NOT pg_is_in_recovery() THEN 0 ELSE GREATEST(0, EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp()))) END AS lag, (NOT pg_is_in_recovery())::int AS in_recovery"
primary: false # replica에서도 실행
target_databases: ["postgres"]
metrics:
- lag:
usage: "GAUGE"
description: "복제 지연(초)"
- in_recovery:
usage: "GAUGE"
description: "recovery 상태 여부"usage에는 컬럼의 성격에 맞는 종류를 지정한다.
| usage | 쓰임 |
|---|---|
LABEL | 이 컬럼 값을 metric의 label로 |
GAUGE | 오르내리는 순간값 |
COUNTER | 누적 증가값 |
HISTOGRAM | 분포 |
DURATION | 소요 시간 |
DISCARD | 결과에서 버림 |
operator metrics
인스턴스뿐 아니라 Operator 자신도 metrics를 노출한다. 이쪽은 8080 포트의 /metrics이며, 조정 루프 처리량이나 에러 같은 컨트롤러 지표를 담는다. 별도의 PodMonitor로 긁는다.
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: cnpg-controller-manager
namespace: cnpg-system
spec:
selector:
matchLabels:
app.kubernetes.io/name: cloudnative-pg
podMetricsEndpoints:
- port: metricsGrafana 대시보드
CloudNativePG는 곧바로 쓸 수 있는 Grafana 대시보드를 cloudnative-pg/grafana-dashboards 저장소에 공개해 둔다. grafana-dashboard.json을 내려받아 Grafana의 Dashboard > New > Import로 불러오면, 앞서 본 기본 metrics를 기반으로 한 패널이 바로 채워진다.
.spec.monitoring.tls.enabled: true를 주고, Operator metrics는 METRICS_CERT_DIR 환경 변수로 인증서 디렉토리를 지정한다. 사내망이 아니라 노출된 환경이라면 metrics도 접근 통제 대상임을 잊지 않는다.정리
- 각 인스턴스는 9187 포트
/metrics에 Prometheus 포맷 metrics를 노출한다 - PodMonitor로 scrape 대상을 선언하고, Grafana 공식 대시보드를 import해 시작한다
- 기본 metrics는
cnpg-default-monitoringConfigMap에서, 부족하면 custom query로 확장한다 - Operator 자신의 metrics는 8080 포트에서 별도 PodMonitor로 수집한다
다음 절(10.2)에서는 metrics로는 보이지 않는 사건의 흔적, 즉 로그를 다룬다.