ルーティングツリーとバーンレートのアラート
한국어 원문으로 표시합니다.
목표
Alertmanager 설정을 라우팅 트리부터 억제 규칙까지 직접 쓰고, SLO 에서 역산한 번 레이트 알림 두 개를 만들고, 런북 누락을 빌드에서 막는 게이트를 작성합니다.
왜 중요한가
알림의 성공 기준은 "문제를 감지했는가"가 아니라 "사람이 지금 무언가를 해야 하는가" 입니다. 이 기준을 통과하지 못하는 알림은 정확해도 해롭습니다. 정확한 알림 400개가 온콜의 반응 속도를 무너뜨리면 정확도는 아무 의미가 없습니다. 그래서 순서가 정해집니다. 사용자 증상으로 SLO 를 정의하고, 예산에서 임계값을 역산하고, 긴 창과 짧은 창을 AND 로 묶어 민감도와 오탐을 동시에 잡고, 그룹핑과 억제로 알림 개수를 사람이 읽을 수 있는 수준으로 줄이고, 페이지에는 런북을 강제합니다. 임계값을 "과거 최대치의 1.2배" 같은 방식으로 정하면 왜 그 값인지 설명할 수 없고, 설명할 수 없는 임계값은 사고가 날 때마다 조금씩 올라갑니다.
단계
/root/pca-alerting/alertmanager.yml을 만들고 루트route를 씁니다.receiver: ticket-queue,group_by: ['alertname', 'cluster', 'slo'],group_wait: 30s,group_interval: 5m,repeat_interval: 4h.- 루트의
routes첫 항목에 자식 라우트를 넣습니다.matchers: ['severity="page"'],receiver: oncall-pager,group_wait: 10s,repeat_interval: 1h. receivers에 두 수신자를 정의합니다.ticket-queue와oncall-pager각각에webhook_configs를 두고url은http://로 시작하는 아무 내부 주소면 됩니다.inhibit_rules첫 항목을 씁니다.source_matchers: ['alertname="ClusterDown"', 'severity="page"'],target_matchers: ['severity=~"page|ticket"'],equal: ['cluster']./root/pca-alerting/burnrate.yml을 만들고 그룹 아래 알림CheckoutErrorBudgetBurnFast를 씁니다.expr은job:slo_errors:ratio_rate1h{job="checkout-api"} > (14.4 * 0.001)과job:slo_errors:ratio_rate5m{job="checkout-api"} > (14.4 * 0.001)과job:http_requests:rate5m{job="checkout-api"} > 1세 항을and로 묶은 것,for: 2m,labels에severity: page와slo: checkout-availability,annotations에summary와runbook_url.- 같은 파일에 알림
CheckoutErrorBudgetBurnSlow를 추가합니다.expr은job:slo_errors:ratio_rate6h{job="checkout-api"} > (6 * 0.001)과job:slo_errors:ratio_rate30m{job="checkout-api"} > (6 * 0.001)을and로 묶은 것,for: 15m,labels에severity: ticket과slo: checkout-availability. /root/pca-alerting/runbook-gate.sh를 작성합니다. 첫 번째 인자로 룰 파일 경로를 받아,labels.severity가page인데annotations.runbook_url이 없는 알림이 하나라도 있으면 그 이름을 출력하고 0 이 아닌 코드로 종료하고, 하나도 없으면 0 으로 종료합니다.
참고
- 5단계와 6단계의
expr은expr: |블록으로 여러 줄에 써도 됩니다. 채점은 공백을 무시합니다. - 7단계 검증은 여러분이 만든
burnrate.yml(통과해야 함)과 채점기가 만든 런북 누락 파일(막아야 함) 두 가지로 이뤄집니다.severity: ticket인 알림까지 막으면 실패합니다. - 힌트:
yq '.groups[].rules[] | select(...) | .alert' "$1"로 목록을 뽑아 비어 있지 않으면exit 1. - 흔한 실수 1:
group_by에instance를 넣는 것. 파드 수만큼 알림이 옵니다. - 흔한 실수 2: 억제 규칙에서
equal을 빼먹는 것. 다른 클러스터의 알림까지 억제됩니다.
루트 라우트 쓰기
/root/pca-alerting/alertmanager.yml 을 만들고 루트 route 를 씁니다. receiver: ticket-queue, group_by: ['alertname', 'cluster', 'slo'], group_wait: 30s, group_interval: 5m, repeat_interval: 4h.
루트의 receiver 는 매칭되는 자식이 없을 때의 기본값입니다. group_by 에 무엇을 넣느냐가 알림 개수를 결정한다는 점을 기억하세요. 세 타이머는 각각 첫 전송 대기, 그룹 갱신 간격, 무변화 반복 간격입니다.
심각도별 자식 라우트
루트의 routes 첫 항목에 자식 라우트를 넣습니다. matchers: ['severity="page"'], receiver: oncall-pager, group_wait: 10s, repeat_interval: 1h.
routes 는 루트 아래의 리스트이고 위에서 아래로 매칭됩니다. continue 를 켜지 않으면 첫 매칭에서 멈춥니다. 자식은 부모의 설정을 상속하되 명시한 값만 덮어씁니다.
수신자 정의
receivers 에 두 수신자를 정의합니다. ticket-queue 와 oncall-pager 각각에 webhook_configs 를 두고 url 은 http:// 로 시작하는 아무 내부 주소면 됩니다.
라우트에서 이름으로 참조한 수신자가 receivers 목록에 없으면 설정이 로드되지 않습니다. 이 실습 환경에는 실제 전송 대상이 없으므로 웹훅 URL 로 형태만 갖춥니다.
억제 규칙
inhibit_rules 첫 항목을 씁니다. source_matchers: ['alertname="ClusterDown"', 'severity="page"'], target_matchers: ['severity=~"page|ticket"'], equal: ['cluster'].
억제는 원인 알림이 살아 있을 때 하위 증상 알림을 막습니다. equal 에 적은 레이블 값이 양쪽에서 같아야 성립하므로, 이 레이블을 빼먹으면 다른 클러스터의 알림까지 억제됩니다.
빠른 소진 알림
/root/pca-alerting/burnrate.yml 을 만들고 그룹 아래 알림 CheckoutErrorBudgetBurnFast 를 씁니다. expr 은 job:slo_errors:ratio_rate1h{job="checkout-api"} > (14.4 * 0.001) 과 job:slo_errors:ratio_rate5m{job="checkout-api"} > (14.4 * 0.001) 과 job:http_requests:rate5m{job="checkout-api"} > 1 세 항을 and 로 묶은 것, for: 2m, labels 에 severity: page 와 slo: checkout-availability, annotations 에 summary 와 runbook_url.
긴 창은 태우는 속도를, 짧은 창은 지금도 진행 중인지를 판정합니다. 여기에 최소 트래픽 게이트를 더해 세 항을 AND 로 묶습니다. 긴 창을 이미 쓰고 있으므로 for 는 결측 흡수용으로 짧게 겁니다.
느린 소진 알림
같은 파일에 알림 CheckoutErrorBudgetBurnSlow 를 추가합니다. expr 은 job:slo_errors:ratio_rate6h{job="checkout-api"} > (6 * 0.001) 과 job:slo_errors:ratio_rate30m{job="checkout-api"} > (6 * 0.001) 을 and 로 묶은 것, for: 15m, labels 에 severity: ticket 과 slo: checkout-availability.
예산이 새고는 있지만 속도가 느린 경우는 사람을 깨울 일이 아니라 티켓입니다. 짧은 창은 긴 창의 12분의 1로 잡는 관례를 따르고, severity 는 페이지가 아니어야 합니다.
런북 CI 게이트 스크립트
/root/pca-alerting/runbook-gate.sh 를 작성합니다. 첫 번째 인자로 룰 파일 경로를 받아, labels.severity 가 page 인데 annotations.runbook_url 이 없는 알림이 하나라도 있으면 그 이름을 출력하고 0 이 아닌 코드로 종료하고, 하나도 없으면 0 으로 종료합니다.
스크립트는 첫 번째 인자로 룰 파일 경로를 받습니다. yq 로 severity 가 page 인 규칙 중 runbook_url 어노테이션이 없는 것을 뽑아, 하나라도 있으면 이름을 출력하고 실패로 끝내면 됩니다. 티켓 등급까지 막으면 안 됩니다.