LabHub
배우기 러닝패스 코스

PCA — Prometheus Certified Associate

The Routing Tree and Burn-Rate Alerts

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

Alertmanager 설정을 라우팅 트리부터 억제 규칙까지 직접 쓰고, SLO 에서 역산한 번 레이트 알림 두 개를 만들고, 런북 누락을 빌드에서 막는 게이트를 작성합니다.

왜 중요한가

알림의 성공 기준은 "문제를 감지했는가"가 아니라 "사람이 지금 무언가를 해야 하는가" 입니다. 이 기준을 통과하지 못하는 알림은 정확해도 해롭습니다. 정확한 알림 400개가 온콜의 반응 속도를 무너뜨리면 정확도는 아무 의미가 없습니다. 그래서 순서가 정해집니다. 사용자 증상으로 SLO 를 정의하고, 예산에서 임계값을 역산하고, 긴 창과 짧은 창을 AND 로 묶어 민감도와 오탐을 동시에 잡고, 그룹핑과 억제로 알림 개수를 사람이 읽을 수 있는 수준으로 줄이고, 페이지에는 런북을 강제합니다. 임계값을 "과거 최대치의 1.2배" 같은 방식으로 정하면 왜 그 값인지 설명할 수 없고, 설명할 수 없는 임계값은 사고가 날 때마다 조금씩 올라갑니다.

단계

  1. /root/pca-alerting/alertmanager.yml 을 만들고 루트 route 를 씁니다. receiver: ticket-queue, group_by: ['alertname', 'cluster', 'slo'], group_wait: 30s, group_interval: 5m, repeat_interval: 4h.
  2. 루트의 routes 첫 항목에 자식 라우트를 넣습니다. matchers: ['severity="page"'], receiver: oncall-pager, group_wait: 10s, repeat_interval: 1h.
  3. receivers 에 두 수신자를 정의합니다. ticket-queueoncall-pager 각각에 webhook_configs 를 두고 urlhttp:// 로 시작하는 아무 내부 주소면 됩니다.
  4. inhibit_rules 첫 항목을 씁니다. source_matchers: ['alertname="ClusterDown"', 'severity="page"'], target_matchers: ['severity=~"page|ticket"'], equal: ['cluster'].
  5. /root/pca-alerting/burnrate.yml 을 만들고 그룹 아래 알림 CheckoutErrorBudgetBurnFast 를 씁니다. exprjob: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, labelsseverity: pageslo: checkout-availability, annotationssummaryrunbook_url.
  6. 같은 파일에 알림 CheckoutErrorBudgetBurnSlow 를 추가합니다. exprjob:slo_errors:ratio_rate6h{job="checkout-api"} > (6 * 0.001)job:slo_errors:ratio_rate30m{job="checkout-api"} > (6 * 0.001)and 로 묶은 것, for: 15m, labelsseverity: ticketslo: checkout-availability.
  7. /root/pca-alerting/runbook-gate.sh 를 작성합니다. 첫 번째 인자로 룰 파일 경로를 받아, labels.severitypage 인데 annotations.runbook_url 이 없는 알림이 하나라도 있으면 그 이름을 출력하고 0 이 아닌 코드로 종료하고, 하나도 없으면 0 으로 종료합니다.

참고

루트 라우트 쓰기

/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-queueoncall-pager 각각에 webhook_configs 를 두고 urlhttp:// 로 시작하는 아무 내부 주소면 됩니다.

라우트에서 이름으로 참조한 수신자가 receivers 목록에 없으면 설정이 로드되지 않습니다. 이 실습 환경에는 실제 전송 대상이 없으므로 웹훅 URL 로 형태만 갖춥니다.

억제 규칙

inhibit_rules 첫 항목을 씁니다. source_matchers: ['alertname="ClusterDown"', 'severity="page"'], target_matchers: ['severity=~"page|ticket"'], equal: ['cluster'].

억제는 원인 알림이 살아 있을 때 하위 증상 알림을 막습니다. equal 에 적은 레이블 값이 양쪽에서 같아야 성립하므로, 이 레이블을 빼먹으면 다른 클러스터의 알림까지 억제됩니다.

빠른 소진 알림

/root/pca-alerting/burnrate.yml 을 만들고 그룹 아래 알림 CheckoutErrorBudgetBurnFast 를 씁니다. exprjob: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, labelsseverity: pageslo: checkout-availability, annotationssummaryrunbook_url.

긴 창은 태우는 속도를, 짧은 창은 지금도 진행 중인지를 판정합니다. 여기에 최소 트래픽 게이트를 더해 세 항을 AND 로 묶습니다. 긴 창을 이미 쓰고 있으므로 for 는 결측 흡수용으로 짧게 겁니다.

느린 소진 알림

같은 파일에 알림 CheckoutErrorBudgetBurnSlow 를 추가합니다. exprjob:slo_errors:ratio_rate6h{job="checkout-api"} > (6 * 0.001)job:slo_errors:ratio_rate30m{job="checkout-api"} > (6 * 0.001)and 로 묶은 것, for: 15m, labelsseverity: ticketslo: checkout-availability.

예산이 새고는 있지만 속도가 느린 경우는 사람을 깨울 일이 아니라 티켓입니다. 짧은 창은 긴 창의 12분의 1로 잡는 관례를 따르고, severity 는 페이지가 아니어야 합니다.

런북 CI 게이트 스크립트

/root/pca-alerting/runbook-gate.sh 를 작성합니다. 첫 번째 인자로 룰 파일 경로를 받아, labels.severitypage 인데 annotations.runbook_url 이 없는 알림이 하나라도 있으면 그 이름을 출력하고 0 이 아닌 코드로 종료하고, 하나도 없으면 0 으로 종료합니다.

스크립트는 첫 번째 인자로 룰 파일 경로를 받습니다. yq 로 severity 가 page 인 규칙 중 runbook_url 어노테이션이 없는 것을 뽑아, 하나라도 있으면 이름을 출력하고 실패로 끝내면 됩니다. 티켓 등급까지 막으면 안 됩니다.