Windows DNS’te Round Robin ile Yük Dağıtımı

Yük dengeleme denilince aklına hemen F5, HAProxy ya da Nginx geliyorsa, seni anlıyorum. Ben de yıllarca o yola gittim. Ama bir gün küçük bir müşterimizin altyapısında, hiçbir donanım yük dengeleyicisi olmadan, sadece Windows DNS üzerindeki Round Robin konfigürasyonuyla üç web sunucusuna trafik dağıttığımı fark ettim ve düşündüm: “Bu kadar basit miydi?” Evet, bazen bu kadar basit. Tabii bazı önemli sınırlamaları var, onları da konuşacağız.

DNS Round Robin Nedir, Ne Değildir?

DNS Round Robin, aynı hostname için birden fazla A kaydı tanımladığınızda DNS sunucusunun bu kayıtları sıralı olarak döndürmesidir. Client ilk sorgu yaptığında 192.168.1.10 alır, ikinci client sorgu yaptığında 192.168.1.11 alır, üçüncüsü 192.168.1.12 alır, dördüncüsü tekrar 192.168.1.10’dan başlar.

Burada kritik bir noktayı hemen söyleyeyim: Bu bir yük dengeleyici değildir. Gerçek bir load balancer sunucu sağlığını kontrol eder, session affinity yapabilir, ağırlıklı dağıtım yapabilir. DNS Round Robin bunların hiçbirini yapmaz. Yaptığı şey DNS yanıtlarını sırayla döndürmektir, o kadar.

Peki neden kullanalım? Çünkü:

  • Sıfır ek maliyet (Windows Server DNS rolü zaten kurulu)
  • Minimal konfigürasyon
  • Stateless uygulamalar için yeterli
  • İç ağ servislerinde (intranet, monitoring, internal API) gayet iş görür

Senaryo: Üç Web Sunucusuna İç Trafik Dağıtımı

Diyelim ki şirket içi bir web uygulamanız var. app.sirket.local adresine gelen istekleri üç sunucuya dağıtmak istiyorsunuz. Sunucularınız:

  • webserver01 – 10.10.1.11
  • webserver02 – 10.10.1.12
  • webserver03 – 10.10.1.13

Bu senaryo üzerinden ilerleyelim.

DNS Rolünün Kurulu Olup Olmadığını Kontrol Etmek

Önce DNS rolünün kurulu olduğundan emin olalım. PowerShell ile:

Get-WindowsFeature -Name DNS

Kurulu değilse:

Install-WindowsFeature -Name DNS -IncludeManagementTools

DNS rolü zaten çalışıyorsa zone yapılandırmasına geçebiliriz.

Zone Kontrolü ve A Kayıtlarının Eklenmesi

sirket.local zone’unun mevcut olduğunu varsayıyorum. Önce mevcut kayıtları görelim:

Get-DnsServerResourceRecord -ZoneName "sirket.local" -Name "app"

Eğer kayıt yoksa hiçbir şey dönmeyecek. Şimdi üç A kaydını ekleyelim:

Add-DnsServerResourceRecordA -ZoneName "sirket.local" -Name "app" -IPv4Address "10.10.1.11" -TimeToLive 00:00:30
Add-DnsServerResourceRecordA -ZoneName "sirket.local" -Name "app" -IPv4Address "10.10.1.12" -TimeToLive 00:00:30
Add-DnsServerResourceRecordA -ZoneName "sirket.local" -Name "app" -IPv4Address "10.10.1.13" -TimeToLive 00:00:30

TTL değerini 30 saniye olarak ayarladım. Bunu biraz sonra neden düşük tutmam gerektiğini açıklayacağım.

Kayıtları doğrulayalım:

Get-DnsServerResourceRecord -ZoneName "sirket.local" -Name "app" | Select-Object HostName, RecordType, @{Name="IP";Expression={$_.RecordData.IPv4Address}}

Round Robin’i DNS Sunucusunda Etkinleştirmek

Windows DNS’te Round Robin varsayılan olarak etkin gelir ama bunu teyit etmek gerekir. Bazı kurumsal ortamlarda GPO veya önceki yöneticilerin müdahaleleri bu ayarı kapatmış olabilir.

Get-DnsServerSetting -ComputerName "dc01" | Select-Object RoundRobin, LocalNetPriority

Burada iki önemli parametre var:

  • RoundRobin: True olmalı. DNS sorgu yanıtlarındaki A kayıtlarının sırasını her sorguda döndürür.
  • LocalNetPriority: Bu parametre etkin olduğunda DNS sunucusu, client’ın IP adresiyle aynı subnet’teki kaydı listedeki ilk sıraya koyar. Round Robin’in düzgün çalışması için bunu duruma göre yönetmeniz gerekebilir.

Eğer Round Robin kapalıysa açalım:

Set-DnsServerSetting -ComputerName "dc01" -RoundRobin $true

LocalNetPriority konusunda dikkatli olun. Eğer tüm sunucularınız aynı subnet’teyse sorun yok, ama farklı subnet’lerdeyse LocalNetPriority Round Robin sıralamasını bozabilir. Bunu kapatmak için:

Set-DnsServerSetting -ComputerName "dc01" -LocalNetPriority $false

Ben genellikle iç ağ yük dağıtımı senaryolarında LocalNetPriority’yi kapatırım. Aksi halde Round Robin beklendiği gibi çalışmaz ve tüm trafik aynı sunucuya gider.

TTL Ayarının Önemi

Round Robin’in gerçek anlamda çalışması için TTL’i düşük tutmanız gerekiyor. Eğer TTL 3600 saniye (1 saat) olarak ayarlıysa, client ilk sorguya aldığı IP’yi 1 saat boyunca önbelleğinde tutar ve bir sonraki sorguyu 1 saat sonra yapar. Bu durumda Round Robin amacına hizmet etmez.

30 saniye ile 5 dakika arası genellikle iç ağ için kabul edilebilir. Üretim ortamına göre ayarlayın:

# Mevcut kaydın TTL'ini güncellemek için önce kaydı alıp değiştirmek gerekir
$record = Get-DnsServerResourceRecord -ZoneName "sirket.local" -Name "app" -RRType A | Where-Object {$_.RecordData.IPv4Address -eq "10.10.1.11"}
$newrecord = $record.Clone()
$newrecord.TimeToLive = [System.TimeSpan]::FromSeconds(30)
Set-DnsServerResourceRecord -ZoneName "sirket.local" -OldInputObject $record -NewInputObject $newrecord

Bu işlemi üç kayıt için de tekrar etmeniz gerekiyor. Toplu yapmak istiyorsanız:

$ips = @("10.10.1.11", "10.10.1.12", "10.10.1.13")
foreach ($ip in $ips) {
    $record = Get-DnsServerResourceRecord -ZoneName "sirket.local" -Name "app" -RRType A | 
              Where-Object {$_.RecordData.IPv4Address -eq $ip}
    $newrecord = $record.Clone()
    $newrecord.TimeToLive = [System.TimeSpan]::FromSeconds(30)
    Set-DnsServerResourceRecord -ZoneName "sirket.local" -OldInputObject $record -NewInputObject $newrecord
}

Test: Round Robin Gerçekten Çalışıyor mu?

Konfigürasyonu yaptıktan sonra test etmek için basit ama etkili bir yöntem:

# Birkaç kez resolve işlemi yapın ve sonuçları karşılaştırın
1..10 | ForEach-Object {
    $result = Resolve-DnsName -Name "app.sirket.local" -Server "10.10.1.1" -Type A
    Write-Host "Sorgu $_: $($result.IPAddress -join ', ')"
    Start-Sleep -Seconds 1
}

Burada -Server parametresiyle DNS sunucusunu doğrudan belirtiyorum, böylece local DNS önbelleği devreye girmiyor. Farklı IP’lerin listelendiğini görmeniz gerekiyor. Eğer her sorguda aynı IP geliyorsa LocalNetPriority veya client-side caching sorununa bakın.

nslookup ile klasik yöntem:

# CMD'de
for /L %i in (1,1,10) do nslookup app.sirket.local 10.10.1.1

Gerçek Dünya Problemi: Bir Sunucu Çöktüğünde Ne Olur?

İşte DNS Round Robin’in en büyük açmazı burada ortaya çıkar. webserver02 çöktüğünde DNS sunucusu bundan haberdar olmaz ve 10.10.1.12’yi döndürmeye devam eder. Client bu IP’ye bağlanmaya çalışır, timeout alır, kullanıcı hata görür.

Bunu tamamen çözmek DNS Round Robin’in kapasitesinin dışında. Ama zararı minimize etmek için yapabileceğiniz şeyler var.

Seçenek 1: Periyodik sağlık kontrolü scripti

DNS kaydını otomatik olarak kaldıran ve tekrar ekleyen bir PowerShell scripti yazabilirsiniz. Basit bir örnek:

$servers = @(
    @{Name="app"; IP="10.10.1.11"; Port=80},
    @{Name="app"; IP="10.10.1.12"; Port=80},
    @{Name="app"; IP="10.10.1.13"; Port=80}
)

$zone = "sirket.local"

foreach ($server in $servers) {
    $tcp = New-Object System.Net.Sockets.TcpClient
    try {
        $connect = $tcp.BeginConnect($server.IP, $server.Port, $null, $null)
        $wait = $connect.AsyncWaitHandle.WaitOne(3000, $false)
        
        if (-not $wait) {
            Write-Host "$($server.IP) yanit vermiyor, DNS kaydi kaldiriliyor..."
            Remove-DnsServerResourceRecord -ZoneName $zone -Name $server.Name -RRType A -RecordData $server.IP -Force
        } else {
            # Kayit yoksa ekle, varsa dokunma
            $existing = Get-DnsServerResourceRecord -ZoneName $zone -Name $server.Name -RRType A -ErrorAction SilentlyContinue | 
                        Where-Object {$_.RecordData.IPv4Address -eq $server.IP}
            if (-not $existing) {
                Write-Host "$($server.IP) tekrar aktif, DNS kaydi ekleniyor..."
                Add-DnsServerResourceRecordA -ZoneName $zone -Name $server.Name -IPv4Address $server.IP -TimeToLive 00:00:30
            }
        }
    } catch {
        Write-Host "Hata: $_"
    } finally {
        $tcp.Close()
    }
}

Bu scripti Windows Task Scheduler ile her 1-2 dakikada bir çalıştırabilirsiniz. Primitive ama küçük iç ağ servisleri için yeterli.

DNS Netmask Ordering ve Round Robin Etkileşimi

Active Directory ortamlarında sık karşılaşılan bir durum: netmask ordering özelliği Round Robin davranışını etkiler. Windows DNS’teki LocalNetPriority aslında bu mekanizmanın bir parçasıdır.

Ortamınızda birden fazla site varsa ve sunucularınız farklı subnet’lerdeyse bu özelliği dikkatli yönetmeniz gerekir. Örneğin İstanbul ofisi 10.10.1.0/24, Ankara ofisi 10.10.2.0/24 subnet’ini kullanıyorsa ve her iki ofiste de uygulama sunucuları varsa, LocalNetPriority ile her ofisin kendi sunucusunu önce görmesini sağlayabilirsiniz. Bu aslında Round Robin ile tam tersi bir yaklaşım.

Şu anki ayarları görmek için:

Get-DnsServerSetting | Format-List RoundRobin, LocalNetPriority, LocalNetPriorityMask

LocalNetPriorityMask değeri hangi subnet maskesinin kullanılacağını belirler. Varsayılan 255 (0x000000FF) sadece son octet’e bakar. Bunu değiştirerek davranışı özelleştirebilirsiniz:

# /16 subnet için priority mask
Set-DnsServerSetting -LocalNetPriorityMask 255

Birden Fazla DNS Sunucusu Olan Ortamlarda Senkronizasyon

Primary-Secondary DNS yapınız varsa, Round Robin ayarları sadece primary’den yapılır ve secondary’ler zone transferi ile güncellenir. Ama dikkat: RoundRobin ve LocalNetPriority ayarları DNS sunucusu genelinde geçerlidir, zone bazlı değildir. Yani her DNS sunucusunu ayrı ayrı yapılandırmanız gerekir.

# Birden fazla DNS sunucusunu aynı anda yapılandırmak
$dnsservers = @("dc01", "dc02", "dc03")
foreach ($dns in $dnsservers) {
    Set-DnsServerSetting -ComputerName $dns -RoundRobin $true -LocalNetPriority $false
    Write-Host "$dns yapılandırıldı."
}

Monitoring ve Loglama

Round Robin kurulduktan sonra gözlemlememek büyük hata. En azından şunları takip edin:

DNS sorgu loglarını etkinleştirmek:

Set-DnsServerDiagnostics -ComputerName "dc01" -Queries $true -Answers $true -LogFilePath "C:DNSdns_debug.log" -MaxMBFileSize 500

Bu log dosyası hızla büyüyebilir, dikkatli olun. Sorun giderme sırasında açıp bitince kapatın.

Anlık DNS istatistikleri:

Get-DnsServerStatistics -ComputerName "dc01" | Select-Object -ExpandProperty Query

Zone’daki kayıtların mevcut durumunu raporlamak:

Get-DnsServerResourceRecord -ZoneName "sirket.local" -Name "app" -RRType A | 
    Select-Object HostName, @{Name="IP";Expression={$_.RecordData.IPv4Address}}, TimeToLive |
    Format-List

DNS Round Robin’in Sınırlamalarını Bilmek

Dürüst olmak gerekirse şunları kabul etmeliyiz:

  • Sağlık kontrolü yoktur. Sunucu çöktüğünde DNS onu döndürmeye devam eder. Yukarıdaki script geçici bir çözümdür, kalıcı değil.
  • Session persistence yoktur. Aynı kullanıcının tüm istekleri farklı sunuculara gidebilir. Stateful uygulamalar için kullanmayın.
  • Ağırlıklı dağıtım yoktur. Bir sunucu 32 core, diğeri 4 core olsa bile her ikisi de eşit trafik alır.
  • Client-side caching’i kontrol edemezsiniz. Modern tarayıcılar ve işletim sistemleri DNS yanıtlarını önbelleğe alır. TTL ne kadar düşük olursa olsun, bazı client’lar daha uzun süre aynı IP’yi kullanır.
  • Coğrafi yönlendirme yoktur. GSLB (Global Server Load Balancing) yapamaz.

DNS Round Robin’in doğru olduğu senaryolar şunlardır: stateless internal servisler, intranet uygulamaları, gelişmiş yük dengeleyici alamayacak küçük bütçeli ortamlar, ve geçici çözüm olarak hızla kurulması gereken dağıtım mekanizmaları.

Sonuç

Windows DNS üzerindeki Round Robin, sysadmin araç kutunuzda mutlaka bulunması gereken basit ama işlevsel bir yöntemdir. Kurulumu beş dakika, bakımı minimaldur. Ancak sınırlamalarını bilerek kullanmak şarttır.

Küçük bir iç ağ servisini üç sunucuya dağıtmak için bütçe ayırmak yerine, mevcut Active Directory altyapınızdan yararlanmak son derece makul bir karardır. Ben bunu onlarca müşteri ortamında başarıyla kullandım, intranet portallarında, iç API gatewaylerde, monitoring servislerinde.

Ama eğer dış dünyaya açık, yüksek erişilebilirlik gerektiren, kullanıcı oturumlarının korunması gereken bir servis söz konusuysa lütfen gerçek bir load balancer düşünün. DNS Round Robin orada yeterli olmaz ve sizi gece uyandıran bir incident’a davet eder.

Son olarak, her konfigürasyon değişikliği sonrası test etme alışkanlığı edinin. Yukarıdaki test scriptini bir monitoring aracına bağlayabilir, her beş dakikada bir çalıştırarak Round Robin’in beklenen şekilde dönüp dönmediğini takip edebilirsiniz. Konfigüre ettiğiniz şeyin çalıştığını varsaymak değil, kanıtlamak önemlidir.

Bir yanıt yazın

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