Kubernetes CKA課程筆記 30
考量到以下K8s場景,當有兩個Pod分別各自有對應的Service元件
當其中一個Pod要對另一個Pod所屬的Service進行"請求"
請求發動的是使用Service的名稱
這過程Service的名稱又是如何轉換為該Service的IP位置呢?
最簡單想法是如下:
在上述情況下就能夠解析出請求的Service Name所對應的IP位置
並且反過來db要請求my-app的Service Name也能解析到IP位置
但是當考量Pods數量有成百上千,每個Pod內/etc/hosts檔異動就會過於頻繁
所以比較靠普方式,是將這些Domain Name與IP位置對應
全都儲存在一個集中的地方:
如上,並且Pod內僅儲存DNS Server在哪則記錄在/etc/resolv.conf檔案內
若要解析Service Name(Domain Name)要找誰(DNS Server)位置
Kubernetes DNS Server:
- 屬於K8s的Cluster
- 管理記錄著所有Service Names及對應的IP位置
- 所有的Pod都會指向這個DNS Server
- K8s目前使用的DNS Server : CoreDNS
- CoreDNS在筆記第16篇做kubeadm init安裝過程最後addons安裝時
- 同時安裝了CoreDNS & kube-proxy(就是這一步完成CoreDNS安裝的)
- 另外K8s在v1.12以前使用的DNS Server是kube-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
CoreDNS:
- 所以後面加入Service Name與IP位置的對應,都會更新到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
仔細看還有寫好search:
這裡就有一個疑問! 到底又是誰將”nameserver 10.96.0.10"寫到Pod內的呢?
其實就是kubelet做的,相關設定在/var/lib/kubelet/config.yaml內:
Service — Fully Qualified Domain Name(FQDN):
至此可能還會有個疑問是不同namespace內各自的Pod是否也能正常解析DNS
直接做以下嘗試:
用指令進到這個剛建立的Pod內,並嘗試打curl到上面default的Service:
如上結果
不同nameSpace的Pod無法直接地解析到不同nameSpace的ServiceName
詳細細節原因是因為CoreDNS的機制:
CoreDNS:
- CoreDNS會以nameSpace建立Subdomain
- 這還沒完,後面還會再用Type再接一層Subdomain
- 最終還用cluster給一層Root Domain
- (概念圖如下)
透過上述CoreDNS完成在Cluster內定義完整的Service名稱如下:
<servicename>.<namespace>.svc.cluster.local
上述又可以稱為service的:Fully Qualified Domain Name(FQDN)
所以在不同nameSpace直接curl到
結論:
- 相同nameSpace下,可以直接<serviceName>:<PORT>
- 不同nameSpace下,可以直接<serviceName>.<nameSpace>:<PORT>
上述不同nameSpace的下法還是簡化的,實際上可以如下:
至於為何我們不需要帶"svc.cluster.local"也能通呢?
主要原因在/etc/resolv.conf內有以下定義:
上圖DNS解析檔內會在指定domain內自動搜尋紅框的subdomain對應
在curl到nginx-service.default:8080時會自動查找
是否可以對應到其中一個subdomain
變成打到nginx-service.default.svc.cluster.local:8080
而在相同nameSpace則是透過以下這個解析出來的:
所以當如果只有curl到<serviceName>.<nameSpace>打不到
但是curl到完整的FQDN名稱可以
那麼也就是這個/etc/resolv.conf內的search出問題了
這樣也比較知道去哪邊debug