CoreDNS ile Fallthrough ve Fallback Yapılandırması

Kubernetes ortamında DNS sorunlarını ayıklarken fark ettim ki çoğu mühendis CoreDNS’in fallthrough ve fallback mekanizmalarını birbirine karıştırıyor ya da hiç kullanmıyor. Bu iki özellik aslında çok farklı problemleri çözüyor ve doğru kullanıldığında DNS altyapınızı ciddi ölçüde esnekleştiriyor. Gelin bu ikisini derinlemesine inceleyelim.

Fallthrough ve Fallback: Kavramsal Ayrım

Önce zihinsel modeli oturtmak lazım. CoreDNS plugin tabanlı bir mimariye sahip. Her DNS sorgusu, Corefile’da tanımladığınız plugin zincirinden geçiyor. Bu zincirde bir plugin sorguyu yanıtlayabilir, reddedebilir ya da bir sonraki plugin’e devredebilir.

Fallthrough, bir plugin’in sorguyu yanıtlayamadığında “ben bunu bilmiyorum, bir sonraki plugin’e bak” demesini sağlar. Yani zincirleme devir işlemi. Kritik nokta: hata durumunda değil, yanıt bulunamadığında devretmesi.

Fallback ise tamamen farklı bir senaryo. Upstream DNS sunucunuz yanıt vermediğinde ya da SERVFAIL döndürdüğünde devreye giren alternatif yönlendirme mekanizması. Birincil sunucu çöktüğünde yedek sunucuya geçiş gibi düşünebilirsiniz.

Bu ayrımı anlamadan yapılandırma yazmaya kalkmak, ileride başınıza beklenmedik sorunlar açar.

Temel Corefile Yapısı

Başlamadan önce basit bir Corefile örneği:

. {
    hosts /etc/coredns/hosts {
        192.168.1.10 internal.example.com
        fallthrough
    }
    forward . 8.8.8.8 8.8.4.4
    cache 300
    log
    errors
}

Burada hosts plugin’i önce kendi dosyasına bakıyor. internal.example.com için kayıt varsa onu döndürüyor. Ama sorgu başka bir alan adına gelirse ve hosts dosyasında karşılık yoksa, fallthrough sayesinde zincirdeki bir sonraki plugin’e, yani forward‘a geçiyor.

fallthrough olmadan ne olurdu? Plugin “kayıt yok, NXDOMAIN döner” diye yanıt üretirdi ve zincir orada kesilirdi. İnternet adreslerine erişemezdiniz.

Hosts Plugin ile Fallthrough Kullanımı

Gerçek dünya senaryosu: Şirket içi bazı alan adlarını statik olarak tanımlamak istiyorsunuz ama geri kalan her şeyin internete çıkmasını istiyorsunuz.

. {
    hosts /etc/coredns/custom-hosts {
        192.168.10.5  gitlab.sirket.local
        192.168.10.6  nexus.sirket.local
        192.168.10.7  jenkins.sirket.local
        10.0.0.1      monitoring.sirket.local
        
        ttl 60
        reload 30s
        fallthrough
    }
    
    forward . 10.0.0.53 {
        prefer_udp
    }
    
    cache 300
    health
    log
    errors
}

reload 30s parametresi önemli: hosts dosyasını her 30 saniyede bir kontrol ediyor, değişiklik varsa yeniden yüklüyor. Bu sayede CoreDNS’i restart etmeden hosts dosyasını güncelleyebiliyorsunuz.

Şimdi birden fazla zone için fallthrough:

example.com {
    file /etc/coredns/zones/example.com.db {
        fallthrough
    }
    log
}

. {
    forward . 8.8.8.8
    cache 300
}

Bu yapıda example.com için yerel zone dosyası kullanılıyor. Zone dosyasında bulunmayan bir kayıt sorgulandığında fallthrough devreye giriyor ve query yukarı çıkıyor, ama bu sefer de bulunamazsa forward’a gidiyor.

File Plugin ile Kapsamlı Fallthrough

Zone dosyası kullanırken daha ince bir nokta var. fallthrough direktifi domain listesi de alabiliyor:

. {
    file /etc/coredns/zones/internal.db {
        fallthrough example.com sirket.local
    }
    forward . 8.8.8.8 1.1.1.1
    cache 600
    log
    errors
}

Bu yapılandırmada zone dosyası sadece example.com ve sirket.local için yanıt bulunamazsa fallthrough yapıyor. Diğer domainler için zone dosyası zaten yanıt üretmeyecek (kendi scope’u dışında) ama bu direktif davranışı netleştiriyor.

Fallback Plugin Kurulumu

fallback plugin’i CoreDNS’in harici plugin’i, yani varsayılan olarak gelmiyor. External plugin olduğu için build aşamasında dahil etmeniz gerekiyor.

Önce plugin.cfg’ye ekleyin:

# plugin.cfg dosyasına fallback satırını ekleyin
# Doğru pozisyona dikkat edin, forward'dan sonra ama önce olmamalı

git clone https://github.com/coredns/coredns.git
cd coredns

# plugin.cfg'yi düzenleyin
# fallback:github.com/coredns/fallback satırını ekleyin
sed -i '/^forward/a fallback:github.com/coredns/fallback' plugin.cfg

make

Kubernetes ortamındaysanız ve custom image build etmek istemiyorsanız, alternatif olarak secondary veya alternate plugin’leri benzer işlevler sunuyor ve bazı dağıtımlarda mevcut.

Fallback plugin’in temel sözdizimi:

. {
    fallback RCODE ZONE upstream_server
}

Basit bir örnek, primary DNS yanıt vermezse veya SERVFAIL dönerse yedek sunucuya geç:

. {
    forward . 10.0.0.53
    fallback SERVFAIL . 8.8.8.8
    cache 300
    log
    errors
}

Gerçek Dünya Senaryosu: Hybrid DNS Mimarisi

Diyelim ki şirketinizde iki ortam var: on-premise ve bulut. On-premise uygulamalar internal.company.com altında, bulut servisleri ise cloud.company.com altında. Hem internal hem external DNS sunucusu var ve bunlar bazen kararsız davranıyor.

# Hybrid ortam için kapsamlı Corefile

internal.company.com {
    forward . 10.10.0.10 10.10.0.11 {
        policy round_robin
        health_check 5s
        expire 30s
    }
    fallback SERVFAIL internal.company.com 10.10.0.12
    cache 120 {
        success 800
        denial 100
        prefetch 10
    }
    log
    errors
}

cloud.company.com {
    forward . 10.20.0.10 {
        prefer_udp
    }
    fallback SERVFAIL cloud.company.com 8.8.8.8
    cache 300
    log
}

. {
    hosts /etc/coredns/overrides {
        192.168.1.100 legacy-app.old-domain.com
        fallthrough
    }
    forward . 1.1.1.1 8.8.8.8 {
        policy sequential
        max_fails 3
        expire 60s
    }
    cache 300
    log
    errors
    health :8080
    prometheus :9153
}

Bu yapıda:

  • Internal DNS sunucuları round-robin ile yük dengeleniyor
  • Herhangi biri SERVFAIL dönerse üçüncü sunucu devreye giriyor
  • Cloud DNS için birincil sunucu çöktüğünde Google DNS yedek olarak kullanılıyor
  • Legacy bir uygulamanın alan adı hosts override ile çözümleniyor
  • Geri kalan her şey Cloudflare ve Google DNS’e gidiyor, sıralı politikayla

Kubernetes’te ConfigMap ile Yönetim

Kubernetes’te CoreDNS’in ConfigMap’i genellikle şöyle görünür, ama fallthrough ile zenginleştirilmiş hali:

apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        health {
           lameduck 5s
        }
        ready
        
        kubernetes cluster.local in-addr.arpa ip6.arpa {
           pods insecure
           fallthrough in-addr.arpa ip6.arpa
           ttl 30
        }
        
        hosts /etc/coredns/customdomains {
           10.96.0.200  external-db.company.com
           10.96.0.201  message-broker.company.com
           fallthrough
        }
        
        prometheus :9153
        
        forward . /etc/resolv.conf {
           max_concurrent 1000
        }
        
        cache 30
        loop
        reload
        loadbalance
    }

Burada dikkat edilmesi gereken kubernetes plugin’indeki fallthrough in-addr.arpa ip6.arpa satırı. Bu olmadan reverse DNS sorguları Kubernetes’te düzgün çalışmıyor. Pod’ların IP’leri üzerinden hostname çözümlemesi bozuluyor ki bu bazı uygulamaların (özellikle eski Java uygulamalarının) çalışmamasına yol açıyor.

Fallthrough ile Sorun Giderme

Debug için en değerli araç log plugin’ini verbose modda kullanmak:

. {
    log . {
        class all
    }
    
    hosts /etc/coredns/test-hosts {
        192.168.1.1 test.example.com
        fallthrough
    }
    
    forward . 8.8.8.8
    errors
}

CoreDNS loglarını izleyin:

# Pod loglarını takip et
kubectl logs -n kube-system -l k8s-app=kube-dns -f --tail=100

# Belirli bir domain için filtreleme
kubectl logs -n kube-system -l k8s-app=kube-dns | grep "test.example.com"

# Systemd ile çalışıyorsa
journalctl -u coredns -f | grep -E "(SERVFAIL|NXDOMAIN|fallthrough)"

CoreDNS’in query logları [INFO] prefix’iyle geliyor ve şöyle görünüyor:

[INFO] 10.244.1.5:52341 - 12345 "A IN test.example.com. udp 45 false 512" NOERROR qr,aa,rd 67 0.000234s
[INFO] 10.244.1.5:52342 - 12346 "A IN unknown.domain.com. udp 49 false 512" - - - 0s

İkinci satırda - görmek fallthrough gerçekleştiğini değil, plugin’in yanıt üretmediğini gösteriyor. Gerçek fallthrough’u takip etmek için trace plugin’ini kullanabilirsiniz ama bu production’da çok fazla log üretir.

Yaygın Hatalar ve Çözümleri

Plugin sırası yanlış: CoreDNS’te plugin sırası kritik. fallthrough düzgün çalışsın istiyorsanız plugin’lerin sırası Corefile’daki gibi değil, plugin.cfg‘deki gibi işleniyor. Ama genel kural şu: hosts‘u her zaman forward‘dan önce tanımlayın.

Fallthrough scope karışıklığı: fallthrough sadece tek bir plugin bloğuna ait. Şunu yazmak hata:

# YANLIS - fallthrough'u yanlış yerde kullanmak
. {
    forward . 8.8.8.8
    fallthrough  # Bu burada anlamsız, forward zaten son plugin
    cache 300
}

Doğrusu:

# DOGRU
. {
    hosts /etc/coredns/hosts {
        fallthrough  # hosts plugin'ine ait
    }
    forward . 8.8.8.8
    cache 300
}

Cache ile etkileşim: Fallthrough sonucu dönen yanıtlar cache’leniyor ama bazen beklenmedik şekillerde. Eğer önce hosts’tan yanıt verdiyse sonra hosts’tan silseniz bile cache süresi dolmadan eski yanıtı görebilirsiniz. Bunu önlemek için:

. {
    hosts /etc/coredns/hosts {
        fallthrough
    }
    forward . 8.8.8.8
    cache 60 {  # Düşük TTL
        success 200
        denial 50
        prefetch 5
    }
}

Performans Optimizasyonu

Fallthrough zinciri ne kadar uzunsa sorgu süresi o kadar artıyor. Her plugin atlama bir maliyet. Birkaç pratik öneri:

Prefetch ile cache ısıtmak: Sık kullanılan domainler için cache prefetch’i açın:

cache 3600 {
    success 10000
    denial 500  
    prefetch 20 1m 10%
}

Bu direktif: TTL’nin %10’u kalmışsa ve son 1 dakikada en az 20 kez sorgulanmışsa cache’i önceden yenile.

Health check aralığını ayarlama: Forward plugin’deki health check aralığı fallback’in ne kadar hızlı devreye gireceğini belirliyor:

forward . 10.0.0.53 {
    max_fails 2
    expire 15s
    health_check 3s
}

max_fails 2 demek: art arda 2 başarısız denemeden sonra sunucuyu geçici olarak devre dışı bırak. expire 15s ise: devre dışı bırakılan sunucuyu 15 saniye sonra tekrar dene.

Monitoring ve Alerting

Fallback mekanizmalarının ne zaman ve ne sıklıkla devreye girdiğini izlemek önemli. Prometheus ile:

# CoreDNS prometheus metriklerini etkinleştirin
. {
    prometheus :9153
    # ...diğer pluginler
}

Kritik metrikler:

  • coredns_dns_requests_total: Toplam sorgu sayısı, tip ve rcode’a göre ayrışık
  • coredns_forward_requests_total: Forward edilen sorgular
  • coredns_forward_healthcheck_failures_total: Sağlık kontrolü başarısızlıkları, fallback’in ne sıklıkla tetiklendiğini gösterir
  • coredns_cache_hits_total ve coredns_cache_misses_total: Cache verimliliği

Bir Prometheus alert örneği, DNS çözümleme başarı oranı düştüğünde:

- alert: CoreDNSHighServfailRate
  expr: |
    rate(coredns_dns_responses_total{rcode="SERVFAIL"}[5m]) /
    rate(coredns_dns_requests_total[5m]) > 0.05
  for: 2m
  labels:
    severity: warning
  annotations:
    summary: "CoreDNS SERVFAIL orani yüksek"
    description: "Son 5 dakikada sorgularin %5'inden fazlasi SERVFAIL donuyor. Fallback mekanizmasi devrede olabilir."

Sonuç

fallthrough ve fallback‘i doğru kullanmak, DNS altyapınızın hem esnek hem de dayanıklı olmasını sağlıyor. Fallthrough, plugin zincirindeki yanıt devrini yönetirken fallback, upstream sunucu başarısızlıklarına karşı sigorta görevi görüyor.

Pratikte en çok işe yarayan yapılandırma şablonu şu: statik kayıtlar için hosts ya da file plugin ile fallthrough, upstream DNS için forward ile health check ve expire parametreleri, kritik ortamlarda ise fallback plugin ile yedek sunucu tanımı. Bunların üzerine cache ve prometheus monitoring ekleyince production’a hazır bir DNS katmanı elde ediyorsunuz.

Son bir not: CoreDNS’i değiştirmeden önce mutlaka mevcut Corefile’ı yedekleyin ve test ortamında deneyin. Kubernetes cluster’ında DNS bozulduğunda her şey bozuluyor, bunu zor yoldan öğrenmek istemezsiniz.

Bir yanıt yazın

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