BIND Cache Yönetimi ve TTL Optimizasyonu

DNS altyapısının performansı, kullanıcı deneyimini doğrudan etkileyen kritik bir faktördür. BIND üzerinde cache yönetimini doğru yapılandırmak ve TTL değerlerini optimize etmek, hem yanıt sürelerini dramatik biçimde kısaltır hem de upstream DNS sunucularına giden sorgu yükünü önemli ölçüde azaltır. Bu yazıda BIND’ın cache mekanizmasını derinlemesine inceleyecek, TTL optimizasyonu için pratik stratejiler paylaşacak ve gerçek dünya senaryolarında karşılaşılan sorunlara çözüm üretmeye çalışacağız.

BIND Cache Nasıl Çalışır?

BIND, bir DNS sorgusuna yanıt verirken önce kendi cache’ini kontrol eder. Cache’te geçerli bir kayıt varsa bunu doğrudan döndürür, yoksa ilgili yetkili sunuculara recursive sorgu gönderir ve aldığı yanıtı hem istemciye iletir hem de cache’e yazar. Bu yapı recursive resolver mantığıyla çalışır.

Cache’in omurgası birkaç temel kavrama dayanır:

  • TTL (Time To Live): Bir DNS kaydının cache’de ne kadar süre kalacağını saniye cinsinden belirler. Yetkili sunucu bu değeri kayıtla birlikte gönderir.
  • Negative TTL: Var olmayan kayıtlar için NXDOMAIN yanıtlarının cache’de tutulma süresi. SOA kaydının minimum alanından türetilir.
  • max-cache-ttl: BIND’ın yetkili sunucudan gelen TTL değerini override ettiği üst sınır.
  • min-cache-ttl: TTL değerlerinin düşürülmesini engelleyen alt sınır.

BIND cache’i varsayılan olarak bellekte tutar. Sunucu yeniden başlatıldığında cache temizlenir. Bu basit bir gerçektir ama özellikle production ortamlarında restart işlemlerini planlarken akılda tutulması gerekir, çünkü cold start sonrası sorgu sürelerinde geçici bir artış yaşanır.

named.conf ile Temel Cache Yapılandırması

BIND’ın cache davranışını kontrol eden direktifler options bloğunda tanımlanır. Varsayılan değerler çoğu ortam için yeterli olmadığından bunları ihtiyaca göre ayarlamak gerekir.

# /etc/named.conf veya /etc/bind/named.conf.options

options {
    directory "/var/named";

    # Cache için maksimum bellek kullanımı (bytes cinsinden)
    max-cache-size 256m;

    # Upstream sunucudan gelen TTL değerini bu değerle sınırla
    max-cache-ttl 86400;

    # Negative yanıtların (NXDOMAIN) cache süresi
    max-ncache-ttl 3600;

    # TTL değeri bu değerin altındaysa bu değere yükselt
    min-cache-ttl 30;

    # Minimum negative cache TTL
    min-ncache-ttl 5;

    # Recursive sorgu izni
    recursion yes;
    allow-recursion { 10.0.0.0/8; 192.168.0.0/16; 127.0.0.1; };

    # DNSSEC doğrulama
    dnssec-validation auto;
};

Buradaki max-cache-size 256m değeri dikkat gerektiriyor. Eğer BIND sunucunuz yüksek trafikli bir ortamda çalışıyorsa bu değeri artırmanız gerekebilir. Sistemin toplam RAM’inin yaklaşık yüzde onunu BIND cache’ine ayırmak iyi bir başlangıç noktasıdır. 32 GB RAM’li bir sunucuda bu 3-4 GB anlamına gelir.

TTL Optimizasyon Stratejileri

TTL değerleri bir denge oyunudur. Çok düşük TTL değerleri upstream sunucuya giden sorgu sayısını artırır, propagasyon hızını artırır ama performansı düşürür. Çok yüksek TTL değerleri ise DNS değişikliklerinin yayılmasını geciktirir.

Kayıt Türüne Göre TTL Stratejisi

Farklı DNS kayıt türleri için farklı TTL değerleri kullanmak akıllıca bir yaklaşımdır:

  • A ve AAAA kayıtları: 300-3600 saniye. Değişme olasılığı yüksek IP adresleri için 300, stabil altyapı için 3600.
  • CNAME kayıtları: 3600-86400 saniye. Genellikle yavaş değişir.
  • MX kayıtları: 3600-86400 saniye. E-posta altyapısı değişiklikleri nadiren anlık olmaz.
  • NS kayıtları: 86400-172800 saniye. Nameserver değişiklikleri önceden planlanır.
  • TXT kayıtları: 300-3600 saniye. SPF, DKIM gibi kayıtlar güvenlik gerekçesiyle daha hızlı yayılabilmeli.
  • SOA kaydı: TTL planlamasının merkezidir, dikkatle ayarlanmalı.

Zone Dosyasında TTL Yapılandırması

# /var/named/example.com.zone

$ORIGIN example.com.
$TTL 3600   ; Varsayılan TTL - tüm kayıtlar için geçerli

@   IN  SOA ns1.example.com. admin.example.com. (
        2024010101  ; Serial
        3600        ; Refresh
        900         ; Retry
        604800      ; Expire
        300 )       ; Minimum/Negative TTL

; NS kayıtları - yüksek TTL
        86400   IN  NS  ns1.example.com.
        86400   IN  NS  ns2.example.com.

; MX kayıtları - orta TTL
        3600    IN  MX  10 mail.example.com.

; A kayıtları - değişiklik riski var, orta TTL
ns1     3600    IN  A   203.0.113.1
ns2     3600    IN  A   203.0.113.2
mail    3600    IN  A   203.0.113.10

; Web sunucusu - load balancer arkasında, düşük TTL
www     300     IN  A   203.0.113.100
www     300     IN  A   203.0.113.101

; CDN CNAME - yüksek TTL
cdn     86400   IN  CNAME   example.cdn-provider.net.

; SPF kaydı - güvenlik kritik, orta TTL
        1800    IN  TXT "v=spf1 mx ip4:203.0.113.0/24 ~all"

Burada dikkat edilmesi gereken nokta www kaydı için 300 saniyelik düşük TTL kullanımı. Bu sunucu load balancer arkasındaysa ve failover senaryoları söz konusuysa hızlı DNS güncellemesi kritik önem taşır.

Cache Yönetim Araçları

rndc ile Cache Yönetimi

rndc BIND’ın operasyonel yönetim aracıdır ve cache operasyonları için vazgeçilmezdir.

# Tüm cache'i temizle (dikkatli kullan!)
rndc flush

# Belirli bir view'ın cache'ini temizle
rndc flush external

# Belirli bir domain için cache'i temizle
rndc flushname example.com

# Belirli bir domain ve alt domainler için cache'i temizle
rndc flushtree example.com

# Cache istatistiklerini görüntüle
rndc stats
cat /var/named/data/named_stats.txt | grep -A 20 "Cache Statistics"

# Cache dump al (debug amaçlı)
rndc dumpdb -cache
cat /var/named/data/cache_dump.db | head -100

rndc flushname ile rndc flushtree arasındaki farkı anlamak önemli. flushname yalnızca belirttiğiniz ismin kaydını siler. flushtree ise o isim ve tüm alt alanlarını temizler. Örneğin rndc flushtree example.com komutu example.com, www.example.com, mail.example.com gibi tüm kayıtları cache’den atar.

dig ile Cache Analizi

# TTL değerlerini kontrol et
dig @localhost example.com A +ttlunits

# Cache'deki güncel TTL'i görüntüle (kalan süreyi gösterir)
dig @localhost www.example.com A

# Negative cache kontrolü
dig @localhost nonexistent.example.com A

# Recursion olmadan sorgula (cache'i atla)
dig @localhost example.com A +norec

# Trace ile sorgu yolunu izle
dig example.com A +trace

# DNSSEC bilgileriyle birlikte
dig @localhost example.com A +dnssec

Bir kaydın TTL’i zamanla azalır. dig çıktısında gördüğünüz TTL değeri o anki kalan süredir, orijinal TTL değil. Bunu anlamak cache davranışını debug ederken kritik öneme sahiptir.

Gerçek Dünya Senaryoları

Senaryo 1: Web Sunucusu Göçü

Şirketin web sunucusunu yeni bir IP adresine taşıyacaksınız. DNS propagasyonu sırasında bazı kullanıcıların eski sunucuya, bazılarının yeni sunucuya gitmesini engellemek istiyorsunuz.

Yaklaşım:

Göçten 24-48 saat önce TTL değerini düşürün:

# Mevcut TTL'i kontrol et
dig @ns1.example.com www.example.com A | grep -i ttl

# Zone dosyasını düzenle - TTL'i 300'e düşür
# /var/named/example.com.zone dosyasında:
# www   300   IN  A  203.0.113.100

# Serial numarasını güncelle ve reload et
rndc reload example.com

# 300 saniye (5 dakika) sonra değişiklik yayılmış olacak
# Artık IP değişikliğini güvenle yapabilirsin
# Göç tamamlandıktan sonra TTL'i tekrar yükselt
# www   3600  IN  A  203.0.113.200

Bu yaklaşım DNS propagasyon penceresini 24 saatten 5 dakikaya indirmenizi sağlar. Göç tamamlandıktan sonra TTL’i tekrar normal seviyeye çıkarın.

Senaryo 2: Yüksek Trafikli Ortamda Cache Optimizasyonu

Günde 50 milyon sorgu işleyen bir resolver için cache yapılandırması:

# /etc/named.conf

options {
    directory "/var/named";

    # Yüksek trafikli ortam için büyük cache
    max-cache-size 2048m;

    # Çok sık değişmeyen kayıtları daha uzun tut
    max-cache-ttl 86400;

    # Negative cache'i kısa tut (NXDOMAIN flood'una karşı)
    max-ncache-ttl 900;

    # Çok düşük TTL'li kayıtları biraz yükselt (upstream yükü azalt)
    min-cache-ttl 60;

    # Fetching paralelleştirme
    fetches-per-server 100;
    fetches-per-zone 100;

    # Recursive client limiti
    recursive-clients 10000;

    # Sorgu limitleme
    rate-limit {
        responses-per-second 100;
        errors-per-second 10;
        nxdomains-per-second 20;
        slip 2;
    };
};

Senaryo 3: Planned Maintenance Öncesi Cache Temizleme

Bir servis güncelleme senaryosunda cache’i kontrollü temizlemek gerekebilir:

#!/bin/bash
# dns-cache-flush.sh - Maintenance öncesi DNS cache yönetimi

DOMAIN="example.com"
LOG_FILE="/var/log/dns-maintenance.log"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')

echo "[$TIMESTAMP] Cache temizleme başlıyor: $DOMAIN" | tee -a $LOG_FILE

# Mevcut cache durumunu kaydet
rndc dumpdb -cache
cp /var/named/data/cache_dump.db /var/log/dns-cache-before-${TIMESTAMP//[ :]/-}.db

# Domain tree'yi temizle
rndc flushtree $DOMAIN
echo "[$TIMESTAMP] Cache temizlendi: $DOMAIN" | tee -a $LOG_FILE

# Temizlemenin başarılı olduğunu doğrula
RESULT=$(dig @localhost www.$DOMAIN A +short)
echo "[$TIMESTAMP] Doğrulama sorgusu sonucu: $RESULT" | tee -a $LOG_FILE

# İstatistikleri güncelle
rndc stats
echo "[$TIMESTAMP] İstatistikler güncellendi" | tee -a $LOG_FILE

echo "[$TIMESTAMP] Cache yönetimi tamamlandı" | tee -a $LOG_FILE

Cache Boyutu ve Bellek Yönetimi

Cache boyutunu doğru hesaplamak performans için kritiktir. BIND her cache girişi için yaklaşık 300-500 byte bellek kullanır. 1 milyon unique kayıt için 300-500 MB bellek gerekebilir.

# Mevcut cache kullanımını kontrol et
rndc stats
grep -i "cache" /var/named/data/named_stats.txt

# Named process'inin bellek kullanımını izle
ps aux | grep named | awk '{print "RSS: " $6/1024 " MB, VSZ: " $5/1024 " MB"}'

# Daha detaylı bellek analizi
cat /proc/$(pidof named)/status | grep -i vm

# Cache hit/miss oranını hesapla
rndc stats && grep -E "(QueryDupIn|QueryRecursive|CacheHits|CacheMisses)" 
    /var/named/data/named_stats.txt

Cache hit oranı izlemenin operasyonel değeri büyüktür. Yüzde 80’nin altına düşen hit oranı ya cache boyutunu küçük ya da TTL değerlerini çok düşük ayarladığınızın işaretidir.

Named Statistics ile Performans İzleme

# İstatistik toplamayı etkinleştir
# named.conf içinde:
statistics-channels {
    inet 127.0.0.1 port 8080 allow { 127.0.0.1; };
};

# HTTP üzerinden istatistik al
curl -s http://127.0.0.1:8080/xml/v3/server | 
    python3 -c "import sys; import xml.dom.minidom; 
    print(xml.dom.minidom.parseString(sys.stdin.read()).toprettyxml())" | 
    grep -A 2 -i "cache"

# Periyodik istatistik toplama scripti
#!/bin/bash
# dns-stats-monitor.sh

while true; do
    TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
    rndc stats 2>/dev/null

    # Cache istatistiklerini parse et
    CACHE_HITS=$(grep "cache hits" /var/named/data/named_stats.txt | 
        tail -1 | awk '{print $1}')
    CACHE_MISSES=$(grep "cache misses" /var/named/data/named_stats.txt | 
        tail -1 | awk '{print $1}')

    if [ -n "$CACHE_HITS" ] && [ -n "$CACHE_MISSES" ]; then
        TOTAL=$((CACHE_HITS + CACHE_MISSES))
        if [ $TOTAL -gt 0 ]; then
            HIT_RATIO=$(echo "scale=2; $CACHE_HITS * 100 / $TOTAL" | bc)
            echo "[$TIMESTAMP] Cache Hit Ratio: %$HIT_RATIO (Hits: $CACHE_HITS, Misses: $CACHE_MISSES)"
        fi
    fi

    sleep 60
done

DNSSEC ile Cache Güvenliği

DNSSEC etkinleştirildiğinde cache yönetimi biraz daha karmaşık hale gelir. İmzalı kayıtlar da cache’de tutulur ve RRSIG kayıtlarının kendi TTL değerleri vardır.

# DNSSEC doğrulama durumunu kontrol et
dig @localhost example.com A +dnssec +multiline

# Trust anchor kontrolü
rndc secroots
cat /var/named/data/named.secroots

# DNSSEC ile negative cache
# NSEC/NSEC3 kayıtları da cache'lenir
dig @localhost nonexistent.example.com A +dnssec

# Güven zinciri sorununu debug et
dig @localhost example.com DNSKEY +dnssec
dig @localhost example.com DS @parent-ns

# DNSSEC cache sorunlarını temizle
rndc flushtree example.com
rndc validation check

DNSSEC kullanıyorsanız min-cache-ttl değerini çok düşük tutmamaya dikkat edin. RRSIG doğrulama işlemleri CPU yoğun olduğundan, imzalı kayıtların cache’den hızla düşmesi performans sorunlarına yol açabilir.

TTL Önerileri ve Sık Yapılan Hatalar

TTL yönetiminde sık karşılaşılan hatalar ve bunlardan nasıl kaçınılacağı:

  • Tüm kayıtlar için tek TTL kullanmak: Her kayıt türünün değişim frekansı farklıdır. $TTL direktifini genel varsayılan olarak kullanın, kritik kayıtlar için override edin.
  • DNS değişikliği öncesi TTL düşürmeyi unutmak: Değişiklikten en az bir TTL periyodu önce değeri düşürün. Mevcut TTL 86400 saniyeyse (24 saat), değişiklikten 24+ saat önce harekete geçmeniz gerekir.
  • Çok düşük global TTL: TTL’i 60 saniyenin altına düşürmek upstream DNS sunucusuna aşırı yük bindirir ve latency artar. Sadece gerçekten anlık failover gerektiren kayıtlar için 60 saniye altı TTL kullanın.
  • Negative TTL’i unutmak: SOA kaydındaki minimum değer, NXDOMAIN yanıtlarının cache süresini belirler. Bu değeri çok yüksek bırakmak yeni subdomain’lerin yayılmasını geciktirir.
  • max-cache-size’ı ayarlamamak: Varsayılan değer genellikle düşük kalır. Yüksek trafikli ortamlarda BIND bellek tüketimini izlemeye almadan cache boyutunu belirsiz bırakmak tehlikeli olabilir.
# Mevcut zone'lardaki TTL dağılımını analiz et
named-checkzone example.com /var/named/example.com.zone

# Tüm zone'ları kontrol et
for zone in /var/named/*.zone; do
    echo "=== $zone ==="
    named-checkzone $(basename $zone .zone) $zone 2>&1
    grep -v "^;" $zone | awk '/IN/ {print $2}' | sort | uniq -c | sort -rn | head -5
done

Logging ile Cache Davranışını İzleme

Cache sorunlarını teşhis etmek için detaylı loglama büyük avantaj sağlar:

# named.conf içinde logging yapılandırması
logging {
    channel cache_log {
        file "/var/log/named/cache.log" versions 5 size 50m;
        severity debug 3;
        print-time yes;
        print-severity yes;
    };

    channel query_log {
        file "/var/log/named/queries.log" versions 10 size 100m;
        severity info;
        print-time yes;
    };

    category resolver { cache_log; };
    category cname { cache_log; };
    category dnssec { cache_log; };
    category queries { query_log; };
};

Logging dizinini oluşturmayı unutmayın:

mkdir -p /var/log/named
chown named:named /var/log/named
chmod 750 /var/log/named

# Log rotasyonu için logrotate yapılandırması
cat > /etc/logrotate.d/named << 'EOF'
/var/log/named/*.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    postrotate
        rndc reconfig
    endscript
}
EOF

Sonuç

BIND cache yönetimi ve TTL optimizasyonu, DNS altyapısının performansını ve güvenilirliğini doğrudan etkileyen, ancak çoğu zaman göz ardı edilen bir alan. Bu yazıda incelediğimiz konuları özetlemek gerekirse:

max-cache-size, max-cache-ttl ve min-cache-ttl parametrelerini ortamınıza göre dikkatle ayarlayın. Varsayılan değerler genellikle yeterli değildir. Kayıt türüne göre farklı TTL stratejileri benimseyin; kritik ve değişken kayıtlar için düşük, stabil kayıtlar için yüksek TTL kullanın. DNS değişiklikleri öncesinde TTL’i önceden düşürmeyi alışkanlık haline getirin; bu basit adım pek çok operasyonel kabusu ortadan kaldırır.

rndc araçlarını günlük operasyonlarınıza entegre edin. Cache hit oranını periyodik olarak izleyin ve yüzde seksenin altına düştüğünde müdahale edin. DNSSEC kullanıyorsanız cache boyutu ve TTL hesaplamalarına ekstra dikkat gösterin.

DNS altyapısı sessiz sedasız çalıştığında fark edilmez, ama sorun çıkardığında her şeyi etkiler. Cache yönetimini proaktif biçimde yapmak, gece yarısı alarm çağrılarının önüne geçmenin en etkili yollarından biridir.

Yorum yapın