SO_REUSEPORT) mendistribusikan beban paket secara adil ke seluruh thread CPU.
Anatomi Kegagalan: Dari Database Replication Lag Menuju OOM dan Socket Drop
TEXT
+-------------------------------------------------------------+
| Edge DNS Node |
| |
| UDP Ingress: 53 |
| | |
| v |
| +---------------------+ L1 Cache Hit |
| | CoreDNS (Caching) |-------------------------> Response |
| | cgroups: dns.slice | |
| +---------------------+ |
| | (Cache Miss / In-flight Timeout) |
| v |
| +---------------------+ DB Read |
| | PowerDNS (Auth) |-------------------------> Local DB |
| | cgroups: pdns.slice | Replica |
| +---------------------+ | |
| | (Lag/Lock)|
| (Thread Starvation) v |
| | Replication|
| Memory Ballooning -> PSI Spike -> OOM Killer! Fails |
+-------------------------------------------------------------+recvmsg() secara cepat. Dampaknya, socket receive buffer meluap, memicu metrik RcvbufErrors dan silent drop paket UDP yang berujentung pada downtime resolver bagi aplikasi klien.
Isolasi Resource Menggunakan cgroups v2 dan Systemd Slices
/etc/systemd/system/dns-infrastructure.slice:
INI
[Unit]
Description=Dedicated cgroup slice for DNS services
Before=slices.target
[Slice]
# Alokasi prioritas CPU (skala 1-10000, default 100)
CPUWeight=1000
# Batasi IO starvation menggunakan PSI limit
IOWeight=800
# Proteksi memori minimal agar page cache daemon DNS tidak direbut proses batch
MemoryMin=1G
MemoryLow=2G
MemoryHigh=3.5G
MemoryMax=4G
# Cegah krisis swap thrashing
MemorySwapMax=0/etc/systemd/system/coredns.service.d/override.conf) ke slice tersebut dan mengatur perlindungan OOM:
INI
[Service]
Slice=dns-infrastructure.slice
LimitNOFILE=1048576
LimitMEMLOCK=infinity
# Lindungi proses dari OOM Score Killer (-1000 adalah proteksi absolut)
OOMScoreAdjust=-900
# Terapkan isolasi memori spesifik proses
MemoryHigh=1.8G
MemoryMax=2G
Restart=always
RestartSec=2s
# Matikan swap sama sekali untuk CoreDNS guna menjaga latensi sub-milidetik
MemorySwapMax=0
TasksMax=8192/etc/systemd/system/pdns.service.d/override.conf):
INI
[Service]
Slice=dns-infrastructure.slice
LimitNOFILE=1048576
OOMScoreAdjust=-800
MemoryHigh=1.5G
MemoryMax=1.8G
Restart=on-failure
RestartSec=3s
TasksMax=4096MemoryHigh), kernel akan memperlambat alokasi dan memaksa proses mereklamasi memori tanpa langsung mengeksekusi proses melalui SIGKILL. Jika batas MemoryMax 2GB tertembus, hanya instans CoreDNS yang diterminasi dan segera direstart oleh systemd dalam 2 detik, tanpa mengganggu daemon lain di server.
Tuning UDP Socket Buffer Kernel dan Penanganan RcvbufErrors
net.core.rmem_default sekitar 212KB) sering kali terisi penuh hanya dalam hitungan milidetik saat burst query terjadi. Untuk memvalidasi packet drop pada level kernel, jalankan perintah diagnostik berikut:
BASH
# Periksa apakah ada socket buffer overflow pada UDP
netstat -su | grep -E '(RcvbufErrors|SndbufErrors|InErrors)'
# Atau periksa statistik drop per interface
ip -s link show dev eth0
# Amati socket queue depth pada port 53 secara real-time
ss -n -u -a '( sport = :53 or dport = :53 )'RcvbufErrors terus bertambah, ukuran buffer sistem dan kemampuan pemrosesan socket harus ditingkatkan. Terapkan konfigurasi kernel berikut di /etc/sysctl.d/99-dns-network.conf:
INI
# Naikkan batas maksimum receive and send socket buffer (64MB)
net.core.rmem_max = 67108864
net.core.wmem_max = 67108864
# Set buffer default untuk socket baru (8MB)
net.core.rmem_default = 8388608
net.core.wmem_default = 8388608
# Alokasi halaman memori minimum, default, dan maksimum untuk UDP (dalam satuan halaman/pages)
net.ipv4.udp_mem = 262144 524288 1048576
# Naikkan queue backlog kartu jaringan untuk mencegah drop sebelum masuk IP stack
net.core.netdev_max_backlog = 50000
# Izinkan socket reuseport load balancing secara efisien di level kernel
net.ipv4.tcp_fastopen = 3sysctl -p /etc/sysctl.d/99-dns-network.conf.
Konfigurasi PowerDNS: Thread Sizing dan Database Pool Protection
/etc/powerdns/pdns.conf untuk server dengan 16 vCPU:
INI
# Binding IP dan port
local-address=127.0.0.1,192.168.10.15
local-port=5353
# Gunakan SO_REUSEPORT di Linux kernel
reuseport=yes
# Distribusi thread yang optimal untuk menahan socket queue
receiver-threads=4
distributor-threads=12
# Tuning cache internal PowerDNS untuk meredam kueri ke database backend
cache-ttl=60
negquery-cache-ttl=15
query-cache-ttl=60
max-cache-entries=1000000
max-packet-cache-entries=1000000
# Proteksi backend timeout agar thread tidak hang selamanya
gpgsql-host=127.0.0.1
gpgsql-port=5432
gpgsql-dbname=pdns
gpgsql-user=pdns_user
gpgsql-password=supersecretpassword
# Timeout koneksi ke database Postgres (dalam detik)
gpgsql-connect-timeout=2
# Aktifkan DNSSEC dengan algoritma ECDSA P-256 (Algorithm 13)
default-ksk-algorithm=ecdsa256
default-zsk-algorithm=ecdsa256ecdsa256) sangat disarankan dibandingkan RSA-2048. ECDSA P-256 memangkas ukuran payload DNS response secara drastis, mengurangi fragmentasi UDP, dan menghemat konsumsi memori serta instruksi siklus CPU saat menandatangani zone transfer atau verifikasi signature.
CoreDNS Resiliency: Plugin Caching dan Upstream Starvation Mitigation
cache pada CoreDNS harus diatur untuk menyajikan data usang (stale data) jika upstream mengalami kegagalan.
Berikut konfigurasi CoreDNS (/etc/coredns/Corefile):
COREFILE
.:53 {
bind 0.0.0.0
# Logging error saja di lingkungan produksi untuk menghemat IOPS
log . {
class error
}
# Prometheus metrics exporter untuk monitoring PSI dan Goroutines
prometheus 0.0.0.0:9153
# Health check endpoint
health :8080
# Isolasi cache dengan mekanisme Serve Stale dan Prefetch
cache 300 {
success 65536 300 30
denial 10000 60 10
prefetch 3 1m 20%
serve_stale 1h immediate
}
# Forwarding