CoreDNS Sorun Giderme ve Log Analizi
Kubernetes cluster’ında bir şeyler ters gidince, ilk bakacağın yer genellikle CoreDNS olur. Servisler birbirini bulamıyor, pod’lar dış dünyayla konuşamıyor ya da DNS sorguları timeout’a düşüyor – bunların hepsi seni eninde sonunda CoreDNS loglarına götürür. Bu yazıda, gerçek prodüksiyon ortamlarında karşılaştığım sorunlardan yola çıkarak CoreDNS sorun giderme sürecini adım adım ele alacağım.
Temel Durum Tespiti
Sorun gidermeye başlamadan önce CoreDNS’in genel sağlık durumunu kontrol etmek gerekir. Basit görünen bu adım, aslında çok fazla zaman kazandırır.
# CoreDNS pod'larının durumunu kontrol et
kubectl get pods -n kube-system -l k8s-app=kube-dns
# Daha detaylı bilgi için
kubectl get pods -n kube-system -l k8s-app=kube-dns -o wide
# CoreDNS deployment'ını incele
kubectl describe deployment coredns -n kube-system
Çıktıda pod’ların Running durumda olduğunu görüyorsunuz diyelim, ama sorun devam ediyor. O zaman restart sayısına bakın. Eğer RESTARTS sütununda yüksek bir sayı görüyorsanız, CoreDNS sürekli çöküyor ve yeniden başlıyor demektir. Bu durumda önce neden çöktüğünü anlamak lazım.
# Mevcut log'lara bak
kubectl logs -n kube-system -l k8s-app=kube-dns
# Önceki container'ın loglarına bak (crash sonrası)
kubectl logs -n kube-system -l k8s-app=kube-dns --previous
# Belirli bir pod'un loglarını takip et
kubectl logs -n kube-system coredns-<pod-id> -f
Burada dikkat edilmesi gereken nokta: birden fazla CoreDNS pod’u çalışıyorsa, -l ile label selector kullanmak tüm pod’ların loglarını birleştirir. Bu bazen kafa karıştırıcı olabilir. Hangi pod’un hangi logu ürettiğini anlamak için pod adını açıkça belirtmek daha temiz bir yaklaşım.
Log Seviyesini Artırma
Varsayılan CoreDNS kurulumunda log plugin’i aktif değildir. Prodüksiyonda bu genellikle doğru bir tercih çünkü her DNS sorgusunu loglamak ciddi bir I/O yükü oluşturur. Ama sorun giderirken bu logsuzluk can sıkıcı bir hal alır.
CoreDNS yapılandırmasını görmek için:
kubectl get configmap coredns -n kube-system -o yaml
Tipik bir Corefile şuna benzer:
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
Log plugin’ini etkinleştirmek için:
kubectl edit configmap coredns -n kube-system
errors satırının altına şunu ekleyin:
log
Daha ayrıntılı hata ayıklama için log yerine şunu kullanabilirsiniz:
log . {
class all
}
Değişikliği uyguladıktan sonra CoreDNS pod’larını yeniden başlatmanız gerekebilir. reload plugin’i varsa otomatik algılamalı, ama her zaman güvenmemek daha sağlıklı:
kubectl rollout restart deployment coredns -n kube-system
Uyarı: Yoğun trafikli bir ortamda log plugin’ini uzun süre açık bırakmayın. Birkaç dakikalık log topladıktan sonra kapatın.
Gerçek Dünya Senaryosu: Servis Bulunamıyor
Geçen ay bir müşterinin ortamında şöyle bir durum yaşadık: Uygulama pod’ları, aynı namespace içindeki bir veritabanı servisine bağlanamıyordu. Hata mesajı connection refused değil, name resolution failed şeklindeydi. Bu DNS sorununa işaret ediyordu.
Önce sorunun DNS mi yoksa network mi olduğunu doğrulamak için test pod’u kaldırdık:
# DNS test için geçici pod
kubectl run dns-test --image=busybox:1.28 --rm -it --restart=Never -- nslookup kubernetes.default
# Daha gelişmiş araçlarla
kubectl run dns-test --image=tutum/dnsutils --rm -it --restart=Never -- bash
Pod içinden:
# Cluster içi servis çözümlemesi
nslookup myservice.mynamespace.svc.cluster.local
# Kısa form da çalışmalı (aynı namespace içindeyse)
nslookup myservice
# Dış DNS çözümlemesi
nslookup google.com
# dig ile daha detaylı
dig @10.96.0.10 myservice.mynamespace.svc.cluster.local
CoreDNS loglarına baktığımızda şunu gördük:
[ERROR] plugin/errors: 2 SERVFAIL myservice.default.svc.cluster.local. A: unreachable backend
SERVFAIL hatası genellikle upstream DNS sunucusuna erişilemiyor anlamına gelir. Bizim durumumuzda forward plugin’in yapılandırıldığı /etc/resolv.conf dosyasındaki nameserver’a erişim sorunu vardı. Node’un network politikaları değiştirilmişti ve CoreDNS pod’ları dış DNS sunucularına ulaşamıyordu.
CoreDNS Metriklerine Bakış
Prometheus endpoint’i aktifse (ki varsayılan Corefile’da prometheus :9153 satırı var), metrikleri doğrudan çekebilirsiniz:
# CoreDNS pod'una port-forward aç
kubectl port-forward -n kube-system pod/coredns-<pod-id> 9153:9153
# Başka bir terminalde metrikleri çek
curl localhost:9153/metrics | grep coredns_dns_request
İlgilenmeniz gereken temel metrikler:
- coredns_dns_requests_total: Toplam istek sayısı, type ve rcode bazında
- coredns_dns_responses_total: Yanıt sayıları
- coredns_forward_requests_total: Upstream’e yönlendirilen istekler
- coredns_forward_healthcheck_failures_total: Bu sıfırdan büyükse upstream sağlık sorunları var
- coredns_cache_hits_total ve coredns_cache_misses_total: Cache etkinliği
- coredns_dns_request_duration_seconds: Yanıt süreleri
# SERVFAIL oranını kontrol et
curl -s localhost:9153/metrics | grep 'rcode="SERVFAIL"'
# Forward plugin sağlık durumu
curl -s localhost:9153/metrics | grep coredns_forward_healthcheck_failures
Eğer coredns_forward_healthcheck_failures_total metriği sürekli artıyorsa, upstream DNS sunucunuzda sorun var demektir.
Loop Tespiti ve Çözümü
CoreDNS’in en sık karşılaşılan sorunlarından biri DNS loop’tur. loop plugin tam da bunun için var, algıladığında CoreDNS’i durdurur. Log’larda şunu görürsünüz:
[FATAL] Loop (127.0.0.1:53 -> :53) detected for zone ".", see https://coredns.io/plugins/loop#troubleshooting
Bu genellikle şu durumlarda olur: Node’un /etc/resolv.conf dosyasında 127.0.0.1 veya 127.0.0.53 (systemd-resolved) yazıyor ve CoreDNS bu adresi upstream olarak kullanmaya çalışıyor, döngü oluşuyor.
Teşhis etmek için:
# Node'da çalıştırın
cat /etc/resolv.conf
# systemd-resolved kullanılıyorsa
systemd-resolve --status | grep "DNS Servers"
Çözüm seçenekleri:
# Seçenek 1: CoreDNS'i belirli upstream DNS'e yönlendir
# Corefile'da forward satırını değiştir:
# forward . 8.8.8.8 8.8.4.4
# Seçenek 2: resolv.conf yerine Corefile'da explicit IP kullan
# forward . 1.1.1.1 1.0.0.1 {
# policy sequential
# }
Eğer systemd-resolved kullanan bir Ubuntu/Debian sistemindeyseniz:
# Node'da gerçek DNS sunucusunu bul
systemd-resolve --status | grep "Current DNS Server"
# CoreDNS configmap'ini bu IP ile güncelle
kubectl edit configmap coredns -n kube-system
ndots ve Search Domain Sorunları
Bu başlık altında anlatacağım konu, performans sorunlarının çok büyük bir kısmından sorumludur ama çoğu zaman göz ardı edilir.
Kubernetes’te varsayılan DNS politikası ndots:5 olarak ayarlıdır. Bu şu anlama gelir: Eğer sorguladığınız hostname 5’ten az nokta içeriyorsa, Kubernetes önce cluster search domain’leri ile tam adı oluşturmaya çalışır, başarısız olursa sonra bare hostname’i dener.
Örneğin google.com için bir pod sorgu yaptığında, aslında şu sırayla sorgular gider:
google.com.default.svc.cluster.local
google.com.svc.cluster.local
google.com.cluster.local
google.com.
Dört istek yapıyor sadece bir hostname için. Bunu log’larda görmek için:
kubectl logs -n kube-system -l k8s-app=kube-dns | grep "google.com"
Eğer uygulamanız çok fazla dış DNS sorgusu yapıyorsa bu ciddi bir yük oluşturur. Çözüm için pod spec’inize DNS yapılandırması ekleyebilirsiniz:
apiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
dnsConfig:
options:
- name: ndots
value: "2"
- name: single-request-reopen
containers:
- name: my-app
image: my-app:latest
ndots:2 ile birlikte google.com için sadece iki sorgu gidecektir, dördü yerine.
CoreDNS Sertifika ve Upstream TLS Sorunları
DNS-over-TLS kullanıyorsanız, sertifika sorunları da gündemin bir parçası haline gelir:
# TLS ile forward yapılandırması örneği
# Corefile'da:
# forward . tls://1.1.1.1 tls://1.0.0.1 {
# tls_servername cloudflare-dns.com
# health_check 5s
# }
TLS bağlantı sorunlarını debug etmek için:
# OpenSSL ile upstream DNS TLS bağlantısını test et
openssl s_client -connect 1.1.1.1:853 -servername cloudflare-dns.com
# CoreDNS pod'u içinden test
kubectl exec -n kube-system coredns-<pod-id> -- wget -O- https://1.1.1.1/dns-query
TLS hatalarını log’larda şöyle görebilirsiniz:
[ERROR] plugin/forward: no healthy upstream
[ERROR] plugin/forward: 1.1.1.1:853 is marked as unhealthy
Bu durumda sertifika doğrulama sorununu atlamak için geçici çözüm (sadece test ortamında!):
forward . tls://1.1.1.1 {
tls_servername cloudflare-dns.com
health_check 5s
expire 10s
}
Cache Analizi ve Optimizasyonu
CoreDNS cache plugin’i doğru yapılandırılmadığında hem performans sorunlarına hem de stale kayıt sorunlarına yol açabilir.
# Cache metriklerini kontrol et
curl -s localhost:9153/metrics | grep coredns_cache
# Örnek çıktı:
# coredns_cache_hits_total{server="dns://:53",type="success"} 45231
# coredns_cache_misses_total{server="dns://:53"} 12847
Hit oranını hesaplamak için: hits / (hits + misses). Eğer bu oran düşükse (yüzde 60’ın altında), cache TTL’ini veya cache boyutunu artırmayı düşünebilirsiniz.
Corefile’da cache yapılandırması:
cache 300 {
success 9984 300
denial 9984 5
prefetch 10 1m 10%
}
Buradaki parametreler:
- 300: Maksimum TTL (saniye)
- success 9984 300: Başarılı yanıtlar için 9984 kayıt, 300 saniye
- denial 9984 5: NXDOMAIN yanıtları için 9984 kayıt, 5 saniye
- prefetch 10 1m 10%: 10 kez sorgulanan, 1 dakika içinde süresi dolacak kayıtları önceden yenile
Eğer bir kaydın güncellendiğini ama DNS’in hala eski değeri döndürdüğünden şüpheleniyorsanız:
# Cache'i flush etmek için CoreDNS'i restart et
kubectl rollout restart deployment coredns -n kube-system
# Ya da cache plugin'e purge endpoint'i ekle (v1.7+)
# Corefile'da:
# cache 300 {
# denial 9984 5
# }
Pratik Sorun Giderme Senaryosu: Aralıklı DNS Hataları
En sinir bozucu durum budur: sorun sürekli değil, aralıklı oluyor. Sabah çalışıyor, öğleden sonra çalışmıyor, akşam tekrar çalışıyor.
Bu tür sorunları yakalamak için sürekli DNS testi yapan bir pod bırakabilirsiniz:
kubectl run dns-monitor --image=busybox:1.28 --restart=Never -- sh -c '
while true; do
result=$(nslookup kubernetes.default 2>&1)
if echo "$result" | grep -q "can't resolve"; then
echo "$(date): DNS FAILED - $result"
else
echo "$(date): DNS OK"
fi
sleep 5
done
'
# Log'ları takip et
kubectl logs dns-monitor -f
Aynı zamanda CoreDNS pod’larının kaynak kullanımını izleyin:
kubectl top pods -n kube-system -l k8s-app=kube-dns
Eğer CoreDNS pod’ları memory limit’e yaklaşıyorsa, OOMKilled ile ölebilirler. Bu aralıklı hata kalıbına yol açar çünkü pod ölüp yeniden başlarken kısa süreli DNS kesintisi yaşanır.
# OOMKilled geçmişini kontrol et
kubectl describe pods -n kube-system -l k8s-app=kube-dns | grep -A 5 "Last State"
Çözüm olarak CoreDNS kaynaklarını artırın:
kubectl edit deployment coredns -n kube-system
Resource bölümünü şu şekilde güncelleyin:
resources:
limits:
memory: 256Mi
cpu: 500m
requests:
memory: 70Mi
cpu: 100m
CoreDNS Health Endpoint Kontrolü
CoreDNS’in kendi sağlık kontrol mekanizması vardır:
# CoreDNS pod'una exec ile gir
kubectl exec -n kube-system coredns-<pod-id> -- wget -qO- http://localhost:8080/health
# Ready endpoint (tüm plugin'ler hazır mı?)
kubectl exec -n kube-system coredns-<pod-id> -- wget -qO- http://localhost:8181/ready
/health endpoint’i OK dönüyorsa CoreDNS çalışıyor demektir. /ready endpoint’i ise tüm plugin’lerin hazır olup olmadığını gösterir. Eğer ready endpoint timeout alıyorsa, bir plugin başlatma aşamasında takılmış olabilir.
Sonuç
CoreDNS sorun giderme, sabır isteyen ama bir kez öğrenildiğinde oldukça sistematik ilerlenebilen bir süreç. En önemli nokta şu: DNS sorunları her zaman doğrudan DNS sorunu olmayabilir. Network politikaları, kaynak kısıtlamaları, upstream sunucu sorunları ve yanlış yapılandırmalar DNS hataları olarak tezahür edebilir.
Şu altın kuralları aklınızda tutun: Önce kubectl get pods ile genel durumu kontrol edin, sonra kubectl logs ile log’lara bakın, ardından test pod’u ile DNS sorgularını manuel olarak deneyin. Metrikler size tablo verir, loglar ise hikayeyi anlatır. İkisini birlikte kullanın.
Prodüksiyonda log plugin’ini kalıcı açık bırakmaktan kaçının, ama sorun giderirken de log olmadan körü körüne çalışmayın. Birkaç dakikalık log toplamak çoğu zaman saatlik uğraşı önler.
Son olarak: CoreDNS versiyon notlarını takip edin. Kubernetes sürümleriyle birlikte gelen CoreDNS sürümleri arasında önemli davranış farkları olabiliyor. Bir cluster’ı yükselttiğinizde CoreDNS Corefile’ınızı da gözden geçirin.
