การมีระบบ Monitoring ที่ดีไม่เพียงพอหากไม่มี On-Call Alerting ที่สามารถแจ้งเตือนทีมได้ทันเวลาเมื่อเกิดปัญหาในเวลากลางคืนหรือวันหยุด การตั้ง Alertmanager ร่วมกับ PagerDuty ช่วยให้ทีม SRE/DevOps สามารถ rotate เวร รับ alert ผ่านโทรศัพท์ และจัดการ incident ได้อย่างเป็นระบบ ลด MTTR (Mean Time To Recovery) และป้องกัน alert fatigue
Workshop นี้จะสอนการเชื่อมต่อ Prometheus Alertmanager กับ PagerDuty ตั้งแต่การสร้าง Service, กำหนด Routing rules, จัดการ Alert Grouping, Inhibition, และ Silencing เพื่อให้ทีมได้ระบบแจ้งเตือนที่เชื่อถือได้สำหรับ Production
ทำไมต้อง On-Call Alerting
ระบบแจ้งเตือนผ่าน Email หรือ Slack เพียงอย่างเดียวมีข้อจำกัดเมื่อเกิด incident นอกเวลาทำการ — ทีมอาจไม่เห็นข้อความหรือตอบสนองช้า On-Call Alerting ผ่าน PagerDuty แก้ปัญหานี้ด้วยการโทรเรียกหรือส่ง SMS ไปยังคนที่อยู่เวรตาม schedule ที่กำหนดไว้ พร้อม escalation policy ที่ส่งต่อให้คนถัดไปหากไม่มีการ acknowledge ภายในเวลาที่กำหนด
Prerequisites
- Prometheus server ที่ติดตั้งแล้ว (จาก Workshop ก่อนหน้า)
- Alertmanager version 0.26+
- บัญชี PagerDuty (มี Free tier สำหรับทดสอบ)
- ความเข้าใจ PromQL และ Alert Rules พื้นฐาน
Step 1: สร้าง PagerDuty Service และ Integration Key
เข้าสู่ PagerDuty แล้วสร้าง Service ใหม่ โดยเลือก Integration Type เป็น “Prometheus” หรือ “Events API v2” ระบบจะสร้าง Integration Key (routing key) ให้เก็บค่านี้ไว้ใช้กับ Alertmanager
- ไปที่ Services > Service Directory > + New Service
- ตั้งชื่อ Service เช่น “Production API”
- กำหนด Escalation Policy (ใครรับก่อน, ใครรับต่อ)
- เลือก Integration: “Events API v2”
- คัดลอก Integration Key ที่ได้
Step 2: ตั้งค่า Alertmanager Config
แก้ไขไฟล์ alertmanager.yml เพื่อเชื่อมต่อกับ PagerDuty โดยใช้ pagerduty_configs ใน receivers:
global:
resolve_timeout: 5m
route:
group_by: ['alertname', 'cluster', 'service']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: 'default-pagerduty'
routes:
- match:
severity: critical
receiver: 'critical-pagerduty'
continue: true
- match:
severity: warning
receiver: 'slack-warnings'
receivers:
- name: 'default-pagerduty'
pagerduty_configs:
- routing_key: 'YOUR_INTEGRATION_KEY_HERE'
severity: 'error'
description: '{{ .CommonAnnotations.summary }}'
- name: 'critical-pagerduty'
pagerduty_configs:
- routing_key: 'YOUR_CRITICAL_KEY_HERE'
severity: 'critical'
client: 'Alertmanager'
client_url: 'https://alerts.example.com'
details:
firing: '{{ .Alerts.Firing | len }}'
resolved: '{{ .Alerts.Resolved | len }}'
- name: 'slack-warnings'
slack_configs:
- api_url: 'https://hooks.slack.com/services/XXX/YYY/ZZZ'
channel: '#alerts-warning'
title: '{{ .CommonAnnotations.summary }}'
Step 3: กำหนด Alert Rules ใน Prometheus
เขียน alert rules ที่มี label severity เพื่อให้ Alertmanager routing ได้ถูกต้อง ตัวอย่าง alerts.yml:
groups:
- name: production-alerts
interval: 30s
rules:
- alert: HighErrorRate
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m])) by (service)
/
sum(rate(http_requests_total[5m])) by (service)
> 0.05
for: 5m
labels:
severity: critical
team: backend
annotations:
summary: "Error rate สูงเกิน 5% บน {{ $labels.service }}"
description: "Service {{ $labels.service }} มี error rate {{ $value | humanizePercentage }} ในช่วง 5 นาทีที่ผ่านมา"
runbook_url: "https://wiki.example.com/runbooks/high-error-rate"
- alert: PodCrashLooping
expr: rate(kube_pod_container_status_restarts_total[15m]) > 0
for: 10m
labels:
severity: critical
team: platform
annotations:
summary: "Pod {{ $labels.namespace }}/{{ $labels.pod }} กำลัง crash loop"
- alert: DiskSpaceLow
expr: |
(node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100 < 15
for: 15m
labels:
severity: warning
team: infra
annotations:
summary: "Disk space เหลือน้อยกว่า 15% บน {{ $labels.instance }}"
Step 4: ทดสอบ End-to-End
ทดสอบว่า alert ส่งไปยัง PagerDuty จริงโดย trigger alert ด้วยมือผ่าน amtool หรือ curl ตรงไปที่ Alertmanager API:
curl -XPOST http://alertmanager:9093/api/v2/alerts -H "Content-Type: application/json" -d '[
{
"labels": {
"alertname": "TestCriticalAlert",
"severity": "critical",
"service": "test-service"
},
"annotations": {
"summary": "ทดสอบการแจ้งเตือน PagerDuty"
},
"generatorURL": "http://prometheus:9090"
}
]'
ภายใน 30 วินาที ควรได้รับการโทรหรือ notification จาก PagerDuty ไปยังคนที่อยู่เวรตาม Escalation Policy
Step 5: Alert Grouping และ Inhibition
เมื่อ incident ใหญ่เกิดขึ้น (เช่น เครือข่ายล่ม) อาจมี alert นับสิบเข้ามาพร้อมกัน Alertmanager มี feature สำคัญ 2 อย่างที่ช่วยลด noise:
- Grouping: รวม alert ที่มี label เดียวกันเข้าเป็น notification เดียว ใช้ group_by, group_wait, group_interval
- Inhibition: ระงับ alert ระดับรองเมื่อมี alert ระดับสูงเกิดขึ้นแล้ว เช่น ถ้า cluster ทั้งหมดล่ม ไม่ต้อง alert รายบริการ
inhibit_rules:
- source_matchers:
- severity = "critical"
- alertname = "ClusterDown"
target_matchers:
- severity = "warning"
equal: ['cluster']
Step 6: Silencing ระหว่าง Maintenance
ก่อนทำ maintenance หรือ deployment ที่รู้ล่วงหน้าว่าจะมี alert เกิดขึ้น ควรสร้าง Silence ไว้ก่อนเพื่อไม่ให้รบกวนคนอยู่เวร ใช้ amtool หรือ Alertmanager UI:
amtool silence add alertname="HighErrorRate" service="payment-api" \
--author="[email protected]" \
--comment="Scheduled maintenance window" \
--duration=2h
Best Practices สำหรับ On-Call
- Runbook Link: ทุก alert ต้องมี runbook_url ระบุวิธีแก้ไขเบื้องต้น
- Alert ต้อง actionable: หาก alert ไม่สามารถลงมือแก้ไขได้ทันที ควรลดระดับเป็น warning หรือ ticket แทน
- Severity แยกชัดเจน: critical = โทรเรียกตีสอง, warning = รอเช้าค่อยดู
- Rotate ไม่เกิน 1 สัปดาห์ต่อคน: ป้องกัน burnout
- Post-Incident Review: หลัง incident ต้อง review ว่า alert รายนี้เป็น false positive, missing coverage, หรือ actionable
Alert Fatigue: ศัตรูตัวร้ายของ On-Call
หากทีมได้รับ alert มากเกินไปจะเริ่มมองข้าม alert ที่สำคัญจริง ๆ วิธีลด alert fatigue ที่ได้ผล: ตั้งค่า for: ให้นานพอ (5-15 นาที) ไม่ให้ flaky metrics trigger alert, ใช้ SLO-based alerting แทน threshold-based, และทำ weekly review ของ alert ที่ส่งไปยัง PagerDuty เพื่อลบหรือปรับเกณฑ์ของ alert ที่ไม่มีประโยชน์
สรุป
การต่อ Alertmanager เข้ากับ PagerDuty เป็นขั้นตอนสำคัญที่ทำให้ระบบ Monitoring กลายเป็น Alerting Pipeline ที่ใช้งานจริงใน Production ได้ การออกแบบ routing, grouping, inhibition, และ escalation ที่ดีจะช่วยให้ทีมตอบสนองต่อ incident ได้เร็ว ลด MTTR และป้องกันไม่ให้เกิด alert fatigue
สิ่งสำคัญที่ต้องจำคือ alert ทุกตัวควรเป็น actionable มี runbook รองรับ และทีมต้องมี culture ของการ review alert อย่างสม่ำเสมอ ไม่ใช่ตั้งไว้แล้วลืม

