K8s CoreDNS、kubelet 與 resolv.conf
K8s CoreDNS、kubelet 與 resolv.conf的重點整理。
K8s CoreDNS、kubelet 與 resolv.conf
先背角色 kubectl 管設定、kubelet 準備 Pod 的 DNS 設定、resolv.conf 告訴程式問誰、CoreDNS 回答查詢。 應用程式查 DNS 不會經過 kubectl。
kube-dns 到 CoreDNS
早期常見的叢集 DNS 實作是 kube-dns;Kubernetes 1.11 起,CoreDNS 已 GA,且 kubeadm 預設安裝 CoreDNS。這是實作的替換,不只是改名,也不是以 1.2 為分界。
為了相容,CoreDNS 對外的 Service 通常仍叫 kube-dns;看到這個 Service 名稱,不代表後端還在跑舊 kube-dns。
它們怎麼合作
以一般 dnsPolicy: ClusterFirst 的 Pod 為例:
flowchart TD
A["管理者用 kubectl 建立 Service/修改 CoreDNS ConfigMap"] --> B["API Server 儲存資源"]
B --> C["CoreDNS 監看 Service/EndpointSlice 等資訊"]
K["kubelet 的 clusterDNS/clusterDomain 與 Pod dnsPolicy"] --> R["準備 Pod 的 /etc/resolv.conf"]
R -. "應用程式讀取設定" .-> P["Pod 應用程式查詢名稱"]
P --> S["kube-dns Service IP:53"]
S --> D["CoreDNS"]
C -. "叢集名稱資料" .-> D
D --> I["叢集內名稱:由 kubernetes plugin 回答"]
D --> F["外部名稱:forward 到上游 DNS"]
kubectl 是 API Server 的操作工具,不是 DNS server。建立 Service 後,CoreDNS 透過 Kubernetes API 取得資訊,不需要逐筆手寫 DNS 紀錄。一般 ClusterIP Service 名稱解析到 Service IP;實際 Service 封包轉送則由 kube-proxy 或替代實作處理。
resolv.conf:不是 DNS 紀錄表
Pod 內常見的 /etc/resolv.conf 類似:
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
| 欄位 | 意義 |
|---|---|
nameserver |
DNS 查詢要送給誰;此例是 kube-dns Service IP,實際值依叢集設定 |
search |
短名稱查詢可嘗試補上的後綴;此例 Pod 位於 default namespace |
ndots:5 |
少於 5 個點的名稱通常先嘗試 search 後綴;實際順序依 resolver 實作 |
同 namespace 與跨 namespace:web-service 範例
以下假設使用一般 ClusterFirst DNS 設定、標準 search 後綴,叢集網域為 cluster.local。Service 的完整名稱格式是:
服務名稱.namespace.svc.叢集網域
web-service.payroll.svc.cluster.local
例一:App 在 default,web-service 也在 default。
| App 使用的名稱 | 能否解析到目標 Service |
|---|---|
web-service |
可以,同 namespace 可省略後綴 |
web-service.default |
可以,明確指定 namespace |
web-service.default.svc |
可以,透過 search 補上 cluster.local |
web-service.default.svc.cluster.local |
可以,已寫出完整名稱 |
例二:App 在 default,web-service 在 payroll。
| App 使用的名稱 | 能否解析到 payroll 的目標 Service |
|---|---|
web-service |
不行,會先找 default 裡的同名 Service |
web-service.payroll |
可以,跨 namespace 最常用的簡寫 |
web-service.payroll.svc |
可以,透過 search 補上 cluster.local |
web-service.payroll.svc.cluster.local |
可以,已寫出完整名稱 |
如果 default 剛好也有 web-service,只寫 web-service 就會解析到 default 的那個,不會因為它找得到,就表示連到 payroll 的服務。若 App 與 Service 都在 payroll,一樣能直接寫 web-service;重點是兩者是否在同一個 namespace,default 沒有特例。
短名稱是怎麼補完整的?
以上面 default Pod 的 search 設定為例,resolver 會嘗試補上不同後綴。以下只列出能對應到目標的組合,不代表所有查詢的完整順序:
web-service
+ default.svc.cluster.local
→ web-service.default.svc.cluster.local
web-service.payroll
+ svc.cluster.local
→ web-service.payroll.svc.cluster.local
web-service.payroll.svc
+ cluster.local
→ web-service.payroll.svc.cluster.local
補後綴的是 App 使用的 DNS resolver,依據 Pod 的 resolv.conf;CoreDNS 收到查詢後,按名稱回答。 CoreDNS 不會自動猜測你想找哪個 namespace,也不會遍歷所有 namespaces 尋找同名 Service。
以 . 結尾,例如 web-service.payroll.svc.cluster.local.,表示絕對名稱,不再補 search 後綴。DNS 解析成功只是取得位址;實際連線仍要使用正確的 Service port,並符合網路政策等條件。
考前記法 同 namespace:服務名;跨 namespace:服務名.namespace;完整名稱:服務名.namespace.svc.cluster.local。 題目問哪個名稱不能用,先確認呼叫端 App 的 namespace。
kubelet 依 clusterDNS、clusterDomain、Pod 的 dnsPolicy/dnsConfig 等設定準備容器的 resolver 設定;kubectl 不會替應用程式逐次解析名稱。dnsPolicy: Default 主要沿用 Node 的 DNS 設定,與 ClusterFirst 不同;hostNetwork Pod 要使用叢集 DNS 時,通常指定 ClusterFirstWithHostNet。
Corefile:CoreDNS 收到查詢後怎麼處理
# 在實際有掛載此檔案的環境中執行;通常是 CoreDNS 容器內
cat /etc/coredns/Corefile
Linux 路徑區分大小寫,檔名通常是 Corefile。這不是每台 Node 都必然存在的檔案;CoreDNS image 也未必有 shell 或 cat。從叢集外查看設定,直接讀 ConfigMap:
kubectl get cm coredns -n kube-system -o yaml
ConfigMap 名稱、Corefile 與 DNS Service 的區別
一般 kubeadm 叢集使用名為 coredns 的 ConfigMap 儲存 CoreDNS 設定,位於 kube-system namespace;設定內容放在 data.Corefile。實際名稱以叢集中的物件為準:
# 查詢結果的關鍵結構,不是完整 manifest
metadata:
name: coredns # ConfigMap 物件名稱
namespace: kube-system
data:
Corefile: | # ConfigMap 裡面的 key,內容可掛載成檔案
.:53 {
# DNS 設定內容
}
記成:ConfigMap 叫 coredns → 裡面有 data.Corefile → 掛載為 /etc/coredns/Corefile;對外 DNS Service 則通常仍叫 kube-dns。
常見關鍵設定可縮成以下片段;它不是完整預設 Corefile:
.:53 {
kubernetes cluster.local in-addr.arpa ip6.arpa
forward . /etc/resolv.conf
cache 30
reload
}
.:53:接收 DNS 查詢。kubernetes cluster.local ...:處理叢集內 DNS 區域,cluster domain 可自訂。forward . /etc/resolv.conf:把需要轉送的查詢交給該檔中的上游 DNS。cache:快取結果;reload:偵測 Corefile 變動後重新載入。
這裡有兩份 resolv.conf 應用 Pod 的 resolv.conf 指向叢集 DNS;Corefile 裡的
/etc/resolv.conf則是 CoreDNS 容器看到的檔案,用來找上游 DNS,通常源自 Node 的 resolver 設定。不能把兩者當成同一份,更不能讓 CoreDNS 把查詢轉送回自己造成迴圈。
必要查詢與排錯順序
kubectl get svc kube-dns -n kube-system
kubectl get pods -n kube-system -l k8s-app=kube-dns
# app 是範例 Pod;需有 cat/nslookup 才能執行
kubectl exec app -- cat /etc/resolv.conf
kubectl exec app -- nslookup kubernetes.default.svc.cluster.local
先看應用 Pod 問哪個 DNS,再看 DNS Service/Pod 是否可用,最後看 Corefile 與上游。叢集名稱正常、外部名稱失敗時,優先查 forward 與上游連線。使用多容器 Pod 時,exec 加 -c 選對容器。
相關:K8s Calico 安裝與網路判讀小抄、K8s 各 Component 說明。