在 Kubernetes 叢集中使用 NodeLocal DNSCache
Kubernetes v1.18 [穩定]
本頁面概述 Kubernetes 中的 NodeLocal DNSCache 功能。
開始之前
您需要有一個 Kubernetes 叢集,並且必須將 kubectl 命令列工具設定為與您的叢集通訊。建議在至少有兩個節點且未充當控制平面主機的叢集上執行本教學課程。如果您還沒有叢集,可以使用 minikube 建立一個叢集,或者您可以使用這些 Kubernetes 實驗環境
若要檢查版本,請輸入kubectl version
。簡介
NodeLocal DNSCache 透過在叢集節點上以 DaemonSet 形式執行 DNS 快取代理程式,來改善叢集 DNS 效能。在目前的架構中,處於 'ClusterFirst' DNS 模式的 Pod 會連線到 kube-dns serviceIP
以進行 DNS 查詢。這會透過 kube-proxy 新增的 iptables 規則轉換為 kube-dns/CoreDNS 端點。透過這個新架構,Pod 將連線到在相同節點上執行的 DNS 快取代理程式,藉此避免 iptables DNAT 規則與連線追蹤。本機快取代理程式將查詢 kube-dns 服務,以尋找叢集主機名稱的快取未命中(預設為 "cluster.local
" 後綴)。
動機
在目前的 DNS 架構中,如果沒有本機 kube-dns/CoreDNS 執行個體,則具有最高 DNS QPS 的 Pod 可能必須連線到不同的節點。擁有本機快取將有助於改善此類情境中的延遲。
略過 iptables DNAT 與連線追蹤將有助於減少 conntrack 競爭,並避免 UDP DNS 項目填滿 conntrack 表格。
從本機快取代理程式到 kube-dns 服務的連線可以升級為 TCP。TCP conntrack 項目將在連線關閉時移除,這與必須逾時的 UDP 項目形成對比(預設
nf_conntrack_udp_timeout
為 30 秒)將 DNS 查詢從 UDP 升級為 TCP 將減少因 UDP 封包丟失與 DNS 逾時(通常長達 30 秒,3 次重試 + 10 秒逾時)導致的尾部延遲。由於 nodelocal 快取監聽 UDP DNS 查詢,因此應用程式不需要變更。
節點層級 DNS 請求的指標與可見性。
可以重新啟用負面快取,藉此減少 kube-dns 服務的查詢數量。
架構圖
這是啟用 NodeLocal DNSCache 後 DNS 查詢遵循的路徑
Nodelocal DNSCache 流程
此映像檔顯示 NodeLocal DNSCache 如何處理 DNS 查詢。
組態
注意
NodeLocal DNSCache 的本機監聽 IP 位址可以是任何可保證不會與叢集中任何現有 IP 衝突的位址。建議使用具有本機範圍的位址,例如,來自 IPv4 的 'link-local' 範圍 '169.254.0.0/16' 或來自 IPv6 的 'Unique Local Address' 範圍 'fd00::/8'。可以使用下列步驟啟用此功能
準備一個類似於範例
nodelocaldns.yaml
的資訊清單,並將其另存為nodelocaldns.yaml
。如果使用 IPv6,則 CoreDNS 組態檔需要將所有 IPv6 位址括在方括號中(如果在 'IP:Port' 格式中使用)。如果您使用先前重點中的範例資訊清單,則這會要求您修改 組態行 L70,如下所示:"
health [__PILLAR__LOCAL__DNS__]:8080
"使用正確的值取代資訊清單中的變數
kubedns=`kubectl get svc kube-dns -n kube-system -o jsonpath={.spec.clusterIP}` domain=<cluster-domain> localdns=<node-local-address>
<cluster-domain>
預設為 "cluster.local
"。<node-local-address>
是為 NodeLocal DNSCache 選擇的本機監聽 IP 位址。如果 kube-proxy 在 IPTABLES 模式下執行
sed -i "s/__PILLAR__LOCAL__DNS__/$localdns/g; s/__PILLAR__DNS__DOMAIN__/$domain/g; s/__PILLAR__DNS__SERVER__/$kubedns/g" nodelocaldns.yaml
__PILLAR__CLUSTER__DNS__
與__PILLAR__UPSTREAM__SERVERS__
將由node-local-dns
Pod 填入。在此模式下,node-local-dns
Pod 會同時監聽 kube-dns 服務 IP 以及<node-local-address>
,因此 Pod 可以使用任一 IP 位址查閱 DNS 記錄。如果 kube-proxy 在 IPVS 模式下執行
sed -i "s/__PILLAR__LOCAL__DNS__/$localdns/g; s/__PILLAR__DNS__DOMAIN__/$domain/g; s/,__PILLAR__DNS__SERVER__//g; s/__PILLAR__CLUSTER__DNS__/$kubedns/g" nodelocaldns.yaml
在此模式下,
node-local-dns
Pod 僅監聽<node-local-address>
。node-local-dns
介面無法繫結 kube-dns 叢集 IP,因為用於 IPVS 負載平衡的介面已使用此位址。__PILLAR__UPSTREAM__SERVERS__
將由 node-local-dns Pod 填入。
執行
kubectl create -f nodelocaldns.yaml
如果在 IPVS 模式下使用 kube-proxy,則需要修改 kubelet 的
--cluster-dns
旗標,以使用 NodeLocal DNSCache 正在監聽的<node-local-address>
。否則,沒有必要修改--cluster-dns
旗標的值,因為 NodeLocal DNSCache 同時監聽 kube-dns 服務 IP 以及<node-local-address>
。
啟用後,node-local-dns
Pod 將在每個叢集節點上的 kube-system
命名空間中執行。此 Pod 在快取模式下執行 CoreDNS,因此不同外掛程式公開的所有 CoreDNS 指標都將在每個節點上可用。
您可以透過移除 DaemonSet 來停用此功能,方法是使用 kubectl delete -f <manifest>
。您也應該還原您對 kubelet 組態所做的任何變更。
StubDomains 與上游伺服器組態
在 kube-system
命名空間中,kube-dns
ConfigMap 裡指定的 StubDomains 和上游伺服器會被 node-local-dns
Pod 自動擷取。ConfigMap 內容需要遵循範例中顯示的格式。node-local-dns
ConfigMap 也可以直接修改,並使用 Corefile 格式設定 stubDomain。某些雲端供應商可能不允許直接修改 node-local-dns
ConfigMap。在這些情況下,可以更新 kube-dns
ConfigMap。
設定記憶體限制
node-local-dns
Pod 使用記憶體來儲存快取條目和處理查詢。由於它們不監看 Kubernetes 物件,因此叢集大小或服務 / EndpointSlice 的數量不會直接影響記憶體使用量。記憶體使用量受 DNS 查詢模式影響。根據 CoreDNS 文件,
預設快取大小為 10000 個條目,完全填滿時約使用 30 MB 的記憶體。
這將是每個伺服器區塊的記憶體使用量(如果快取完全填滿)。可以透過指定較小的快取大小來減少記憶體使用量。
並行查詢的數量與記憶體需求相關,因為用於處理查詢的每個額外 goroutine 都需要一定量的記憶體。您可以使用 forward 外掛程式中的 max_concurrent
選項來設定上限。
如果 node-local-dns
Pod 嘗試使用超出可用記憶體的量(由於系統總資源,或由於設定的資源限制),作業系統可能會關閉該 Pod 的容器。如果發生這種情況,被終止(“OOMKilled”)的容器不會清除它先前在啟動期間新增的自訂封包過濾規則。node-local-dns
容器應該會重新啟動(因為是 DaemonSet 的一部分進行管理),但每次容器故障時,都會導致短暫的 DNS 停機時間:封包過濾規則將 DNS 查詢導向到不健康的本機 Pod。
您可以透過在沒有限制的情況下執行 node-local-dns Pod 並測量峰值使用量來確定合適的記憶體限制。您也可以設定和使用推薦模式的 VerticalPodAutoscaler,然後查看其建議。