Memecahkan masalah kube-dns di GKE


Halaman ini menunjukkan cara menyelesaikan masalah terkait kube-dns di Google Kubernetes Engine (GKE).

Mengidentifikasi sumber masalah DNS di kube-dns

Error seperti dial tcp: i/o timeout, no such host, atau Could not resolve host sering kali menandakan masalah pada kemampuan kube-dns untuk me-resolve kueri.

Jika Anda telah melihat salah satu error tersebut, tetapi tidak mengetahui penyebabnya, gunakan bagian berikut untuk membantu Anda menemukannya. Bagian berikut disusun untuk memulai dengan langkah-langkah yang paling mungkin membantu Anda, jadi coba setiap bagian secara berurutan.

Memeriksa apakah Pod kube-dns berjalan

Pod kube-dns sangat penting untuk resolusi nama dalam cluster. Jika tidak berjalan, Anda mungkin akan mengalami masalah dengan resolusi DNS.

Untuk memverifikasi bahwa Pod kube-dns berjalan tanpa dimulai ulang baru-baru ini, lihat status Pod ini:

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

Outputnya mirip dengan hal berikut ini:

NAME                   READY          STATUS          RESTARTS       AGE
kube-dns-POD_ID_1      5/5            Running         0              16d
kube-dns-POD_ID_2      0/5            Terminating     0              16d

Dalam output ini, POD_ID_1 dan POD_ID_2 mewakili ID unik yang otomatis ditambahkan ke Pod kube-dns.

Jika output menunjukkan bahwa Pod kube-dns Anda tidak memiliki status Running, lakukan langkah-langkah berikut:

  1. Gunakan log audit Aktivitas Admin untuk menyelidiki apakah ada perubahan terbaru seperti upgrade versi cluster atau node pool, atau perubahan pada ConfigMap kube-dns. Untuk mempelajari log audit lebih lanjut, lihat Informasi logging audit GKE. Jika Anda menemukan perubahan, kembalikan dan lihat status Pod lagi.

  2. Jika Anda tidak menemukan perubahan terbaru yang relevan, selidiki apakah Anda mengalami error OOM pada node tempat Pod kube-dns berjalan. Jika Anda melihat error yang mirip dengan berikut dalam pesan log Cloud Logging, Pod ini mengalami error OOM:

    Warning: OOMKilling Memory cgroup out of memory
    

    Untuk mengatasi error ini, lihat Pesan Error: "Warning: OOMKilling Memory cgroup out of memory".

  3. Jika Anda tidak menemukan pesan error OOM, mulai ulang Deployment kube-dns:

    kubectl rollout restart deployment/kube-dns --namespace=kube-system
    

    Setelah memulai ulang Deployment, periksa apakah Pod kube-dns Anda berjalan.

Jika langkah-langkah ini tidak berhasil, atau semua Pod kube-dns Anda memiliki status Running, tetapi Anda masih mengalami masalah DNS, pastikan file /etc/resolv.conf dikonfigurasi dengan benar.

Pastikan /etc/resolv.conf dikonfigurasi dengan benar

Tinjau file /etc/resolv.conf Pod yang mengalami masalah DNS dan pastikan entri yang ada sudah benar:

  1. Lihat file /etc/resolv.conf Pod:

    kubectl exec -it POD_NAME -- cat /etc/resolv.conf
    

    Ganti POD_NAME dengan nama Pod yang mengalami masalah DNS. Jika ada beberapa Pod yang mengalami masalah, ulangi langkah-langkah di bagian ini untuk setiap Pod.

    Jika biner Pod tidak mendukung perintah kubectl exec, perintah ini mungkin gagal. Jika hal ini terjadi, buat Pod sederhana untuk digunakan sebagai lingkungan pengujian. Dengan prosedur ini, Anda dapat menjalankan Pod pengujian di namespace yang sama dengan Pod yang bermasalah.

  2. Verifikasi bahwa alamat IP server nama dalam file /etc/resolv.conf sudah benar:

    • Pod yang menggunakan jaringan host harus menggunakan nilai dalam file /etc/resolv.conf node. Alamat IP server nama harus berupa 169.254.169.254.
    • Untuk Pod yang tidak menggunakan jaringan host, alamat IP Layanan kube-dns harus sama dengan alamat IP server nama. Untuk membandingkan alamat IP, selesaikan langkah-langkah berikut:

      1. Dapatkan alamat IP Layanan kube-dns:

        kubectl get svc kube-dns -n kube-system
        

        Outputnya mirip dengan hal berikut ini:

        NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE
        kube-dns   ClusterIP   192.0.2.10   <none>        53/UDP,53/TCP   64d
        
      2. Catat nilai di kolom Cluster IP. Dalam contoh ini, parameternya adalah 192.0.2.10.

      3. Bandingkan alamat IP Layanan kube-dns dengan alamat IP dari file /etc/resolv.conf:

        # cat /etc/resolv.conf
        
        search default.svc.cluster.local svc.cluster.local cluster.local c.PROJECT_NAME google.internal
        nameserver 192.0.2.10
        options ndots:5
        

        Dalam contoh ini, kedua nilai cocok, sehingga alamat IP server nama yang salah bukan penyebab masalah Anda.

        Namun, jika alamat IP tidak cocok, artinya kolom dnsConfig dikonfigurasi dalam manifes Pod aplikasi.

        Jika nilai di kolom dnsConfig.nameservers sudah benar, selidiki server DNS Anda dan pastikan server tersebut berfungsi dengan benar.

        Jika Anda tidak ingin menggunakan server nama kustom, hapus kolom tersebut dan lakukan mulai ulang bertahap Pod:

        kubectl rollout restart deployment POD_NAME
        

        Ganti POD_NAME dengan nama Pod Anda.

  3. Verifikasi entri search dan ndots di /etc/resolv.conf. Pastikan tidak ada kesalahan ejaan, konfigurasi yang sudah tidak berlaku, dan permintaan yang gagal menunjuk ke layanan yang ada di namespace yang benar.

Melakukan pencarian DNS

Setelah Anda mengonfirmasi bahwa /etc/resolv.conf dikonfigurasi dengan benar dan data DNS sudah benar, gunakan alat command line dig untuk melakukan pencarian DNS dari Pod yang melaporkan error DNS:

  1. Buat kueri Pod secara langsung dengan membuka shell di dalamnya:

    kubectl exec -it POD_NAME -n NAMESPACE_NAME -- SHELL_NAME
    

    Ganti kode berikut:

    • POD_NAME: nama Pod yang melaporkan error DNS.
    • NAMESPACE_NAME: namespace tempat Pod berada.
    • SHELL_NAME: Nama shell yang ingin Anda buka. Misalnya sh atau /bin/bash.

    Perintah ini mungkin gagal jika Pod Anda tidak mengizinkan perintah kubectl exec atau jika Pod tidak memiliki biner dig. Jika hal ini terjadi, buat Pod pengujian dengan image yang telah menginstal dig:

    kubectl run "test-$RANDOM" ti --restart=Never --image=thockin/dnsutils - bash
    
  2. Periksa apakah Pod dapat me-resolve Layanan DNS internal cluster dengan benar:

    dig kubernetes
    

    Karena file /etc/resolv.conf mengarah ke alamat IP Layanan kube-dns, saat Anda menjalankan perintah ini, server DNS adalah Layanan kube-dns.

    Anda akan melihat respons DNS yang berhasil dengan alamat IP Layanan API Kubernetes (sering kali seperti 10.96.0.1). Jika Anda melihat SERVFAIL atau tidak ada respons, hal ini biasanya menunjukkan bahwa Pod kube-dns tidak dapat me-resolve nama layanan internal.

  3. Periksa apakah Layanan kube-dns dapat me-resolve nama domain eksternal:

    dig example.com
    
  4. Jika Anda mengalami kesulitan dengan Pod kube-dns tertentu yang merespons kueri DNS, periksa apakah Pod tersebut dapat me-resolve nama domain eksternal:

     dig example.com @KUBE_DNS_POD_IP
    

    Ganti KUBE_DNS_POD_IP dengan alamat IP Pod kube-dns. Jika Anda tidak mengetahui nilai alamat IP ini, jalankan perintah berikut:

     kubectl get pods -n kube-system -l k8s-app=kube-dns -o wide
    

    Alamat IP berada di kolom IP.

    Jika resolusi perintah berhasil, Anda akan melihat status: NOERROR dan detail data A seperti yang ditunjukkan dalam contoh berikut:

     ; <<>> DiG 9.16.27 <<>> example.com
     ;; global options: +cmd
     ;; Got answer:
     ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31256
     ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
    
     ;; OPT PSEUDOSECTION:
     ; EDNS: version: 0, flags:; udp: 512
     ;; QUESTION SECTION:
     ;example.com.                   IN      A
    
     ;; ANSWER SECTION:
     example.com.            30      IN      A       93.184.215.14
    
     ;; Query time: 6 msec
     ;; SERVER: 10.76.0.10#53(10.76.0.10)
     ;; WHEN: Tue Oct 15 16:45:26 UTC 2024
     ;; MSG SIZE  rcvd: 56
    
  5. Keluar dari shell:

    exit
    

Jika salah satu perintah ini gagal, lakukan mulai ulang bertahap Deployment kube-dns:

kubectl rollout restart deployment/kube-dns --namespace=kube-system

Setelah menyelesaikan mulai ulang, coba lagi perintah dig dan lihat apakah sekarang berhasil. Jika masih gagal, lanjutkan untuk mengambil rekaman paket.

Mengambil rekaman aktivitas paket

Ambil rekaman paket untuk memverifikasi apakah kueri DNS diterima dan dijawab dengan benar oleh Pod kube-dns:

  1. Menggunakan SSH, hubungkan ke node yang menjalankan Pod kube-dns. Contoh:

    1. Di konsol Google Cloud, buka halaman Instance VM.

      Buka Instance VM

    2. Temukan node yang ingin Anda hubungkan. Jika Anda tidak mengetahui nama node di Pod kube-dns, jalankan perintah berikut:

      kubectl get pods -n kube-system -l k8s-app=kube-dns -o wide
      

      Nama node tercantum di kolom Node.

    3. Di kolom Connect, klik SSH.

  2. Di terminal, mulai toolbox; alat proses debug yang telah diinstal sebelumnya:

    toolbox
    
  3. Di prompt root, instal paket tcpdump:

    apt update -y && apt install -y tcpdump
    
  4. Dengan tcpdump, ambil tangkapan paket traffic DNS Anda:

    tcpdump -i eth0 port 53" -w FILE_LOCATION
    

    Ganti FILE_LOCATION dengan jalur ke tempat Anda ingin menyimpan rekaman.

  5. Tinjau penangkapan paket. Periksa apakah ada paket dengan alamat IP tujuan yang cocok dengan alamat IP Layanan kube-dns. Hal ini memastikan bahwa permintaan DNS mencapai tujuan yang tepat untuk resolusi. Kegagalan untuk melihat traffic DNS yang mendarat di Pod yang benar, mungkin menunjukkan adanya kebijakan jaringan yang memblokir permintaan.

Memeriksa kebijakan jaringan

Kebijakan jaringan yang membatasi terkadang dapat mengganggu traffic DNS. Untuk memverifikasi apakah kebijakan jaringan ada di namespace kube-system, jalankan perintah berikut:

kubectl get networkpolicy -n kube-system

Jika Anda menemukan kebijakan jaringan, tinjau dan pastikan kebijakan tersebut mengizinkan komunikasi DNS yang diperlukan. Misalnya, jika Anda memiliki kebijakan jaringan yang memblokir semua traffic keluar, kebijakan tersebut juga akan memblokir permintaan DNS.

Jika outputnya adalah No resources found in kube-system namespace, berarti Anda tidak memiliki kebijakan jaringan dan dapat mengesampingkan hal ini sebagai penyebab masalah. Menyelidiki log dapat membantu Anda menemukan lebih banyak titik kegagalan.

Mengaktifkan logging kueri DNS sementara

Untuk membantu Anda mengidentifikasi masalah seperti respons DNS yang salah, sementara ini aktifkan logging debug kueri DNS.

Ini adalah prosedur yang membutuhkan banyak resource, jadi sebaiknya Anda menonaktifkan logging ini setelah mengumpulkan sampel log yang sesuai.

Menyelidiki Pod kube-dns

Tinjau cara Pod kube-dns menerima dan me-resolve kueri DNS dengan Cloud Logging.

Untuk melihat entri log yang terkait dengan Pod kube-dns, selesaikan langkah-langkah berikut:

  1. Di Konsol Google Cloud, buka halaman Logs Explorer.

    Buka Logs Explorer

  2. Di panel kueri, masukkan filter berikut untuk melihat peristiwa yang terkait dengan penampung kube-dns:

    resource.type="k8s_container"
    resource.labels.namespace_name="kube-system"
    resource.labels.Pod_name:"kube-dns"
    resource.labels.cluster_name="CLUSTER_NAME"
    resource.labels.location="CLUSTER_LOCATION"
    

    Ganti kode berikut:

    • CLUSTER_NAME: nama cluster tempat Pod kube-dns berada.
    • CLUSTER_LOCATION: lokasi cluster Anda.
  3. Klik Run query.

  4. Tinjau output. Contoh output berikut menunjukkan salah satu kemungkinan error yang mungkin Anda lihat:

    {
       "timestamp": "2024-10-10T15:32:16.789Z",
       "severity": "ERROR",
       "resource": {
          "type": "k8s_container",
          "labels": {
          "namespace_name": "kube-system",
          "Pod_name": "kube-dns",
          "cluster_name": "CLUSTER_NAME",
          "location": "CLUSTER_LOCATION"
          }
       },
       "message": "Failed to resolve 'example.com': Timeout."
    },
    

    Dalam contoh ini, kube-dns tidak dapat me-resolve example.com dalam waktu yang wajar. Jenis error ini dapat disebabkan oleh beberapa masalah. Misalnya, server upstream mungkin salah dikonfigurasi di ConfigMap kube-dns, atau mungkin ada traffic jaringan yang tinggi.

Jika Anda tidak mengaktifkan Cloud Logging, lihat log Kubernetes:

Pod=$(kubectl get Pods -n kube-system -l k8s-app=kube-dns -o name | head -n1)
kubectl logs -n kube-system $Pod -c dnsmasq
kubectl logs -n kube-system $Pod -c kubedns
kubectl logs -n kube-system $Pod -c sidecar

Menyelidiki perubahan terbaru di ConfigMap kube-dns

Jika Anda tiba-tiba mengalami kegagalan resolusi DNS di cluster, salah satu penyebabnya adalah perubahan konfigurasi yang salah pada ConfigMap kube-dns. Secara khusus, perubahan konfigurasi pada domain stub dan definisi server upstream dapat menyebabkan masalah.

Untuk memeriksa update pada setelan domain stub, selesaikan langkah-langkah berikut:

  1. Di Konsol Google Cloud, buka halaman Logs Explorer.

    Buka Logs Explorer

  2. Di panel kueri, masukkan kueri berikut:

    resource.labels.cluster_name="clouddns"
    resource.type="k8s_container"
    resource.labels.namespace_name="kube-system"
    labels.k8s-pod/k8s-app="kube-dns" jsonPayload.message=~"Updated stubDomains to"
    
  3. Klik Run query.

  4. Tinjau output. Jika ada update, output-nya akan mirip dengan berikut:

    Updated stubDomains to map[example.com: [8.8.8.8 8.8.4.4 1.1.3.3 1.0.8.111]]
    

    Jika Anda melihat update, luaskan hasilnya untuk mempelajari perubahan lebih lanjut. Pastikan setiap domain stub dan server DNS upstream-nya yang sesuai ditentukan dengan benar. Entri yang salah di sini dapat menyebabkan kegagalan resolusi untuk domain tersebut.

Untuk memeriksa perubahan pada server upstream, selesaikan langkah-langkah berikut:

  1. Di Konsol Google Cloud, buka halaman Logs Explorer.

    Buka Logs Explorer

  2. Di panel kueri, masukkan kueri berikut:

    resource.labels.cluster_name="clouddns"
    resource.type="k8s_container" resource.labels.namespace_name="kube-system"
    labels.k8s-pod/k8s-app="kube-dns" jsonPayload.message=~"Updated upstreamNameservers to"
    
  3. Klik Run query.

  4. Tinjau output. Jika ada perubahan, output-nya akan mirip dengan hal berikut:

    Updated upstreamNameservers to [8.8.8.8]
    

    Luaskan hasil untuk mempelajari perubahan lebih lanjut. Pastikan daftar server DNS upstream akurat dan server ini dapat dijangkau dari cluster Anda. Jika server ini tidak tersedia atau salah dikonfigurasi, resolusi DNS umum mungkin gagal.

Jika Anda telah memeriksa perubahan pada domain stub dan server upstream, tetapi tidak menemukan hasil apa pun, periksa semua perubahan dengan filter berikut:

resource.type="k8s_cluster"
protoPayload.resourceName:"namespaces/kube-system/configmaps/kube-dns"
protoPayload.methodName=~"io.k8s.core.v1.configmaps."

Tinjau perubahan yang tercantum untuk melihat apakah perubahan tersebut menyebabkan error.

Menghubungi Cloud Customer Care

Jika Anda telah menyelesaikan bagian sebelumnya, tetapi masih tidak dapat mendiagnosis penyebab masalah, hubungi Cloud Customer Care.

Memecahkan masalah umum

Jika Anda mengalami error atau masalah tertentu, gunakan saran di bagian berikut.

Masalah: Waktu tunggu DNS habis secara berkala

Jika Anda melihat waktu tunggu resolusi DNS yang terputus-putus yang terjadi saat ada peningkatan traffic DNS atau saat jam buka dimulai, coba solusi berikut untuk mengoptimalkan performa DNS Anda:

  • Periksa jumlah Pod kube-dns yang berjalan di cluster dan bandingkan dengan jumlah total node GKE. Jika tidak ada resource yang memadai, pertimbangkan untuk melakukan penskalaan ke atas Pod kube-dns.

  • Untuk meningkatkan waktu pencarian DNS rata-rata, aktifkan NodeLocal DNS Cache.

  • Resolusi DNS ke nama eksternal dapat membebani Pod kube-dns. Untuk mengurangi jumlah kueri, sesuaikan setelan ndots dalam file /etc/resolv.conf. ndots mewakili jumlah titik yang harus muncul dalam nama domain untuk me-resolve kueri sebelum kueri absolut awal.

    Contoh berikut adalah file /etc/resolv.conf dari Pod aplikasi:

    search default.svc.cluster.local svc.cluster.local cluster.local c.PROJECT_ID.internal google.internal
    nameserver 10.52.16.10
    options ndots:5
    

    Dalam contoh ini, kube-dns mencari lima titik di domain yang di-kueri. Jika Pod melakukan panggilan resolusi DNS untuk example.com, log Anda akan terlihat mirip dengan contoh berikut:

    "A IN example.com.default.svc.cluster.local." NXDOMAIN
    "A IN example.com.svc.cluster.local." NXDOMAIN
    "A IN example.com.cluster.local." NXDOMAIN
    "A IN example.com.google.internal." NXDOMAIN
    "A IN example.com.c.PROJECT_ID.internal." NXDOMAIN
    "A IN example.com." NOERROR
    

    Untuk mengatasi masalah ini, ubah nilai ndots menjadi 1 untuk hanya mencari satu titik atau tambahkan titik (.) di akhir domain yang Anda kueri atau gunakan. Contoh:

    dig example.com.
    

Masalah: Kueri DNS gagal secara berkala dari beberapa node

Jika Anda melihat kueri DNS gagal secara berkala dari beberapa node, Anda mungkin melihat gejala berikut:

  • Saat Anda menjalankan perintah dig ke alamat IP Layanan kube-dns atau alamat IP Pod, kueri DNS akan gagal secara berkala dengan waktu tunggu habis.
  • Menjalankan perintah dig dari Pod di node yang sama dengan Pod kube-dns akan gagal.

Untuk mengatasi masalah ini, selesaikan beberapa langkah berikut:

  1. Lakukan Uji Konektivitas. Tetapkan Pod atau node yang bermasalah sebagai sumber, dan tujuan sebagai alamat IP Pod kube-dns. Dengan begitu, Anda dapat memeriksa apakah Anda telah menerapkan aturan firewall yang diperlukan untuk mengizinkan traffic ini.
  2. Jika pengujian tidak berhasil, dan traffic diblokir oleh aturan firewall, gunakan Cloud Logging untuk mencantumkan perubahan manual apa pun yang dilakukan pada aturan firewall. Cari perubahan yang memblokir jenis traffic tertentu:

    1. Di Konsol Google Cloud, buka halaman Logs Explorer.

      Buka Logs Explorer

    2. Di panel kueri, masukkan kueri berikut:

      logName="projects/project-name/logs/cloudaudit.googleapis.com/activity"
      resource.type="gce_firewall_rule"
      
    3. Klik Run query. Gunakan output kueri untuk menentukan apakah ada perubahan yang telah dilakukan. Jika Anda melihat error, perbaiki dan terapkan kembali aturan firewall.

      Pastikan Anda tidak melakukan perubahan pada aturan firewall otomatis.

  3. Jika tidak ada perubahan pada aturan firewall, periksa versi node pool dan pastikan versi tersebut kompatibel dengan panel kontrol dan node pool lain yang berfungsi. Jika salah satu node pool cluster memiliki lebih dari dua versi minor yang lebih lama daripada panel kontrol, hal ini mungkin menyebabkan masalah. Untuk informasi selengkapnya tentang inkompatibilitas ini, lihat Versi node tidak kompatibel dengan versi panel kontrol.

  4. Untuk menentukan apakah permintaan dikirim ke IP layanan kube-dns yang benar, rekam traffic jaringan di node yang bermasalah dan filter untuk port 53 (traffic DNS). Rekam traffic di Pod kube-dns itu sendiri untuk melihat apakah permintaan mencapai Pod yang diinginkan dan apakah permintaan tersebut berhasil di-resolve.

Langkah selanjutnya