AWS SNS Bildirim Sistemi Yapılandırması ve Yönetimi

Bir sistemi yönetirken en can sıkıcı şeylerden biri, bir şeylerin bozulduğunu kullanıcılardan öğrenmektir. “Hocam sitenizdeki şu özellik çalışmıyor, dün baktım çalışmıyordu” cümlesi her sysadmin’in kabusu. İşte tam bu noktada AWS SNS devreye giriyor. SNS (Simple Notification Service), bulut altyapınızda olan her şeyi anında size bildiren, esnek ve ölçeklenebilir bir mesajlaşma servisi. Bu yazıda SNS’i sıfırdan yapılandıracak, gerçek dünya senaryolarında nasıl kullanacağınızı göreceksiniz.

AWS SNS Nedir ve Neden Kullanmalısınız

AWS SNS, publisher-subscriber (yayıncı-abone) modeline dayalı bir bildirim servisidir. Bir olay gerçekleştiğinde (mesela EC2 instance’ınız kapandığında, S3 bucket’ınıza beklenmedik bir dosya yüklendiğinde veya RDS’iniz belirli bir CPU eşiğini aştığında) SNS bu olayı alır ve önceden tanımladığınız abonelere iletir.

Aboneler çeşitli formatlarda olabilir:

  • Email: Klasik e-posta bildirimi, hızlı kurulum için ideal
  • SMS: Kritik alarmlar için telefon mesajı
  • HTTP/HTTPS Endpoint: Kendi uygulamanıza webhook tarzı bildirim
  • SQS Queue: Mesajları kuyruğa alarak asenkron işleme
  • Lambda Function: Bildirim geldiğinde otomatik aksiyon almak
  • Mobile Push: iOS/Android push notification
  • Firehose: Büyük veri akışları için Kinesis entegrasyonu

SNS’in en güzel yanı, bir olayı birden fazla hedefe aynı anda iletebilmesi. Yani disk dolduğunda hem email alırsınız, hem Slack’e mesaj gider, hem de otomatik temizleme Lambda’sı tetiklenir.

Temel Kavramlar

SNS’i anlamak için birkaç temel kavramı netleştirmek gerekiyor:

Topic (Konu): Mesajların yayınlandığı ve abonelerin dinlediği kanal. Her topic bir ARN (Amazon Resource Name) ile tanımlanır.

Publisher: Topic’e mesaj gönderen kaynak. CloudWatch Alarms, EventBridge, uygulama kodunuz veya AWS CLI olabilir.

Subscriber: Topic’ten mesaj alan hedef. Yukarıda saydığımız email, SMS, Lambda gibi servisler.

Message Filtering: Her abonenin sadece belirli mesajları almasını sağlayan özellik. Örneğin kritik hatalar sadece SMS ile gelsin, uyarılar ise sadece emaile gitsin.

AWS CLI ile SNS Kurulumu

Önce AWS CLI’ın kurulu ve yapılandırılmış olduğunu varsayıyorum. Değilse şu komutla başlayın:

# AWS CLI yapılandırması
aws configure
# Access Key ID, Secret Access Key, Region ve output format gireceksiniz
# Region için: eu-west-1, us-east-1 gibi değerler kullanın

# Yapılandırmayı doğrula
aws sts get-caller-identity

İlk Topic’i Oluşturma

# Standart bir topic oluşturma
aws sns create-topic --name production-alerts

# FIFO topic oluşturma (sıralı mesaj garantisi için)
aws sns create-topic 
  --name production-alerts.fifo 
  --attributes FifoTopic=true,ContentBasedDeduplication=true

# Topic ARN'ini değişkene alalım
TOPIC_ARN=$(aws sns create-topic --name production-alerts --query 'TopicArn' --output text)
echo "Topic ARN: $TOPIC_ARN"

# Mevcut topic'leri listele
aws sns list-topics

Abonelik Ekleme

Topic oluşturdunuz, şimdi kim bu bildirimleri alacak?

# Email aboneliği ekle
aws sns subscribe 
  --topic-arn $TOPIC_ARN 
  --protocol email 
  --notification-endpoint [email protected]

# SMS aboneliği (Türkiye için +90 ile başlamalı)
aws sns subscribe 
  --topic-arn $TOPIC_ARN 
  --protocol sms 
  --notification-endpoint "+905551234567"

# HTTPS endpoint aboneliği (webhook)
aws sns subscribe 
  --topic-arn $TOPIC_ARN 
  --protocol https 
  --notification-endpoint "https://monitoring.sirketiniz.com/sns-webhook"

# Lambda aboneliği
aws sns subscribe 
  --topic-arn $TOPIC_ARN 
  --protocol lambda 
  --notification-endpoint "arn:aws:lambda:eu-west-1:123456789:function:alert-handler"

# Abonelikleri listele
aws sns list-subscriptions-by-topic --topic-arn $TOPIC_ARN

Email aboneliği eklediğinizde AWS, o adrese bir onay emaili gönderir. Abone olmak için email içindeki linke tıklanması gerekir.

Test Mesajı Gönderme

# Basit test mesajı
aws sns publish 
  --topic-arn $TOPIC_ARN 
  --message "Test bildirimi - SNS yapılandırması başarılı!" 
  --subject "AWS SNS Test"

# JSON formatında detaylı mesaj
aws sns publish 
  --topic-arn $TOPIC_ARN 
  --message '{"alarm": "disk_usage", "server": "web-01", "value": "92%", "threshold": "90%"}' 
  --subject "UYARI: Disk Kullanımı Kritik Seviyede" 
  --message-attributes '{"severity":{"DataType":"String","StringValue":"critical"}}'

CloudWatch Alarm Entegrasyonu

SNS’in en yaygın kullanım senaryosu CloudWatch Alarm’larla entegrasyon. Senaryo şu: EC2 instance’larınızdan birinin CPU kullanımı %80’i geçtiğinde bildirim almak istiyorsunuz.

# Önce SNS topic'imizi oluşturalım
TOPIC_ARN=$(aws sns create-topic --name cloudwatch-alerts --query 'TopicArn' --output text)

# Email aboneliği ekleyelim
aws sns subscribe 
  --topic-arn $TOPIC_ARN 
  --protocol email 
  --notification-endpoint "[email protected]"

# CloudWatch Alarm oluştur ve SNS'e bağla
aws cloudwatch put-metric-alarm 
  --alarm-name "ec2-cpu-high" 
  --alarm-description "EC2 CPU kullanimi %80 ustune cikti" 
  --metric-name CPUUtilization 
  --namespace AWS/EC2 
  --statistic Average 
  --period 300 
  --threshold 80 
  --comparison-operator GreaterThanThreshold 
  --dimensions Name=InstanceId,Value=i-1234567890abcdef0 
  --evaluation-periods 2 
  --alarm-actions $TOPIC_ARN 
  --ok-actions $TOPIC_ARN 
  --insufficient-data-actions $TOPIC_ARN

# Alarm durumunu kontrol et
aws cloudwatch describe-alarms --alarm-names "ec2-cpu-high"

Bu yapılandırmayla 5 dakika boyunca (period=300) CPU %80’in üzerinde kaldığında SNS topic’inize mesaj gider ve siz anında email alırsınız.

Mesaj Filtreleme ile Akıllı Bildirimler

Gerçek dünya senaryosu: 10 farklı sunucunuz var, 3 farklı ekip var. Veritabanı ekibi sadece RDS alarmlarını görmek istiyor, frontend ekibi CloudFront ve S3 sorunlarıyla ilgileniyor. Hepsine her şeyi göndermek yerine filtreleme kullanırsınız.

# Tüm alarmlar için tek bir topic
MAIN_TOPIC=$(aws sns create-topic --name all-alerts --query 'TopicArn' --output text)

# Veritabanı ekibi aboneliği - sadece "database" tipindeki mesajları al
aws sns subscribe 
  --topic-arn $MAIN_TOPIC 
  --protocol email 
  --notification-endpoint "[email protected]" 
  --attributes '{"FilterPolicy":"{"alert_type":["database","rds","aurora"]}"}'

# Frontend ekibi aboneliği - sadece "frontend" tipindeki mesajlar
aws sns subscribe 
  --topic-arn $MAIN_TOPIC 
  --protocol email 
  --notification-endpoint "[email protected]" 
  --attributes '{"FilterPolicy":"{"alert_type":["cloudfront","s3","api_gateway"]}"}'

# Kritik alarmları sadece SMS ile al (tüm ekip)
aws sns subscribe 
  --topic-arn $MAIN_TOPIC 
  --protocol sms 
  --notification-endpoint "+905551234567" 
  --attributes '{"FilterPolicy":"{"severity":["critical"]}"}'

Artık mesaj yayınlarken doğru attribute’ları kullanmanız gerekiyor:

# Veritabanı alarmı - sadece db-team ve SMS (eğer critical ise) alır
aws sns publish 
  --topic-arn $MAIN_TOPIC 
  --message "RDS instance'i yanit vermiyor!" 
  --subject "KRITIK: Veritabani Sorunu" 
  --message-attributes '{
    "alert_type":{"DataType":"String","StringValue":"rds"},
    "severity":{"DataType":"String","StringValue":"critical"}
  }'

Lambda ile Otomatik Aksiyon

En güçlü kullanım senaryolarından biri: Bir alarm geldiğinde sadece bildirim almakla kalmayıp otomatik aksiyon da almak. Mesela disk dolduğunda eski log dosyalarını temizleyen bir Lambda.

Önce Lambda fonksiyonunu Python ile yazalım:

# disk_cleanup_lambda.py
import json
import boto3
import os

def lambda_handler(event, context):
    # SNS mesajını parse et
    for record in event['Records']:
        message = json.loads(record['Sns']['Message'])
        
        instance_id = message.get('instance_id', 'unknown')
        disk_usage = message.get('disk_usage', 0)
        
        print(f"Alarm alindi: {instance_id} - Disk: {disk_usage}%")
        
        if disk_usage > 90:
            # SSM Run Command ile remote cleanup
            ssm = boto3.client('ssm')
            
            response = ssm.send_command(
                InstanceIds=[instance_id],
                DocumentName='AWS-RunShellScript',
                Parameters={
                    'commands': [
                        'find /var/log -name "*.gz" -mtime +7 -delete',
                        'journalctl --vacuum-time=7d',
                        'df -h / | tail -1'
                    ]
                }
            )
            
            # Slack'e de bildir
            notify_slack(f"Otomatik temizlik baslatildi: {instance_id}")
            
            return {
                'statusCode': 200,
                'body': f'Cleanup initiated for {instance_id}'
            }

def notify_slack(message):
    import urllib.request
    webhook_url = os.environ.get('SLACK_WEBHOOK_URL')
    
    if webhook_url:
        data = json.dumps({'text': message}).encode('utf-8')
        req = urllib.request.Request(webhook_url, data=data, 
                                     headers={'Content-Type': 'application/json'})
        urllib.request.urlopen(req)

Lambda’yı deploy ettikten sonra SNS topic’e bağlayın:

# Lambda'ya SNS'den invoke izni ver
aws lambda add-permission 
  --function-name disk-cleanup-handler 
  --statement-id sns-invoke 
  --action lambda:InvokeFunction 
  --principal sns.amazonaws.com 
  --source-arn $TOPIC_ARN

# Lambda'yı topic'e abone yap
aws sns subscribe 
  --topic-arn $TOPIC_ARN 
  --protocol lambda 
  --notification-endpoint "arn:aws:lambda:eu-west-1:123456789:function:disk-cleanup-handler"

SNS ile Slack Entegrasyonu

Bir sysadmin olarak söylüyorum, email bildirimleri çoğu zaman gözden kaçıyor. Ekibinizin birlikte çalıştığı Slack kanalına bildirim göndermek çok daha etkili. Bunun için bir Lambda yazıp SNS’e bağlayabilirsiniz.

# Slack webhook URL'inizi Lambda environment variable olarak ekleyin
aws lambda update-function-configuration 
  --function-name sns-to-slack 
  --environment Variables="{SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T.../B.../...}"

# SNS topic policy güncellemesi - cross-account için gerekebilir
aws sns set-topic-attributes 
  --topic-arn $TOPIC_ARN 
  --attribute-name Policy 
  --attribute-value '{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Principal": {"Service": "cloudwatch.amazonaws.com"},
      "Action": "SNS:Publish",
      "Resource": "'"$TOPIC_ARN"'"
    }]
  }'

Dead Letter Queue Yapılandırması

Üretim ortamında kritik bir sorun var: SNS mesajı iletmeye çalıştı ama hedef (örneğin Lambda) defalarca hata verdi. Bu mesaj kaybolup gidecek mi? DLQ (Dead Letter Queue) ile kaybolmasını önleyebilirsiniz.

# Önce SQS DLQ oluştur
DLQ_URL=$(aws sqs create-queue 
  --queue-name sns-dlq 
  --query 'QueueUrl' 
  --output text)

DLQ_ARN=$(aws sqs get-queue-attributes 
  --queue-url $DLQ_URL 
  --attribute-names QueueArn 
  --query 'Attributes.QueueArn' 
  --output text)

echo "DLQ ARN: $DLQ_ARN"

# Lambda aboneliğine DLQ ekle
SUBSCRIPTION_ARN="arn:aws:sns:eu-west-1:123456789:production-alerts:abcdef"

aws sns set-subscription-attributes 
  --subscription-arn $SUBSCRIPTION_ARN 
  --attribute-name RedrivePolicy 
  --attribute-value "{"deadLetterTargetArn":"$DLQ_ARN"}"

# DLQ'daki mesajları kontrol et
aws sqs receive-message 
  --queue-url $DLQ_URL 
  --max-number-of-messages 10 
  --attribute-names All

Terraform ile SNS Altyapısı

Birden fazla ortamınız varsa (dev, staging, production) her şeyi elle yapmak yerine Infrastructure as Code kullanmak şart. İşte basit ama işlevsel bir Terraform yapılandırması:

# sns.tf
variable "environment" {
  description = "Ortam adi (dev/staging/prod)"
  type        = string
}

variable "ops_email" {
  description = "Ops ekibi email adresi"
  type        = string
}

# Ana alert topic
resource "aws_sns_topic" "main_alerts" {
  name = "${var.environment}-production-alerts"
  
  # Mesaj saklanamama durumunda yeniden deneme politikası
  delivery_policy = jsonencode({
    http = {
      defaultHealthyRetryPolicy = {
        minDelayTarget     = 20
        maxDelayTarget     = 20
        numRetries         = 3
        numMaxDelayRetries = 0
        numNoDelayRetries  = 0
        numMinDelayRetries = 0
        backoffFunction    = "linear"
      }
      disableSubscriptionOverrides = false
    }
  })
  
  tags = {
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

# Email aboneliği
resource "aws_sns_topic_subscription" "ops_email" {
  topic_arn = aws_sns_topic.main_alerts.arn
  protocol  = "email"
  endpoint  = var.ops_email
}

# DLQ
resource "aws_sqs_queue" "alerts_dlq" {
  name                      = "${var.environment}-alerts-dlq"
  message_retention_seconds = 1209600  # 14 gun
}

# CloudWatch Alarm - CPU
resource "aws_cloudwatch_metric_alarm" "high_cpu" {
  alarm_name          = "${var.environment}-high-cpu"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = "2"
  metric_name         = "CPUUtilization"
  namespace           = "AWS/EC2"
  period              = "300"
  statistic           = "Average"
  threshold           = "80"
  alarm_description   = "CPU kullanimi yuzde 80 ustune cikti"
  alarm_actions       = [aws_sns_topic.main_alerts.arn]
  ok_actions          = [aws_sns_topic.main_alerts.arn]
}

output "topic_arn" {
  value = aws_sns_topic.main_alerts.arn
}
# Terraform ile deploy
terraform init
terraform plan -var="environment=production" -var="[email protected]"
terraform apply -var="environment=production" -var="[email protected]"

Maliyet Optimizasyonu ve Best Practices

SNS kullanırken dikkat etmeniz gereken birkaç kritik nokta:

Mesaj boyutu limiti: Standart topic’lerde maksimum 256 KB. Büyük mesajlar için S3’e yükleyip SNS’den sadece S3 URL’ini gönderebilirsiniz.

SMS maliyetleri: Türkiye’ye SMS göndermek Kuzey Amerika’dan pahalı. Gereksiz SMS göndermekten kaçının, sadece gerçekten kritik alarmlar için kullanın.

Mesaj şifreleme: Hassas bilgiler içeren topic’lerinizi KMS ile şifreleyin:

# KMS şifreli topic oluştur
aws sns create-topic 
  --name secure-alerts 
  --attributes KmsMasterKeyId=alias/aws/sns

# Veya kendi KMS key'inizle
aws sns create-topic 
  --name secure-alerts 
  --attributes KmsMasterKeyId=arn:aws:kms:eu-west-1:123456789:key/mrk-...

Topic başına abone limiti: Bir topic’te maksimum 12.5 milyon abone olabilir ama pratik olarak birkaç bini geçince yönetim zorlaşır. Mantıklı topic grouping yapın.

CloudWatch Log’lara gönderme: SNS iletim loglarını CloudWatch’a göndererek hangi mesajların iletilip iletilmediğini izleyebilirsiniz:

# SNS iletim loglama aktif et
aws sns set-topic-attributes 
  --topic-arn $TOPIC_ARN 
  --attribute-name LambdaSuccessFeedbackRoleArn 
  --attribute-value "arn:aws:iam::123456789:role/SNSFeedbackRole"

aws sns set-topic-attributes 
  --topic-arn $TOPIC_ARN 
  --attribute-name LambdaSuccessFeedbackSampleRate 
  --attribute-value 100

Gerçek Dünya Senaryosu: E-ticaret Altyapısı

Haydi hepsini bir araya getirelim. Bir e-ticaret platformu yönettiğinizi düşünün. Gece yarısı sipariş akışı dursa ne olur? Sabah işe gelene kadar fark edemezsiniz ve bu ciddi gelir kaybı demek.

İşte bu senaryoya özel yapılandırma:

  • Ödeme sistemi topic’i: Kritik, SMS + email + Slack
  • Envanter topic’i: Yüksek, email + Slack
  • Performans topic’i: Orta, sadece Slack
  • Log topic’i: Düşük, sadece SQS (sonra analiz için)

Her servisin kendi topic’i var, mesaj filtreleme ile doğru kişiler doğru bildirimleri alıyor. Lambda entegrasyonu sayesinde ödeme sistemi 3 kez hata verirse otomatik olarak yedek ödeme gateway’ine geçiş yapılıyor. DLQ sayesinde hiçbir kritik mesaj kaybolmuyor.

Bu yapıyı devreye aldıktan sonra “kullanıcıdan öğrenmek” sorunu ortadan kalkıyor. Kullanıcı fark etmeden siz sorunu çözmüş oluyorsunuz.

Sonuç

AWS SNS, doğru yapılandırıldığında altyapınızın sinir sistemi gibi çalışıyor. Basit email bildirimiyle başlayıp Lambda otomasyonuna, mesaj filtrelemeden DLQ’ya kadar ihtiyacınıza göre genişletebilirsiniz.

Başlangıç için şu adımları takip edin: Önce bir production-alerts topic’i oluşturun, ops ekibinin emailini ekleyin, ardından en kritik CloudWatch alarmlarınızı bu topic’e bağlayın. Bu bile tek başına büyük fark yaratır.

Daha ileri gitmek istiyorsanız, Terraform ile tüm altyapıyı kodlayın ve Lambda entegrasyonuyla tekrarlayan görevleri otomatize edin. Slack entegrasyonunu da ihmal etmeyin; email bildirimleri çoğu zaman gözden kaçar ama Slack mesajları kaçmaz.

Unutmayın, en iyi monitoring sistemi, siz uyurken de sizin adınıza nöbet tutan sistemdir.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir