4.3 Rule과 Cardinality
Recording rule은 자주 쓰거나 계산 비용이 큰 PromQL 결과를 새 time series로 저장합니다. Alerting rule은 query 조건이 일정 시간 지속되면 alert 상태를 만듭니다. 두 rule 모두 편리하지만 잘못 집계하면 틀린 숫자를 빠르게 반복하게 됩니다.
Recording rule
TPS를 instance 단위로 미리 계산합니다.
groups:
- name: postgres-recording
interval: 30s
rules:
- record: instance:pg_transactions_per_second:rate5m
expr: |
sum by (instance, cluster, environment) (
rate(pg_stat_database_xact_commit{datname!~"template.*"}[5m])
+ rate(pg_stat_database_xact_rollback{datname!~"template.*"}[5m])
)
이름은 level:metric:operations 형태로 읽을 수 있게 만듭니다. instance는 aggregation 수준이고 rate5m은 적용한 연산을 나타냅니다.
Alerting rule
- alert: PostgreSQLExporterCannotReachDatabase
expr: up{job="postgres"} == 1 and pg_up == 0
for: 2m
labels:
severity: ticket
annotations:
summary: "Exporter is reachable but PostgreSQL collection fails"
description: "instance={{ $labels.instance }}, cluster={{ $labels.cluster }}"
runbook_url: "https://dbalog.dev/observability/reliability-operations/incident-runbook"
for는 짧은 network blip이나 rolling restart가 바로 firing되는 것을 막습니다. 사용자 영향이 큰 증상은 더 빠르게, 예방성 경보는 더 길게 기다리도록 구분합니다.
Syntax 검증
promtool check rules prometheus/postgres.rules.yml
Rule의 실제 결과는 unit test로 고정할 수 있습니다.
rule_files:
- postgres.rules.yml
evaluation_interval: 1m
tests:
- interval: 1m
input_series:
- series: 'up{job="postgres",instance="db-a",cluster="lab"}'
values: '1+0x5'
- series: 'pg_up{job="postgres",instance="db-a",cluster="lab"}'
values: '0+0x5'
alert_rule_test:
- eval_time: 3m
alertname: PostgreSQLExporterCannotReachDatabase
exp_alerts:
- exp_labels:
cluster: lab
instance: db-a
job: postgres
severity: ticket
exp_annotations:
summary: "Exporter is reachable but PostgreSQL collection fails"
description: "instance=db-a, cluster=lab"
runbook_url: "https://dbalog.dev/observability/reliability-operations/incident-runbook"
promtool test rules postgres.rules.test.yml
Cardinality budget
새 collector를 켜기 전후에 sample 수를 비교합니다.
scrape_samples_post_metric_relabeling{job="postgres"}
Prometheus 전체에서 metric별 series 수를 확인합니다.
topk(20, count by (__name__) ({__name__!=""}))
다음 변화는 review 대상으로 둡니다.
- 한 exporter의 sample 수가 배포 후 급증
queryid,table,userlabel 값 종류가 지속 증가- recording rule이 원본보다 더 많은 series를 생성
- dashboard query가 수천 series를 반환
- rule evaluation 시간이 interval에 가까워짐
Pre-aggregation 경계
Recording rule에서 datname을 제거하면 dashboard는 가벼워지지만 database별 원인을 볼 수 없습니다. Overview용 instance aggregation과 drill-down용 database aggregation을 별도로 둡니다.
- record: instance:pg_transactions_per_second:rate5m
expr: sum by (instance) (...)
- record: instance_datname:pg_transactions_per_second:rate5m
expr: sum by (instance, datname) (...)
사용하지 않는 모든 차원을 보존하는 것은 안전해 보이지만 비용을 그대로 유지합니다. 실제 조사 경로에 필요한 resolution만 남깁니다.
참고: Prometheus Recording rules, Defining recording and alerting rules