Episode ini membahas policy berbasis nama domain (FQDN): cara kerja DNS proxy Cilium, aturan egress dengan toFQDNs, pengelolaan TTL dan cache, serta praktik mengizinkan akses keluar hanya ke domain tertentu. Kalian juga belajar memverifikasi rule FQDN dengan Hubble.

Policy egress yang kita buat di episode 6 masih berbasis IP — dan itu bermasalah. Banyak aplikasi berkomunikasi ke layanan eksternal lewat nama domain seperti api.external.com, yang alamat IP-nya bisa berubah sewaktu-waktu. Menulis policy terhadap IP domain akan pecah begitu DNS berubah. Episode 10 menjawab masalah ini dengan DNS-based policy (FQDN).
Cilium menangani DNS dengan DNS proxy: seluruh permintaan DNS dari pod melewati proxy, yang mencatat nama domain yang diminta dan alamat IP hasil resolusi. Dari catatan ini, policy toFQDNs bisa mengizinkan egress ke domain tertentu — bukan ke IP. Ini cara yang jauh lebih stabil dan manusiawi untuk menulis aturan.
DNS proxy aktif secara default di Cilium modern. Ketika sebuah pod melakukan query DNS, permintaan tidak langsung ke server upstream — ia melewati proxy Cilium dulu. Proxy meneruskan query, menyimpan hasilnya, dan memberi tahu dataplane alamat IP mana yang terhubung dengan nama domain mana.
Dengan data ini, sebuah policy bisa berbunyi: "izinkan pod frontend melakukan egress ke api.external.com". Cilium akan menerjemahkannya menjadi aturan yang mengizinkan egress ke IP apa pun yang saat ini diselesaikan oleh domain tersebut. Ketika alamat IP domain berubah, proxy memperbarui aturannya secara otomatis.
Perlu ditekankan bahwa DNS proxy tidak mengubah hasil resolusi. Ia hanya menambahkan lapisan observasi dan kontrol di antara pod dan server DNS. Jika pod bertanya tentang api.external.com, proxy tetap meneruskan query ke server DNS yang sebenarnya dan mengembalikan jawaban yang sama — yang berbeda adalah Cilium kini tahu nama domain apa yang dipakai pod tersebut.
Keuntungan tambahan dari pendekatan ini: proxy bisa menerapkan policy DNS itu sendiri. Di versi terbaru, kalian bisa membatasi query DNS ke daftar domain tertentu (DNS policy), sehingga bahkan sebelum koneksi dibuat, pod tidak bisa menanyakan domain yang dilarang. Ini lapisan pertahanan tambahan di luar policy jaringan.
Verifikasi bahwa DNS proxy aktif di cluster kalian:
cilium status | grep -i dnscilium status | grep -i dns harus menampilkan baris yang menyebutkan proxy DNS aktif. Jika tidak, aktifkan dengan --set dnsProxy.enable=true saat install.
Rule FQDN ditulis di dalam blok egress dengan field toFQDNs. Setiap item berisi nama domain yang diizinkan. Contoh policy yang mengizinkan pod frontend mengakses API eksternal dan DNS server:
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-fqdn
spec:
endpointSelector:
matchLabels:
app: frontend
egress:
- toFQDNs:
- matchName: api.external.com
- matchPattern: "*.external.com"
toPorts:
- ports:
- port: "443"
protocol: TCP
- toEndpoints:
- matchLabels:
io.kubernetes.pod.namespace: kube-system
matchLabels:
k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDPmatchName: api.external.com mencocokkan nama domain secara eksak, sedangkan matchPattern: "*.external.com" mencocokkan subdomain. Blok kedua mengizinkan akses ke CoreDNS cluster agar resolusi DNS tetap berjalan — tanpa ini, pod tidak akan bisa melakukan query DNS sama sekali.
Hasil resolusi DNS disimpan oleh proxy di cache bersama dataplane. Setiap entri cache punya masa hidup (TTL) yang diambil dari respons DNS upstream. Ketika TTL berakhir, proxy melakukan resolusi ulang dan memperbarui alamat IP yang diizinkan.
Penting untuk dipahami: selama domain terus di-query, alamatnya tetap segar dan policy berjalan normal. Namun jika sebuah domain tidak pernah di-query selama TTL-nya, entri cache bisa kedaluwarsa dan traffic egress ke alamat lama akan ditolak — inilah alasan banyak bug "tiba-tiba tidak bisa akses" muncul di production. Untuk mencegahnya, pastikan aplikasi memakai resolusi DNS berulang (TDD atau cache dengan refresh), bukan menyimpan IP selamanya.
Mari kita gabungkan semua konsep dalam satu skenario nyata: pod frontend hanya boleh mengakses api.external.com lewat HTTPS, dan semua akses lain harus di-block. Terapkan policy di atas, lalu verifikasi dengan Hubble:
hubble observe --namespace default --type to-endpoint
hubble observe --verdict DROPPED --namespace defaulthubble observe --namespace default --type to-endpoint menampilkan flow keluar; perhatikan bahwa alamat yang dituju adalah IP hasil resolusi api.external.com. Jika kalian mencoba mengakses domain lain, hubble observe --verdict DROPPED akan menunjukkan penolakan dengan drop reason terkait policy.
Untuk uji cepat langsung dari pod:
kubectl exec frontend -- curl -s -o /dev/null -w "%{http_code}" https://api.external.com
kubectl exec frontend -- curl -s -o /dev/null -w "%{http_code}" https://www.google.comkubectl exec frontend -- curl https://api.external.com harus berhasil, sementara akses ke domain lain harus gagal karena tidak diizinkan oleh policy FQDN.
Ketika sebuah domain tiba-tiba tidak bisa diakses, jangan menebak — lihat apa yang terjadi di DNS proxy dan dataplane. Dua perintah Hubble berikut menjawab pertanyaan paling umum:
hubble observe --dns --since 15m
hubble observe --verdict DROPPED --since 15mhubble observe --dns --since 15m menampilkan semua query DNS yang melewati proxy lengkap dengan domain yang diminta. hubble observe --verdict DROPPED --since 15m menampilkan flow yang ditolak beserta drop reason. Jika domain yang di-query tidak muncul di log DNS, masalahnya bukan policy — aplikasi bahkan tidak melakukan resolusi.
Perhatikan bahwa kejadian di dua lapisan ini bisa berbeda urutannya: sebuah flow bisa di-drop karena policy FQDN belum mengenali alamat hasil resolusi (cache belum siap), atau karena alamat tersebut kedaluwarsa dari cache (TTL habis). Membandingkan waktu di kedua output Hubble memberi petunjuk mana yang terjadi.
kubectl exec -n kube-system -it ds/cilium -- cilium-dbg bpf fqdn cache listcilium-dbg bpf fqdn cache list menampilkan isi cache FQDN di dataplane: nama domain, alamat IP, dan masa berlaku. Jika domain yang ingin diakses tidak ada di cache, aplikasi belum pernah meng-query domain tersebut selama TTL — ini kembali ke aturan praktis dari bagian TTL: pastikan aplikasi melakukan resolusi berulang, bukan menyimpan IP selamanya.
Warning
Jangan memakai toFQDNs untuk domain yang sering berubah alamat tanpa memastikan aplikasi melakukan resolusi ulang. Pola yang benar adalah aplikasi melakukan DNS lookup berkala dan menggunakan matchName untuk domain yang stabil atau matchPattern untuk blok subdomain.
Inti yang harus dibawa pulang:
toFQDNs mengizinkan egress berdasarkan nama domain, bukan IP.matchName untuk domain eksak; matchPattern untuk wildcard subdomain.hubble observe --verdict DROPPED membuktikan bahwa akses di luar domain terblokir.Di episode 11 selanjutnya kita akan membahas bandwidth management dan QoS — bandwidth manager berbasis eBPF, pacing dengan BBR untuk throughput tinggi, annotation kubernetes.io/egress-bandwidth, dan cara memverifikasi rate limit serta dampaknya terhadap latensi. Ini mengubah QoS dari konsep menjadi angka yang bisa diukur.