Kubernetes CKA課程筆記 30

DNS in Kubernetes

ZONGRU Li
7 min readOct 23, 2021

考量到以下K8s場景,當有兩個Pod分別各自有對應的Service元件

當其中一個Pod要對另一個Pod所屬的Service進行"請求"

請求發動的是使用Service的名稱

這過程Service的名稱又是如何轉換為該Service的IP位置呢?

最簡單想法是如下:

在上述情況下就能夠解析出請求的Service Name所對應的IP位置

並且反過來db要請求my-appService Name也能解析到IP位置

但是當考量Pods數量有成百上千,每個Pod內/etc/hosts檔異動就會過於頻繁

所以比較靠普方式,是將這些Domain NameIP位置對應

全都儲存在一個集中的地方:

如上,並且Pod內僅儲存DNS Server在哪則記錄在/etc/resolv.conf檔案內

若要解析Service Name(Domain Name)要找誰(DNS Server)位置

Kubernetes DNS Server:

  • 屬於K8sCluster
  • 管理記錄著所有Service Names及對應的IP位置
  • 所有的Pod都會指向這個DNS Server
  • K8s目前使用的DNS Server : CoreDNS
  • CoreDNS在筆記第16篇做kubeadm init安裝過程最後addons安裝時
  • 同時安裝了CoreDNS & kube-proxy(就是這一步完成CoreDNS安裝的)
  • 另外K8sv1.12以前使用的DNS Serverkube-dns
  • v1.12之後才改採用CoreDNS(由CNCF維護)
  • 並且前面筆記常常看Pod都有顯示:
  • CoreDNS的Pod總共兩個kube-system這個namespace
  • 這是為了防止其中一個CoreDNS Pod掛掉,會導致所有服務無法運作!
  • 所以在正式環境通常至少要兩個Pod以上!!
  • 並且開發者發現Service Name解析出問題時
  • 可以第一時間檢查CoreDNS Pod是否有正常運作或是否無法進入?
  • 並且也能檢查CoreDNS Pod內的log

為了快速查看CoreDNS Pod裡面的log,先快速找到他本身有帶的labels:

kubectl get pod -n kube-system --show-labels

在用前面學到得指令,依次查看兩個CoreDNS Pod的log內容:

kubectl logs -n kube-system -l k8s-app=kube-dns

目前兩個Pod裡面log都短短的

CoreDNS:

  • 所以後面加入Service NameIP位置的對應,都會更新到CoreDNS Pod

接著我們應該確認每個Pod內的/etc/resolv.conf都有紀錄到CoreDNS Pod?

嘗試執行指令進到測試Pod裡的Container內部查看其/etc/resolv.conf:

kubectl exec -it {Pod Name} -- bash

並且由以下指令也能查看到所安裝的Core-DNS的Service元件:

kubectl get svc -n kube-system -o wide

在測試Pod內的Container內的設定檔確實記載解析Domain Name的Server位置對應到CoreDNS的Service元件

仔細看還有寫好search:

這裡就有一個疑問! 到底又是誰將”nameserver 10.96.0.10"寫到Pod內的呢?

其實就是kubelet做的,相關設定在/var/lib/kubelet/config.yaml內:

kebelet會將這個/etc/resolv.conf內容寫入每個Pod內

Service — Fully Qualified Domain Name(FQDN):

至此可能還會有個疑問是不同namespace內各自的Pod是否也能正常解析DNS

直接做以下嘗試:

不同ns可以存在同名稱的k8s元件(如上的Pod)
確認已經在運作了

用指令進到這個剛建立的Pod內,並嘗試打curl到上面default的Service:

如上結果

不同nameSpacePod無法直接地解析到不同nameSpaceServiceName

詳細細節原因是因為CoreDNS的機制:

CoreDNS:

  • CoreDNS會以nameSpace建立Subdomain
  • 這還沒完,後面還會再用Type再接一層Subdomain
  • 最終還用cluster給一層Root Domain
  • (概念圖如下)
CoreDNS定義的多層Subdomain

透過上述CoreDNS完成在Cluster內定義完整的Service名稱如下:

<servicename>.<namespace>.svc.cluster.local

上述又可以稱為service的:Fully Qualified Domain Name(FQDN)

所以在不同nameSpace直接curl到

結論:

  1. 相同nameSpace下,可以直接<serviceName>:<PORT>
  2. 不同nameSpace下,可以直接<serviceName>.<nameSpace>:<PORT>

上述不同nameSpace的下法還是簡化的,實際上可以如下:

至於為何我們不需要帶"svc.cluster.local"也能通呢?

主要原因在/etc/resolv.conf內有以下定義:

上圖DNS解析檔內會在指定domain內自動搜尋紅框的subdomain對應

curlnginx-service.default:8080時會自動查找

是否可以對應到其中一個subdomain

變成打到nginx-service.default.svc.cluster.local:8080

而在相同nameSpace則是透過以下這個解析出來的:

所以當如果只有curl到<serviceName>.<nameSpace>打不到

但是curl到完整的FQDN名稱可以

那麼也就是這個/etc/resolv.conf內的search出問題了

這樣也比較知道去哪邊debug

參考課程(reference)

--

--

ZONGRU Li
ZONGRU Li

Written by ZONGRU Li

2022/11/17 開源部分個人筆記給LINE "Java程式語言討論區"社群,希望能對社群的技術學習做一點點貢獻.(掩面....記得退訂閱!

No responses yet