CoreDNS ile Chaos Engineering: DNS Arızalarını Simüle Ederek Dayanıklılık Testi Yapma

Üretim ortamınızda DNS çöktüğünde ne olur? Uygulamalarınız sessizce başarısız olur mu, yoksa kullanıcıya anlamlı bir hata mı gösterir? Bu soruların cevabını bir kriz anında öğrenmek yerine, kontrollü bir ortamda test etmek çok daha akıllıca. İşte tam burada CoreDNS’in chaos engineering yetenekleri devreye giriyor. DNS katmanında kasıtlı arızalar yaratarak sistemlerinizin gerçek dayanıklılığını ölçebilir, zayıf noktaları önceden keşfedebilirsiniz.

Chaos Engineering Neden DNS Katmanında Başlamalı?

Çoğu ekip chaos engineering deneyine uygulama katmanından başlar. Pod’ları öldürür, ağ gecikmesi ekler, CPU baskısı yaratır. Ancak DNS, modern dağıtık sistemlerin tam kalbinde yer alır ve gözden kaçan en kritik bağımlılık noktasıdır.

Düşünün: Kubernetes ortamında servisler birbirini IP adresiyle değil, DNS adıyla bulur. Bir mikroservis başka bir servise bağlanmak istediğinde önce DNS çözümlemesi yapar, sonra bağlantı kurar. DNS bu süreçte başarısız olursa, uygulama kodunuzun ne kadar iyi yazıldığının önemi kalmaz.

Gerçek dünya senaryosu: 2021 yılında yaşanan Fastly CDN kesintisi, bir DNS yapılandırma değişikliğinin nasıl domino etkisi yaratabileceğini gözler önüne serdi. Büyük yayın platformları, e-ticaret siteleri ve haber ajansları kısa sürede erişilemez hale geldi. Benzer olayların şirketinizde nasıl sonuçlanacağını bilmek istemez misiniz?

CoreDNS, özellikle Kubernetes ekosisteminde varsayılan DNS çözümleyici olarak kullanılır ve plugin mimarisi sayesinde chaos engineering senaryoları için mükemmel bir araç haline gelir.

CoreDNS Plugin Mimarisini Anlamak

CoreDNS’i güçlü kılan şey, her şeyin plugin üzerinden çalışmasıdır. Chaos senaryoları için temel olarak şu pluginleri kullanacağız:

  • errors: Hata loglama ve yönetimi
  • chaos: Kasıtlı hata enjeksiyonu (üçüncü taraf)
  • rewrite: DNS sorgularını yönlendirme ve manipüle etme
  • template: Dinamik yanıt üretme
  • health: Sağlık kontrolü endpoint’i
  • loop: Döngü tespiti

Corefile, CoreDNS’in ana yapılandırma dosyasıdır ve her plugin’i sırayla işler. Bu sıra kritiktir; bir plugin zinciri oluşturursunuz ve DNS sorgusu bu zincirden geçer.

# Mevcut CoreDNS yapılandırmanızı görüntüleme
kubectl get configmap coredns -n kube-system -o yaml

# CoreDNS pod'larını listeleme
kubectl get pods -n kube-system -l k8s-app=coredns

# CoreDNS loglarını takip etme
kubectl logs -n kube-system -l k8s-app=coredns -f

Test Ortamını Hazırlamak

Chaos testlerini asla doğrudan production ortamında çalıştırmayın. Önce izole bir test namespace’i oluşturun ve CoreDNS’i bu ortamda ayrı bir instance olarak çalıştırın.

# Test namespace'i oluşturma
kubectl create namespace dns-chaos-test

# Test için örnek bir deployment
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dns-test-client
  namespace: dns-chaos-test
spec:
  replicas: 3
  selector:
    matchLabels:
      app: dns-test-client
  template:
    metadata:
      labels:
        app: dns-test-client
    spec:
      containers:
      - name: client
        image: nicolaka/netshoot
        command: ["sleep", "infinity"]
        resources:
          requests:
            memory: "64Mi"
            cpu: "50m"
EOF

# Test client pod'una bağlanma
kubectl exec -it -n dns-chaos-test 
  $(kubectl get pod -n dns-chaos-test -l app=dns-test-client -o jsonpath='{.items[0].metadata.name}') 
  -- bash

Şimdi chaos testleri için özel bir CoreDNS ConfigMap oluşturalım. Bu ConfigMap’i production’dakinden ayrı tutacağız.

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns-chaos
  namespace: dns-chaos-test
data:
  Corefile: |
    .:53 {
        errors
        health {
            lameduck 5s
        }
        ready
        log
        prometheus :9153
        forward . 8.8.8.8 8.8.4.4
        cache 30
        loop
        reload
        loadbalance
    }
EOF

Senaryo 1: NXDOMAIN Hataları ile Servis Keşfi Testi

İlk chaos senaryomuzda belirli DNS sorgularına kasıtlı olarak NXDOMAIN yanıtı döndüreceğiz. Bu, “bu alan adı mevcut değil” hatasını simüle eder ve uygulamanızın servis bulamadığında nasıl davrandığını test eder.

# NXDOMAIN chaos Corefile
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns-chaos
  namespace: dns-chaos-test
data:
  Corefile: |
    .:53 {
        errors
        log
        
        # payment-service için kasıtlı NXDOMAIN
        template IN A payment-service.production.svc.cluster.local {
            rcode NXDOMAIN
        }
        
        # Diğer sorgular normal devam eder
        forward . /etc/resolv.conf
        cache 30
        reload
    }
EOF

Bu yapılandırmayla payment-service.production.svc.cluster.local için yapılan tüm DNS sorgularına NXDOMAIN dönecek. Test client’ınızdan şunu deneyin:

# Test pod'u içinden DNS çözümlemesi deneme
nslookup payment-service.production.svc.cluster.local
# Beklenen: ** server can't find payment-service... NXDOMAIN

# dig ile daha detaylı inceleme
dig @<chaos-dns-ip> payment-service.production.svc.cluster.local

# Normal bir servisin hala çalıştığını doğrulama
nslookup kubernetes.default.svc.cluster.local

Ne gözlemlemelisiniz?: Uygulamanız NXDOMAIN aldığında circuit breaker devreye giriyor mu? Retry mekanizması var mı ve kaç kez deniyor? Kullanıcıya hangi hata mesajı gösteriliyor?

Senaryo 2: DNS Gecikmesi Simülasyonu

Gerçek dünyada DNS sunucusu tamamen çökmez, genellikle yavaşlar. Bu senaryo, timeout değerlerini ve uygulama davranışını test etmek için kritiktir.

# Gecikme simülasyonu için özel CoreDNS deployment
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: coredns-chaos
  namespace: dns-chaos-test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: coredns-chaos
  template:
    metadata:
      labels:
        app: coredns-chaos
    spec:
      containers:
      - name: coredns
        image: coredns/coredns:1.11.1
        args: ["-conf", "/etc/coredns/Corefile"]
        volumeMounts:
        - name: config-volume
          mountPath: /etc/coredns
        ports:
        - containerPort: 53
          protocol: UDP
        - containerPort: 9153
          protocol: TCP
      volumes:
      - name: config-volume
        configMap:
          name: coredns-chaos
EOF

Gecikme için Linux tc (traffic control) aracını CoreDNS önüne bir sidecar olarak yerleştirebilirsiniz. Alternatif olarak Toxiproxy gibi araçları kullanabilirsiniz:

# Toxiproxy ile DNS gecikme proxy'si kurma
docker run -d --name toxiproxy 
  -p 8474:8474 
  -p 5353:5353/udp 
  ghcr.io/shopify/toxiproxy

# Toxiproxy CLI ile DNS proxy oluşturma
toxiproxy-cli create dns_proxy 
  --listen 0.0.0.0:5353 
  --upstream 8.8.8.8:53

# 500ms gecikme ekleme
toxiproxy-cli toxic add dns_proxy 
  --type latency 
  --attribute latency=500 
  --attribute jitter=100 
  --name dns_latency

# Timeout davranışını test etme
time dig @localhost -p 5353 google.com

# Gecikmeli yanıt istatistiklerini toplama
for i in {1..20}; do
  time dig @localhost -p 5353 google.com +noall +answer 2>&1 | grep real
done

Senaryo 3: Kısmi DNS Arızası (Split-Brain DNS)

Bu senaryo en ilginç ve tehlikeli olanlardan biridir. DNS bazı sorgulara doğru yanıt verirken, bazılarına yanlış yanıt verir. Uygulamanız yanlış bir IP’ye bağlanır ve bunu fark etmesi zordur.

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns-splitbrain
  namespace: dns-chaos-test
data:
  Corefile: |
    .:53 {
        errors
        log
        
        # Her 3 sorguda 1 kez yanlış IP döndür (simülasyon)
        # Normalde var olmayan bir IP'ye yönlendir
        template IN A database-service.production.svc.cluster.local {
            match "^database-service.production.svc.cluster.local.$"
            answer "{{ .Name }} 0 IN A 192.0.2.1"
            fallthrough
        }
        
        # Geri kalan sorgular gerçek DNS'e
        kubernetes cluster.local in-addr.arpa ip6.arpa {
            pods insecure
            fallthrough in-addr.arpa ip6.arpa
        }
        
        forward . /etc/resolv.conf
        cache 10
        reload
    }
EOF

Gerçek dünya senaryosu: Bir fintech şirketinde yaşadığım olayda, DNS önbelleği zehirlenmesi nedeniyle ödeme servisi yanlış bir veritabanı instance’ına bağlandı. Uygulama bağlantıyı kurabildi (çünkü port açıktı) ama transaction’lar sessizce başarısız oldu. Bu chaos senaryosu tam olarak böyle durumları tespit etmenizi sağlar.

Senaryo 4: DNS Cache Poisoning Simülasyonu

Önbellek zehirlenmesinin etkisini simüle etmek için, TTL değerlerini manipüle edebilir ve yanlış kayıtların uzun süre önbellekte kalmasını test edebilirsiniz.

# Cache TTL manipülasyonu ile test
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns-cache-test
  namespace: dns-chaos-test
data:
  Corefile: |
    .:53 {
        errors
        log
        
        # Çok uzun TTL ile yanlış kayıt enjekte et
        template IN A legacy-api.internal {
            answer "{{ .Name }} 3600 IN A 10.0.0.100"
        }
        
        # Normal cache süresi 30 saniye
        cache 30 {
            success 9984 30
            denial 9984 5
        }
        
        forward . /etc/resolv.conf
        reload
    }
EOF

# Cache davranışını test etme scripti
#!/bin/bash
echo "DNS Cache Poison Test Başlatılıyor..."
echo "================================"

for i in {1..10}; do
  result=$(dig @<chaos-dns-ip> legacy-api.internal +short)
  timestamp=$(date +%H:%M:%S)
  echo "[$timestamp] Sorgu $i: $result"
  sleep 5
done

echo "================================"
echo "Test tamamlandı. Önbellek temizleme testi yapılıyor..."
# CoreDNS önbelleğini temizleme
kubectl rollout restart deployment/coredns-chaos -n dns-chaos-test

Senaryo 5: DNS Flood ile Yük Testi

DNS sunucunuz yoğun sorgu altında nasıl davranır? Rate limiting doğru ayarlandı mı?

# dnsperf ile DNS yük testi
# Önce dnsperf kurulumu
apt-get install -y dnsperf

# Test sorgu dosyası oluşturma
cat > /tmp/dns-queries.txt << 'EOF'
kubernetes.default.svc.cluster.local A
coredns.kube-system.svc.cluster.local A
kube-dns.kube-system.svc.cluster.local A
metrics-server.kube-system.svc.cluster.local A
payment-service.production.svc.cluster.local A
user-service.production.svc.cluster.local A
notification-service.production.svc.cluster.local A
EOF

# 30 saniye boyunca 1000 QPS ile test
dnsperf 
  -s <chaos-dns-ip> 
  -d /tmp/dns-queries.txt 
  -t 30 
  -Q 1000 
  -l 30

# CoreDNS metrics kontrolü (Prometheus formatında)
curl http://<chaos-dns-ip>:9153/metrics | grep -E "(coredns_dns_request|coredns_dns_response)"

Otomatik Chaos Test Pipeline’ı

Manuel testler öğreticidir, ama gerçek güç otomasyonda yatar. Aşağıdaki script, bir CI/CD pipeline’ına entegre edilebilecek kapsamlı bir chaos test suite’i oluşturur.

#!/bin/bash
# dns-chaos-test.sh - Otomatik DNS Chaos Test Suite

set -euo pipefail

NAMESPACE="dns-chaos-test"
TEST_DURATION=60
FAILURE_THRESHOLD=5
RESULTS_DIR="/tmp/dns-chaos-results-$(date +%Y%m%d-%H%M%S)"

mkdir -p "$RESULTS_DIR"

log() {
  echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$RESULTS_DIR/test.log"
}

run_dns_test() {
  local test_name="$1"
  local target="$2"
  local expected_result="$3"
  local iterations=20
  local success=0
  local failure=0

  log "Test: $test_name"
  
  for i in $(seq 1 $iterations); do
    if dig @"$DNS_CHAOS_IP" "$target" +short +timeout=2 > /dev/null 2>&1; then
      ((success++))
    else
      ((failure++))
    fi
    sleep 1
  done

  local failure_rate=$(echo "scale=2; $failure * 100 / $iterations" | bc)
  log "Sonuc: Basari=$success, Basarisiz=$failure, Hata Orani=%${failure_rate}"
  
  echo "$test_name,$success,$failure,$failure_rate" >> "$RESULTS_DIR/summary.csv"
  
  if (( failure > FAILURE_THRESHOLD )); then
    log "UYARI: $test_name testi yuksek hata orani gosterdi!"
    return 1
  fi
  return 0
}

# Test 1: Normal DNS Resolution
log "=== CHAOS TEST SUITE BASLIYOR ==="
apply_chaos_config "normal"
run_dns_test "Normal_Resolution" "kubernetes.default.svc.cluster.local" "exists"

# Test 2: NXDOMAIN Chaos
apply_chaos_config "nxdomain"
run_dns_test "NXDOMAIN_Chaos" "payment-service.production.svc.cluster.local" "nxdomain"

# Test 3: Gecikme testi
apply_chaos_config "latency"
run_dns_test "Latency_Chaos" "user-service.production.svc.cluster.local" "slow"

# Rapor oluşturma
log "=== TEST RAPORU ==="
log "Sonuclar: $RESULTS_DIR/summary.csv"
cat "$RESULTS_DIR/summary.csv"

log "Chaos test suite tamamlandi."

Metrikleri ve Gözlemlenebilirliği Kurmak

Chaos testlerinin değeri, sadece arızaları simüle etmekten değil, bu arızaları gözlemleyebilmekten gelir. CoreDNS’in Prometheus endpoint’i bu noktada çok değerli veriler sunar.

# Grafana dashboard için CoreDNS metriklerini sorgulama
# DNS hata oranı
rate(coredns_dns_responses_total{rcode="NXDOMAIN"}[5m])

# DNS gecikme histogramı
histogram_quantile(0.99, rate(coredns_dns_request_duration_seconds_bucket[5m]))

# Cache hit rate
rate(coredns_cache_hits_total[5m]) / rate(coredns_dns_requests_total[5m])

# Prometheus alerting kuralları
cat <<EOF | kubectl apply -f -
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: coredns-chaos-alerts
  namespace: dns-chaos-test
spec:
  groups:
  - name: dns-chaos
    rules:
    - alert: HighDNSErrorRate
      expr: rate(coredns_dns_responses_total{rcode=~"SERVFAIL|NXDOMAIN"}[5m]) > 0.1
      for: 1m
      labels:
        severity: warning
      annotations:
        summary: "Yuksek DNS hata orani tespit edildi"
        description: "DNS hata orani {{ $value }} istegi/saniye"
    
    - alert: DNSLatencyHigh
      expr: histogram_quantile(0.99, rate(coredns_dns_request_duration_seconds_bucket[5m])) > 0.5
      for: 2m
      labels:
        severity: critical
      annotations:
        summary: "DNS yanit suresi cok yuksek"
        description: "P99 DNS gecikmesi {{ $value }} saniye"
EOF

Bulgulardan Aksiyon Almak

Chaos testleri sonucunda bulduğunuz sorunları bir framework ile ele alın:

Timeout değerlerini gözden geçirin: Uygulamanızda DNS timeout kaç saniye? Çoğu uygulama varsayılan olarak 5 saniye kullanır. Chaos testleriniz 2 saniyelik gecikmelerde bile başarısız oluyorsa, bu değerleri ayarlamanız gerekir.

Retry stratejisi tanımlayın: DNS başarısız olduğunda uygulama kaç kez dener? Exponential backoff kullanıyor mu? Chaos testleri bu davranışı gözlemlemek için mükemmel bir zemin sunar.

Önbellek stratejinizi optimize edin: DNS önbelleği doğru yapılandırılmışsa, kısa süreli DNS arızaları uygulamayı hiç etkilemeyebilir. Testlerinizde önbellek TTL değerlerinin etkisini ölçün.

Circuit breaker’ları doğrulayın: Servislerinizde Hystrix, Resilience4j veya benzeri bir circuit breaker var mı? DNS arızası senaryosunda bu mekanizmalar devreye giriyor mu?

Fallback mekanizmalarını test edin: Primary DNS başarısız olduğunda secondary DNS’e geçiş ne kadar sürüyor? Bu süre kabul edilebilir mi?

Temizlik ve Production’a Geçiş

Test tamamlandıktan sonra chaos configmap ve deployment’ları temizleyin:

# Chaos test kaynaklarını temizleme
kubectl delete configmap coredns-chaos coredns-splitbrain coredns-cache-test 
  -n dns-chaos-test 2>/dev/null || true

kubectl delete deployment coredns-chaos dns-test-client 
  -n dns-chaos-test 2>/dev/null || true

# Namespace'i silme (dikkatli olun)
kubectl delete namespace dns-chaos-test

# Production CoreDNS'in sağlıklı olduğunu doğrulama
kubectl get pods -n kube-system -l k8s-app=coredns
kubectl rollout status deployment/coredns -n kube-system

# Son bir DNS testi
kubectl run dns-test --rm -it --restart=Never 
  --image=busybox:1.35 -- nslookup kubernetes.default

Sonuç

DNS chaos engineering, çoğu ekibin ihmal ettiği ama son derece değerli bir test disiplinidir. CoreDNS’in esnek plugin mimarisi sayesinde NXDOMAIN hataları, gecikme senaryoları, split-brain durumları ve yük testlerini gerçekçi bir şekilde simüle edebilirsiniz.

Bu yazıda anlattığım senaryoları sırasıyla uyguladığınızda, büyük ihtimalle şu şeylerden birini ya da birkaçını keşfedeceksiniz: Uygulamalarınızda DNS timeout değerleri çok düşük veya çok yüksek ayarlanmış, retry mekanizmaları beklediğiniz gibi çalışmıyor, önbellek stratejiniz verimsiz, ya da circuit breaker’larınız DNS hatalarına karşı kör.

Her keşif bir iyileştirme fırsatıdır. Chaos testlerini CI/CD pipeline’ınıza entegre edin ve her büyük deployment öncesinde çalıştırın. DNS katmanındaki dayanıklılık testleri, production’da geçirilen uykusuz gecelerin sayısını ciddi ölçüde azaltır.

En iyi sysadmin, kriz olmadan krizlere hazırlanan sysadmin’dir.

Bir yanıt yazın

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