AWS CloudWatch Alarm ve Bildirim Kurulumu
Bir üretim ortamında çalışan bir servisin gece yarısı çöktüğünü, ama bunu ancak sabah müşteri şikayetlerinden öğrendiğini düşün. Bu senaryo maalesef çok yaygın ve tamamen önlenebilir bir durum. AWS CloudWatch Alarm ve bildirim sistemi, tam da bu tür sorunların önüne geçmek için tasarlanmış, doğru kurulduğunda adeta 7/24 nöbet tutan bir gözetleme sistemi gibi çalışan bir yapıdır. Bu yazıda CloudWatch alarmlarını sıfırdan nasıl kuracağını, SNS ile nasıl entegre edeceğini ve gerçek üretim senaryolarında nasıl kullanacağını adım adım ele alacağız.
CloudWatch Alarm Mantığını Anlamak
CloudWatch, AWS’nin merkezi izleme servisi. Metrikler toplar, logları saklar ve bu verilere dayalı alarmlar oluşturmanı sağlar. Ama birçok sysadmin CloudWatch’u yüzeysel kullanır, sadece CPU alarmı kurar ve bırakır. Oysa doğru yapılandırılmış bir CloudWatch sistemi; EC2, RDS, Lambda, ALB, ve daha onlarca servis için kapsamlı bir gözlemlenebilirlik katmanı oluşturabilir.
Bir alarm temel olarak üç durumda olabilir:
- OK: Metrik eşik değerin altında veya üstünde, her şey normal
- ALARM: Metrik belirlediğin eşiği aştı, aksiyon zamanı
- INSUFFICIENT_DATA: Yeterli veri yok, alarm henüz değerlendirme yapamıyor
Alarm oluştururken şu parametreleri belirliyorsun:
- Metrik: Neyi izliyorsun? CPUUtilization, NetworkIn, HealthyHostCount gibi
- Namespace: Hangi servise ait? AWS/EC2, AWS/RDS, AWS/ApplicationELB gibi
- Period: Her kaç saniyede bir değerlendirme yapılacak? (60, 300, 3600)
- Evaluation Periods: Kaç ardışık period değerlendirilecek?
- Threshold: Eşik değer nedir?
- Comparison Operator: GreaterThanThreshold, LessThanThreshold gibi
- Statistic: Average, Maximum, Sum, Minimum gibi
AWS CLI ile Temel Kurulum
Önce AWS CLI’nin kurulu ve yapılandırılmış olduğundan emin ol. CloudWatch alarmlarını hem konsol üzerinden hem de CLI ile kurabilirsin ama otomasyon ve tekrarlanabilirlik açısından CLI çok daha kullanışlı.
# AWS CLI versiyonunu kontrol et
aws --version
# Hangi region'da çalışacağını ayarla
export AWS_DEFAULT_REGION=eu-west-1
# Mevcut CloudWatch alarmlarını listele
aws cloudwatch describe-alarms
--alarm-types MetricAlarm
--query 'MetricAlarms[*].[AlarmName,StateValue]'
--output table
SNS Topic Oluşturma ve Abone Olma
CloudWatch alarmları tetiklendiğinde aksiyonları SNS (Simple Notification Service) üzerinden gerçekleştirir. Önce bir SNS topic oluşturman gerekiyor.
# Ops ekibi için SNS topic oluştur
aws sns create-topic
--name "production-alerts"
--tags Key=Environment,Value=production Key=Team,Value=ops
# Topic ARN'ını bir değişkene al (çıktıdan)
TOPIC_ARN="arn:aws:sns:eu-west-1:123456789012:production-alerts"
# E-posta aboneliği ekle
aws sns subscribe
--topic-arn $TOPIC_ARN
--protocol email
--notification-endpoint "[email protected]"
# Slack webhook için HTTP aboneliği (Lambda entegrasyonuyla)
aws sns subscribe
--topic-arn $TOPIC_ARN
--protocol https
--notification-endpoint "https://hooks.slack.com/services/XXXXX/YYYYY/ZZZZZ"
# Abonelik listesini kontrol et
aws sns list-subscriptions-by-topic
--topic-arn $TOPIC_ARN
E-posta aboneliği ekledikten sonra belirtilen adrese bir onay maili gider. O maildeki linke tıklanmadan abonelik aktif olmaz. Bunu sıklıkla atlıyorlar, üretimde alarm kurdu ama bildirim gelmiyor diye şikayet ediyorlar.
EC2 CPU Alarmı Kurulumu
En klasik senaryo ile başlayalım. Bir EC2 instance’ının CPU kullanımı 5 dakika boyunca %80’in üzerinde kalırsa alarm tetiklesin.
# EC2 Instance ID'ni bul
INSTANCE_ID="i-0123456789abcdef0"
TOPIC_ARN="arn:aws:sns:eu-west-1:123456789012:production-alerts"
# CPU yüksek kullanım alarmı
aws cloudwatch put-metric-alarm
--alarm-name "EC2-HighCPU-${INSTANCE_ID}"
--alarm-description "CPU kullanimi 5 dakika boyunca %80 uzerinde"
--metric-name CPUUtilization
--namespace AWS/EC2
--statistic Average
--period 300
--evaluation-periods 3
--threshold 80
--comparison-operator GreaterThanThreshold
--dimensions Name=InstanceId,Value=$INSTANCE_ID
--alarm-actions $TOPIC_ARN
--ok-actions $TOPIC_ARN
--treat-missing-data notBreaching
# Alarm durumunu kontrol et
aws cloudwatch describe-alarms
--alarm-names "EC2-HighCPU-${INSTANCE_ID}"
Burada --evaluation-periods 3 önemli bir detay. Bu değer, alarmın tetiklenmesi için 3 ardışık period boyunca (3×300=15 dakika) eşiğin aşılması gerektiği anlamına geliyor. Tek seferlik spike’larda gereksiz alarm gelmesini önler.
--treat-missing-data notBreaching parametresi de kritik. Metrik verisi gelmediğinde alarmın nasıl davranacağını belirler:
- notBreaching: Eksik veriyi normal kabul et
- breaching: Eksik veriyi alarm durumu kabul et
- ignore: Mevcut durumu koru
- missing: INSUFFICIENT_DATA durumuna geç
Disk Kullanımı İçin Özel Metrik Alarmı
EC2 disk kullanımı AWS/EC2 namespace’inde varsayılan olarak gelmez. Bunun için CloudWatch Agent kurman gerekiyor. Ama önce disk alarm mantığını görelim.
# CloudWatch Agent konfigürasyonu (SSM Parameter Store'dan yükle)
aws ssm put-parameter
--name "/cloudwatch-agent/config/production"
--type String
--value '{
"metrics": {
"namespace": "CustomMetrics/EC2",
"metrics_collected": {
"disk": {
"measurement": ["used_percent"],
"metrics_collection_interval": 60,
"resources": ["/", "/data"]
},
"mem": {
"measurement": ["mem_used_percent"],
"metrics_collection_interval": 60
}
}
}
}'
# Agent'ı SSM Run Command ile başlat
aws ssm send-command
--instance-ids $INSTANCE_ID
--document-name "AmazonCloudWatch-ManageAgent"
--parameters '{"action":["configure"],"mode":["ec2"],"optionalConfigurationSource":["ssm"],"optionalConfigurationLocation":["/cloudwatch-agent/config/production"]}'
Agent kurulduktan sonra disk alarmını kur:
# Disk doluluk alarmı (%85 eşiği)
aws cloudwatch put-metric-alarm
--alarm-name "EC2-HighDisk-Root-${INSTANCE_ID}"
--alarm-description "Root disk kullanimi %85 uzerinde"
--metric-name disk_used_percent
--namespace CustomMetrics/EC2
--statistic Average
--period 300
--evaluation-periods 2
--threshold 85
--comparison-operator GreaterThanThreshold
--dimensions Name=InstanceId,Value=$INSTANCE_ID Name=path,Value=/ Name=fstype,Value=ext4
--alarm-actions $TOPIC_ARN
--treat-missing-data breaching
Disk alarmlarında breaching kullanmak daha güvenli. Eğer agent çalışmıyorsa ve disk doluysa, bunu bilmek istersin.
RDS Alarmları: Veritabanı İzleme
Üretim ortamında RDS izleme kritik önem taşır. Disk dolması, bağlantı sayısının artması veya yavaş sorgu yığılması çok ciddi sonuçlar doğurabilir.
DB_INSTANCE="production-db-1"
TOPIC_ARN="arn:aws:sns:eu-west-1:123456789012:production-alerts"
# RDS yüksek CPU alarmı
aws cloudwatch put-metric-alarm
--alarm-name "RDS-HighCPU-${DB_INSTANCE}"
--alarm-description "RDS CPU kullanimi 10 dakika boyunca %70 uzerinde"
--metric-name CPUUtilization
--namespace AWS/RDS
--statistic Average
--period 300
--evaluation-periods 2
--threshold 70
--comparison-operator GreaterThanThreshold
--dimensions Name=DBInstanceIdentifier,Value=$DB_INSTANCE
--alarm-actions $TOPIC_ARN
--ok-actions $TOPIC_ARN
--treat-missing-data notBreaching
# RDS veritabanı bağlantı sayısı alarmı
aws cloudwatch put-metric-alarm
--alarm-name "RDS-HighConnections-${DB_INSTANCE}"
--alarm-description "RDS baglanti sayisi 450 uzerinde (max 500)"
--metric-name DatabaseConnections
--namespace AWS/RDS
--statistic Average
--period 60
--evaluation-periods 5
--threshold 450
--comparison-operator GreaterThanThreshold
--dimensions Name=DBInstanceIdentifier,Value=$DB_INSTANCE
--alarm-actions $TOPIC_ARN
--treat-missing-data notBreaching
# RDS disk alanı alarmı (byte cinsinden, 10GB = 10737418240 byte)
aws cloudwatch put-metric-alarm
--alarm-name "RDS-LowStorage-${DB_INSTANCE}"
--alarm-description "RDS boş disk alani 10GB altina dustu"
--metric-name FreeStorageSpace
--namespace AWS/RDS
--statistic Average
--period 300
--evaluation-periods 2
--threshold 10737418240
--comparison-operator LessThanThreshold
--dimensions Name=DBInstanceIdentifier,Value=$DB_INSTANCE
--alarm-actions $TOPIC_ARN
--treat-missing-data breaching
ALB (Application Load Balancer) Alarmları
Web uygulamalarında ALB metrikleri çok değerli. 5xx hata oranı, yanıt süresi ve sağlıklı host sayısı kritik göstergeler.
ALB_NAME="app/production-alb/1234567890abcdef"
TARGET_GROUP="targetgroup/production-tg/abcdef1234567890"
TOPIC_ARN="arn:aws:sns:eu-west-1:123456789012:production-alerts"
# 5xx hata oranı alarmı
aws cloudwatch put-metric-alarm
--alarm-name "ALB-High5xxRate-Production"
--alarm-description "ALB 5xx hata orani dakikada 50 uzerinde"
--metric-name HTTPCode_ELB_5XX_Count
--namespace AWS/ApplicationELB
--statistic Sum
--period 60
--evaluation-periods 3
--threshold 50
--comparison-operator GreaterThanThreshold
--dimensions Name=LoadBalancer,Value=$ALB_NAME
--alarm-actions $TOPIC_ARN
--ok-actions $TOPIC_ARN
--treat-missing-data notBreaching
# Sağlıklı host sayısı alarmı
aws cloudwatch put-metric-alarm
--alarm-name "ALB-LowHealthyHosts-Production"
--alarm-description "Saglikli host sayisi 2 altina dustu"
--metric-name HealthyHostCount
--namespace AWS/ApplicationELB
--statistic Minimum
--period 60
--evaluation-periods 2
--threshold 2
--comparison-operator LessThanThreshold
--dimensions Name=LoadBalancer,Value=$ALB_NAME Name=TargetGroup,Value=$TARGET_GROUP
--alarm-actions $TOPIC_ARN
--treat-missing-data breaching
# Yüksek gecikme süresi alarmı (saniye cinsinden)
aws cloudwatch put-metric-alarm
--alarm-name "ALB-HighLatency-Production"
--alarm-description "ALB ortalama gecikme suresi 2 saniye uzerinde"
--metric-name TargetResponseTime
--namespace AWS/ApplicationELB
--statistic Average
--period 300
--evaluation-periods 3
--threshold 2
--comparison-operator GreaterThanThreshold
--dimensions Name=LoadBalancer,Value=$ALB_NAME
--alarm-actions $TOPIC_ARN
--treat-missing-data notBreaching
Bileşik Alarm Oluşturma
AWS CloudWatch’un güçlü bir özelliği de Composite Alarm desteği. Birden fazla alarmı mantıksal operatörlerle birleştirip daha akıllı bildirimler oluşturabilirsin. Örneğin hem CPU hem de disk yüksekse alarm ver ama sadece biri yüksekse verme.
# Önce bireysel alarmların kurulu olduğunu varsayıyoruz
# Composite alarm oluştur
aws cloudwatch put-composite-alarm
--alarm-name "Production-Critical-Composite"
--alarm-description "CPU VE disk ayni anda yuksek oldugunda tetiklenir"
--alarm-rule "ALARM(EC2-HighCPU-i-0123456789abcdef0) AND ALARM(EC2-HighDisk-Root-i-0123456789abcdef0)"
--alarm-actions $TOPIC_ARN
--ok-actions $TOPIC_ARN
Bu yapı özellikle büyük ortamlarda çok faydalı. Yüzlerce alarm varken, kritik olanları composite alarmla gruplandırıp gürültüyü azaltabilirsin.
Terraform ile CloudWatch Alarm Otomasyonu
Gerçek üretim ortamlarında alarmları tek tek CLI ile kurmak yerine Infrastructure as Code (IaC) kullanmak çok daha mantıklı. İşte basit bir Terraform örneği:
# terraform/cloudwatch-alarms/main.tf içeriği
# Bu bash değil HCL ama içeriği göstermek için örnek
# Önce mevcut Terraform state'ini kontrol et
terraform init
terraform plan -var="environment=production" -var="sns_topic_arn=${TOPIC_ARN}"
# Alarmları uygula
terraform apply -auto-approve
-var="environment=production"
-var="sns_topic_arn=${TOPIC_ARN}"
# Mevcut alarm listesini JSON formatında çıkar (yedek için)
aws cloudwatch describe-alarms
--query 'MetricAlarms[*]'
--output json > cloudwatch-alarms-backup-$(date +%Y%m%d).json
Alarm Durumunu Manuel Test Etme
Kurduğun alarmın gerçekten çalışıp çalışmadığını test etmek önemli. AWS, alarm durumunu manuel olarak değiştirmene izin veriyor.
# Alarmı manuel olarak ALARM durumuna al (test için)
aws cloudwatch set-alarm-state
--alarm-name "EC2-HighCPU-i-0123456789abcdef0"
--state-value ALARM
--state-reason "Manuel test - bildirim kontrolu"
# 30 saniye bekle
sleep 30
# Alarmı tekrar OK durumuna döndür
aws cloudwatch set-alarm-state
--alarm-name "EC2-HighCPU-i-0123456789abcdef0"
--state-value OK
--state-reason "Test tamamlandi"
# Alarm geçmişini kontrol et
aws cloudwatch describe-alarm-history
--alarm-name "EC2-HighCPU-i-0123456789abcdef0"
--history-item-type StateUpdate
--start-date $(date -d '1 hour ago' -u +%Y-%m-%dT%H:%M:%SZ)
Bu test yöntemi çok değerli. Yeni bir ortam kurduğunda, SNS aboneliklerini doğrulamak ve bildirimlerin doğru kişilere gittiğini teyit etmek için her zaman bu testi yap.
Alarm Bakımı ve Yönetimi
Zamanla birikmiş, artık kullanılmayan alarmlar karmaşa yaratır. Periyodik olarak temizlik yapmak gerekiyor.
# INSUFFICIENT_DATA durumundaki alarmları bul
aws cloudwatch describe-alarms
--state-value INSUFFICIENT_DATA
--query 'MetricAlarms[*].[AlarmName,StateReason]'
--output table
# Belirli bir prefix'e sahip alarmları toplu sil
aws cloudwatch describe-alarms
--alarm-name-prefix "old-staging-"
--query 'MetricAlarms[*].AlarmName'
--output text | tr 't' 'n' | while read alarm; do
echo "Siliniyor: $alarm"
aws cloudwatch delete-alarms --alarm-names "$alarm"
done
# Tüm alarmların anlık durumunu özetle
aws cloudwatch describe-alarms
--query '{
ALARM: MetricAlarms[?StateValue==`ALARM`] | length(@),
OK: MetricAlarms[?StateValue==`OK`] | length(@),
INSUFFICIENT_DATA: MetricAlarms[?StateValue==`INSUFFICIENT_DATA`] | length(@)
}'
Sık Yapılan Hatalar ve Çözümleri
Yıllar içinde gördüğüm en yaygın CloudWatch alarm hatalarını paylaşayım:
Çok düşük period kullanımı: 60 saniyelik period ile çok sayıda alarm, hem CloudWatch maliyetini artırır hem de gereksiz alarm gürültüsüne yol açar. CPU gibi metrikler için 300 saniye genellikle yeterli.
Evaluation periods’u 1 bırakmak: Tek bir period değerinde tetiklenen alarmlar, geçici spike’larda gece yarısı uyandırır. En az 2-3 period koy.
OK aksiyonunu unutmak: Alarm tetiklendi bildirimini alıyorsun ama problem çözüldüğünde bildirim gelmiyor. --ok-actions parametresini eklemek bu sorunu çözer.
Namespace yanlışlığı: Özel metrikler için namespace’i eksik veya yanlış yazmak en sık karşılaşılan hata. Metrik isimlerini şu komutla doğrulayabilirsin:
# Belirli bir namespace'deki metrikleri listele
aws cloudwatch list-metrics
--namespace "CustomMetrics/EC2"
--dimensions Name=InstanceId,Value=$INSTANCE_ID
# Bir metriğin son değerini al (alarm kurmadan önce veri gelip gelmediğini doğrula)
aws cloudwatch get-metric-statistics
--namespace AWS/EC2
--metric-name CPUUtilization
--dimensions Name=InstanceId,Value=$INSTANCE_ID
--start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ)
--end-time $(date -u +%Y-%m-%dT%H:%M:%SZ)
--period 300
--statistics Average
Alarm kota limitini aşmak: AWS hesabı başına varsayılan olarak 5000 MetricAlarm limiti var. Büyük ortamlarda bu limite takılabilirsin. Composite alarmlar bu limiti daha verimli kullanmanı sağlar.
Maliyet Optimizasyonu
CloudWatch alarmları bedava değil. Her alarm aylık ücreti olan bir kaynaktır. Maliyeti optimize etmek için şu yaklaşımları kullanabilirsin:
- Yüksek kardinaliteli metrikler (her instance için ayrı alarm yerine) için CloudWatch Container Insights veya CloudWatch Anomaly Detection kullan
- Sık değerlendirilmesi gerekmeyen alarmlar için period değerini artır
- Staging ortamı alarmlarını çalışma saatlerinde aktif edip diğer zamanlarda devre dışı bırakmak için Lambda + EventBridge kombinasyonu kullan
- Kullanılmayan alarmları düzenli olarak temizle
Sonuç
CloudWatch alarm sistemi, doğru kurulduğunda gerçekten uyku getirebilen bir yapı. Ancak “birkaç alarm kurayım yeter” zihniyetiyle değil, sistematik bir izleme stratejisiyle yaklaşmak gerekiyor. SNS topic yapısından başla, önce kritik servislerin temel metriklerini kur, test et, sonra kapsamı genişlet.
Üretim ortamın için mutlaka şu minimum alarm setini kur: Her EC2 için CPU ve disk alarmı, her RDS için CPU, bağlantı sayısı ve disk alarmı, ALB’ler için 5xx oranı ve sağlıklı host sayısı alarmı. Bunları Terraform veya CloudFormation ile kodlayarak yeni ortamları tutarlı şekilde konfigüre edebilirsin.
Son olarak şunu unutma: En iyi alarm sistemi, gereksiz yere uyandırmayan ama gerçek problemleri asla kaçırmayan sistemdir. Bu dengeyi bulmak biraz deneyim ister ama yukarıdaki pratikler seni doğru yöne götürür. Alarm yorgunluğu (alarm fatigue) gerçek bir tehlike; ekip bildirimleri görmezden gelmeye başladığında tüm sistemi tehlikeye atmış olursun.
