Alerting #
Memiliki metrik yang melimpah dan dasbor visual yang indah di Grafana tidak akan menyelamatkan aplikasi produksi Anda jika tidak ada sistem alarm (alerting) yang andal. Sistem alerting bertindak sebagai mekanisme alarm proaktif yang membangunkan engineer on-call saat terjadi degradasi layanan yang nyata. Namun, merancang sistem alerting di Kubernetes sangatlah menantang. Kluster yang sangat dinamis dapat menghasilkan ribuan alarm bising jika tidak dikonfigurasi dengan benar, memicu fenomena Alert Fatigue — kondisi di mana tim operasional terbiasa mengabaikan notifikasi karena 95% alarm yang masuk berupa pesan palsu (false positive). Artikel ini mengupas filosofi, teknik implementasi, dan pengerasan sistem alerting menggunakan PrometheusRule dan Alertmanager tingkat produksi.
Alur Hidup Peringatan (Alert Lifecycle) #
Aliran data peringatan di Kubernetes dipisahkan secara modular antara mesin pendeteksi (Prometheus) dengan mesin pengelola notifikasi (Alertmanager) untuk memastikan keandalan pengiriman pesan.
flowchart TD
Prometheus["Prometheus Server (TSDB)"] -->|"1. Triggers Alert (Firing)"| Alertmanager["Alertmanager Engine"]
subgraph DeduplicateGroup["Penyaringan & Pengelompokan"]
direction TB
FilterInhibit{"2. Apakah Terkena Rule Inhibition?"}
FilterInhibit -- "Ya" --> SuppressAlert["Redam Alert (Jangan Kirim)"]
FilterInhibit -- "Tidak" --> FilterSilence{"3. Apakah Terkena Active Silence?"}
FilterSilence -- "Ya" --> DropAlert["Abaikan Alert (Muted)"]
FilterSilence -- "Tidak" --> Grouping["4. Kelompokkan (Group by alertname / namespace)"]
end
Alertmanager --> FilterInhibit
Grouping -->|"5. Kirim Batch setelah group_wait"| RouteTree{"6. Evaluasi Routing Tree"}
subgraph Receivers["Tujuan Penerimaan Alert"]
direction LR
Slack["Slack Channel (#alerts-warning)"]
PagerDuty["PagerDuty (SMS / Telepon On-Call)"]
end
RouteTree -- "severity = critical" --> PagerDuty
RouteTree -- "severity = warning" --> Slack
Penjelasan Tahapan Alur Kerja: #
- Prometheus Server: Mengevaluasi ekspresi kueri PromQL yang didefinisikan dalam
PrometheusRule. Jika kondisi bernilai benar selama rentang waktu tertentu (parameterfor), Prometheus mengubah status alert menjadiPENDING, kemudianFIRING, lalu mengirimkan payload alert ke Alertmanager. - Inhibition: Menekan alarm tingkat rendah jika alarm tingkat tinggi yang berhubungan sedang aktif.
- Silencing: Mengabaikan alarm sementara waktu (misalnya saat jadwal pemeliharaan server / maintenance window).
- Grouping: Mengelompokkan beberapa alarm sejenis yang terjadi bersamaan agar tidak membombardir saluran notifikasi.
- Routing Tree: Mengarahkan alarm berdasarkan label (misalnya
severity: criticaldikirim ke PagerDuty, sedangkanseverity: warningdikirim ke Slack).
Kebijakan Perekaman Alert: PrometheusRule CRD #
Untuk membuat aturan alarm di Kubernetes yang dikelola oleh Prometheus Operator, kita menggunakan Custom Resource PrometheusRule.
Berikut adalah perbandingan antara konfigurasi alert yang buruk (kebisingan tinggi) dengan kueri pendeteksi yang diperkeras (actionable alerting rules).
# ANTI-PATTERN: Aturan alarm yang memicu alert fatigue.
# Menggunakan ambang batas statis untuk CPU (CPU spike adalah hal biasa)
# dan tidak menetapkan delay 'for', memicu alert setiap kali ada beban kerja singkat.
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: noisy-alerts
spec:
groups:
- name: noisy.rules
rules:
- alert: PodCPUHigh
expr: container_cpu_usage_seconds_total > 0.8 # JANGAN: CPU tinggi bukan berarti aplikasi rusak
for: 0m # JANGAN: Spike 1 detik akan memicu alarm
labels:
severity: critical # JANGAN: Alarm non-actionable masuk kategori critical
# ==============================================================================
# BENAR: Konfigurasi Peringatan Tingkat Produksi yang Actionable dan Terstruktur.
# File: prometheus-rule.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: api-service-alerts
namespace: monitoring
labels:
release: prometheus-stack
spec:
groups:
- name: api.critical.rules
rules:
# 1. Alert: Latensi Tinggi (Symptom-based)
- alert: HighHttpLatencyP99
expr: |
histogram_quantile(0.99,
sum by (le, job) (
rate(http_request_duration_seconds_bucket{namespace="production"}[5m])
)
) > 2.0 # P99 Latency di atas 2 detik
for: 5m # Harus konsisten di atas 2 detik selama 5 menit
labels:
severity: critical
team: platform-team
annotations:
summary: "Latensi HTTP P99 sangat tinggi pada {{ $labels.job }}"
description: "Latensi p99 saat ini adalah {{ $value | humanizeDuration }} (batas threshold: 2 detik). Harap investigasi dependency down."
runbook_url: "https://wiki.company.com/runbooks/latency-triage"
# 2. Alert: Pod Mengalami CrashLoopBackOff (Infrastructure-based)
- alert: PodCrashLooping
expr: |
increase(kube_pod_container_status_restarts_total{namespace="production"}[15m]) > 3
for: 2m
labels:
severity: warning
team: devops-team
annotations:
summary: "Pod {{ $labels.pod }} mengalami restart berulang"
description: "Kontainer {{ $labels.container }} di Pod {{ $labels.pod }} telah melakukan restart {{ $value }} kali dalam 15 menit terakhir."
runbook_url: "https://wiki.company.com/runbooks/crashloop-triage"
Mengapa Contoh di Atas “Actionable”? #
runbook_url: Setiap alert menyertakan tautan menuju dokumen panduan penyelidikan (runbook). Ini memastikan bahwa siapa saja yang bertugas malam itu langsung tahu langkah awal penyelidikan.- Symptom-Based: Menggunakan latensi dan kegagalan fungsi aplikasi yang dirasakan pengguna, alih-alih metrik sistem mentah seperti CPU/RAM.
Konfigurasi Manajemen Perutean Alertmanager #
Alertmanager mengelola perutean (routing), pengelompokan (grouping), dan tujuan penerima notifikasi (receivers) menggunakan file konfigurasi pusat.
# File: alertmanager-secret.yaml (Bentuk rahasia Kubernetes Config)
global:
resolve_timeout: 5m
slack_api_url: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX'
# Definisi Pohon Perutean (Routing Tree)
route:
receiver: 'slack-default-channel'
group_by: ['alertname', 'namespace', 'job']
group_wait: 30s # Tunggu 30 detik untuk mengumpulkan alert sejenis sebelum mengirim batch pertama
group_interval: 5m # Beri jeda 5 menit sebelum mengirim notifikasi baru untuk grup yang sama
repeat_interval: 12h # Kirim ulang peringatan yang sama setiap 12 jam jika belum di-resolve
routes:
# Rute A: Semua alert ber-severity critical langsung diarahkan ke PagerDuty
- match:
severity: critical
receiver: 'pagerduty-oncall'
repeat_interval: 30m # Kirim ulang ke PagerDuty setiap 30 menit jika tidak di-acknowledge
# Rute B: Semua alert ber-severity warning dialihkan ke channel Slack sekunder
- match:
severity: warning
receiver: 'slack-warnings'
# Konfigurasi Penerima Notifikasi (Receivers)
receivers:
- name: 'slack-default-channel'
slack_configs:
- channel: '#prod-critical-alerts'
send_resolved: true # Kirim notifikasi konfirmasi jika masalah telah selesai
title: '[{{ .Status | upper }}] {{ .CommonAnnotations.summary }}'
text: >-
*Detail Masalah:* {{ .CommonAnnotations.description }}
*Namespace:* {{ .CommonLabels.namespace }}
*Runbook:* {{ .CommonAnnotations.runbook_url }}
- name: 'pagerduty-oncall'
pagerduty_configs:
- routing_key: 'pd-integration-routing-key-here'
client: 'Kubernetes Alertmanager'
send_resolved: true
- name: 'slack-warnings'
slack_configs:
- channel: '#prod-warning-alerts'
send_resolved: true
title: '[WARNING] {{ .CommonAnnotations.summary }}'
Silencing dan Inhibition: Mengurangi Kebisingan Peringatan #
Pipa peringatan yang cerdas harus mampu meredam alarm yang tidak perlu selama operasi pemeliharaan terencana atau saat infrastruktur utama mengalami masalah besar.
1. Silencing Menggunakan amtool #
amtool adalah perkakas baris perintah resmi untuk berinteraksi dengan API Alertmanager. Kita dapat menggunakannya untuk menonaktifkan alarm sementara waktu selama jadwal pemeliharaan agar tidak mengganggu engineer on-call.
# Buat aturan silence selama 4 jam untuk alert HighHttpLatencyP99 di namespace production
amtool silence add \
--alertmanager.url=http://alertmanager.monitoring.svc:9093 \
alertname="HighHttpLatencyP99" \
namespace="production" \
--duration=4h \
--comment="Schedule Maintenance: Database Migration" \
--author="Platform Team"
# Hasil keluaran (contoh):
# Active silence created with ID: 412b70f1-da02-47a2-9b2f-31a89c9e88ef
# Lihat daftar silence yang sedang aktif
amtool silence query --alertmanager.url=http://alertmanager.monitoring.svc:9093
# Batalkan aturan silence sebelum durasi berakhir
amtool silence expire 412b70f1-da02-47a2-9b2f-31a89c9e88ef --alertmanager.url=http://alertmanager.monitoring.svc:9093
2. Aturan Inhibisi (Inhibition Rules) #
Aturan inhibisi digunakan untuk menolak pengiriman alarm tingkat rendah (target) jika ada alarm tingkat tinggi (source) yang saling berkaitan sedang aktif di area yang sama.
# Tambahkan aturan inhibisi di konfigurasi Alertmanager
inhibit_rules:
# Jika node mengalami down total (InstanceDown), redam semua warning disk space atau kubelet api untuk node tersebut.
- source_match:
alertname: 'NodeNetworkPartitionDown'
severity: 'critical'
target_match:
severity: 'warning'
# Pastikan inhibisi hanya berjalan jika terjadi pada node yang identik
equal: ['node', 'instance']
Peringatan Berbasis SLO (SLO-Based Alerting) #
Metode tradisional menetapkan ambang batas statis (seperti “Error rate > 5%”) rentan terhadap dua masalah:
- Jika trafik sedang sepi (misal 1 request per menit), 1 kegagalan akan langsung menghasilkan error rate 100% dan memicu alarm palsu.
- Jika trafik sedang padat (misal 10.000 request per detik), error rate 4.9% tidak memicu alarm padahal berdampak pada ribuan pengguna.
Sebagai gantinya, kita harus menggunakan SLO-Based Alerting yang memantau tingkat pembakaran anggaran kesalahan (Error Budget Burn Rate).
Konsep Dasar #
- SLI (Service Level Indicator): Rasio request sukses, misalnya
http_requests_total{status!~"5.."} / http_requests_total. - SLO (Service Level Objective): Target keandalan, misalnya 99.9% sukses dalam rolling 30 hari.
- Error Budget: Toleransi kegagalan yang diizinkan:
100% - 99.9% = 0.1%. - Burn Rate: Kecepatan konsumsi Error Budget.
- Burn Rate 1x: Anggaran kesalahan akan habis tepat dalam waktu 30 hari.
- Burn Rate 14.4x: Anggaran kesalahan akan habis dalam waktu 50 jam. Jika ini terjadi, kita harus segera memicu alert critical karena 2% anggaran kesalahan terbakar hanya dalam 1 jam!
Implementasi Multi-Window Multi-Burn-Rate Alerting #
Untuk mencegah kepalsuan deteksi, kita menggunakan dua jendela waktu (window) secara bersamaan: jendela panjang (misal 1 jam) untuk akurasi volume, dan jendela pendek (misal 5 menit) untuk konfirmasi bahwa masalah masih berlangsung.
# Manifest Kebijakan SLO Alert
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: billing-slo-alerts
namespace: monitoring
spec:
groups:
- name: billing-slo.alerts
rules:
# Critical Alert: Burn rate 14.4x terbakar (Aplikasi kritis)
- alert: BillingSloErrorBudgetBurnCritical
expr: |
(
# Jendela Panjang 1 Jam: Rasio error > 14.4x dari target 0.1% (SLO 99.9%)
sum(rate(http_requests_total{job="billing", status_code=~"5.."}[1h]))
/
sum(rate(http_requests_total{job="billing"}[1h]))
> (14.4 * 0.001)
)
and
(
# Jendela Pendek 5 Menit: Konfirmasi bahwa error masih berlangsung saat ini
sum(rate(http_requests_total{job="billing", status_code=~"5.."}[5m]))
/
sum(rate(http_requests_total{job="billing"}[5m]))
> (14.4 * 0.001)
)
for: 2m
labels:
severity: critical
team: core-billing
annotations:
summary: "Anggaran Kesalahan (Error Budget) billing terbakar terlalu cepat!"
description: "Tingkat pembakaran anggaran kesalahan (burn rate) saat ini adalah 14.4x pada jendela 1 jam dan 5 menit. Target SLO 99.9% terancam gagal."
runbook_url: "https://wiki.company.com/runbooks/slo-billing-triage"
Dengan metode ini, tim on-call hanya akan dibangunkan jika ada degradasi layanan nyata yang mengancam kepatuhan komitmen performa kita terhadap pengguna (SLA violation).
Anti-Pattern dalam Peringatan #
Berikut adalah kesalahan fatal yang sering ditemui dalam operasional sistem alerting:
1. Alerting Berbasis Penyebab Internal (Cause-Based Alerting) #
# ANTI-PATTERN: Pager dikirim jika memori kontainer > 90%.
# Banyak aplikasi (seperti Java VM) secara alami menggunakan memori penuh untuk cache
# tanpa menyebabkan kegagalan fungsi. Ini menghasilkan pager palsu di malam hari.
container_memory_working_set_bytes > 0.90 * container_spec_memory_limit_bytes
# ==============================================================================
# BENAR: Pager dikirim jika aplikasi mengalami kegagalan fungsi (Out Of Memory / OOM Killed).
# cAdvisor mendeteksi terminasi kontainer secara nyata.
rate(kube_pod_container_status_last_terminated_reason{reason="OOMKilled"}[5m]) > 0
2. Menggunakan Email untuk Alarm Kategori Critical #
Mengirim notifikasi kritis ke email tim yang jarang diperiksa secara real-time. Untuk kategori critical, gunakan sistem alarm pager terintegrasi (seperti PagerDuty atau Opsgenie) yang memicu panggilan telepon ke petugas on-call.
3. Alarm Tanpa Nilai Kontekstual #
Mengirim alarm dengan isi pesan minimal seperti Alert: High Latency. Tanpa menyertakan nilai aktual, nama node worker, atau nama pod yang bermasalah, tim investigasi akan membuang waktu mencari sumber masalah secara manual.
Checklist Audit Alerting Produksi #
Gunakan checklist berikut untuk memverifikasi kesiapan sistem alerting kluster Anda:
RANCANGAN ATURAN PROMETHEUSRULE:
□ Seluruh alert diklasifikasikan secara jelas (critical, warning, ticket).
□ Parameter 'for' dikonfigurasi untuk mencegah noise akibat spike sesaat (min. 2m - 5m).
□ Setiap alert menyertakan anotasi 'summary', 'description', dan 'runbook_url'.
□ Atribut deskripsi menggunakan variabel dinamis ({{ $value }}, {{ $labels.pod }}).
□ Menerapkan SLO-based alerting dengan metode multi-window untuk aplikasi kritis.
KONFIGURASI ALERTMANGER:
□ Kredensial webhook disimpan secara aman di rahasia Kubernetes (Secret).
□ Pengelompokan alarm ('group_by') dikonfigurasi berdasarkan alertname dan namespace.
□ Parameter 'group_wait' diatur secara rasional (30s - 1m) untuk mencegah flooding.
□ Parameter 'repeat_interval' diatur cukup panjang (min. 4h - 12h) agar tidak spamming.
□ Mengaktifkan aturan inhibisi untuk meredam alarm anak saat alarm induk aktif.
□ Prosedur maintenance menyertakan pembuatan rule silence via amtool CLI.
Ringkasan #
- Utamakan Peringatan Berbasis Gejala (Symptom-Based) — Kirim pager hanya jika pengguna mengalami kegagalan fungsi (latensi tinggi, error rate tinggi); hindari alarm berbasis metrik CPU/RAM internal.
- Runbook URL Wajib Disertakan — Setiap alert wajib menyertakan link dokumentasi runbook agar on-call engineer dapat segera mengambil langkah triage secara cepat.
- Kendalikan Alert Fatigue dengan Jendela Waktu — Gunakan delay parameter
for(misal 5 menit) untuk menyaring fluktuasi sementara sebelum metrik dianggap sebagai anomali berbahaya.- Terapkan Inhibisi untuk Mencegah Flooding — Gunakan Alertmanager
inhibit_rulesuntuk meredam notifikasi warning sekunder ketika komponen utama penyuplainya sedang down total.- amtool untuk Silencing Terjadwal — Otomatiskan pembuatan rules silence menggunakan CLI
amtoolsaat jadwal pemeliharaan kluster untuk menjaga ketenangan tim on-call.- SLO-Based Alerting untuk Akurasi Tinggi — Hitung tingkat pembakaran anggaran kesalahan (Error Budget Burn Rate) untuk mendapatkan sinyal peringatan yang presisi dan berorientasi bisnis.
← Sebelumnya: Metrics dan Prometheus Berikutnya: Distributed Tracing →