Tentang kube-dns untuk GKE

Jika Anda menjalankan aplikasi di cluster Standard, 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 terbaiknya untuk mengoptimalkan resolusi DNS dalam lingkungan GKE Anda.

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

Sebelum memulai, pastikan Anda memahami Layanan Kubernetes dan konsep DNS secara 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 tinggi.
  • kube-dns Service: Kubernetes Service jenis ClusterIP ini mengelompokkan Pod kube-dns dan mengeksposnya sebagai satu endpoint yang stabil. ClusterIP bertindak sebagai server DNS untuk cluster, yang digunakan Pod untuk mengirim kueri DNS. kube-dns mendukung hingga 1.000 endpoint per layanan headless.
  • 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 kube-dns Service sebagai server nama.
  2. Kueri DNS: Pod mengirimkan kueri DNS ke Layanan kube-dns.
  3. Resolusi nama: kube-dns menerima kueri. Server ini akan mencari alamat IP yang sesuai di data DNS internalnya dan merespons Pod.
  4. Komunikasi: Pod kemudian menggunakan alamat IP yang di-resolve untuk berkomunikasi dengan Service 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. Server ini meneruskan kueri ke server DNS upstream yang dikonfigurasi dalam file ConfigMap-nya. 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. Selain itu, perintah 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 menyelesaikan myservice.default.svc.cluster.local terlebih dahulu, 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 saat GKE menganggap nama memenuhi syarat sepenuhnya. Nama dianggap sepenuhnya memenuhi syarat jika memiliki lima titik atau lebih.

Pod yang dikonfigurasi dengan setelan hostNetwork: true mewarisi konfigurasi DNS dari host dan tidak mengkueri kube-dns secara langsung.

Sesuaikan kube-dns

kube-dns menyediakan resolusi DNS default yang andal. Anda dapat menyesuaikan perilakunya 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.

Ubah 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 ke:

    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
          "1.1.1.1" # Cloudflare DNS
        ]
    
  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 membuat kueri untuk nama dalam domain stub tersebut, kube-dns meneruskan kueri ke resolver yang ditentukan, bukan menggunakan mekanisme resolusi defaultnya.

Anda menyertakan bagian stubDomains dalam kube-dns ConfigMap.

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 menyelesaikan 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 ConfigMap. Gunakan 169.254.169.254, alamat IP server metadata, sebagai resolver untuk domain stub ini.

Mengelola Deployment kube-dns kustom

Di GKE 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: sesuaikan resource CPU dan memori untuk Pod kube-dns guna mengoptimalkan performa di cluster dengan traffic DNS tinggi.
  • Versi image: gunakan versi spesifik image kube-dns atau beralih ke penyedia DNS alternatif seperti CoreDNS.
  • Konfigurasi lanjutan: sesuaikan 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 penskalaan otomatis Anda sendiri di cluster Anda.

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

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

Memecahkan masalah

Untuk informasi tentang pemecahan 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 ini:

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

kube-dns membatasi jumlah nilai 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 kube-dns ConfigMap.

Peningkatan 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 dengan 40 node memiliki lima replika. Jika cluster berkembang melebihi 120 node, jumlah replika kube-dns tidak bertambah melebihi 15, yang merupakan nilai kolom max.

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

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

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:

  • Pencarian DNS yang sering dalam workload Anda.
  • Kepadatan Pod per node yang tinggi.
  • Menjalankan kube-dns di Spot VM atau preemptible VM, yang dapat menyebabkan penghapusan node yang tidak terduga.
  • Volume kueri tinggi yang melebihi kapasitas instance dnsmasq dalam Pod kube-dns. Satu instance kube-dns memiliki batas 200 koneksi TCP serentak di GKE versi 1.31 dan yang lebih baru, serta batas 20 koneksi TCP serentak di GKE versi 1.30 dan yang lebih lama.

Untuk mempercepat waktu pencarian DNS, lakukan hal-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 penolakan 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 Layanan dapat ditemukan

kube-dns hanya membuat data DNS untuk Layanan yang memiliki Endpoint. Jika Service tidak memiliki Endpoint, kube-dns tidak membuat data DNS untuk Service 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 di cluster langsung dari Pod kube-dns.

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

    kubectl get pods -n kube-system --selector=k8s-app=kube-dns
    

    Outputnya mirip dengan hal berikut ini:

    NAME                        READY     STATUS    RESTARTS   AGE
    kube-dns-548976df6c-98fkd   4/4       Running   0          48m
    kube-dns-548976df6c-x4xsh   4/4       Running   0          47m
    
  2. Pilih salah satu Pod dan siapkan penerusan port untuk mengakses metrik dari Pod tersebut:

    • Port 10055 mengekspos metrik kube-dns.
    • Port 10054 mengekspos metrik dnsmasq.

    Ganti POD_NAME dengan nama Pod yang Anda pilih.

    POD_NAME="kube-dns-548976df6c-98fkd" # Replace with your pod name
    kubectl port-forward pod/${POD_NAME} -n kube-system 10055:10055 10054:10054
    

    Outputnya mirip dengan hal berikut ini:

    Forwarding from 127.0.0.1:10054 -> 10054
    Forwarding from 127.0.0.1:10055 -> 10055
    
  3. Dalam sesi terminal baru, gunakan perintah curl untuk mengakses endpoint metrik.

    # Get kube-dns metrics
    curl http://127.0.0.1:10055/metrics
    
    # Get dnsmasq metrics
    curl http://127.0.0.1:10054/metrics
    

    Outputnya akan seperti ini:

    kubedns_dnsmasq_errors 0
    kubedns_dnsmasq_evictions 0
    kubedns_dnsmasq_hits 3.67351e+06
    kubedns_dnsmasq_insertions 254114
    kubedns_dnsmasq_max_size 1000
    kubedns_dnsmasq_misses 3.278166e+06
    

Langkah berikutnya