Kodeloka
  1. Kodeloka
  2. Kelas Prometheus
  3. Materi

Modul 13 · Modul 13 dari 15

Alertmanager: Routing, Grouping, Inhibition & Silence

Mengubah ratusan alert mentah menjadi sedikit notifikasi yang tepat sasaran, ke orang yang tepat, pada waktu yang tepat.

Pembagian Tugas

Prometheus menentukan kapan alert aktif. Alertmanager menentukan siapa yang diberi tahu, lewat apa, dan seberapa sering. Keduanya terpisah karena tanggung jawabnya memang berbeda.

Empat Kemampuan Inti Alertmanager

FiturMasalah yang diselesaikan
Grouping50 server mati bersamaan → 1 notifikasi, bukan 50
RoutingAlert database ke tim DBA, alert frontend ke tim web
InhibitionBila seluruh klaster mati, jangan kirim juga 200 alert turunannya
SilenceBungkam alert selama maintenance terjadwal

Konfigurasi Routing

alertmanager.ymlyaml
global:
  resolve_timeout: 5m
  slack_api_url_file: /etc/alertmanager/secrets/slack_url   # jangan hardcode

# Template pesan kustom
templates:
  - /etc/alertmanager/templates/*.tmpl

route:
  # ── Pengaturan default untuk semua alert ──
  receiver: tim-platform
  group_by: [alertname, cluster, layanan]
  group_wait:      30s    # tunggu 30 detik, kumpulkan alert serupa
  group_interval:  5m     # jeda sebelum mengirim update grup yang sama
  repeat_interval: 4h     # ulangi pengingat bila masih firing

  routes:
    # ── Alert dengan label tipe:slo -> kanal SLO ──
    - matchers: ['tipe = "slo"']
      receiver: kanal-slo
      group_by: [alertname, layanan]
      continue: true       # LANJUTKAN evaluasi route berikutnya

    # ── Kritis -> PagerDuty, tanpa menunggu lama ──
    - matchers: ['severity = "critical"']
      receiver: pagerduty
      group_wait: 10s
      repeat_interval: 1h

    # ── Per tim, berdasarkan label 'tim' dari alerting rule ──
    - matchers: ['tim = "checkout"']
      receiver: slack-checkout
    - matchers: ['tim = "data"']
      receiver: slack-data

    # ── Alert dari staging: hanya jam kerja ──
    - matchers: ['lingkungan = "staging"']
      receiver: slack-staging
      active_time_intervals: [jam-kerja]

# Jendela waktu bernama
time_intervals:
  - name: jam-kerja
    time_intervals:
      - weekdays: ['monday:friday']
        times: [{ start_time: '01:00', end_time: '10:00' }]   # UTC = 08:00-17:00 WIB

# ── Inhibition: alert besar membungkam alert kecil ──
inhibit_rules:
  # Bila seluruh klaster down, jangan kirim alert per-instance
  - source_matchers: ['alertname = "ClusterDown"']
    target_matchers: ['severity =~ "warning|critical"']
    equal: [cluster]

  # Critical membungkam warning untuk alert & layanan yang sama
  - source_matchers: ['severity = "critical"']
    target_matchers: ['severity = "warning"']
    equal: [alertname, layanan, instance]

receivers:
  - name: tim-platform
    slack_configs:
      - channel: '#alert-platform'
        send_resolved: true
        title: '{{ template "slack.judul" . }}'
        text: '{{ template "slack.isi" . }}'

  - name: pagerduty
    pagerduty_configs:
      - service_key_file: /etc/alertmanager/secrets/pagerduty_key
        severity: '{{ .CommonLabels.severity }}'

  - name: slack-checkout
    slack_configs:
      - channel: '#tim-checkout'
        send_resolved: true

  - name: kanal-slo
    slack_configs:
      - channel: '#slo-alerts'
        send_resolved: true

  - name: slack-data
    slack_configs: [{ channel: '#tim-data', send_resolved: true }]

  - name: slack-staging
    slack_configs: [{ channel: '#alert-staging', send_resolved: true }]
⛔ Route pertama yang cocok akan menang — kecuali ada continue: true

Alertmanager mengevaluasi routes dari atas ke bawah dan berhenti pada yang pertama cocok. Bila route severity = "critical" Anda taruh di atas route tim = "checkout", maka alert kritis tim checkout tidak akan pernah sampai ke kanal tim mereka.

Gunakan continue: true bila sebuah alert memang harus dikirim ke lebih dari satu tujuan.

Grouping — Kenapa Sangat Penting

dampak groupingtext
Tanpa grouping:
  50 node mati -> 50 pesan Slack terpisah
  Setiap 4 jam -> 50 pesan lagi
  Tim berhenti membaca kanal itu dalam 2 hari.

Dengan group_by: [alertname, cluster]:
  50 node mati -> 1 pesan berisi daftar 50 instance
  Ada node ke-51 mati -> 1 update, bukan pesan baru
⚠️ Jangan pakai group_by: [...] berisi label unik

group_by: [alertname, instance] praktis meniadakan grouping, karena setiap instance menjadi grup sendiri. Kelompokkan berdasarkan label yang sama untuk alert-alert yang ingin Anda gabungkan: alertname, cluster, layanan, tim.

Silence — Membungkam Saat Maintenance

amtoolbash
# Pasang amtool (ikut dalam rilis Alertmanager)
amtool --alertmanager.url=http://localhost:9093 alert query

# Bungkam alert untuk satu instance selama 2 jam
amtool silence add instance="10.0.0.5:9100" \
  --duration=2h \
  --comment="Maintenance terjadwal: upgrade kernel — tiket OPS-4821" \
  --author="[email protected]"

# Bungkam seluruh alert dari job tertentu
amtool silence add job="batch-etl" --duration=6h --comment="Migrasi data"

# Lihat & hapus silence
amtool silence query
amtool silence expire <ID>
💡 Selalu isi --comment dan --duration

Silence tanpa keterangan akan menjadi misteri: tidak ada yang tahu kenapa alert produksi dibungkam sejak tiga bulan lalu, dan tidak ada yang berani menghapusnya. Selalu sertakan alasan dan nomor tiket, serta durasi terbatas — jangan pernah membuat silence permanen.

Alertmanager High Availability

habash
// Jalankan 2-3 instance yang saling mengenal lewat gossip.
// Mereka berkoordinasi agar notifikasi tidak dikirim berkali-kali.
alertmanager --cluster.peer=am-2:9094 --cluster.peer=am-3:9094

Di sisi Prometheus, daftarkan semua instance Alertmanager. Prometheus mengirim ke semuanya, dan Alertmanager sendiri yang melakukan deduplikasi.