DNS Kluster

Nama DNS internal untuk Service dan Pod serta cara penyelesaian nama bekerja di dalam kluster.

Daftar isi

Setiap Service di dalam kluster Kubernetes otomatis memperoleh nama DNS, sehingga klien dapat memanggil layanan dengan nama yang stabil alih-alih alamat IP. Topik ini membahas bentuk nama DNS untuk Service dan Pod, cara penyelesaian nama bekerja di dalam kluster, serta tabel pencarian yang disusun oleh skrip simulasi di sandbox. Pemahaman ini menjadi dasar service discovery di dalam kluster, yaitu cara komponen menemukan satu sama lain tanpa menyimpan alamat IP di konfigurasi.

Nama DNS untuk Service#

Bentuk nama DNS paling lengkap untuk sebuah Service adalah <nama-service>.<namespace>.svc.cluster.local. Bagian pertama adalah nama Service pada metadata, bagian kedua adalah namespace tempat Service berada, dan sisanya adalah domain tetap yang berlaku di setiap kluster. Apabila klien berada di namespace yang sama, nama pendek berupa nama Service saja sudah cukup, sedangkan pemanggilan lintas namespace menyertakan namespace tujuan dalam bentuk <nama-service>.<namespace>.

Nama-nama ini dibuat dan diperbarui secara otomatis untuk setiap Service, dan nama tersebut menunjuk ke IP virtual Service. Penyelesaian nama dan pemilihan endpoint tetap dijalankan oleh Service itu sendiri, sehingga nama DNS tidak menggantikan peran Service, melainkan memberi jalan menuju alamat virtualnya. Alamat virtual dihitung ulang hanya saat Service dibuat ulang, sedangkan nama DNS-nya bertahan selama nama itu tidak berubah.

Nama-nama tersebut dapat diuji dari dalam Pod. Berkas /etc/resolv.conf pada setiap container memperlihatkan server DNS dan domain pencarian yang digunakan, sebagaimana ditampilkan perintah berikut. Berkas ini ditulis oleh kubelet secara otomatis, sehingga isi antara Pod hanya berbeda pada domain pencarian pertamanya.

bash
# tidak-dijalankan
# tampilkan isi resolv.conf di dalam salah satu container
kubectl exec pod-aplikasi -- cat /etc/resolv.conf
text Contoh keluaran
nameserver 10.96.0.10
search produksi.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

Cara kerja penyelesaian nama#

Penyelesaian nama di dalam kluster dijalankan oleh komponen DNS kluster, dan pada kluster modern tugas ini dipegang CoreDNS yang berjalan sebagai Pod di namespace kube-system. Komponen tersebut diekspos sebagai Service bernama kube-dns dengan IP virtual yang stabil, dan alamat 10.96.0.10 pada keluaran resolv.conf di atas adalah alamat itu. Kubelet mengisi /etc/resolv.conf pada setiap container dengan alamat tersebut beserta daftar domain pencarian (search domain), yaitu namespace Pod yang diikuti akhiran svc.cluster.local, lalu svc.cluster.local, dan terakhir cluster.local. Apabila container meminta nama pendek, resolver menempelkan domain pencarian satu per satu sampai pencarian berhasil. Permintaan ke nama lengkap yang sudah diakhiri cluster.local dijawab langsung tanpa penambahan apa pun.

Perintah berikut mencari nama lengkap sebuah Service dari dalam Pod, dan jawabannya memuat IP virtual Service tersebut.

bash
# tidak-dijalankan
# cari nama lengkap Service dari di dalam salah satu pod
kubectl exec pod-aplikasi -- nslookup service-aplikasi.produksi.svc.cluster.local
text Contoh keluaran
Server:         10.96.0.10
Address:        10.96.0.10:53

Name:      service-aplikasi.produksi.svc.cluster.local
Address 1: 10.96.42.17 service-aplikasi.produksi.svc.cluster.local

Nama DNS untuk Pod#

Pod juga memperoleh nama DNS, tetapi bentuknya berbeda dan penggunaannya lebih terbatas. Tanpa konfigurasi tambahan, sebuah Pod di namespace produksi dengan alamat 10.244.1.5 dapat dicapai melalui nama 10-244-1-5.produksi.pod.cluster.local, yaitu alamat IP dengan titik yang diganti tanda hubung. Nama ini hanya menunjuk ke alamat Pod saat itu, sehingga nilainya hilang bersama Pod yang dibuat ulang.

Nama per Pod yang stabil memerlukan Service headless. Apabila Pod diberi hostname dan sebuah Service headless yang memilihnya, setiap Pod memperoleh nama nama-pod.nama-service.namespace.svc.cluster.local yang dapat dijangkau secara langsung. Bentuk inilah yang menjadi identitas jaringan stabil bagi beban kerja yang memerlukannya, seperti anggota StatefulSet.

Kebijakan DNS bawaan pada Pod, yaitu ClusterFirst, mengarahkan seluruh permintaan ke DNS kluster terlebih dahulu. Nama yang berada di luar domain kluster, misalnya domain situs web publik, diteruskan ke server DNS Node untuk diselesaikan di luar. Dengan demikian, satu konfigurasi resolver melayani nama internal dan eksternal sekaligus tanpa pengaturan tambahan pada setiap container.

Simulasi penyusunan nama DNS#

Aturan penyusunan nama sebelumnya dapat diringkas menjadi beberapa bentuk yang dihasilkan dari nama Service, nama namespace, dan alamat Pod. Skrip berikut menyusun nama lengkap, bentuk lintas namespace, bentuk pendek, dan nama Pod berbasis alamat IP, lalu menampilkan tabel pencarian dari empat konteks berbeda untuk memperlihatkan kapan nama pendek cukup dan kapan bentuk lengkap diperlukan. Urutan pemeriksaannya meniru resolver kluster, yaitu mencoba nama pendek di namespace sendiri sebelum bentuk lainnya dipertimbangkan.

python simulasi-dns.py
"""Penyusunan nama DNS internal untuk Service dan Pod."""
DOMAIN = "svc.cluster.local"
CLUSTER = "cluster.local"

nama_service = "service-aplikasi"
namespace = "produksi"
ip_pod = "10.244.1.5"

fqdn = f"{nama_service}.{namespace}.{DOMAIN}"
lintas = f"{nama_service}.{namespace}"
nama_pod = f"{ip_pod.replace('.', '-')}.{namespace}.pod.{CLUSTER}"

print(f"Nama lengkap Service : {fqdn}")
print(f"Bentuk lintas        : {lintas}")
print(f"Bentuk pendek        : {nama_service}")
print(f"Nama Pod             : {nama_pod}")
print()
print("Tabel pencarian dari berbagai konteks:")
tabel = [
    ("Pod di namespace produksi", nama_service, fqdn),
    ("Pod di namespace lain", nama_service, "tidak ditemukan"),
    ("Pod di namespace lain", lintas, fqdn),
    ("Pod di namespace mana pun", fqdn, fqdn),
]
for konteks, dicari, ditemukan in tabel:
    print(f"  {konteks:26s} {dicari:44s} -> {ditemukan}")
text Keluaran
Nama lengkap Service : service-aplikasi.produksi.svc.cluster.local
Bentuk lintas        : service-aplikasi.produksi
Bentuk pendek        : service-aplikasi
Nama Pod             : 10-244-1-5.produksi.pod.cluster.local

Tabel pencarian dari berbagai konteks:
  Pod di namespace produksi  service-aplikasi                             -> service-aplikasi.produksi.svc.cluster.local
  Pod di namespace lain      service-aplikasi                             -> tidak ditemukan
  Pod di namespace lain      service-aplikasi.produksi                    -> service-aplikasi.produksi.svc.cluster.local
  Pod di namespace mana pun  service-aplikasi.produksi.svc.cluster.local  -> service-aplikasi.produksi.svc.cluster.local

Tabel tersebut memperlihatkan bahwa nama pendek hanya berhasil dari Pod yang berada di namespace produksi. Dari namespace lain, pencarian wajib menyertakan nama namespace, dan bentuk nama lengkap berhasil dari mana pun. Nama Pod berbasis alamat IP berguna untuk penelusuran masalah, bukan sebagai alamat yang disimpan di konfigurasi aplikasi. Bentuk <nama-service>.<namespace> menjadi kompromi yang lazim untuk konfigurasi lintas namespace karena tetap pendek sekaligus tidak bergantung pada daftar domain pencarian. Nama lengkap paling aman untuk berkas konfigurasi yang berpindah antara lingkungan, karena bentuk tersebut tidak menyisakan ruang untuk salah tafsir mengenai namespace tujuan.

Kesalahan umum#

Tiga kesalahan berikut paling sering muncul saat aplikasi mulai bergantung pada DNS kluster. Gejalanya serupa, yaitu pencarian nama yang gagal, sehingga penyebabnya perlu diperiksa satu per satu.

  • Memanggil Service lintas namespace dengan nama pendek. Daftar domain pencarian hanya menambahkan namespace Pod, sehingga pencarian berakhir dengan nama yang tidak ditemukan. Perbaikannya adalah menulis bentuk <nama-service>.<namespace> pada konfigurasi klien.
  • Salah mengetik namespace pada bentuk lengkap. Pencarian tetap dilakukan, tetapi DNS menjawab bahwa nama tidak ada, dan gejalanya sulit dibedakan dari kasus Service yang memang belum dibuat. Perbaikannya adalah memeriksa daftar namespace dengan kubectl get namespace sebelum menyusun nama.
  • Menyimpan IP virtual Service di konfigurasi aplikasi. Konfigurasi berfungsi sampai Service dibuat ulang dan alamat virtualnya berganti. Perbaikannya adalah mengganti nilai tersebut dengan nama DNS Service, karena nama tetap stabil di seluruh siklus hidup Service.

Ketiga kesalahan ini dapat dihindari dengan satu kebiasaan, yaitu menuliskan nama lengkap pada berkas konfigurasi yang diwariskan antara lingkungan. Bentuk pendek tetap nyaman untuk eksperimen cepat di dalam namespace yang sama, sedangkan bentuk lengkap berfungsi tanpa bergantung pada daftar domain pencarian.

Ringkasan#

  • Setiap Service memperoleh nama DNS <nama-service>.<namespace>.svc.cluster.local secara otomatis, dan bentuk pendek cukup digunakan di dalam namespace yang sama.
  • Kubelet mengisi /etc/resolv.conf tiap container dengan alamat DNS kluster beserta daftar domain pencarian, sedangkan CoreDNS menjawab permintaan tersebut.
  • Nama Pod berbasis alamat IP bersifat sementara, sedangkan nama per Pod yang stabil memerlukan Service headless.

Referensi#