CoreDNS ile Etcd Backend Kullanımı

Kubernetes ortamında ya da büyük ölçekli bir microservice altyapısında çalışıyorsanız, büyük ihtimalle CoreDNS ile karşılaşmışsınızdır. Ama CoreDNS’in etcd backend ile nasıl kullanıldığını, bu ikiliyle nasıl dinamik DNS yönetimi yapılabileceğini bilen sysadmin sayısı bir hayli az. Bu yazıda sıfırdan kurulumdan başlayarak gerçek hayatta karşılaştığım senaryolara kadar her şeyi anlatacağım.

CoreDNS ve Etcd Kombinasyonu Neden Mantıklı?

CoreDNS’i sadece Kubernetes’in dahili DNS çözücüsü olarak bilmek, bu aracı hafife almak demek. CoreDNS aslında plugin tabanlı mimarisiyle son derece esnek bir DNS sunucusu. Etcd backend eklentisi devreye girdiğinde ise elimizde gerçek anlamda programlanabilir, dağıtık, yüksek erişilebilirlik destekli bir DNS altyapısı oluyor.

Neden etcd? Çünkü etcd zaten çoğu Kubernetes ortamında var. Ayrıca watch mekanizması sayesinde DNS kayıtlarınızda yaptığınız değişiklikler neredeyse anında servise yansıyor. Geleneksel zone dosyası tabanlı yaklaşımlarda reload tetiklemek, zonemanager’ı uyandırmak gibi ekstra adımlar gerektiriyordu. Burada hiçbiri yok.

Bir de şunu söyleyeyim: Bu kombinasyonu özellikle şu senaryolarda çok işe yarar buluyorum:

  • Servis keşfi (service discovery) gerektiren microservice altyapıları
  • Kubernetes dışındaki servislerin de DNS üzerinden yönetilmesi gereken hibrit ortamlar
  • Otomatik DNS kayıt oluşturma/silme yapacak CI/CD pipeline’ları
  • Birden fazla datacenter veya region’da çalışan dağıtık sistemler

Ortam Hazırlığı ve Gereksinimler

Ben bu yazıyı Ubuntu 22.04 üzerinde test ettim. Etcd 3.5.x ve CoreDNS 1.11.x kullandım. Kubernetes’siz, bare-metal bir kurulum yapacağız çünkü kavramları daha net görmek için Kubernetes soyutlamasını aradan çıkarmak gerekiyor.

Önce etcd’nin kurulu olduğundan emin olun:

# Etcd versiyonunu kontrol et
etcdctl version

# Etcd cluster sağlığını kontrol et
etcdctl endpoint health --endpoints=http://127.0.0.1:2379

CoreDNS binary’sini indirmek için:

# CoreDNS son versiyonu indir
wget https://github.com/coredns/coredns/releases/download/v1.11.1/coredns_1.11.1_linux_amd64.tgz

tar -xzf coredns_1.11.1_linux_amd64.tgz

# Binary'yi system path'e taşı
sudo mv coredns /usr/local/bin/

# Çalıştırılabilir olduğunu doğrula
coredns -version

Etcd’yi systemd ile ayakta tutuyorsanız şu konfigurasyon yeterli olacaktır. Ama biz burada tek node etcd kuruyoruz, production’da etcd cluster kurulumu ayrı bir yazı konusu.

CoreDNS Corefile Yapılandırması

CoreDNS’in kalbi Corefile. Etcd backend’i aktif etmek için şu yapıyı kullanıyoruz:

# /etc/coredns/Corefile

. {
    etcd skunk.local {
        stubzones
        path /skunk/dns
        endpoint http://localhost:2379
        upstream /etc/resolv.conf
        fallthrough
    }
    forward . 8.8.8.8 8.8.4.4
    cache 30
    log
    errors
}

Buradaki parametreleri açıklayayım:

  • etcd skunk.local: Bu plugin’i skunk.local zone’u için aktif et
  • stubzones: Etcd’de bulunan zone bilgilerini kullan
  • path /skunk/dns: Etcd’deki key prefix’i. Tüm DNS kayıtları bu path altında saklanacak
  • endpoint: Etcd’nin dinlediği adres
  • upstream: Forward sorguları için kullanılacak resolver
  • fallthrough: Etcd’de bulunamazsa bir sonraki plugin’e geç
  • forward: Etcd’de bulunamayan sorgular için upstream DNS
  • cache 30: 30 saniye cache süresi

Bu yapıyı kaydedin ve CoreDNS’i başlatın:

# Test amaçlı ön planda çalıştır
sudo coredns -conf /etc/coredns/Corefile

Etcd’ye DNS Kaydı Yazma

Etcd backend, kayıtları JSON formatında ve belirli bir path yapısında bekliyor. Kural şu: domain adını tersine çevirip etcd path’ine yazıyorsunuz.

Örneğin web.skunk.local için etcd key’i şu oluyor: /skunk/dns/local/skunk/web

# A kaydı ekle: web.skunk.local -> 192.168.1.100
etcdctl put /skunk/dns/local/skunk/web '{"host":"192.168.1.100","ttl":300}'

# Doğrulama
etcdctl get /skunk/dns/local/skunk/web

Şimdi bu kaydı sorgulayalım:

# DNS sorgusu yap
dig @127.0.0.1 web.skunk.local A

# Beklenen çıktı
# web.skunk.local. 300 IN A 192.168.1.100

Birden fazla A kaydı eklemek istiyorsanız, key’e unique suffix eklemeniz gerekiyor:

# Load balancing için birden fazla A kaydı
etcdctl put /skunk/dns/local/skunk/web/x1 '{"host":"192.168.1.100","ttl":300}'
etcdctl put /skunk/dns/local/skunk/web/x2 '{"host":"192.168.1.101","ttl":300}'
etcdctl put /skunk/dns/local/skunk/web/x3 '{"host":"192.168.1.102","ttl":300}'

Bu üç kayıt sorgulandığında CoreDNS round-robin şeklinde cevap verecek. Basit ama etkili bir load balancing.

SRV ve CNAME Kayıtları

A kaydının yanı sıra SRV ve CNAME kayıtları da ekleyebiliyorsunuz. SRV kayıtları özellikle servis keşfinde kritik.

# CNAME kaydı: www.skunk.local -> web.skunk.local
etcdctl put /skunk/dns/local/skunk/www '{"host":"web.skunk.local","ttl":300}'

# SRV kaydı: _http._tcp.skunk.local
# port 80, priority 10, weight 100
etcdctl put /skunk/dns/local/skunk/_tcp/_http '{"host":"web.skunk.local","port":80,"priority":10,"weight":100,"ttl":300}'

# SRV kaydını sorgula
dig @127.0.0.1 _http._tcp.skunk.local SRV

TXT kaydı da ekleyebilirsiniz, SPF veya doğrulama amaçlı kullanımlar için:

# TXT kaydı ekle
etcdctl put /skunk/dns/local/skunk/txt/info '{"text":"v=spf1 ip4:192.168.1.0/24 ~all","ttl":300}'

Systemd Servisi Olarak Yapılandırma

Production’da CoreDNS’i systemd altında çalıştırmak gerekiyor. Şu unit dosyasını kullanıyorum:

# /etc/systemd/system/coredns.service dosyasını oluştur
cat <<EOF | sudo tee /etc/systemd/system/coredns.service
[Unit]
Description=CoreDNS DNS Server
Documentation=https://coredns.io
After=network.target etcd.service
Wants=etcd.service

[Service]
Type=simple
User=coredns
ExecStart=/usr/local/bin/coredns -conf /etc/coredns/Corefile
Restart=on-failure
RestartSec=5s
LimitNOFILE=1048576
LimitNPROC=512
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target
EOF

# Servis kullanıcısını oluştur
sudo useradd -r -s /bin/false -M coredns

# Konfig dizinine izin ver
sudo chown -R coredns:coredns /etc/coredns

# Servisi etkinleştir ve başlat
sudo systemctl daemon-reload
sudo systemctl enable coredns
sudo systemctl start coredns
sudo systemctl status coredns

Gerçek Dünya Senaryosu: Dinamik Servis Kaydı

Şimdi işin ilginç kısmına gelelim. Diyelim ki bir uygulama deploy edildiğinde otomatik olarak DNS kaydı oluşturulsun, uygulama kalktığında ise kayıt silinsin istiyorsunuz. Bu tam anlamıyla etcd backend’in parladığı yer.

Bir bash script ile bunu nasıl yapabileceğimizi göstereyim:

#!/bin/bash
# dns-register.sh

ETCD_ENDPOINT="http://localhost:2379"
DNS_PATH="/skunk/dns"
DOMAIN_SUFFIX="local/skunk"

register_service() {
    local service_name=$1
    local ip_address=$2
    local port=$3
    local ttl=${4:-300}

    # A kaydı oluştur
    local a_key="${DNS_PATH}/${DOMAIN_SUFFIX}/${service_name}"
    local a_value="{"host":"${ip_address}","ttl":${ttl}}"

    etcdctl --endpoints=${ETCD_ENDPOINT} put "${a_key}" "${a_value}"

    # SRV kaydı oluştur (eğer port belirtildiyse)
    if [ -n "$port" ]; then
        local srv_key="${DNS_PATH}/${DOMAIN_SUFFIX}/_tcp/_${service_name}"
        local srv_value="{"host":"${service_name}.skunk.local","port":${port},"priority":10,"weight":100,"ttl":${ttl}}"
        etcdctl --endpoints=${ETCD_ENDPOINT} put "${srv_key}" "${srv_value}"
    fi

    echo "[OK] ${service_name}.skunk.local -> ${ip_address}:${port} kaydedildi"
}

deregister_service() {
    local service_name=$1

    etcdctl --endpoints=${ETCD_ENDPOINT} del "${DNS_PATH}/${DOMAIN_SUFFIX}/${service_name}"
    etcdctl --endpoints=${ETCD_ENDPOINT} del "${DNS_PATH}/${DOMAIN_SUFFIX}/_tcp/_${service_name}"

    echo "[OK] ${service_name}.skunk.local kaydı silindi"
}

# Kullanım
case "$1" in
    register)
        register_service "$2" "$3" "$4"
        ;;
    deregister)
        deregister_service "$2"
        ;;
    *)
        echo "Kullanim: $0 {register|deregister} servis_adi [ip] [port]"
        exit 1
        ;;
esac

Bu scripti şöyle kullanıyorsunuz:

# Servis kaydı ekle
./dns-register.sh register api-gateway 192.168.1.50 8080

# Kaydı sil
./dns-register.sh deregister api-gateway

# Sorgula
dig @127.0.0.1 api-gateway.skunk.local A
dig @127.0.0.1 _api-gateway._tcp.skunk.local SRV

CI/CD pipeline’larınıza bu scripti entegre ettiğinizde, her deploy sonrası DNS otomatik olarak güncellenecek.

Etcd’de DNS Kayıtlarını Yönetme

Mevcut tüm DNS kayıtlarını listelemek için:

# Tüm kayıtları listele
etcdctl get --prefix /skunk/dns

# Sadece belirli bir zone'daki kayıtları listele
etcdctl get --prefix /skunk/dns/local/skunk

# Kayıt sayısını öğren
etcdctl get --prefix /skunk/dns --count-only

# Belirli bir kaydı sil
etcdctl del /skunk/dns/local/skunk/web

# Bir zone'un tüm kayıtlarını sil (dikkatli kullanın!)
etcdctl del --prefix /skunk/dns/local/skunk/web

Etcd’ye TTL atamak da mümkün. Lease mekanizmasıyla geçici DNS kayıtları oluşturabiliyorsunuz. Bu özellikle test ortamları veya canary deployment’lar için çok kullanışlı:

# 1 saatlik lease oluştur (3600 saniye)
LEASE_ID=$(etcdctl lease grant 3600 | awk '{print $2}')

# Lease ile kayıt ekle - 1 saat sonra otomatik silinecek
etcdctl put --lease=${LEASE_ID} /skunk/dns/local/skunk/canary '{"host":"192.168.1.200","ttl":60}'

echo "Canary kaydı oluşturuldu, lease ID: ${LEASE_ID}"
echo "Bu kayıt 1 saat sonra otomatik silinecek"

# Lease'i iptal edip kaydı hemen silmek için
etcdctl lease revoke ${LEASE_ID}

TLS ile Güvenli Etcd Bağlantısı

Production ortamında etcd’ye plain HTTP ile bağlanmak kabul edilemez. TLS yapılandırması şöyle:

# /etc/coredns/Corefile - TLS ile

. {
    etcd skunk.local {
        stubzones
        path /skunk/dns
        endpoint https://localhost:2379
        tls /etc/coredns/certs/client.crt /etc/coredns/certs/client.key /etc/coredns/certs/ca.crt
        upstream /etc/resolv.conf
        fallthrough
    }
    forward . 8.8.8.8 1.1.1.1
    cache 60
    log
    errors
    health :8080
    metrics :9153
}

TLS parametreleri sırasıyla: client certificate, client key, CA certificate. Etcd’de mTLS yapılandırılmışsa bu üçü de gerekli.

Monitoring: Prometheus Metrikleri

CoreDNS Prometheus metrikleri sunuyor. metrics :9153 satırını Corefile’a eklemeniz yeterli. Sonrasında hangi metriklere bakıyorum:

# Temel metrikleri kontrol et
curl -s http://localhost:9153/metrics | grep -E "coredns_dns_request_count|coredns_dns_response_rcode"

# Etcd plugin'ine özel metrikler
curl -s http://localhost:9153/metrics | grep coredns_etcd

# Hata oranını izle
curl -s http://localhost:9153/metrics | grep coredns_dns_response_rcode_count_total

Grafana dashboard’larında CoreDNS için hazır dashboard’lar var (ID: 5926). Bu metrikleri Prometheus ile scrape edip Grafana’ya bağladığınızda DNS altyapınızın tam görünürlüğünü elde ediyorsunuz.

Sık Karşılaşılan Sorunlar ve Çözümleri

Kayıt görünmüyor: En sık karşılaştığım sorun path formatı hatası. Domain adını doğru tersine çevirdiğinizden emin olun. web.skunk.local için path /skunk/dns/local/skunk/web olmalı, /skunk/dns/skunk.local/web değil.

SERVFAIL dönüyor: Genellikle etcd bağlantı sorunu. etcdctl endpoint health ile kontrol edin. Bir de Corefile’daki endpoint adresini ve portu doğrulayın.

Cache sorunları: Geliştirme sırasında cache’i tamamen kapatabilirsiniz, cache yerine cache 0 yazın. Production’da ise makul bir değer tutun, fazla düşük TTL hem etcd’yi hem CoreDNS’i yorar.

Performans düşüklüğü: Etcd’de çok fazla key biriktiğinde prefix sorguları yavaşlayabilir. Düzenli aralıklarla kullanılmayan kayıtları temizleyin.

Birden Fazla Zone Yönetimi

Farklı ortamlar için farklı zone’lar kullanmak iyi bir pratik:

# /etc/coredns/Corefile - Çoklu zone

prod.skunk.local {
    etcd {
        path /skunk/dns/prod
        endpoint https://etcd-prod:2379
        tls /etc/coredns/certs/client.crt /etc/coredns/certs/client.key /etc/coredns/certs/ca.crt
    }
    cache 120
    log
}

staging.skunk.local {
    etcd {
        path /skunk/dns/staging
        endpoint https://etcd-staging:2379
        tls /etc/coredns/certs/client.crt /etc/coredns/certs/client.key /etc/coredns/certs/ca.crt
    }
    cache 30
    log
}

. {
    forward . 8.8.8.8 1.1.1.1
    cache 60
    errors
}

Burada prod ve staging zone’larını farklı etcd cluster’larına yönlendiriyorum. Bu sayede ortamlar birbirinden tamamen izole kalıyor.

Sonuç

CoreDNS ile etcd backend kombinasyonu, modern bir altyapının DNS katmanına gerçek anlamda esneklik katıyor. Statik zone dosyalarının sınırlamalarından kurtulup programatik, dinamik ve dağıtık bir DNS yönetimine geçmek isteyenler için bu ikili güçlü bir seçenek.

Özellikle microservice ortamlarında servis keşfini DNS üzerine inşa etmek, teknolojiden bağımsız ve standart bir yaklaşım sunuyor. Bir servis Consul, Kubernetes veya bare metal üzerinde çalışıyor olsun, DNS arayüzü her zaman aynı kalıyor.

Başlarken önce tek zone, tek etcd node ile başlamanızı öneririm. Sistemi anlayıp kavramları oturtunca cluster kurulumuna ve çoklu zone yönetimine geçebilirsiniz. Etcd’nin backup ve restore prosedürlerini de ihmal etmeyin; DNS kayıtlarınız orada yaşıyor ve bir etcd kaybı ciddi servis kesintisi demek.

Bu yazıda anlattıklarım kendi ortamımda aktif olarak kullandığım ve test ettiğim yapılar. Sorularınız olursa yorumlarda buluşalım.

Bir yanıt yazın

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