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.
