Mühendis Yakılmasına Son: Sağlıklı ve Sürdürülebilir Bir On-Call Kültürü Nasıl Kurulur?
Gece saat 03:00. Slack veya PagerDuty’den gelen o tanıdık siren sesiyle uyanıyorsunuz. Eğer modern bir devops kültürü yerine “kim ayaktaysa baksın” kaosunu yaşıyorsanız, ekibinizde tükenmişlik sendromu (burnout) çanları çoktan çalmaya başlamış demektir. Doğru yapılandırılmamış bir on-call yönetimi, sadece sistemlerin değil, en yetenekli mühendislerinizin de sessizce istifa etmesine (veya daha kötüsü, sistemin ortasına çökmesine) neden olur. Bu yazıda, incident response süreçlerini nasıl insani, sürdürülebilir ve otomatize hale getireceğimizi inceliyoruz. Sıkıcı teorileri bir kenara bırakıp doğrudan production ortamında can kurtaracak pratiklere odaklanıyoruz.
Alert Fatigue ile Savaş: Sadece “Aksiyon Alınabilir” Alarmlar
Alert fatigue (alarm yorgunluğu), on-call mühendislerinin en büyük düşmanıdır. CPU kullanımının %85’e çıkması tek başına bir alarm sebebi olmamalıdır. Eğer alarm çaldığında mühendisin yapabileceği net, manuel bir aksiyon yoksa (örneğin sistem kendi kendine auto-scale oluyorsa), o alarm çöp gürültüdür. Sadece kullanıcı deneyimini doğrudan etkileyen (SLO/SLI ihlalleri) veya sistemin tamamen durma noktasına geldiğini gösteren durumlar pager seviyesinde olmalıdır.
Gürültüyü azaltmak için Prometheus Alertmanager üzerinde akıllı gruplama (grouping) ve engelleme (inhibition) kuralları uygulamalısınız. Örneğin, tüm veri merkezi down olmuşken her bir pod için ayrı ayrı 500 tane “PodDown” alarmı almak yerine, tek bir “DatacenterDown” alarmı tetiklenmeli ve alt alarmlar susturulmalıdır.
Aşağıdaki Alertmanager konfigürasyon bloğu, benzer alarmları nasıl gruplayıp birbirini ezmesini (inhibit) sağlayabileceğinizi gösterir:
# alertmanager.yml
route:
group_by: ['alertname', 'cluster', 'service']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: 'pagerduty-high-priority'
routes:
- match:
severity: warning
receiver: 'slack-low-priority'
inhibit_rules:
- source_match:
alertname: 'NodeNetworkDown'
target_match_re:
alertname: 'InstanceDown|TargetDown'
equal: ['node', 'instance']
Neden böyle yapıyoruz? Çünkü NodeNetworkDown olduğunda, o node üzerindeki tüm container’ların erişilemez olması kaçınılmazdır. Bu engelleme kuralı sayesinde, gece yarısı telefonunuza 50 farklı push bildirimi gelmez; sorunun kök nedenine odaklanan tek bir kritik alarm alırsınız.
Rotasyon ve Eskalasyon Politikalarında Matematiksel Adalet
Adil bir on-call rotasyonu oluşturmak, excel tablolarından fazlasını gerektirir. Tek bir birincil (Primary) nöbetçi koyup tüm yükü ona yıkmak, tek hata noktası (SPOF) yaratmaktır. Sürdürülebilir bir sistemde her zaman Primary ve Secondary (Shadow/Backup) rollerinin tanımlanması gerekir.
Eğer global bir ekipseniz, “Follow-the-Sun” modelini uygulamak hayat kurtarır. Bu modelde nöbetler, coğrafi olarak gündüz vaktinde olan bölgeye devredilir. Eğer lokal bir ekipseniz, haftalık rotasyonların cuma günü saat 17:00’de devredilmesi yerine salı günü öğleden sonra devredilmesi daha sağlıklıdır. Böylece yeni nöbetçi, haftalık iş yoğunluğunun ortasında sisteme ısınır ve olası devir-teslim sorunlarını mesai saatleri içinde çözer.
Bu yapıyı kod olarak yönetmek (Infrastructure as Code) esnekliği artırır. Aşağıdaki Terraform konfigürasyonu, PagerDuty üzerinde adil bir eskalasyon politikasını tanımlar:
# pagerduty.tf
resource "pagerduty_escalation_policy" "production_policy" {
name = "Production Escalation Policy"
num_loops = 2
rule {
escalation_delay_in_minutes = 10
target {
id = pagerduty_schedule.primary_schedule.id
type = "schedule_reference"
}
}
rule {
escalation_delay_in_minutes = 15
target {
id = pagerduty_schedule.secondary_schedule.id
type = "schedule_reference"
}
}
rule {
escalation_delay_in_minutes = 20
target {
id = pagerduty_user.engineering_lead.id
type = "user_reference"
}
}
}
Buradaki felsefe şudur: Primary nöbetçi 10 dakika içinde alarmı ack’lemezse (onaylamazsa), alarm otomatik olarak Secondary nöbetçiye geçer. O da 15 dakika içinde yanıt vermezse, engineering lead seviyesine eskalasyon gerçekleşir. Bu hiyerarşi, nöbetteki mühendisin üzerindeki psikolojik baskıyı azaltır; arkasında her zaman bir güvence olduğunu bilir.
Incident Response Otomasyonu: Self-Healing ve ChatOps
Bir alarm çaldığında mühendisin yaptığı ilk iş genellikle terminali açıp df -h yazmak veya ilgili servisi restart etmekse, burada ciddi bir otomasyon eksiği var demektir. Tekrarlanan runbook adımları, insan müdahalesine gerek kalmadan otomatik olarak çalıştırılmalıdır.
Örneğin, disk doluluk alarmı tetiklendiğinde otomatik olarak geçici cache dosyalarını temizleyen veya log rotasyonunu tetikleyen bir Kubernetes DaemonSet veya serverless fonksiyon yazabilirsiniz. İnsan faktörünü sadece “otomasyonun çözemediği” durumlarda devreye sokmalıyız.
Eğer manuel müdahale şartsa, bunu Slack/MS Teams üzerinden ChatOps ile yapmak hızı katlar. Aşağıdaki basit bash script’i, Alertmanager webhook’undan gelen disk alarmını yakalayıp, AWS API’si üzerinden EBS hacmini otomatik olarak genişleten bir self-healing mekanizmasının mantığını göstermektedir:
#!/usr/bin/env bash
# auto_expand_disk.sh
set -euo pipefail
ALERT_PAYLOAD=$(cat)
VOLUME_ID=$(echo "$ALERT_PAYLOAD" | jq -r '.alerts[0].labels.volume_id')
REGION=$(echo "$ALERT_PAYLOAD" | jq -r '.alerts[0].labels.region')
echo "Kritik disk alarmı alındı: $VOLUME_ID. Disk boyutu %10 artırılıyor..."
# Mevcut boyutu al
CURRENT_SIZE=$(aws ec2 describe-volumes \
--volume-ids "$VOLUME_ID" \
--region "$REGION" \
--query "Volumes[0].Size" --output text)
NEW_SIZE=$(( CURRENT_SIZE + (CURRENT_SIZE * 10 / 100) ))
# AWS üzerinde diski genişlet
aws ec2 modify-volume \
--volume-id "$VOLUME_ID" \
--region "$REGION" \
--size "$NEW_SIZE"
echo "Disk başarıyla $NEW_SIZE GB değerine genişletildi."
Neden böyle bir otomasyon kuruyoruz? Çünkü gece 04:00’te bir mühendisi sadece disk genişletmek için uyandırmak, operasyonel verimliliği baltalamaktan başka bir işe yaramaz. Bırakın otomasyon diski genişletsin, mühendis sabah kahvesini içerken slack kanalındaki log’lardan olayı takip etsin.
Suçsuz (Blameless) Post-Mortem Kültürü
Sürdürülebilir on-call kültürünün teknik olmayan en kritik ayağı, olay sonrası analizlerdir. Bir incident bittiğinde her şey bitmiş sayılmaz. Amaç “Hatayı kim yaptı?” sorusunu sormak değil, “Sistemimiz bu hatanın yapılmasına nasıl izin verdi?” sorusuna yanıt aramaktır.
Blameless post-mortem süreçlerinde şu üç kuralı asla esnetmeyin:
- İnsanlar hata yapabilir: Süreçleriniz ve tool’larınız bu hataları tolere edebilecek şekilde tasarlanmalıdır.
- Zaman çizelgesi çıkarın: Alarmın çalma anından, ilk müdahaleye ve nihai çözüme (mitigation) kadar geçen süreci kronolojik olarak dökün.
- Aksiyon maddeleri (Action Items) üretin: Her post-mortem belgesinden, gelecekte benzer hatanın tekrarlanmasını önleyecek en az 2 adet Jira task’i çıkmalı ve bunlar sonraki sprint’e dahil edilmelidir.
Sonuç: Mühendisleri Yakmadan Sistemleri Ayakta Tutmak
Sağlıklı bir on-call sistemi kurmak, teknik bir zorunluluk olduğu kadar etik bir sorumluluktur. Ekibinizi sürekli yangın söndüren itfaiyecilere dönüştürmek yerine, yangının hiç çıkmamasını sağlayan sistem mimarları haline getirmelisiniz. Alarmlarınızı sadeleştirin, rotasyonlarınızı adilleştirin, otomasyona yatırım yapın ve her hatayı sisteminizi güçlendirmek için bir fırsat olarak görün. Unutmayın; iyi bir SRE, uykusunu en iyi almış SRE’dir.