Memecahkan masalah kube-dns di GKE


Halaman ini menunjukkan cara menyelesaikan masalah 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 menyelesaikan 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 kemungkinan besar akan membantu Anda, jadi coba setiap bagian secara berurutan.

Periksa apakah Pod kube-dns sedang 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 Anda menunjukkan bahwa salah satu Pod kube-dns Anda tidak memiliki status Running, ikuti 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, batalkan perubahan tersebut 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 ini di pesan log Cloud Logging Anda, maka Pod ini mengalami error OOM:

    Warning: OOMKilling Memory cgroup out of memory
    

    Pesan ini menunjukkan bahwa Kubernetes menghentikan proses karena konsumsi resource yang berlebihan. Kubernetes menjadwalkan Pod berdasarkan permintaan resource, tetapi memungkinkan Pod menggunakan hingga batas resource-nya. Jika batas lebih tinggi daripada permintaan atau tidak ada batas, penggunaan resource Pod dapat melebihi resource sistem.

    Untuk mengatasi error ini, Anda dapat menghapus workload yang bermasalah, atau menetapkan batas memori atau CPU. Untuk mempelajari lebih lanjut cara menetapkan batas, lihat Pengelolaan Resource untuk Pod dan Container dalam dokumentasi Kubernetes. Untuk mengetahui informasi selengkapnya tentang peristiwa OOM, lihat Memecahkan masalah peristiwa OOM.

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

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

    Setelah Anda 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, periksa apakah 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 di dalamnya 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. Prosedur ini memungkinkan Anda 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, nilainya 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, jadi alamat IP server nama yang salah bukan penyebab masalah Anda.

        Namun, jika alamat IP tidak cocok, berarti 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 dan lakukan restart 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 tidak berlaku, dan permintaan yang gagal mengarah 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. Mengkueri 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 dapat 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 menyelesaikan 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, biasanya ini 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 ada di kolom IP.

    Jika resolusi perintah berhasil, Anda akan melihat status: NOERROR dan detail catatan 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 pada Deployment kube-dns:

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

Setelah Anda menyelesaikan proses mulai ulang, coba lagi perintah dig dan lihat apakah perintah tersebut berhasil. Jika masih gagal, lanjutkan untuk mengambil rekaman aktivitas jaringan.

Merekam penangkapan paket

Lakukan pengambilan paket untuk memverifikasi apakah kueri DNS diterima dan dijawab dengan tepat oleh Pod kube-dns:

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

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

      Buka Instance VM

    2. Cari 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 debug yang telah diinstal sebelumnya:

    toolbox
    
  3. Pada prompt root, instal paket tcpdump:

    apt update -y && apt install -y tcpdump
    
  4. Dengan menggunakan tcpdump, lakukan pengambilan 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 melihat traffic DNS yang mendarat di Pod yang benar, mungkin menunjukkan adanya kebijakan jaringan yang memblokir permintaan.

Memeriksa kebijakan jaringan

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

kubectl get networkpolicy -n kube-system

Jika Anda menemukan kebijakan jaringan, tinjau kebijakan tersebut dan pastikan kebijakan 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 No resources found in kube-system namespace, berarti Anda tidak memiliki kebijakan jaringan dan Anda dapat mengesampingkan hal ini sebagai penyebab masalah Anda. 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, aktifkan sementara pencatatan debug kueri DNS. Untuk mengaktifkan kueri, buat Pod berdasarkan Pod kube-dns yang ada. Setiap perubahan pada Deployment kube-dns akan otomatis dikembalikan.

Mengaktifkan logging kueri DNS sementara adalah prosedur yang menggunakan banyak resource, jadi sebaiknya hapus Pod yang Anda buat segera setelah mengumpulkan sampel log yang sesuai.

Untuk mengaktifkan logging kueri DNS sementara, selesaikan langkah-langkah berikut:

  1. Ambil Pod kube-dns dan simpan di variabel bernama POD:

    POD=$(kubectl -n kube-system get pods --selector=k8s-app=kube-dns -o jsonpath="{.items[0].metadata.name}")
    
  2. Buat Pod bernama kube-dns-debug. Pod ini adalah salinan Pod yang disimpan dalam variabel POD, tetapi dengan logging dnsmasq diaktifkan. Perintah ini tidak mengubah Pod kube-dns asli:

    kubectl apply -f <(kubectl get pod -n kube-system ${POD} -o json | jq -e '
    
    (
    
    (.spec.containers[] | select(.name == "dnsmasq") | .args) += ["--log-queries"]
    
    )
    
    | (.metadata.name = "kube-dns-debug")
    
    | (del(.metadata.labels."pod-template-hash"))
    
    ')
    
  3. Periksa log:

    kubectl logs -f --tail 100 -c dnsmasq -n kube-system kube-dns-debug
    

    Anda juga dapat melihat kueri di Cloud Logging.

  4. Setelah selesai melihat log kueri DNS, hapus kube-dns-debug Pod:

    kubectl -n kube-system delete pod kube-dns-debug
    

Menyelidiki Pod kube-dns

Tinjau cara Pod kube-dns menerima dan menyelesaikan 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 container 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-nya. 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 yang dilakukan pada ConfigMap kube-dns. Secara khusus, perubahan konfigurasi pada definisi server upstream dan domain stub 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-nya. Jika ada update, outputnya akan mirip dengan berikut ini:

    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 pembaruan, luaskan hasil untuk mempelajari lebih lanjut perubahan tersebut. Verifikasi bahwa semua domain stub dan server DNS upstream yang sesuai telah ditentukan dengan benar. Entri yang salah di sini dapat menyebabkan kegagalan penyelesaian 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-nya. Jika ada perubahan, outputnya akan mirip dengan yang berikut ini:

    Updated upstreamNameservers to [8.8.8.8]
    

    Luaskan hasil untuk mempelajari lebih lanjut perubahan tersebut. 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 setiap perubahan yang tercantum untuk melihat apakah perubahan tersebut menyebabkan error.

Menghubungi Cloud Customer Care

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

Memecahkan masalah umum

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

Masalah: Waktu tunggu DNS terputus-putus

Jika Anda melihat waktu tunggu resolusi DNS yang terjadi secara berkala saat ada peningkatan traffic DNS atau saat jam operasional bisnis dimulai, coba solusi berikut untuk mengoptimalkan performa DNS Anda:

  • Periksa jumlah Pod kube-dns yang berjalan di cluster dan bandingkan dengan total jumlah node GKE. Jika tidak ada cukup resource, pertimbangkan untuk menskalakan 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 menyelesaikan kueri sebelum kueri absolut awal.

    Contoh berikut adalah file /etc/resolv.conf 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 dikueri. Jika Pod membuat panggilan resolusi DNS untuk example.com, maka 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 agar 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 atau alamat IP Pod kube-dns, kueri DNS akan gagal secara berkala karena 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 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 error tersebut 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 bidang kontrol dan node pool lain yang berfungsi. Jika salah satu node pool cluster memiliki lebih dari dua versi minor yang lebih lama daripada bidang kontrol, hal ini mungkin menyebabkan masalah. Untuk mengetahui informasi selengkapnya tentang ketidakcocokan ini, lihat Versi node tidak kompatibel dengan versi bidang kontrol.

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

Langkah berikutnya