本頁說明如何使用 NodeLocal DNSCache,縮短 Google Kubernetes Engine (GKE) 叢集中的 DNS 查詢延遲時間。
如為 GKE Autopilot 叢集,NodeLocal DNSCache 預設為啟用,且無法覆寫。
架構
NodeLocal DNSCache 是 GKE 外掛程式,可與 kube-dns 一併執行。
GKE 會將 NodeLocal DNSCache 實作為 DaemonSet,在叢集中的每個節點上執行 DNS 快取。
當 Pod 發出 DNS 要求時,要求會傳送至與 Pod 位於相同節點的 DNS 快取。如果快取無法解析 DNS 要求,快取會根據查詢目的地,將要求轉送至下列其中一個位置:
- kube-dns:叢集 DNS 網域 (
cluster.local
) 的所有查詢都會轉送至 kube-dns。node-local-dns Pod 會使用 kube-dns-upstream 服務存取 kube-dns Pod。在下圖中,kube-dns Service 的 IP 位址為10.0.0.10:53
。 - 自訂存根網域或上游名稱伺服器:查詢會直接從 NodeLocal DNSCache Pod 轉送。
- Cloud DNS:所有其他查詢都會轉送至與查詢來源 Pod 位於相同節點的本機中繼資料伺服器。本機中繼資料伺服器會存取 Cloud DNS。
在現有叢集上啟用 NodeLocal DNSCache 時,GKE 會根據節點升級程序,重新建立所有執行 GKE 1.15 以上版本的叢集節點。
GKE 重新建立節點後,會自動在節點中新增 addon.gke.io/node-local-dns-ds-ready=true
標籤。您不得手動將這個標籤新增至叢集節點。
NodeLocal DNSCache 的優點
NodeLocal DNSCache 具有下列優點:
- 縮短平均 DNS 查詢時間
- 從 Pods 到本機快取的連線不會建立 conntrack 表格項目。這可防止因 conntrack 資料表耗盡和競爭狀況而導致連線中斷和遭到拒絕。
- 您可以搭配 Cloud DNS for GKE 使用 NodeLocal DNSCache。
- 外部網址 (未參照叢集資源的網址) 的 DNS 查詢會直接轉送至本機 Cloud DNS 中繼資料伺服器,略過 kube-dns。
- 本機 DNS 快取會自動擷取「為存根網域新增自訂解析器」一節中指定的存根網域和上游名稱伺服器。
需求條件和限制
- NodeLocal DNSCache 會耗用叢集每個節點的運算資源。
- NodeLocal DNSCache 不支援 Windows Server 節點集區。
- NodeLocal DNSCache 必須搭配 GKE 1.15 以上版本。
- NodeLocal DNSCache 會使用 TCP 存取 kube-dns Pod。
- 在 GKE 1.18 以上版本中,NodeLocal DNSCache 會透過 TCP 和 UDP 存取
upstreamServers
和stubDomains
。DNS 伺服器必須可透過 TCP 和 UDP 存取。 - DNS 記錄的快取時間如下:
- 記錄的存留時間 (TTL),或 30 秒 (如果 TTL 超過 30 秒)。
- 如果 DNS 回應為
NXDOMAIN
,則為 5 秒。
- NodeLocal DNSCache Pod 會監聽節點上的通訊埠 53、9253、9353 和 8080。如果您執行任何其他
hostNetwork
Pod 或設定使用這些連接埠的hostPorts
,NodeLocal DNSCache 就會失敗,並發生 DNS 錯誤。使用 GKE Dataplane V2 但不使用 Cloud DNS for GKE 時,NodeLocal DNSCache Pod 不會使用hostNetwork
模式。 - 本機 DNS 快取只會在執行 GKE 1.15 以上版本的節點集區上執行。如果您在節點執行舊版叢集中啟用 NodeLocal DNSCache,這些節點上的 Pod 會使用 kube-dns。
啟用 NodeLocal DNSCache
如為 Autopilot 叢集,NodeLocal DNSCache 預設為啟用,且無法覆寫。
如果是標準叢集,您可以使用 Google Cloud CLI,在新叢集或現有叢集上啟用 NodeLocal DNSCache。您可以使用 Google Cloud 控制台,在新叢集中啟用 NodeLocal DNSCache。
在新叢集中啟用 NodeLocal DNSCache
gcloud
如要在新叢集中啟用 NodeLocal DNSCache,請使用 --addons
旗標和 NodeLocalDNS
引數:
gcloud container clusters create CLUSTER_NAME \
--location=COMPUTE_LOCATION \
--addons=NodeLocalDNS
更改下列內容:
CLUSTER_NAME
:新叢集的名稱。COMPUTE_LOCATION
:叢集的 Compute Engine 位置。
控制台
如要在新叢集上啟用 NodeLocal DNSCache,請按照下列步驟操作:
前往 Google Cloud 控制台的「Google Kubernetes Engine」頁面。
按一下「標準」旁的「設定」。
視需要設定叢集。
按一下導覽窗格中的「Networking」(網路)。
在「進階網路選項」部分,選取「啟用 NodeLocal DNSCache」核取方塊。
點選「建立」。
在現有叢集中啟用 NodeLocal DNSCache
如要在現有叢集中啟用 NodeLocal DNSCache,請使用 --update-addons
旗標並加上 NodeLocalDNS=ENABLED
引數:
gcloud container clusters update CLUSTER_NAME \
--location=COMPUTE_LOCATION \
--update-addons=NodeLocalDNS=ENABLED
更改下列內容:
CLUSTER_NAME
:叢集名稱。COMPUTE_LOCATION
:叢集的 Compute Engine 位置。
這項變更需要重新建立節點,可能會導致執行中的工作負載中斷。如要瞭解這項特定變更的詳細資料,請在「manual changes that recreate the nodes using a node upgrade strategy and respecting maintenance policies」(手動變更,使用節點升級策略重建節點,並遵守維護政策) 表格中找到對應的資料列。如要進一步瞭解節點更新,請參閱「規劃節點更新中斷」。
確認已啟用 NodeLocal DNSCache
您可以列出 node-local-dns
Pod,確認 NodeLocal DNSCache 是否正在執行:
kubectl get pods -n kube-system -o wide | grep node-local-dns
輸出結果會與下列內容相似:
node-local-dns-869mt 1/1 Running 0 6m24s 10.128.0.35 gke-test-pool-69efb6b8-5d7m <none> <none>
node-local-dns-htx4w 1/1 Running 0 6m24s 10.128.0.36 gke-test-pool-69efb6b8-wssk <none> <none>
node-local-dns-v5njk 1/1 Running 0 6m24s 10.128.0.33 gke-test-pool-69efb6b8-bhz3 <none> <none>
輸出內容會顯示每個執行 GKE 1.15 以上版本的節點,都有一個 node-local-dns
Pod。
停用 NodeLocal DNSCache
您可以使用下列指令停用 NodeLocal DNSCache:
gcloud container clusters update CLUSTER_NAME \
--location=COMPUTE_LOCATION \
--update-addons=NodeLocalDNS=DISABLED
更改下列內容:
CLUSTER_NAME
:要停用的叢集名稱。COMPUTE_LOCATION
:叢集的 Compute Engine 位置。
這項變更需要重新建立節點,可能會導致執行中的工作負載中斷。如要瞭解這項特定變更的詳細資料,請在「manual changes that recreate the nodes using a node upgrade strategy and respecting maintenance policies」(手動變更,使用節點升級策略重建節點,並遵守維護政策) 表格中找到對應的資料列。如要進一步瞭解節點更新,請參閱「規劃節點更新中斷」。
排解 NodeLocal DNSCache 問題
如需診斷 Kubernetes DNS 問題的一般資訊,請參閱「偵錯 DNS 解析」。
NodeLocal DNSCache 不會立即啟用
在現有叢集上啟用 NodeLocal DNSCache 時,如果叢集已設定維護期間或排除時段,GKE 可能不會立即更新節點。詳情請參閱節點重建和維護期間的注意事項。
如果不想等待,可以呼叫 gcloud container clusters upgrade
指令並傳遞 --cluster-version
旗標,將節點手動變更為節點集區目前執行的 GKE 版本。如要使用此解決方法,必須使用 Google Cloud CLI。
搭配 Cloud DNS 使用 NodeLocal DNSCache
如果您搭配使用 NodeLocal DNSCache 和 Cloud DNS,叢集會使用名稱伺服器 IP 位址 169.254.20.10
,如下圖所示:
因此,kube-dns
服務的 IP 位址可能與 Pod 使用的名稱伺服器 IP 位址不同。這是預期行為,因為 Cloud DNS 必須使用 169.254.20.10
名稱伺服器 IP 位址,才能正常運作。
如要檢查 IP 位址,請執行下列指令:
查看
kube-dns
Service 的 IP 位址:kubectl get svc -n kube-system kube-dns -o jsonpath="{.spec.clusterIP}"
輸出內容是
kube-dns
的 IP 位址,例如10.0.0.10:53
在 Pod 中開啟殼層工作階段:
kubectl exec -it POD_NAME -- /bin/bash
在 Pod Shell 工作階段中,讀取
/etc/resolv.conf
檔案的內容:cat /etc/resolv.conf
輸出內容為
169.254.20.10
搭配 NodeLocal DNSCache 使用的網路政策
如果您使用 NodeLocal DNSCache 搭配網路政策,且未使用 Cloud DNS 或 GKE Dataplane V2,則必須設定規則,允許工作負載和 node-local-dns
Pod 傳送 DNS 查詢。
在資訊清單中使用 ipBlock
規則,允許 Pod 與 kube-dns 之間的通訊。
下列資訊清單說明使用 ipBlock
規則的網路政策:
spec:
egress:
- ports:
- port: 53
protocol: TCP
- port: 53
protocol: UDP
to:
- ipBlock:
cidr: KUBE_DNS_SVC_CLUSTER_IP/32
podSelector: {}
policyTypes:
- Egress
將 KUBE_DNS_SVC_CLUSTER_IP
替換為 kube-dns 服務的 IP 位址。您可以使用下列指令取得 kube-dns 服務的 IP 位址:
kubectl get svc -n kube-system kube-dns -o jsonpath="{.spec.clusterIP}"
已知問題
使用 NodeLocal DNSCache 和 GKE Dataplane V2 時,ClusterFirstWithHostNet dnsPolicy 中的 DNS 超時
在採用 GKE Dataplane V2 和 NodeLocal DNSCache 的叢集上,如果 Pod 的 hostNetwork
設為 true
,且 dnsPolicy
設為 ClusterFirstWithHostNet
,就無法連線至叢集 DNS 後端。DNS 記錄可能包含類似下列內容的項目:
nslookup: write to 'a.b.c.d': Operation not permitted
;; connection timed out; no servers could be reached
輸出內容表示 DNS 要求無法連上後端伺服器。
解決方法是為 hostNetwork
Pod 設定 dnsPolicy
和 dnsConfig
:
spec:
dnsPolicy: "None"
dnsConfig:
nameservers:
- KUBE_DNS_UPSTREAM
searches:
- cluster.local
- svc.cluster.local
- NAMESPACE.svc.cluster.local
- c.PROJECT_ID.internal
- google.internal
options:
- name: ndots
value: "5"
更改下列內容:
NAMESPACE
:hostNetwork
Pod 的命名空間。PROJECT_ID
:您的 Google Cloud 專案 ID。KUBE_DNS_UPSTREAM
:上游 kube-dns 服務的 ClusterIP。您可以使用下列指令取得這個值:kubectl get svc -n kube-system kube-dns-upstream -o jsonpath="{.spec.clusterIP}"
Pod 的 DNS 要求現在可以連上 kube-dns,並略過 NodeLocal DNSCache。
NodeLocal DNSCache 逾時錯誤
在啟用 NodeLocal DNSCache 的叢集上,記錄可能包含類似下列的項目:
[ERROR] plugin/errors: 2 <hostname> A: read tcp <node IP: port>-><kubedns IP>:53: i/o timeout
輸出內容包含 kube-dns-upstream
Cluster IP 服務的 IP 位址。在本例中,kube-dns 未在 2 秒內收到 DNS 要求的回應。可能原因如下:
- 網路連線問題。
- 工作負載的 DNS 查詢量大幅增加,或因節點集區擴充而增加。
因此,現有的 kube-dns
Pod 無法及時處理所有要求。解決方法是調整自動調度資源參數,增加 kube-dns 副本數量。
擴充 kube-dns
您可以調低「nodesPerReplica
」的值,確保在叢集節點擴充時,系統會建立更多 kube-dns Pod。強烈建議您設定明確的 max
值,確保 GKE 控制層虛擬機器 (VM) 不會因大量 kube-dns Pod 監控 Kubernetes API 而不堪負荷。
您可以將 max
設為叢集中的節點數。如果叢集的節點超過 500 個,請將 max
設為 500。
如果是標準叢集,您可以編輯 kube-dns-autoscaler
ConfigMap,修改 kube-dns 副本數量。Autopilot 叢集不支援這項設定。
kubectl edit configmap kube-dns-autoscaler --namespace=kube-system
輸出結果會與下列內容相似:
linear: '{"coresPerReplica":256, "nodesPerReplica":16,"preventSinglePointFailure":true}'
kube-dns 副本數量是使用下列公式計算而得:
replicas = max( ceil( cores × 1/coresPerReplica ) , ceil( nodes × 1/nodesPerReplica ), maxValue )
如要擴大,請將 nodesPerReplica
變更為較小的值,並加入 max
值。
linear: '{"coresPerReplica":256, "nodesPerReplica":8,"max": 15,"preventSinglePointFailure":true}'
設定會為叢集中的每 8 個節點建立 1 個 kube-dns Pod。24 節點叢集會有 3 個副本,40 節點叢集則會有 5 個副本。如果叢集節點超過 120 個,kube-dns 副本數不會超過 15 個,也就是 max
值。
如要確保叢集中的 DNS 達到基準可用性,請為 kube-dns 設定備用資源數量下限。
kube-dns-autoscaler
ConfigMap 輸出內容 (含 min
欄位) 應如下所示:
linear: '{"coresPerReplica":256, "nodesPerReplica":8,"max": 15,"min": 5,"preventSinglePointFailure":true}'
後續步驟
- 閱讀總覽,瞭解 GKE 如何提供代管 DNS。
- 如要瞭解 Kubernetes 叢集如何使用 DNS,請參閱「服務和 Pod 的 DNS」。
- 瞭解如何使用 Cloud DNS for GKE。