Tentang kube-dns untuk GKE

Jika Anda menjalankan aplikasi di cluster Standar, kube-dns adalah penyedia DNS default yang membantu Anda mengaktifkan penemuan dan komunikasi layanan. Dokumen ini menjelaskan cara mengelola DNS dengan kube-dns, termasuk arsitektur, konfigurasi, dan praktik terbaik untuk mengoptimalkan resolusi DNS dalam lingkungan GKE Anda.

Dokumen ini ditujukan untuk Developer dan Admin serta arsitek yang bertanggung jawab mengelola DNS di GKE. Untuk mengetahui konteks tentang peran umum dan tugas di Google Cloud, lihat Peran dan tugas pengguna GKE umum.

Sebelum memulai, pastikan Anda memahami Layanan Kubernetes dan konsep DNS umum.

Memahami arsitektur kube-dns

kube-dns beroperasi di dalam cluster GKE Anda untuk mengaktifkan resolusi DNS antara Pod dan Layanan.

Diagram berikut menunjukkan cara Pod Anda berinteraksi dengan Layanan kube-dns:

Gambar 1: Diagram yang menunjukkan cara Pod mengirim kueri DNS ke Layanan `kube-dns`, yang didukung oleh Pod `kube-dns`. Pod `kube-dns` menangani resolusi DNS internal dan meneruskan kueri eksternal ke server DNS upstream.

Komponen utama

kube-dns mencakup komponen utama berikut:

  • Pod kube-dns: Pod ini menjalankan software server kube-dns. Beberapa replika Pod ini berjalan di namespace kube-system, dan memberikan ketersediaan dan redundansi yang tinggi.
  • Layanan kube-dns: Tabel berikut membandingkan batas skalabilitas dan konfigurasi versi lama dan berbasis CoreDNS dari kube-dns:
    Fitur Versi lama (kube-dns 1.35 dan yang lebih lama) kube-dns di CoreDNS (1.36 dan yang lebih baru)
    Pengetahuan endpoint Mengetahui hingga 1.000 endpoint per layanan. Jika layanan memiliki lebih dari 1.000 Pod, kube-dns tidak mengetahui endpoint tambahan. Mengetahui semua endpoint. Versi ini menggunakan EndpointSlices untuk memastikan kebenaran dan meningkatkan efisiensi untuk layanan besar.
    Server nama upstream Terbatas hingga 3 Mendukung hingga 15
    Koneksi TCP keluar serentak Terbatas hingga 200 Mendukung hingga 1.500
  • kube-dns-autoscaler: Pod ini menyesuaikan jumlah replika kube-dns berdasarkan ukuran cluster, yang mencakup jumlah node dan core CPU. Pendekatan ini membantu memastikan bahwa kube-dns dapat menangani berbagai beban kueri DNS.

Resolusi DNS internal

Saat Pod perlu me-resolve nama DNS dalam domain cluster, seperti myservice.my-namespace.svc.cluster.local, proses berikut akan terjadi:

  1. Konfigurasi DNS Pod: kubelet di setiap node mengonfigurasi file /etc/resolv.conf Pod. File ini menggunakan ClusterIP Layanan kube-dns sebagai server nama.
  2. Kueri DNS: Pod mengirim kueri DNS ke Layanan kube-dns.
  3. Resolusi nama:

    • GKE versi 1.36 atau yang lebih baru: implementasi berbasis CoreDNS menggunakan EndpointSlices sehingga kube-dns mengetahui semua Pod dalam Layanan. Hal ini meningkatkan kebenaran dan efisiensi untuk Layanan skala besar.
    • GKE versi 1.35 atau yang lebih lama: kube-dns me-resolve nama berdasarkan Cloud Endpoints API yang lebih lama, yang dibatasi hingga 1.000 endpoint. Jika Layanan memiliki lebih dari 1.000 Pod pendukung, kube-dns tidak mengetahui endpoint tambahan.
  4. Komunikasi: Pod kemudian menggunakan alamat IP yang di-resolve untuk berkomunikasi dengan Layanan target.

Resolusi DNS eksternal

Saat Pod perlu me-resolve nama DNS eksternal, atau nama yang berada di luar domain cluster, kube-dns bertindak sebagai resolver rekursif. Layanan ini meneruskan kueri ke server DNS upstream yang dikonfigurasi dalam file ConfigMap. Anda juga dapat mengonfigurasi resolver kustom untuk domain tertentu, yang juga dikenal sebagai domain stub. Konfigurasi ini mengarahkan kube-dns untuk meneruskan permintaan untuk domain tersebut ke server DNS upstream tertentu.

Mengonfigurasi DNS Pod

Di GKE, agen kubelet di setiap node mengonfigurasi setelan DNS untuk Pod yang berjalan di node tersebut.

Mengonfigurasi file /etc/resolv.conf

Saat GKE membuat Pod, agen kubelet akan mengubah file /etc/resolv.conf Pod. File ini mengonfigurasi server DNS untuk resolusi nama dan menentukan domain penelusuran. Secara default, kubelet mengonfigurasi Pod untuk menggunakan layanan DNS internal cluster, kube-dns, sebagai server namanya. Layanan ini juga mengisi domain penelusuran dalam file. Domain penelusuran ini memungkinkan Anda menggunakan nama yang tidak memenuhi syarat dalam kueri DNS. Misalnya, jika Pod mengkueri myservice, Kubernetes akan mencoba me-resolve myservice.default.svc.cluster.local, lalu myservice.svc.cluster.local, dan kemudian domain lain dari daftar search.

Contoh berikut menunjukkan konfigurasi /etc/resolv.conf default:

nameserver 10.0.0.10
search default.svc.cluster.local svc.cluster.local cluster.local c.my-project-id.internal google.internal
options ndots:5

File ini memiliki entri berikut:

  • nameserver: menentukan ClusterIP layanan kube-dns.
  • search: menentukan domain penelusuran yang ditambahkan ke nama yang tidak memenuhi syarat selama pencarian DNS.
  • options ndots:5: menetapkan nilai minimum untuk kapan GKE menganggap nama memenuhi syarat sepenuhnya. Nama dianggap memenuhi syarat sepenuhnya jika memiliki lima titik atau lebih.

Pod yang dikonfigurasi dengan hostNetwork: true mewarisi konfigurasi DNS dari host dan tidak mengkueri kube-dns secara langsung, kecuali jika menggunakan dnsPolicy ClusterFirstWithHostNet.

Menyesuaikan kube-dns

kube-dns menyediakan resolusi DNS default yang andal. Anda dapat menyesuaikan perilaku `kube-dns` untuk kebutuhan tertentu, seperti meningkatkan efisiensi resolusi atau menggunakan resolver DNS pilihan. Domain stub dan server nama upstream dikonfigurasi dengan mengubah ConfigMap kube-dns di namespace kube-system.

Mengubah ConfigMap kube-dns

Untuk mengubah ConfigMap kube-dns, lakukan hal berikut:

  1. Buka ConfigMap untuk diedit:

    kubectl edit configmap kube-dns -n kube-system
    
  2. Di bagian data, tambahkan kolom stubDomains dan upstreamNameservers sebagai berikut:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      labels:
        addonmanager.kubernetes.io/mode: EnsureExists
      name: kube-dns
      namespace: kube-system
    data:
      stubDomains: |
        {
          "example.com": [
            "8.8.8.8",
            "8.8.4.4"
          ],
          "internal": [ # Required if your upstream nameservers can't resolve GKE internal domains
            "169.254.169.254" # IP of the metadata server
          ]
        }
      upstreamNameservers: |
        [
          "8.8.8.8", # Google Public DNS
          "8.8.4.4" # Google Public DNS Backup
        ]
    
  3. Simpan ConfigMap. kube-dns akan otomatis memuat ulang konfigurasi.

Domain stub

Domain stub memungkinkan Anda menentukan resolver DNS kustom untuk domain tertentu. Saat Pod mengkueri nama dalam domain stub tersebut, kube-dns akan meneruskan kueri ke resolver yang ditentukan, bukan menggunakan mekanisme resolusi default.

Anda menyertakan bagian stubDomains di ConfigMap kube-dns.

Bagian ini menentukan domain dan server nama upstream yang sesuai. kube-dns kemudian meneruskan kueri untuk nama dalam domain tersebut ke server yang ditentukan. Misalnya, Anda dapat merutekan semua kueri DNS untuk internal.mycompany.com ke 192.168.0.10, menambahkan "internal.mycompany.com": ["192.168.0.10"] ke stubDomains.

Saat Anda menetapkan resolver kustom untuk domain stub, seperti example.com, kube-dns akan meneruskan semua permintaan resolusi nama untuk domain tersebut, termasuk subdomain seperti *.example.com, ke server yang ditentukan.

Server nama upstream

Anda dapat mengonfigurasi kube-dns untuk menggunakan server nama upstream kustom guna me-resolve nama domain eksternal. Konfigurasi ini menginstruksikan kube-dns untuk meneruskan semua permintaan DNS, kecuali permintaan untuk domain internal cluster (*.cluster.local), ke server upstream yang ditentukan. Domain internal seperti metadata.internal dan *.google.internal mungkin tidak dapat di-resolve oleh server upstream kustom Anda. Jika Anda mengaktifkan Workload Identity Federation for GKE atau memiliki workload yang bergantung pada domain ini, tambahkan domain stub untuk internal di dalam ConfigMap. Gunakan 169.254.169.254, alamat IP server metadata, sebagai resolver untuk domain stub ini.

Mengelola Deployment kube-dns kustom

Di cluster Standar, kube-dns berjalan sebagai Deployment. Deployment kube-dns kustom berarti Anda, sebagai administrator cluster, dapat mengontrol Deployment dan menyesuaikannya dengan kebutuhan Anda, bukan menggunakan deployment default yang disediakan GKE.

Alasan untuk deployment kustom

Pertimbangkan deployment kube-dns kustom karena alasan berikut:

  • Alokasi resource: menyetel resource CPU dan memori untuk Pod kube-dns guna mengoptimalkan performa di cluster dengan traffic DNS tinggi.
  • Versi image: menggunakan versi tertentu dari image kube-dns atau beralih ke penyedia DNS alternatif seperti CoreDNS.
  • Konfigurasi lanjutan: menyesuaikan tingkat logging, kebijakan keamanan, dan perilaku caching DNS.

Penskalaan otomatis untuk Deployment kustom

kube-dns-autoscaler bawaan berfungsi dengan Deployment kube-dns default. Jika Anda membuat Deployment kube-dns kustom, autoscaler bawaan tidak akan mengelolanya. Oleh karena itu, Anda harus menyiapkan autoscaler terpisah yang dikonfigurasi secara khusus untuk memantau dan menyesuaikan jumlah replika Deployment kustom Anda. Pendekatan ini melibatkan pembuatan dan deployment konfigurasi autoscaler Anda sendiri di cluster Anda.

Saat mengelola Deployment kustom, Anda bertanggung jawab atas semua komponennya, seperti menjaga image autoscaler tetap terbaru. Penggunaan komponen yang sudah tidak berlaku dapat menyebabkan penurunan performa atau kegagalan DNS.

Untuk mengetahui petunjuk mendetail tentang cara mengonfigurasi dan mengelola kube-dns deployment Anda sendiri, lihat Menyiapkan Deployment kube-dns kustom.

Memecahkan masalah

Untuk mengetahui informasi tentang cara memecahkan masalah kube-dns, lihat halaman berikut:

Mengoptimalkan resolusi DNS

Bagian ini menjelaskan masalah umum dan praktik terbaik untuk mengelola DNS di GKE.

Batas domain penelusuran dnsConfig Pod

Kubernetes membatasi jumlah domain penelusuran DNS hingga 32. Jika Anda mencoba menentukan lebih dari 32 domain penelusuran di dnsConfig Pod, kube-apiserver tidak akan membuat Pod, dengan error yang mirip dengan berikut:

The Pod "dns-example" is invalid: spec.dnsConfig.searches: Invalid value: []string{"ns1.svc.cluster-domain.example", "my.dns.search.suffix1", "ns2.svc.cluster-domain.example", "my.dns.search.suffix2", "ns3.svc.cluster-domain.example", "my.dns.search.suffix3", "ns4.svc.cluster-domain.example", "my.dns.search.suffix4", "ns5.svc.cluster-domain.example", "my.dns.search.suffix5", "ns6.svc.cluster-domain.example", "my.dns.search.suffix6", "ns7.svc.cluster-domain.example", "my.dns.search.suffix7", "ns8.svc.cluster-domain.example", "my.dns.search.suffix8", "ns9.svc.cluster-domain.example", "my.dns.search.suffix9", "ns10.svc.cluster-domain.example", "my.dns.search.suffix10", "ns11.svc.cluster-domain.example", "my.dns.search.suffix11", "ns12.svc.cluster-domain.example", "my.dns.search.suffix12", "ns13.svc.cluster-domain.example", "my.dns.search.suffix13", "ns14.svc.cluster-domain.example", "my.dns.search.suffix14", "ns15.svc.cluster-domain.example", "my.dns.search.suffix15", "ns16.svc.cluster-domain.example", "my.dns.search.suffix16", "my.dns.search.suffix17"}: must not have more than 32 search paths.

kube-apiserver menampilkan pesan error ini sebagai respons terhadap upaya pembuatan Pod. Untuk mengatasi masalah ini, hapus jalur penelusuran tambahan dari konfigurasi.

Batas nameservers upstream untuk kube-dns

Versi lama kube-dns (versi 1.35 dan yang lebih lama) membatasi jumlah upstreamNameservers hingga tiga. Jika Anda menentukan lebih dari tiga, Cloud Logging akan menampilkan error yang mirip dengan berikut:

Invalid configuration: upstreamNameserver cannot have more than three entries (value was &TypeMeta{Kind:,APIVersion:,}), ignoring update

Dalam skenario ini, kube-dns mengabaikan konfigurasi upstreamNameservers dan terus menggunakan konfigurasi valid sebelumnya. Untuk mengatasi masalah ini, hapus upstreamNameservers tambahan dari ConfigMap kube-dns.

Meningkatkan skala kube-dns

Di cluster Standar, Anda dapat menggunakan nilai yang lebih rendah untuk nodesPerReplica sehingga lebih banyak Pod kube-dns yang dibuat saat node cluster ditingkatkan skalanya. Sebaiknya tetapkan nilai eksplisit untuk kolom max guna membantu memastikan bahwa mesin virtual (VM) bidang kontrol GKE tidak kewalahan karena banyaknya Pod kube-dns yang memantau Kubernetes API.

Anda dapat menetapkan nilai kolom max ke jumlah node dalam cluster. Jika cluster memiliki lebih dari 500 node, tetapkan nilai kolom max ke 500.

Anda dapat mengubah jumlah replika kube-dns dengan mengedit kube-dns-autoscaler ConfigMap.

kubectl edit configmap kube-dns-autoscaler --namespace=kube-system

Outputnya mirip dengan hal berikut ini:

linear: '{"coresPerReplica":256, "nodesPerReplica":16,"preventSinglePointFailure":true}'

Jumlah replika kube-dns dihitung menggunakan formula berikut:

replicas = max( ceil( cores * 1/coresPerReplica ) , ceil( nodes * 1/nodesPerReplica ) )

Untuk meningkatkan skala, ubah nilai kolom nodesPerReplica ke nilai yang lebih kecil, dan sertakan nilai untuk kolom max.

linear: '{"coresPerReplica":256, "nodesPerReplica":8,"max": 15,"preventSinglePointFailure":true}'

Konfigurasi ini membuat satu Pod kube-dns untuk setiap delapan node dalam cluster. Cluster dengan 24 node memiliki tiga replika dan cluster 40 node memiliki lima replika. Jika cluster berkembang melebihi 120 node, jumlah replika kube-dns tidak bertambah melebihi 15, yaitu nilai kolom max.

Untuk membantu memastikan tingkat ketersediaan DNS dasar di cluster Anda, tetapkan jumlah replika minimum untuk kolom kube-dns.

Output untuk ConfigMap kube-dns-autoscaler dengan kolom min yang dikonfigurasi mirip dengan berikut:

linear: '{"coresPerReplica":256, "nodesPerReplica":8,"max": 15,"min": 5,"preventSinglePointFailure":true}'

Mempercepat waktu pencarian DNS

Beberapa faktor dapat menyebabkan latensi tinggi dengan pencarian DNS atau kegagalan resolusi DNS dengan penyedia kube-dns default. Aplikasi mungkin mengalami masalah ini sebagai error getaddrinfo EAI_AGAIN, yang menunjukkan kegagalan sementara dalam resolusi nama. Penyebabnya meliputi hal berikut:

  • Pencarian DNS yang sering dalam workload Anda.
  • Kepadatan Pod yang tinggi per node.
  • Menjalankan kube-dns di Spot VM atau preemptible VM, yang dapat menyebabkan penghapusan node yang tidak terduga.
  • Batas koneksi: versi lama kube-dns (GKE versi 1.35 dan yang lebih lama) dibatasi hingga 200 koneksi TCP serentak. kube-dns di CoreDNS (GKE versi 1.36 dan yang lebih baru) menghapus batas tetap ini untuk koneksi masuk dan memberikan kapasitas yang jauh lebih tinggi untuk koneksi keluar.

Untuk mempercepat waktu pencarian DNS, lakukan hal berikut:

  • Hindari menjalankan komponen sistem penting seperti kube-dns di Spot VM atau preemptible VM. Buat setidaknya satu node pool yang memiliki VM standar dan tidak memiliki Spot VM atau Preemptible VM. Gunakan taint dan toleransi untuk membantu memastikan workload penting dijadwalkan di node yang andal ini.
  • Aktifkan NodeLocal DNSCache. NodeLocal DNSCache meng-cache respons DNS langsung di setiap node, yang mengurangi latensi dan beban pada layanan kube-dns. Jika Anda mengaktifkan NodeLocal DNSCache dan menggunakan kebijakan jaringan dengan aturan tolak default, tambahkan kebijakan untuk mengizinkan workload mengirim kueri DNS ke Pod node-local-dns.
  • Tingkatkan skala kube-dns.
  • Pastikan aplikasi Anda menggunakan fungsi berbasis dns.resolve*, bukan fungsi berbasis dns.lookup karena dns.lookup bersifat sinkron.
  • Gunakan nama domain yang sepenuhnya memenuhi syarat (FQDN), misalnya, https://google.com./, bukan https://google.com/.

Kegagalan resolusi DNS dapat terjadi selama upgrade cluster GKE karena upgrade serentak komponen bidang kontrol, termasuk kube-dns. Kegagalan ini biasanya memengaruhi sebagian kecil node. Uji upgrade cluster secara menyeluruh di lingkungan non-produksi sebelum Anda menerapkannya ke cluster produksi.

Memastikan kemampuan penemuan Layanan

kube-dns hanya membuat data DNS untuk Layanan yang memiliki Endpoint. Jika Layanan tidak memiliki Endpoint, kube-dns tidak akan membuat data DNS untuk Layanan tersebut.

Mengelola perbedaan TTL DNS

Jika kube-dns menerima respons DNS dari DNS resolver upstream dengan TTL yang besar atau tak terbatas, kube-dns akan menyimpan nilai TTL ini. Perilaku ini dapat menimbulkan perbedaan antara entri yang di-cache dan alamat IP sebenarnya.

GKE mengatasi masalah ini dalam versi bidang kontrol tertentu, seperti 1.21.14-gke.9100 dan yang lebih baru atau 1.22.15-gke.2100 dan yang lebih baru. Versi ini menetapkan nilai TTL maksimum ke 30 detik untuk setiap respons DNS yang memiliki TTL lebih tinggi. Perilaku ini mirip dengan NodeLocal DNSCache.

Melihat metrik kube-dns

Anda dapat mengambil metrik tentang kueri DNS langsung dari Pod kube-dns. Cara Anda mengambil metrik ini bergantung pada versi GKE Anda.

GKE versi 1.36 dan yang lebih baru

Jika cluster Anda menjalankan GKE versi 1.36 atau yang lebih baru (kube-dns di CoreDNS), Anda dapat memantau performa DNS menggunakan dasbor yang telah ditentukan di Cloud Monitoring atau mengambil metrik secara manual dari Pod.

Melihat metrik di Google Cloud konsol

  1. Di Google Cloud konsol, buka halaman Dashboards.
  2. Pilih dasbor GKE DNS Observability - Cluster View.

Atau, Anda dapat mengkueri metrik ini langsung di Google Cloud konsol dengan membuka Monitoring > Metrics explorer dan menelusuri nama metrik tertentu.

Mengambil metrik secara manual

Untuk mengambil metrik dari Pod secara manual, lakukan hal berikut:

  1. Temukan Pod kube-dns.

    kubectl get pods -n kube-system --selector=k8s-app=kube-dns
    
  2. Teruskan port 9153 ke salah satu Pod.

    kubectl port-forward pod/POD_NAME -n kube-system 9153:9153
    

    Ganti POD_NAME dengan nama salah satu Pod kube-dns dari output sebelumnya.

  3. Akses metrik.

    curl http://127.0.0.1:9153/metrics
    

GKE versi 1.35 dan yang lebih lama

Versi kube-dns ini menggunakan Pod multi-container. Untuk mengambil metrik, lakukan hal berikut:

  1. Temukan Pod kube-dns di namespace kube-system.

    kubectl get pods -n kube-system --selector=k8s-app=kube-dns
    
  2. Teruskan port ke port 10055 (untuk container kube-dns) dan 10054 (untuk container dnsmasq):

    #For the kube-dns container
    kubectl port-forward pod/POD_NAME -n kube-system 10055:10055
    #For the dnsmasq container
    kubectl port-forward pod/POD_NAME -n kube-system 10054:10054
    

    Ganti POD_NAME dengan nama salah satu Pod kube-dns dari output sebelumnya. Jalankan perintah penerusan port ini dalam sesi terminal terpisah.

  3. Akses metrik.

    #Metrics from the kube-dns container
    curl http://127.0.0.1:10055/metrics
    
    #Metrics from the dnsmasq container
    curl http://127.0.0.1:10054/metrics
    

Langkah berikutnya