[Production Case] Menelusuri Misteri Kubernetes DNS Penyebab "ENOTFOUND"

August 20, 2022

[Production Case] Menelusuri Misteri Kubernetes DNS Penyebab "ENOTFOUND"

Sepengal kisah tentang jejak penelusuran pada salah satu komponen utama Kubernetes Cluster.


Latar belakang

Dikisahkan di sebuah startup terdapat urban legend mengenai Apps yang berjalan di atas Kubernetes namun sering mendapatkan logs error dikarenakan gagal melakukan resolve ke DNS. Apps tersebut dibangun dengan menggunakan Java Scripts berjalan dengan Runtime node.js.

getaddrinfo ENOTFOUND disini.namadomain.com

Dikarenakan gagalnya resolve ke DNS tersebut, membuat apps sering bermasalah.

Penelusuran

Pada malam jum'at pukul 23:11, Kota Bekasi, Jawa Barat. Di sebuah kamar temenung sosok pemuda yang sedang menatapi langit-langit kamar. Dengan suara latar lagu NDX AKA - Sido Sayang Ora. Pemuda tersebut dalam hati berkata "Si A███ lagi ngopo yo ?, jane ki kepiye to karep e ki ?" pemuda itu adalah saya Sobat Ambyar. Untuk kedepannya akan kita sebut singkat sebagai "Sobyar".

Sobyar seketika terbangun dari ranjang tidurnya. Karena ingin melepaskan penat memikirkan sang pujaan hati yang entah menghilang kemana. Ia ingin menghibur diri. CTRL + ENTER, terbukalah Terminal dengan mode fullscreen. Dirinya teringat akan getaddrinfo ENOTFOUND yang terjadi di Cluster Kubernetes tempat Sobyar bekerja.

Sobyar kemudian membuka nvim sambil membuka browser.

Pencarian Solusi

Setelah membaca berbagai sumber, sobyar mengkrucutkan ke beberapa pendekatan solusi. Diataranya sebagai berikut

1. Masalah Node.js Library

Dikarenakan apps berjalan menggunakan runtime node.js, maka Sobyar mencari - cari apakah ada keterkaitan dengan Bug di NodeJS. Hingga dia menemukan artikel terkait salah satu bug di node/lib/dns.js.

function errnoException(err, syscall, hostname) {
  // FIXME(bnoordhuis) Remove this backwards compatibility nonsense and pass
  // the true error to the user. ENOTFOUND is not even a proper POSIX error!
  if (err === uv.UV_EAI_MEMORY ||
      err === uv.UV_EAI_NODATA ||
      err === uv.UV_EAI_NONAME) {
    err = 'ENOTFOUND';
  }

Namun ternyata issue tersebut sudah di-fix pada node v8.x, dan node di production sudah menggunakan v12.x. Dapat disimpulkan bahwa masalah yang terjadi bukan dari bug Runtime.

2. Memasang Pod CoreDNS Cache Dengan Node Local DNS

Selain masalah ETNOTFOUND ada masalah lain yang terjadi di kantor Sobyar, yaitu waktu resolving yang cukup lama ketika traffic sedang tinggi-tingginya.

Seakan Qos coredns termakan HABIS!, maka pada malam itu Sobyar mencari juga apakah ada "tune-up" untuk masalah performa coredns tersebut, dan ia menemukan; KubeCon Talk Going from 5s to 5ms: Benefits of a Node-Local DNSCache - Pavithra Ramesh & Blake Barnett .

Sebenarnya Sobyar nga ngerti-ngerti amat secara detil mendalamnya namun dia paham gambaran gampangnya. NodeLocalDNS Topology

Penjelasan Singat dan Hasil Implementasi

NodeLocalDNS akan membuat pods di setiap nodes kubernetes yang berperan sebagai coredns cache (Daemonset).

Pod tersebut akan menggunakan hostNetwork dan membuat interface baru, dengan IP address yang sama seperti IP dari service kube-dns. Sehingga ketika pods di setiap nodes akan melakukan resolve dns maka akan di-routing ke pods LocalDNS di masing-masing nodes. CMIIW

Contoh

Hari semakin larut, jam dinding menujukan waktu pukul dua dini hari. Sobyar bergegas tidur agar besok tidak mengantuk di KRL.

Siang hari di jam kerja, Sobyar melakukan diskusi dan meminta izin kepada petuah di startup tempat ia bekerja untuk melakukan ritual pemasangan nodelocaldns. Dengan segera para petuah pun menyetujui.

Ritual pemasangan nodelocaldns berjalan dengan lancar, namun masih belum terlihat jelas perbedaan yang signifikan.

Hingga hari event tiba, beberapa cluster mendadak stuck ketika melakukan resolving dns. Namun tidak terjadi pada cluser yang sudah dilakukan ritual nodelocaldns. Sehingga sekarang dapat terlihat jelas perbandingannya.

Setelah itu semua cluster critical Kubernetes dilakukan ritual nodelocaldns., dan benar saja seketia cluster yang stuck langsung berjalan normal kembali.

Sobyar pun membuat HELM Template untuk mempermudah ritualnya.

helm repo add auto-node-local-dns https://nicolasjulian.github.io/node-local-dns/
helm install my-node-local-dns auto-node-local-dns/node-local-dns --version 0.1.0

Namun, apakah sudah tidak ditemukan logs ENOTFOUND ? jawabannya masih, namun tidak sebanyak sebelumnya.

3. Efisiensi resolv.conf

Di malam hari Soybar menyalakan rokok, dan membuat secangkir kopi dengan mug yang bertuliskan "1000 hari mengenang bapak █████████" saat itu malam minggu. Sobyar tidak keluar malam itu, suasana hatinya masih sama "ra karu - karu an, pokok e".

Dinyalakannya Laptop, dan seketika terminal terbuka. Ia bergumam, "opo aku kurang sat set sat set yo ?, dek'e wis karo wong liyo koyone.., jan██████"

Untuk menghilangkan penat. Maka sobyar memilih membaca die.net dikarenakan Ia menemukan salah satu artikel tentang penurunan performa coredns ketika menggunakan ndots:5

resolv.conf akan menentukan bagaimana perilaku ketika melakukan resolving ke DNS Server.

Ada dua hal yang perlu dipahami

search

search Search list for host-name lookup.

The search list is normally determined from the local domain name; by default, it contains only the local domain name. This may be changed by listing the desired domain search path following the search keyword with spaces or tabs separating the names. Resolver queries having fewer than ndots dots (default is 1) in them will be attempted using each component of the search path in turn until a match is found. For environments with multiple subdomains please read options ndots:n below to avoid man-in-the-middle attacks and unnecessary traffic for the root-dns-servers. Note that this process may be slow and will generate a lot of network traffic if the servers for the listed domains are not local, and that queries will time out if no server is available for one of the domains.

The search list is currently limited to six domains with a total of 256 characters.

ndots

ndots:n

sets a threshold for the number of dots which must appear in a name given to res_query(3) (see resolver(3)) before an initial absolute query will be made. The default for n is 1, meaning that if there are any dots in a name, the name will be tried first as an absolute name before any search list elements are appended to it. The value for this option is silently capped to 15.

Default Kubernetes Config resolv.conf

root@nginx:/# cat /etc/resolv.conf 
nameserver 10.96.0.10
search <namespace>.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

Rangkuman search & ndots

Search memiliki 4 list value, seperti yang dilihat di atas, list tersebut berisikan local domain name default dari kubernetes. Sedangkan ndots menentukan berapa jumlah titik yang diperlukan sebuah domain dapat disebut "FQDN (Fully qualified domain name)" dan dilakukan resolv pertama kali.

Bagaimana kerja default resolv.conf Kubernetes

Supaya mempercepat latency, ndots diberikan value 5 (default). Sehingga domain yang pertama kali dilakukan resolv adalah nama-service.<namespace>.svc.cluster.local.Sangat masuk akal performanya akan sangat baik, jika domain name yang diresolve adalah pada level service Kubernetes Cluster. Namun jika yang di-resolve adalah public domain maka hal tersebut hanya akan menimbulkan becana.

Berikut adalah contoh melakukan resolve public domain, jika menggunakan default ndots values. Empat kali proses pathing nama domain dengan local domain name search supaya mencapai path yang benar.

ndots value 5

Berikut contoh hasil jika menggunakan ndots:1, dikarenakan hanya perlu satu titik di dalam nama domain untuk menjadi FQDN maka nama dns langsung menuju ke google.com

ndots value 1


Malam itu berjalan dengan cepat. Singkat certia hari Senin tiba, Sobyar menyampaikan temuannya kepada petuah, dan meminta izin untuk melakukan ritual perubahan Deployment.

  dnsConfig:
    options:
      - name: ndots
        value: "1"

Petuah memberi izin,

"minggu depan yaa ..."

"Wokeee ..." jawab Sobyar. Minggu yang dimaksud telah tiba, pada hari itu developer Apps tersebut juga menanyakan perihal solusi untuk masalah tersebut. Momen yang tepat. Deployment pun dilakukan perubahan di hari itu.

Benar saja. Logs ENOTFOUND berangsur menghilang untuk service tersebut, dan 1 jam kemudian semua error ENOTFOUND sudah tidak terlihat. Everybody happy!

Berikut logs selama 2 minggu setelah melakukan tuning.

Kibana Logs Last 2 Weeks

Satu chart spike terakhir di atas adalah percobaan apabila deployment tidak menggunakan efisien resolv.conf

Penyesuaian Lainnya

Perubahan Upstream DNS

Hal ini dilakukan karena ternyata /etc/resolv.conf bawaan dari cloud provider, mengarah ke DNS yang berada di belahan dunia lain. Sobyar mengangap hal seperti itu tidak best practice.

Server di Singapore tapi DNS di Paris

Mengaktifkan AutoPath

Menjadi tidak berguna apabila sudah melakukan efisiensi resolv.conf

If the autopath plugin sees a query that matches the first element of the configured search path, it will follow the chain of search path elements and return the first reply that is not NXDOMAIN

Berikut adalah full configMaps pada bagian Corefile.

  Corefile: |-
    .:53 {
        log
        errors
        autopath @kubernetes
        health {
            lameduck 5s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
            pods verified
            fallthrough in-addr.arpa ip6.arpa
            ttl 30
        }
        prometheus :9153
        forward . 8.8.8.8 8.8.4.4 {
          prefer_udp
          policy sequential
        }
        cache 30
        loop
        reload
        loadbalance
    }

Referensi


Profile picture

Written by Nicolas Julian Seseorang yang mencoba berkarya. Chit Chat with me in Twitter