전체 비유: 환자 모니터 경보 시스템#
Alerting Rules를 중환자실 환자 모니터 경보 시스템에 비유하면 이해하기 쉽습니다:
| 환자 모니터 비유 | Alerting Rules | 역할 |
|---|---|---|
| 맥박 비정상 조건 | expr (조건) | 알림 발동 조건 정의 |
| 5분간 지속 시 알림 | for (지속 시간) | 일시적 변동 무시 |
| 긴급/주의 분류 | severity 라벨 | 심각도 구분 |
| 담당 의료진 호출 | 알림 라우팅 | 적절한 담당자에게 전달 |
| 알림 상세 정보 | annotations | 문제 설명, 조치 가이드 |
| 경보 피로 방지 | 적절한 임계값 | 의미 있는 알림만 |
| 연쇄 경보 억제 | inhibition | 중복 알림 방지 |
| 대응 매뉴얼 링크 | runbook_url | 문제 해결 가이드 |
이처럼 환자 모니터가 이상 징후를 감지하여 의료진에게 알리듯, Alerting Rules로 시스템 문제를 감지합니다.
대상 독자: 모니터링 알림을 설정하려는 개발자, SRE 선수 지식: Recording Rules 소요 시간: 약 25-30분 이 문서를 읽으면: 오탐을 줄이고 실제 문제만 알림받는 규칙을 작성할 수 있습니다
TL;DR
for: 지정 시간 동안 조건 만족 시 발동 (오탐 방지)labels: 심각도, 팀 등 메타데이터 추가annotations: 알림 메시지, 런북 URL 포함- Recording Rules 결과를 활용하여 간결하게 작성
왜 Alerting Rules가 필요한가?#
대시보드를 24시간 쳐다보고 있을 수는 없습니다. 새벽 3시에 에러율이 치솟아도 아무도 대시보드를 보지 않으면 장애는 방치됩니다. Alerting Rules는 “조건이 일정 시간 지속되면 자동으로 알린다"는 규칙을 선언적으로 정의하여, 사람이 모니터링하지 않는 시간에도 시스템이 스스로 문제를 감지하고 담당자에게 알릴 수 있게 합니다.
기본 문법#
Alerting Rule 구조#
groups:
- name: <그룹명>
rules:
- alert: <알림명>
expr: <PromQL 조건>
for: <지속 시간>
labels:
<라벨명>: <값>
annotations:
<어노테이션명>: <값>기본 예제#
groups:
- name: availability
rules:
- alert: ServiceDown
expr: up == 0
for: 5m
labels:
severity: critical
annotations:
summary: "{{ $labels.instance }} is down"
description: "{{ $labels.job }} has been down for more than 5 minutes."
runbook_url: "https://wiki.example.com/runbook/service-down"핵심 구성요소#
expr (조건)#
알림이 발동하는 조건입니다.
# 타겟 다운
expr: up == 0
# 에러율 5% 초과
expr: |
sum by (service) (rate(http_requests_total{status=~"5.."}[5m]))
/ sum by (service) (rate(http_requests_total[5m]))
> 0.05
# P99 응답시간 500ms 초과
expr: |
histogram_quantile(0.99,
sum by (service, le) (rate(http_request_duration_seconds_bucket[5m]))
) > 0.5
# Recording Rule 결과 사용 (권장)
expr: service:http_requests_errors:ratio_rate5m > 0.05for (지속 시간)#
조건이 지속되어야 알림이 발동합니다. 일시적 스파이크로 인한 오탐을 방지합니다.
# 5분간 지속되어야 발동
for: 5m
# 즉시 발동 (for 없음)
# 주의: 오탐 위험graph LR
subgraph "for: 5m"
P["Pending<br>(조건 만족)"]
F["Firing<br>(5분 경과)"]
end
P --> |"5분 지속"| F
P --> |"조건 해제"| R["해제<br>(알림 취소)"]for 설정에 따라 조건 만족 시 Pending 상태에서 5분 지속되면 Firing으로, 중간에 해제되면 취소되는 흐름입니다.
권장 값:
| 상황 | for 값 | 이유 |
|---|---|---|
| 서비스 다운 | 1-5m | 빠른 감지 필요 |
| 에러율 증가 | 5-10m | 일시적 스파이크 필터링 |
| 리소스 부족 | 10-15m | 자동 복구 대기 |
| 디스크 부족 | 30m-1h | 천천히 증가 |
labels (라벨)#
알림에 메타데이터를 추가합니다.
labels:
severity: critical # 심각도
team: platform # 담당 팀
service: "{{ $labels.service }}" # 동적 라벨심각도 레벨:
| 레벨 | 설명 | 대응 |
|---|---|---|
critical | 서비스 중단 | 즉시 대응 (호출) |
warning | 성능 저하 | 업무 시간 내 대응 |
info | 참고 사항 | 기록만 |
annotations (어노테이션)#
알림 내용을 상세히 설명합니다.
annotations:
summary: "High error rate on {{ $labels.service }}"
description: |
Error rate is {{ $value | humanizePercentage }}.
Current threshold: 5%
runbook_url: "https://wiki.example.com/runbook/high-error-rate"
dashboard_url: "https://grafana.example.com/d/abc/errors?var-service={{ $labels.service }}"템플릿 변수:
| 변수 | 설명 |
|---|---|
{{ $labels }} | 알림의 모든 라벨 |
{{ $labels.name }} | 특정 라벨 값 |
{{ $value }} | 표현식 결과 값 |
| `{{ $value | humanize }}` |
| `{{ $value | humanizePercentage }}` |
| `{{ $value | humanizeDuration }}` |
실전 알림 규칙#
가용성 알림#
groups:
- name: availability
rules:
# 타겟 다운
- alert: TargetDown
expr: up == 0
for: 5m
labels:
severity: critical
annotations:
summary: "Target {{ $labels.instance }} is down"
description: "{{ $labels.job }} target {{ $labels.instance }} has been down for more than 5 minutes."
# 서비스 가용성 저하
- alert: ServiceAvailabilityLow
expr: |
sum by (service) (rate(http_requests_total{status!~"5.."}[5m]))
/ sum by (service) (rate(http_requests_total[5m]))
< 0.99
for: 5m
labels:
severity: warning
annotations:
summary: "{{ $labels.service }} availability below 99%"
description: "Current availability: {{ $value | humanizePercentage }}"에러율 알림#
groups:
- name: errors
rules:
# 높은 에러율
- alert: HighErrorRate
expr: |
sum by (service) (rate(http_requests_total{status=~"5.."}[5m]))
/ sum by (service) (rate(http_requests_total[5m]))
> 0.05
for: 5m
labels:
severity: warning
annotations:
summary: "High error rate on {{ $labels.service }}"
description: "Error rate is {{ $value | humanizePercentage }}"
# 심각한 에러율
- alert: CriticalErrorRate
expr: |
sum by (service) (rate(http_requests_total{status=~"5.."}[5m]))
/ sum by (service) (rate(http_requests_total[5m]))
> 0.10
for: 2m
labels:
severity: critical
annotations:
summary: "Critical error rate on {{ $labels.service }}"
description: "Error rate is {{ $value | humanizePercentage }}. Immediate action required."지연시간 알림#
groups:
- name: latency
rules:
# P99 지연시간 높음
- alert: HighP99Latency
expr: |
histogram_quantile(0.99,
sum by (service, le) (rate(http_request_duration_seconds_bucket[5m]))
) > 0.5
for: 5m
labels:
severity: warning
annotations:
summary: "High P99 latency on {{ $labels.service }}"
description: "P99 latency is {{ $value | humanizeDuration }}"
# Recording Rule 사용
- alert: HighP99LatencyFromRule
expr: service:http_request_duration_seconds:p99 > 0.5
for: 5m
labels:
severity: warning
annotations:
summary: "High P99 latency on {{ $labels.service }}"리소스 알림#
groups:
- name: resources
rules:
# CPU 높음
- alert: HighCPUUsage
expr: |
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 10m
labels:
severity: warning
annotations:
summary: "High CPU usage on {{ $labels.instance }}"
description: "CPU usage is {{ $value | humanize }}%"
# 메모리 부족
- alert: LowMemory
expr: |
(node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) < 0.1
for: 5m
labels:
severity: warning
annotations:
summary: "Low memory on {{ $labels.instance }}"
description: "Available memory is {{ $value | humanizePercentage }}"
# 디스크 부족
- alert: DiskSpaceLow
expr: |
(node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) < 0.1
for: 30m
labels:
severity: warning
annotations:
summary: "Low disk space on {{ $labels.instance }}"
description: "Available disk space is {{ $value | humanizePercentage }}"Kafka 알림#
groups:
- name: kafka
rules:
# Consumer Lag 높음
- alert: KafkaConsumerLagHigh
expr: |
sum by (consumer_group, topic) (kafka_consumer_group_lag) > 10000
for: 10m
labels:
severity: warning
annotations:
summary: "High consumer lag for {{ $labels.consumer_group }}"
description: "Lag is {{ $value | humanize }} messages on topic {{ $labels.topic }}"
# Under-replicated 파티션
- alert: KafkaUnderReplicatedPartitions
expr: kafka_server_replicamanager_underreplicatedpartitions > 0
for: 5m
labels:
severity: critical
annotations:
summary: "Kafka under-replicated partitions detected"알림 피로 방지#
1. 적절한 임계값#
# ❌ 너무 민감
expr: error_rate > 0.001 # 0.1%
# ✅ 의미 있는 임계값
expr: error_rate > 0.01 # 1%2. 충분한 for 시간#
# ❌ 일시적 스파이크에도 발동
for: 30s
# ✅ 지속적인 문제만 감지
for: 5m3. 계층적 알림#
# Warning: 5% 에러, 5분 지속
- alert: HighErrorRate
expr: error_rate > 0.05
for: 5m
labels:
severity: warning
# Critical: 10% 에러, 2분 지속 (더 빠르게)
- alert: CriticalErrorRate
expr: error_rate > 0.10
for: 2m
labels:
severity: critical4. Alertmanager에서 그룹화#
# alertmanager.yml
route:
group_by: ['alertname', 'service']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h규칙 검증#
문법 검사#
promtool check rules alerts/*.yml단위 테스트#
# tests/alert_tests.yml
rule_files:
- ../alerts/errors.yml
evaluation_interval: 1m
tests:
- interval: 1m
input_series:
- series: 'http_requests_total{service="api", status="500"}'
values: '0+10x10'
- series: 'http_requests_total{service="api", status="200"}'
values: '0+100x10'
alert_rule_test:
- eval_time: 10m
alertname: HighErrorRate
exp_alerts:
- exp_labels:
service: api
severity: warning
exp_annotations:
summary: "High error rate on api"promtool test rules tests/alert_tests.yml알림 상태#
stateDiagram-v2
[*] --> Inactive: 조건 불만족
Inactive --> Pending: 조건 만족
Pending --> Inactive: 조건 해제
Pending --> Firing: for 시간 경과
Firing --> Inactive: 조건 해제 (Resolved)알림의 Inactive → Pending → Firing 상태 전환과 각 상태 간 조건을 보여주는 상태 다이어그램입니다.
| 상태 | 설명 |
|---|---|
| Inactive | 조건 불만족 |
| Pending | 조건 만족, for 대기 중 |
| Firing | 알림 발동됨 |
핵심 정리#
| 구성요소 | 역할 | 예시 |
|---|---|---|
expr | 발동 조건 | error_rate > 0.05 |
for | 오탐 방지 | 5m |
labels | 메타데이터 | severity: critical |
annotations | 알림 내용 | summary, runbook_url |
좋은 알림의 조건:
- 즉각적인 조치가 필요한 상황만
- 명확한 심각도 분류
- 상세한 컨텍스트 (runbook, dashboard)
- 적절한 for 시간으로 오탐 방지
다음 단계#
| 추천 순서 | 문서 | 배우는 것 |
|---|---|---|
| 1 | SRE 황금 신호 | 알림 대상 지표 선정 |
| 2 | 알림 후 액션 가이드 | 알림 수신 후 대응 |