服務與 Pod 的 DNS
Kubernetes 為服務與 Pod 建立 DNS 記錄。您可以使用一致的 DNS 名稱而非 IP 位址來聯絡服務。
Kubernetes 發布關於 Pod 與服務的資訊,這些資訊用於程式設計 DNS。Kubelet 設定 Pod 的 DNS,以便執行中的容器可以使用名稱而非 IP 查詢服務。
在叢集中定義的服務會被指派 DNS 名稱。預設情況下,用戶端 Pod 的 DNS 搜尋清單包含 Pod 自己的命名空間與叢集的預設網域。
服務的命名空間
DNS 查詢可能會根據發出查詢的 Pod 的命名空間傳回不同的結果。未指定命名空間的 DNS 查詢僅限於 Pod 的命名空間。透過在 DNS 查詢中指定其他命名空間來存取其他命名空間中的服務。
例如,考量在 test
命名空間中的 Pod。data
服務位於 prod
命名空間中。
對 data
的查詢不會傳回任何結果,因為它使用 Pod 的 test
命名空間。
對 data.prod
的查詢會傳回預期的結果,因為它指定了命名空間。
DNS 查詢可以使用 Pod 的 /etc/resolv.conf
進行擴充。Kubelet 為每個 Pod 設定此檔案。例如,僅對 data
的查詢可能會擴充為 data.test.svc.cluster.local
。search
選項的值用於擴充查詢。若要深入瞭解 DNS 查詢,請參閱 resolv.conf
手冊頁面。
nameserver 10.32.0.10
search <namespace>.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
總之,test 命名空間中的 Pod 可以成功解析 data.prod
或 data.prod.svc.cluster.local
。
DNS 記錄
哪些物件取得 DNS 記錄?
- 服務
- Pod
以下章節詳細說明支援的 DNS 記錄類型與支援的版面配置。任何其他版面配置或名稱或碰巧可運作的查詢都被視為實作細節,並且可能會在沒有警告的情況下變更。如需最新的規格,請參閱 Kubernetes 基於 DNS 的服務發現。
服務
A/AAAA 記錄
「一般」(非 Headless)服務會被指派 DNS A 及/或 AAAA 記錄,取決於服務的 IP 系列或系列,名稱格式為 my-svc.my-namespace.svc.cluster-domain.example
。這會解析為服務的叢集 IP。
Headless 服務(沒有叢集 IP)服務也會被指派 DNS A 及/或 AAAA 記錄,名稱格式為 my-svc.my-namespace.svc.cluster-domain.example
。與一般服務不同,這會解析為服務所選取的所有 Pod 的 IP 集合。用戶端預期會使用該集合,否則會從該集合中使用標準的循環配置資源選擇。
SRV 記錄
SRV 記錄是為屬於一般或 Headless 服務的具名連接埠建立的。對於每個具名連接埠,SRV 記錄的格式為 _port-name._port-protocol.my-svc.my-namespace.svc.cluster-domain.example
。對於一般服務,這會解析為連接埠號碼與網域名稱:my-svc.my-namespace.svc.cluster-domain.example
。對於 Headless 服務,這會解析為多個答案,每個答案對應一個支援服務的 Pod,並包含連接埠號碼與 Pod 的網域名稱,格式為 hostname.my-svc.my-namespace.svc.cluster-domain.example
。
Pod
A/AAAA 記錄
在 DNS 規格實作之前,Kube-DNS 版本具有以下 DNS 解析
pod-ipv4-address.my-namespace.pod.cluster-domain.example
.
例如,如果 default
命名空間中的 Pod 的 IP 位址為 172.17.0.3,並且您叢集的網域名稱為 cluster.local
,則 Pod 的 DNS 名稱為
172-17-0-3.default.pod.cluster.local
.
服務公開的任何 Pod 都有以下可用的 DNS 解析
pod-ipv4-address.service-name.my-namespace.svc.cluster-domain.example
.
Pod 的 hostname 與 subdomain 欄位
目前,當 Pod 建立時,其主機名稱(從 Pod 內部觀察到的)是 Pod 的 metadata.name
值。
Pod 規格具有選用的 hostname
欄位,可用於指定不同的主機名稱。指定時,它優先於 Pod 的名稱,成為 Pod 的主機名稱(再次,從 Pod 內部觀察到的)。例如,給定一個 spec.hostname
設定為 "my-host"
的 Pod,該 Pod 將會將其主機名稱設定為 "my-host"
。
Pod 規格也具有選用的 subdomain
欄位,可用於指示 Pod 是命名空間子群組的一部分。例如,在 "my-namespace"
命名空間中,spec.hostname
設定為 "foo"
,且 spec.subdomain
設定為 "bar"
的 Pod,其主機名稱將設定為 "foo"
,而其完整網域名稱 (FQDN) 將設定為 "foo.bar.my-namespace.svc.cluster.local"
(再次,從 Pod 內部觀察到的)。
如果與 Pod 在相同命名空間中存在與子網域名稱相同的 Headless 服務,則叢集的 DNS 伺服器也會傳回 Pod 完整限定主機名稱的 A 及/或 AAAA 記錄。
範例
apiVersion: v1
kind: Service
metadata:
name: busybox-subdomain
spec:
selector:
name: busybox
clusterIP: None
ports:
- name: foo # name is not required for single-port Services
port: 1234
---
apiVersion: v1
kind: Pod
metadata:
name: busybox1
labels:
name: busybox
spec:
hostname: busybox-1
subdomain: busybox-subdomain
containers:
- image: busybox:1.28
command:
- sleep
- "3600"
name: busybox
---
apiVersion: v1
kind: Pod
metadata:
name: busybox2
labels:
name: busybox
spec:
hostname: busybox-2
subdomain: busybox-subdomain
containers:
- image: busybox:1.28
command:
- sleep
- "3600"
name: busybox
給定上述服務 "busybox-subdomain"
與將 spec.subdomain
設定為 "busybox-subdomain"
的 Pod,第一個 Pod 會將自己的 FQDN 視為 "busybox-1.busybox-subdomain.my-namespace.svc.cluster-domain.example"
。DNS 在該名稱提供 A 及/或 AAAA 記錄,指向 Pod 的 IP。Pod "busybox1
" 與 "busybox2
" 都會有自己的位址記錄。
EndpointSlice 可以指定任何端點位址的 DNS 主機名稱,以及其 IP。
注意
不會為 Pod 名稱建立 A 與 AAAA 記錄,因為 Pod 缺少hostname
。沒有 hostname
但有 subdomain
的 Pod 將僅為 Headless 服務 (busybox-subdomain.my-namespace.svc.cluster-domain.example
) 建立 A 或 AAAA 記錄,指向 Pod 的 IP 位址。此外,Pod 需要處於就緒狀態才能擁有記錄,除非在服務上設定 publishNotReadyAddresses=True
。Pod 的 setHostnameAsFQDN 欄位
Kubernetes v1.22 [stable]
當 Pod 組態為具有完整網域名稱 (FQDN) 時,其主機名稱是簡短主機名稱。例如,如果您有一個完整網域名稱 busybox-1.busybox-subdomain.my-namespace.svc.cluster-domain.example
的 Pod,則預設情況下,該 Pod 內部的 hostname
命令會傳回 busybox-1
,而 hostname --fqdn
命令會傳回 FQDN。
當您在 Pod 規格中設定 setHostnameAsFQDN: true
時,kubelet 會將 Pod 的 FQDN 寫入該 Pod 命名空間的主機名稱。在這種情況下,hostname
與 hostname --fqdn
都會傳回 Pod 的 FQDN。
注意
在 Linux 中,核心的主機名稱欄位 (struct utsname
的 nodename
欄位) 限制為 64 個字元。
如果 Pod 啟用此功能,且其 FQDN 超過 64 個字元,則會啟動失敗。Pod 將維持在 Pending
狀態(kubectl
顯示為 ContainerCreating
),並產生錯誤事件,例如:Failed to construct FQDN from Pod hostname and cluster domain, FQDN long-FQDN
is too long (64 characters is the max, 70 characters requested)。改善此情境使用者體驗的一種方法是建立一個許可 контролер 網頁掛鉤,以便在使用者建立頂層物件(例如 Deployment)時控制 FQDN 大小。
Pod 的 DNS 原則
DNS 原則可以在每個 Pod 的基礎上設定。目前 Kubernetes 支援以下 Pod 特定的 DNS 原則。這些原則在 Pod 規格的 dnsPolicy
欄位中指定。
"Default"
:Pod 從 Pod 執行的節點繼承名稱解析組態。請參閱相關討論以取得更多詳細資訊。"ClusterFirst"
:任何與已設定的叢集網域後綴(例如"www.kubernetes.io"
)不符的 DNS 查詢,都會由 DNS 伺服器轉發到上游名稱伺服器。叢集管理員可能已設定額外的存根網域和上游 DNS 伺服器。請參閱相關討論以取得關於在這些情況下如何處理 DNS 查詢的詳細資訊。"ClusterFirstWithHostNet"
:對於使用 hostNetwork 執行的 Pod,您應該明確地將其 DNS 原則設定為"ClusterFirstWithHostNet"
。否則,使用 hostNetwork 和"ClusterFirst"
執行的 Pod 將會退回"Default"
原則的行為。- 注意:Windows 不支援此功能。請參閱下方的 DNS 與 Windows 以取得詳細資訊
"None"
:它允許 Pod 忽略來自 Kubernetes 環境的 DNS 設定。所有 DNS 設定都應使用 Pod 規格中的dnsConfig
欄位提供。請參閱下方 Pod 的 DNS 組態 子章節。
注意
“Default” 不是預設的 DNS 原則。如果未明確指定dnsPolicy
,則會使用 “ClusterFirst”。以下範例顯示一個 DNS 原則設定為 "ClusterFirstWithHostNet"
的 Pod,因為它已將 hostNetwork
設定為 true
。
apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: default
spec:
containers:
- image: busybox:1.28
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
name: busybox
restartPolicy: Always
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
Pod 的 DNS 組態
Kubernetes v1.14 [stable]
Pod 的 DNS 組態允許使用者更精細地控制 Pod 的 DNS 設定。
dnsConfig
欄位是選用的,它可以與任何 dnsPolicy
設定搭配使用。但是,當 Pod 的 dnsPolicy
設定為 "None"
時,則必須指定 dnsConfig
欄位。
以下是使用者可以在 dnsConfig
欄位中指定的屬性
nameservers
:將用作 Pod 的 DNS 伺服器的 IP 位址清單。最多可以指定 3 個 IP 位址。當 Pod 的dnsPolicy
設定為"None"
時,此清單必須包含至少一個 IP 位址,否則此屬性為選用。列出的伺服器將與從指定的 DNS 原則產生的基本名稱伺服器合併,並移除重複的位址。searches
:用於 Pod 中主機名稱查詢的 DNS 搜尋網域清單。此屬性為選用。指定後,提供的清單將合併到從選定的 DNS 原則產生的基本搜尋網域名稱中。重複的網域名稱會被移除。Kubernetes 允許最多 32 個搜尋網域。options
:一個選用物件清單,其中每個物件可能具有name
屬性(必要)和value
屬性(選用)。此屬性中的內容將合併到從指定的 DNS 原則產生的選項中。重複的項目會被移除。
以下是具有自訂 DNS 設定的 Pod 範例
apiVersion: v1
kind: Pod
metadata:
namespace: default
name: dns-example
spec:
containers:
- name: test
image: nginx
dnsPolicy: "None"
dnsConfig:
nameservers:
- 192.0.2.1 # this is an example
searches:
- ns1.svc.cluster-domain.example
- my.dns.search.suffix
options:
- name: ndots
value: "2"
- name: edns0
當上述 Pod 建立時,容器 test
會在其 /etc/resolv.conf
檔案中取得以下內容
nameserver 192.0.2.1
search ns1.svc.cluster-domain.example my.dns.search.suffix
options ndots:2 edns0
對於 IPv6 設定,應如下設定搜尋路徑和名稱伺服器
kubectl exec -it dns-example -- cat /etc/resolv.conf
輸出結果類似於此
nameserver 2001:db8:30::a
search default.svc.cluster-domain.example svc.cluster-domain.example cluster-domain.example
options ndots:5
DNS 搜尋網域列表限制
Kubernetes 1.28 [stable]
Kubernetes 本身不限制 DNS 組態,除非搜尋網域列表的長度超過 32 個,或所有搜尋網域的總長度超過 2048 個字元。此限制分別適用於節點的解析器組態檔、Pod 的 DNS 組態和合併的 DNS 組態。
注意
早期版本的一些容器執行期可能對 DNS 搜尋網域的數量有自己的限制。根據容器執行期環境,具有大量 DNS 搜尋網域的 Pod 可能會卡在等待中狀態。
已知 containerd v1.5.5 或更早版本以及 CRI-O v1.21 或更早版本有此問題。
Windows 節點上的 DNS 解析
- 在 Windows 節點上執行的 Pod 不支援 ClusterFirstWithHostNet。Windows 將所有帶有
.
的名稱視為 FQDN,並跳過 FQDN 解析。 - 在 Windows 上,可以使用多個 DNS 解析器。由於它們的行為略有不同,因此建議使用
Resolve-DNSName
PowerShell Cmdlet 進行名稱查詢解析。 - 在 Linux 上,您有一個 DNS 後綴列表,在完全合格名稱解析失敗後使用。在 Windows 上,您只能有一個 DNS 後綴,即與該 Pod 命名空間關聯的 DNS 後綴(例如:
mydns.svc.cluster.local
)。Windows 可以解析 FQDN、服務或可以使用此單一後綴解析的網路名稱。例如,在default
命名空間中產生的 Pod 將具有 DNS 後綴default.svc.cluster.local
。在 Windows Pod 內部,您可以解析kubernetes.default.svc.cluster.local
和kubernetes
,但不能解析部分合格的名稱 (kubernetes.default
或kubernetes.default.svc
)。
下一步
有關管理 DNS 組態的指南,請查看設定 DNS 服務