CoreDNS Rewrite Plugin ile DNS İstek Yönlendirme ve Alan Adı Dönüştürme
Kubernetes ortamlarında ya da kendi altyapını yönetirken DNS katmanında esneklik ihtiyacı er ya da geç karşına çıkar. Bir servisi taşıdın ama eski alan adına gelen istekleri yeni adrese yönlendirmen gerekiyor, ya da geliştirme ortamında production alan adlarını iç servislere map etmek istiyorsun. İşte tam bu noktada CoreDNS’in rewrite plugin’i devreye giriyor ve hayatını ciddi ölçüde kolaylaştırıyor.
Bu yazıda CoreDNS rewrite plugin’ini derinlemesine inceleyeceğiz. Temel sözdiziminden başlayıp gerçek dünya senaryolarına kadar her şeyi ele alacağız.
CoreDNS Rewrite Plugin Nedir?
CoreDNS, Go ile yazılmış, plugin tabanlı mimarisiyle öne çıkan modern bir DNS sunucusudur. Kubernetes’in varsayılan DNS çözümleyicisi olması sayesinde son yıllarda çok yaygınlaştı. Rewrite plugin ise gelen DNS sorgularını, sorgular backend’e ulaşmadan önce değiştirmenize ya da yanıtları istemciye dönmeden önce dönüştürmenize olanak tanır.
Birkaç önemli kullanım senaryosu şunlardır:
- İstek tarafı yeniden yazma: Gelen sorgu adını değiştirerek farklı bir alan adına yönlendirme
- Yanıt tarafı yeniden yazma: Upstream’den gelen yanıttaki alan adını değiştirme
- CNAME zinciri kırma: Gereksiz CNAME hop’larını ortadan kaldırma
- Geliştirme ortamı izolasyonu: Production URL’lerini test ortamına yönlendirme
Kurulum ve Temel Yapılandırma
CoreDNS zaten sisteminizde kuruluysa rewrite plugin varsayılan olarak geliyor. Eğer binary’yi kendiniz derliyorsanız plugin.cfg dosyasında rewrite satırının bulunduğundan emin olun.
Kubernetes kullanıyorsanız CoreDNS konfigürasyonu genellikle bir ConfigMap içinde tutulur:
kubectl -n kube-system get configmap coredns -o yaml
Kubernetes dışında bir sistemde CoreDNS’i başlatmak için şu şekilde bir Corefile oluşturabilirsiniz:
# /etc/coredns/Corefile
.:53 {
errors
health {
lameduck 5s
}
ready
log
cache 30
forward . 8.8.8.8 8.8.4.4
}
CoreDNS servisini başlatmak için:
sudo systemctl start coredns
sudo systemctl enable coredns
# Durumu kontrol et
sudo systemctl status coredns
Rewrite Plugin Sözdizimi
Rewrite plugin’in genel sözdizimi şöyle:
rewrite [continue|stop] FIELD [TYPE] FROM TO
Parametreleri açıklayalım:
- continue: Eşleşme olduktan sonra sonraki kuralları da değerlendirmeye devam et
- stop: Eşleşme olduktan sonra dur (varsayılan davranış)
- FIELD: Hangi alanın değiştirileceği.
name,class,type,edns0olabilir - TYPE: Eşleşme türü.
exact,prefix,suffix,substring,regex - FROM: Eşleştirilecek değer veya regex deseni
- TO: Dönüştürülecek değer
Temel Rewrite Senaryoları
Exact Match ile Basit Yönlendirme
En yaygın kullanım, belirli bir alan adını tam eşleşmeyle başka bir adrese yönlendirmektir. Diyelim ki eski-servis.sirket.local sorgularını yeni-servis.sirket.local‘a yönlendirmek istiyorsunuz:
.:53 {
rewrite stop name exact eski-servis.sirket.local. yeni-servis.sirket.local.
forward . 192.168.1.1
log
errors
}
Önemli bir nokta: CoreDNS dahili olarak alan adlarını FQDN (Fully Qualified Domain Name) formatında işler. Yani trailing dot (sondaki nokta) eklemeyi unutmayın, aksi takdirde eşleşme gerçekleşmeyebilir.
Prefix ile Çoklu Alan Adı Yönlendirmesi
Birden fazla alt alan adını tek kuralda yönetmek için prefix kullanabilirsiniz. Örneğin tüm dev. prefix’li sorguları staging ortamına yönlendirmek için:
.:53 {
rewrite stop name prefix dev. staging-proxy.internal.
hosts {
192.168.10.50 staging-proxy.internal
}
forward . 8.8.8.8
log
errors
}
Bu yapılandırmayla dev.api.sirket.com, dev.web.sirket.com gibi tüm sorgular staging proxy’ye gidecek.
Regex ile Gelişmiş Desen Eşleştirme
Regex desteği, rewrite plugin’in en güçlü özelliğidir. Karmaşık dönüşümler için {1}, {2} gibi yakalama gruplarını kullanabilirsiniz:
.:53 {
rewrite stop name regex ^(.+).test.sirket.com.$ {1}.production.sirket.com.
forward . 192.168.1.1
log
errors
}
Bu kural api.test.sirket.com sorgusunu api.production.sirket.com‘a dönüştürür. (.+) yakalama grubu ilk bölümü yakalar, {1} ise bunu TO kısmında kullanır.
Gerçek Dünya Senaryosu 1: Kubernetes’te Servis Geçişi
Kubernetes ortamında bir mikroservisi orders-v1 namespace’inden orders-v2 namespace’ine taşıdığınızı düşünün. Eski servisi referans eden uygulamaları hemen güncelleyemiyorsunuz. CoreDNS rewrite ile geçişi sorunsuz yapabilirsiniz.
Kubernetes CoreDNS ConfigMap’ini düzenleyelim:
kubectl -n kube-system edit configmap coredns
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
# orders-service v1'den v2'ye yönlendir
rewrite stop name exact orders-service.orders-v1.svc.cluster.local. orders-service.orders-v2.svc.cluster.local.
prometheus :9153
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
Değişikliği uyguladıktan sonra CoreDNS pod’larının yeniden yüklenmesini bekleyin:
# CoreDNS pod'larını listele
kubectl -n kube-system get pods -l k8s-app=kube-dns
# Reload'u zorla (gerekirse)
kubectl -n kube-system rollout restart deployment coredns
# Test et
kubectl run -it --rm debug --image=busybox --restart=Never -- nslookup orders-service.orders-v1.svc.cluster.local
Yanıt Tarafı Yeniden Yazma (Answer Rewrite)
Bazı durumlarda sadece sorguyu değil, dönen yanıttaki ismi de değiştirmeniz gerekir. Bu özellikle CNAME kayıtlarıyla uğraşırken önemlidir:
.:53 {
rewrite stop {
name regex ^(.+).eski-domain.com.$ {1}.yeni-domain.com.
answer name (.+).yeni-domain.com.$ {1}.eski-domain.com.
}
forward . 8.8.8.8
log
errors
}
answer name direktifi, upstream’den dönen yanıttaki alan adını istemci için geri dönüştürür. Böylece istemci kendi sorguladığı alan adıyla tutarlı bir yanıt alır.
Gerçek Dünya Senaryosu 2: Geliştirici Ortamı Split-Horizon DNS
Geliştirme ekibinin production URL’lerini kullanarak test yapabilmesi için split-horizon DNS kurgusu çok işe yarar. Geliştiricilerin api.sirket.com adresine yaptığı istekleri, yerel geliştirme sunucusuna yönlendirelim:
# /etc/coredns/Corefile - Geliştirici workstation için
.:53 {
# Production API'yi local mock'a yönlendir
rewrite stop name exact api.sirket.com. local-api-mock.dev.
rewrite stop name exact cdn.sirket.com. local-cdn.dev.
rewrite stop name exact auth.sirket.com. local-auth.dev.
hosts /etc/coredns/dev-hosts {
192.168.1.100 local-api-mock.dev
192.168.1.100 local-cdn.dev
192.168.1.100 local-auth.dev
fallthrough
}
# Diğer tüm sorgular için upstream
forward . 8.8.8.8 1.1.1.1
log
errors
cache 10
}
Bu yapılandırmayla geliştirici api.sirket.com‘u çağırdığında gerçek production sunucusu yerine yerel mock servisine ulaşır. Diğer tüm DNS sorguları normal şekilde çözümlenir.
Gerçek Dünya Senaryosu 3: Çoklu Ortam DNS Yönetimi
Büyük organizasyonlarda dev, staging ve production ortamları için farklı Corefile’lar kullanmak yaygın bir pratiktir. Ancak merkezi bir CoreDNS instance’ından tüm ortamları yönetmek de mümkündür:
# /etc/coredns/Corefile - Merkezi DNS sunucusu
# Staging ortamı sorguları
staging.sirket.internal:53 {
rewrite stop name suffix .staging.sirket.internal. .production.sirket.com.
forward . 10.0.1.1
log
errors
}
# Dev ortamı sorguları
dev.sirket.internal:53 {
rewrite continue name regex ^(.+).dev.sirket.internal.$ {1}.dev-cluster.internal.
rewrite continue name regex ^db-(.+).dev.sirket.internal.$ db-mock.dev-infra.internal.
forward . 10.0.2.1
log
errors
}
# Default zone
.:53 {
forward . 8.8.8.8 8.8.4.4
cache 300
errors
}
Burada continue direktifini kullandığımıza dikkat edin. Birden fazla kural uygulanabiliyorsa hepsinin değerlendirileceği anlamına gelir. Bu, veritabanı sorgularını mock’a yönlendirirken diğer servisleri de dönüştürmenizi sağlar.
EDNS0 ile Metadata Tabanlı Yönlendirme
Rewrite plugin yalnızca alan adlarıyla sınırlı değil. EDNS0 option’larını da değiştirebilirsiniz. Bu özellikle DNS tabanlı yük dengeleyiciler veya GeoDNS çözümleriyle entegrasyon için kullanışlıdır:
# /etc/coredns/Corefile
.:53 {
rewrite stop edns0 local set 0xffee "istanbul-datacenter"
forward . 10.10.1.1
log
errors
}
Bu yapılandırma giden sorgulara EDNS0 option ekler ve upstream sunucunun isteği hangi veri merkezinden geldiğini anlamasına yardımcı olur.
Hata Ayıklama ve Test
Rewrite kurallarını test etmek için dig komutunu kullanabilirsiniz:
# Temel sorgu testi
dig @127.0.0.1 -p 53 eski-servis.sirket.local A
# Trace modu ile detaylı inceleme
dig @127.0.0.1 -p 53 +trace api.test.sirket.com
# Kısa çıktı formatı
dig @127.0.0.1 -p 53 +short orders-service.orders-v1.svc.cluster.local
# TTL ve tüm kayıt tipleri
dig @127.0.0.1 -p 53 +noall +answer sirket.local ANY
CoreDNS log çıktısını gerçek zamanlı izlemek için:
# Systemd servis logları
journalctl -u coredns -f
# Kubernetes pod logları
kubectl -n kube-system logs -f -l k8s-app=kube-dns
# Belirli bir sorguyu filtrele
kubectl -n kube-system logs -l k8s-app=kube-dns | grep "orders-service"
CoreDNS’i debug modunda çalıştırmak için Corefile’a debug ve log direktiflerini ekleyin:
.:53 {
debug
log
errors
rewrite stop name exact test.local. production.local.
forward . 8.8.8.8
}
Yaygın Hatalar ve Çözümleri
Rewrite kurallarını yazarken sıkça karşılaşılan sorunlar ve çözümleri:
- Trailing dot unutmak: CoreDNS dahili olarak FQDN kullanır.
sirket.comyerinesirket.com.yazın. Aksi halde exact match çalışmaz.
- Regex özel karakterleri escape etmemek: Nokta (
.) regex’te herhangi bir karakteri eşler. Alan adlarında.kullanın.
- continue/stop direktifini yanlış kullanmak: Birden fazla kural uygulayacaksanız
continue, ilk eşleşmede durmak istiyorsanızstopkullanın. Varsayılanstop‘tur ama bunu açıkça belirtmek kodu daha okunabilir kılar.
- Yanıt yeniden yazma eksikliği: Sadece sorguyu yeniden yazıp yanıtı yazmamak, istemcinin beklenmedik alan adları almasına neden olabilir.
answer namebloğunu unutmayın.
- Cache sorunları: Rewrite kuralı ekledikten sonra eski DNS yanıtları cache’den gelmeye devam edebilir. Cache TTL’ini düşürün ya da cache plugin’ini geçici olarak devre dışı bırakın.
- Plugin sırası önemli: CoreDNS’te plugin’lerin Corefile’daki sırası işlenme sırasını belirler. Rewrite’ı her zaman forward ve cache’den önce tanımlayın.
Performans Optimizasyonu
Çok sayıda rewrite kuralı performansı etkileyebilir. Büyük ölçekli ortamlarda şu noktalara dikkat edin:
- Regex yerine exact/prefix/suffix kullanın: Mümkün olduğunda regex yerine daha basit eşleşme türleri kullanın. Regex her sorgu için derlenir ve işlenir.
- Kural sayısını minimize edin: On binlerce kural yerine, birkaç akıllı regex kuralı tercih edin.
- Cache’i aktif tutun: Rewrite edilmiş yanıtlar da cache’lenebilir. Cache plugin’ini mutlaka kullanın.
# Optimum cache yapılandırması
.:53 {
rewrite stop name regex ^(.+).legacy.com.$ {1}.modern.com.
cache {
success 9984
denial 9984
ttl 30
}
forward . 8.8.8.8
errors
}
Prometheus ile Monitoring
CoreDNS rewrite işlemlerini izlemek için Prometheus entegrasyonu çok değerlidir:
.:53 {
rewrite stop name exact eski.sirket.com. yeni.sirket.com.
prometheus 0.0.0.0:9153
forward . 8.8.8.8
errors
log
}
Prometheus scrape config:
# /etc/prometheus/prometheus.yml konfigürasyon parçası
scrape_configs:
- job_name: 'coredns'
static_configs:
- targets: ['localhost:9153']
scrape_interval: 15s
coredns_dns_requests_total ve coredns_dns_responses_total metrikleriyle hangi sorguların ne sıklıkla rewrite edildiğini takip edebilirsiniz.
Sonuç
CoreDNS rewrite plugin, DNS katmanında inanılmaz esneklik sağlayan güçlü bir araçtır. Kubernetes servis geçişlerinden geliştirici ortamı izolasyonuna, legacy sistemlerin modern altyapıya sorunsuz entegrasyonundan split-horizon DNS uygulamalarına kadar geniş bir kullanım yelpazesi sunar.
Pratikte en çok değer aldığım senaryolar şunlar oldu: Kubernetes’te sıfır kesinti servis geçişleri, geliştirme ekibi için production ortamını simüle eden yerel DNS yapılandırmaları ve büyük şirket birleşmelerinde iki farklı DNS namespace’ini tek çatı altında yönetmek.
Dikkat edilmesi gereken kritik nokta, her rewrite kuralını mutlaka test etmek. Yanlış bir regex deseni beklenmedik alanları da etkileyebilir. dig ile kapsamlı test, CoreDNS debug log’larıyla doğrulama ve kademeli rollout her zaman doğru yaklaşımdır.
Rewrite plugin’i doğru kullandığınızda, uygulama katmanında hiçbir değişiklik yapmadan DNS düzeyinde büyük esneklik kazanırsınız. Bu, özellikle büyük ve köklü altyapılarda “kod değiştirmeden geçiş” stratejilerinin temel taşlarından biri haline gelir.
