1. Anasayfa
  2. Docker

DNS Cache’i Olmayan Bir Container Nasıl Production’ı Çökerttir


Modern yazılım sistemleri artık çok katmanlı ve dağıtık yapılardan oluşuyor. Microservice mimarileri, container tabanlı dağıtımlar ve dinamik servis keşifleri hayatımızı kolaylaştırdığı kadar, yeni kırılganlık alanlarını da beraberinde getiriyor.

Bu makalede, dışarıdan bakıldığında sağlıklı çalışan bir sistemin, sadece DNS çözümlemelerinin cache’lenmemesi nedeniyle nasıl zincirleme bir şekilde çöktüğünü inceleyeceğiz.

Senaryonun Başlangıcı: Sessiz Bir Tehlike

  • Uygulama konteynerleri sorunsuz çalışıyor
  • CPU, bellek, disk kullanımı normal seviyelerde
  • Monitoring araçlarında bir anormallik gözlemlenmiyor
  • Load balancer aktif, pod’lar ayakta, response time normal

Ancak birden, kullanıcılar bazı API’lerin çalışmadığını bildirmeye başlıyor. Arka arkaya gelen loglarda “timeout”, “connection refused” gibi hata mesajları görülmeye başlanıyor. İlginç olan şu ki:

  • Her şey hala “çalışıyor gibi”
  • Hiçbir servis doğrudan crash etmemiş
  • Ağ bağlantısı kesilmemiş

Fakat sistem işlevini yerine getiremiyor. Hatalar görünmüyor ama etkiliyor.

Derinlemesine İnceleme: DNS’in Görünmeyen Etkisi

İncelemeler sonucunda olayın DNS tarafında başladığı ortaya çıkıyor. Peki ne olmuştu?

Teknik Süreç:

  1. Container içinde çalışan uygulama, her outbound HTTP çağrısı öncesi DNS çözümlemesi yapıyor.
  2. Uygulama herhangi bir DNS çözümleme önbelleği kullanmıyor (ne işletim sistemi düzeyinde ne de uygulama içinde).
  3. Her sorgu 8.8.8.8 gibi harici bir DNS sunucusuna gönderiliyor.
  4. DNS sunucusunda birkaç saniyelik latency artışı (örneğin 300-500ms) yaşanıyor.
  5. Yüzlerce pod aynı anda bu sunucuya DNS sorgusu gönderiyor → DNS sunucusu yanıt veremez hale geliyor.
  6. Uygulama, çözümleyemediği hostname’ler nedeniyle bağlantı kuramıyor → timeout zinciri başlıyor.
  7. Downstream servisler erişilemez hale geliyor, bazıları bağlantı kuyruğunda boğuluyor.
  8. Load balancer’lar backend’i “fail” olarak işaretliyor → fallback tetikleniyor ama cache yok.

Teknik Kırılım: DNS Nasıl Çalışır ve Neden Cache Önemlidir?

DNS (Domain Name System), bir alan adını (örneğin api.myservice.com) IP adresine çeviren bir sistemdir. Bu çözümleme süreci 4 seviyede gerçekleşir:

  1. Yerel Resolver (cache): İlk olarak sistem belleğindeki önbelleğe bakılır.
  2. /etc/hosts dosyası: Manuel tanımlı adres varsa kullanılır.
  3. Recursive DNS Resolver: Genellikle resolv.conf dosyasındaki adresler kullanılır.
  4. Root, TLD ve Authoritative DNS: Gerekirse zincirin sonunda gerçek DNS sağlayıcısına ulaşılır.

DNS Cache’in Rolü

DNS çözümlemesi hızlı gibi görünse de, her sorgunun recursive şekilde yukarıdaki aşamalardan geçmesi milisaniyelerle ifade edilen gecikmelere neden olabilir. Çok sayıda sorguda bu, sistemde ciddi gecikmelere yol açar.

Ayrıca:

  • DNS sunucuları rate-limit uygular.
  • Ağ gecikmesi, paket kaybı gibi etmenlerle birleşince çözümleme süreleri uzar.
  • Aynı sorguların tekrar tekrar yapılması büyük bir israf ve risk doğurur.

Container’larda Neden Bu Kadar Kırılgan?

Container ortamlarında (özellikle Docker/Kubernetes), DNS çözümlemesi izole bir ağ ortamında çalışır. Çoğu zaman aşağıdaki sorunlar görülür:

  1. Minimal container image’lar (alpine, distroless gibi) sistem cache mekanizmalarını içermez.
  2. glibc yerine musl kullanılan sistemlerde nscd gibi DNS cache daemon’ları çalışmaz.
  3. Uygulama dilleri (örn: Go) kendi DNS resolver’ını kullanır ve işletim sistemine bağımlı değildir.
  4. Kubernetes ortamında CoreDNS sorgularını hızla peş peşe alan binlerce pod nedeniyle throttling yaşanabilir.

Görünmeyen Krizin Belirtileri

Bu tip problemler, klasik monitoring sistemleriyle tespit edilmez. Aşağıdaki belirtiler gözlemlenebilir:

BelirtiAçıklama
Yavaşlayan response timeÖzellikle dış servislere yapılan çağrılarda
Aralıklı timeout hatalarıBazı servislerde zaman zaman yanıt alınamaması
Connection refusedDNS çözümleme başarısızsa IP bile bulunamaz
“Pod sağlıklı” ama çalışmıyorHealth check’ler IP’yi çözdüğü sürece pod “healthy” gözükür
Servis discovery hatalarıSRV veya A kayıtlarının çözülememesi

Nasıl Önlenebilir?

1. Lokal DNS Cache Daemon Kullanın

Container içinde DNS cache proxy kurarak çözümlemeleri lokal olarak saklayabilirsiniz:

apt install dnsmasq

/etc/resolv.conf dosyasını şu şekilde yapılandırın:

nameserver 127.0.0.1

2. CoreDNS Cache Plugin (Kubernetes)

Kubernetes cluster’ınızda CoreDNS konfigürasyonuna şu bloğu ekleyin:

cache 30

Bu sayede aynı DNS sorgusu için 30 saniyelik bir cache süresi uygulanır.

3. Uygulama DNS Ayarlarını Gözden Geçirin

Özellikle Go, Java, Python gibi dillerde DNS cache süreleri ayarlanabilir:

Java:

security.provider.1=sun.security.provider.Sun
networkaddress.cache.ttl=60

Go:

Go’nun net.Resolver çözümleyicisi genellikle işletim sistemi çözümleyicisini atlayabilir.

Python:

requests veya aiohttp gibi kütüphaneler DNS çözümlemeyi her istek için yeniden yapabilir.

4. Observability Araçları ile DNS Trafiğini İzleyin

  • tcpdump ile DNS sorgularını gözlemleyiniz tcpdump -i eth0 port 53
  • strace ile DNS çağrılarını yakalayınız: strace -e trace=network ./app
  • dig, drill, resolvectl ile manuel çözümleme süresi ölçümleri yapın.

5. Harici DNS’e Bağımlılığı Azaltın

  • Internal DNS sunucuları (örneğin bind, unbound) kullanın.
  • Kubernetes servisleri için FQDN kullanmak yerine ClusterIP veya DNS SRV kayıtları tercih edin.
  • Eğer mümkünse servis discovery’i DNS dışı bir protokolle gerçekleştirin (örn: Consul, Istio, gRPC resolver).

DNS sorunları genellikle loglara yansımaz. Uygulama hatası gibi görünmez. Ancak sonuçları zincirleme şekilde tüm sistemde hissedilir. Özellikle cache yapılmayan DNS sorguları yüzünden:

  • Ağ yükü artar
  • DNS servisleri çökebilir
  • Servis discovery başarısız olur
  • Sistem kullanılamaz hale gelir

Bu yüzden DNS konfigürasyonu bir “altyapı detayı” değil, doğrudan uygulama güvenilirliği stratejisinin parçası olmalıdır.

İlginizi Çekebilir