本頁說明 Google Kubernetes Engine (GKE) 如何使用 kube-dns (GKE 叢集的預設 DNS 提供者) 實作服務探索功能。
如為 Autopilot 叢集,您無法修改預設的 kube-dns 設定。
架構
建立叢集時,GKE 會在 kube-system
命名空間中自動部署 kube-dns Pod。Pod 會透過對應的服務存取 kube-dns 部署,該服務會將 kube-dns Pod 分組,並為這些 Pod 提供單一 IP 位址 (ClusterIP)。根據預設,叢集中的所有 Pod 都會使用這項服務解析 DNS 查詢。下圖顯示 Pod 與 kube-dns 服務之間的關係。
kube-dns 會調度資源,以滿足叢集的 DNS 需求。這項調度作業是由 kube-dns-autoscaler
控制,這個 Pod 預設會部署在所有 GKE 叢集中。kube-dns-autoscaler
會根據叢集中的節點和核心數量,調整 kube-dns Deployment 中的副本數量。
kube-dns 支援每個無標題服務最多 1000 個端點。
如何設定 Pod DNS
在每個節點上執行的 kubelet 會設定 Pod 的 etc/resolv.conf
,以使用 kube-dns 服務的 ClusterIP。以下設定範例顯示 kube-dns 服務的 IP 位址為 10.0.0.10
。這個 IP 位址在其他叢集中會有所不同。
nameserver 10.0.0.10
search default.svc.cluster.local svc.cluster.local cluster.local c.my-project-id.internal google.internal
options ndots:5
kube-dns 是叢集網域 (cluster.local) 的權威名稱伺服器,會以遞迴方式解析外部名稱。系統會先使用本機搜尋路徑,完成不完全符合資格的簡稱,例如 myservice
。
為存根網域新增自訂解析器
您可以修改 kube-dns 的 ConfigMap,在叢集內的 DNS 基礎架構中設定虛設常式網域。
存根網域可讓您設定自訂的網域專屬解析器,以便在解析這些網域時,kube-dns 會將 DNS 要求轉送至特定的上游 DNS 伺服器。
以下 kube-dns 的 ConfigMap 資訊清單範例包含 stubDomains
設定,可為網域 example.com 設定自訂解析程式。
apiVersion: v1
kind: ConfigMap
metadata:
labels:
addonmanager.kubernetes.io/mode: EnsureExists
name: kube-dns
namespace: kube-system
data:
stubDomains: |
{
"example.com": [
"8.8.8.8",
"8.8.4.4",
"1.1.1.1",
"1.0.0.1"
]
}
執行下列指令來開啟文字編輯器:
kubectl edit configmap kube-dns -n kube-system
將檔案內容替換為資訊清單,然後結束文字編輯器,將資訊清單套用至叢集。
上游網域名稱伺服器
如果您修改 kube-dns 的 ConfigMap 以納入 upstreamNameservers
,kube-dns 會將 *.cluster.local
以外的所有 DNS 要求轉送至這些伺服器。包括 metadata.internal
和 *.google.internal
,上游伺服器無法解析這些項目。
如果您啟用 GKE 適用的工作負載身分聯盟,或任何依賴 metadata.internal
解析的工作負載,請在 ConfigMap 中新增 stubDomain
,保留 *.internal
名稱解析。
data:
stubDomains: |
{
"internal": [
"169.254.169.254"
]
}
upstreamNameservers: |
["8.8.8.8"]
疑難排解
如要瞭解如何排解 kube-dns 問題,請參閱下列頁面:
- 如需 GKE 中 kube-dns 的相關建議,請參閱「排解 GKE 中的 kube-dns 問題」。
- 如需診斷 Kubernetes DNS 問題的一般建議,請參閱「偵錯 DNS 解析」。
限制
如要瞭解 kube-dns 的限制,請參閱下列各節。
搜尋網域限制
/etc/resolv.conf
最多可有六個 DNS 搜尋網域。如果定義超過六個搜尋網域,執行 kubectl describe pod
指令時會顯示下列警告:
Search Line limits were exceeded, some search paths have been omitted, the applied search line is: default.svc.cluster.local svc.cluster.local cluster.local c.<project ID>.internal google.internal
這項警告會記錄在容器記錄的 Cloud Logging 區段中。
如要解決這個問題,請從設定中移除額外的搜尋路徑。
請注意 upstreamNameservers
限制
Kubernetes 最多可設定三個 upstreamNameservers
值。如果定義超過三個 upstreamNameservers
,您會在 kube-dns
部署記錄的 Cloud Logging 中看到下列錯誤:
Invalid configuration: upstreamNameserver cannot have more than three entries (value was &TypeMeta{Kind:,APIVersion:,}), ignoring update
發生這種情況時,kube-dns 的行為就像沒有設定 upstreamNameservers
一樣。如要解決這個問題,請從設定中移除多餘的 upstreamNameservers
。
kube-dns 的效能限制
如果使用預設的 kube-dns 供應商時,DNS 查詢延遲時間過長或 DNS 解析失敗,可能是因為:
- 在工作負載中頻繁執行 DNS 查詢
- 部署每個節點的 Pod 密度較高。
- 超過每個 kube-dns Pod 的每秒查詢次數 (QPS) 上限 (20)。
- 在 Spot 或先占 VM 上執行 kube-dns,這可能會導致節點意外遭到刪除,進而發生 DNS 解析問題。
如要縮短 DNS 查詢時間,可以選擇下列任一選項:
- 請避免在 Spot 或先占 VM 上執行 kube-dns 等重要系統元件。使用 Spot VM 或先占 VM 做為 DNS 可能會導致故障,並中斷叢集運作。
- 最佳做法是建立至少一個由標準 (非 Spot 或先占型) VM 組成的節點集區,用於代管 kube-dns 等重要系統元件。如要確保重要工作負載只會排程到可靠的節點集區,避免在 Spot 或先占 VM 上執行,可以對 Spot VM 使用 taint 和容許條件。
- 啟用 NodeLocal DNSCache。
- 擴充 kube-dns。
- 請確保應用程式使用以 dns.resolve* 為基礎的函式,而非以 dns.lookup 為基礎的函式,因為 dns.lookup 是同步函式。dns.resolve* 函式一律會在網路上執行非同步 DNS 查詢。
服務 DNS 記錄
kube-dns 只會為具有 Endpoints 的服務建立 DNS 記錄。
DNS 上游伺服器的存留時間較長
如果 kube-dns 從上游 DNS 解析器收到 DNS 回應,且 TTL 較大或為「無限」,則會將這個 TTL 值保留在快取中的 DNS 項目。這個項目永遠不會過期,因此可能會造成項目與為 TTL 名稱解析的實際 IP 位址之間出現差異。
GKE 會針對 TTL 高於 30 秒的 DNS 回應,將 TTL 值上限設為 30 秒,藉此解決下列控制層版本中的問題:
- 1.21.14-gke.9100
- 1.22.15-gke.2100
- 1.23.13-gke.500
- 1.24.7-gke.500
- 1.25.2-gke.500 以上版本
這項行為與 NodeLocal DNSCache 類似。
記錄 kube-dns 或 dnsmasq 指標
您可以取得 GKE 叢集中的 DNS 查詢相關指標。這是快速取得 kube-dns 或 dnsmasq 指標的方法,不需要修改部署作業。
列出 kube-dns 部署作業下的 Pod。
$ kubectl get pods -n kube-system --selector=k8s-app=kube-dns
畫面中會顯示如下的輸出結果:
NAME READY STATUS RESTARTS AGE kube-dns-548976df6c-98fkd 4/4 Running 0 48m kube-dns-548976df6c-x4xsh 4/4 Running 0 47m
選取 Pod 並將其名稱設為變數。
POD="kube-dns-548976df6c-98fkd"
為所選 kube-dns Pod 設定通訊埠轉送。
$ kubectl port-forward pod/${POD} -n kube-system 10054:10054 10055:10055
畫面中會顯示如下的輸出結果:
Forwarding from 127.0.0.1:10054 -> 10054 Forwarding from 127.0.0.1:10055 -> 10055
在端點上執行下列 curl 指令,即可取得指標。
$ curl http://127.0.0.1:10054/metrics; curl http://127.0.0.1:10055/metrics
通訊埠 10054 包含 dnsmasq 指標,通訊埠 10055 則包含 kube-dns 指標。
畫面中會顯示如下的輸出結果:
kubedns_dnsmasq_errors 0 kubedns_dnsmasq_evictions 0 kubedns_dnsmasq_hits 3.67351e+06 kubedns_dnsmasq_insertions 254114 kubedns_dnsmasq_max_size 1000 kubedns_dnsmasq_misses 3.278166e+06
後續步驟
- 閱讀 GKE 中叢集 DNS 的總覽。
- 如要瞭解 Kubernetes 叢集如何使用 DNS,請參閱「服務和 Pod 的 DNS」。