【K8s概念】Pod 與 Service 的 DNS


參考:https://kubernetes.io/zh/docs/concepts/services-networking/dns-pod-service/

Kubernetes 為服務和 Pods 創建 DNS 記錄。 你可以使用一致的 DNS 名稱而非 IP 地址來訪問服務。

介紹

Kubernetes DNS 在集群上調度 DNS Pod 和服務,並配置 kubelet 以告知各個容器 使用 DNS 服務的 IP 來解析 DNS 名稱。

集群中定義的每個 Service (包括 DNS 服務器自身)都被賦予一個 DNS 名稱。 默認情況下,客戶端 Pod 的 DNS 搜索列表會包含 Pod 自身的名字空間和集群 的默認域。

Service 的名字空間

DNS 查詢可能因為執行查詢的 Pod 所在的名字空間而返回不同的結果。 不指定名字空間的 DNS 查詢會被限制在 Pod 所在的名字空間內。 要訪問其他名字空間中的服務,需要在 DNS 查詢中給出名字空間。

例如,假定名字空間 test 中存在一個 Pod,prod 名字空間中存在一個服務 data。

Pod 查詢 data 時沒有返回結果,因為使用的是 Pod 的名字空間 test。

Pod 查詢 data.prod 時則會返回預期的結果,因為查詢中指定了名字空間。

DNS 查詢可以使用 Pod 中的 /etc/resolv.conf 展開。kubelet 會為每個 Pod 生成此文件。例如,對 data 的查詢可能被展開為 data.prod.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.cluster.local。

DNS 記錄

哪些對象會獲得 DNS 記錄呢?

  • Services
  • Pods

以下各節詳細介紹了被支持的 DNS 記錄類型和被支持的布局。 其它布局、名稱或者查詢即使碰巧可以工作,也應視為實現細節, 將來很可能被更改而且不會因此發出警告。 有關最新規范請查看 Kubernetes 基於 DNS 的服務發現。

服務

A/AAAA 記錄

“普通” 服務(除了無頭服務)會以 my-svc.my-namespace.svc.cluster-domain.example 這種名字的形式被分配一個 DNS A 或 AAAA 記錄,取決於服務的 IP 協議族。 該名稱會解析成對應服務的集群 IP。

“無頭(Headless)” 服務(沒有集群 IP)也會以 my-svc.my-namespace.svc.cluster-domain.example 這種名字的形式被指派一個 DNS A 或 AAAA 記錄, 具體取決於服務的 IP 協議族。 與普通服務不同,這一記錄會被解析成對應服務所選擇的 Pod 集合的 IP。 客戶端要能夠使用這組 IP,或者使用標准的輪轉策略從這組 IP 中進行選擇。

SRV 記錄

Kubernetes 會為命名端口創建 SRV 記錄,這些端口是普通服務或 無頭服務的一部分。 對每個命名端口,SRV 記錄具有 _my-port-name._my-port-protocol.my-svc.my-namespace.svc.cluster-domain.example 這種形式。 對普通服務,該記錄會被解析成端口號和域名:my-svc.my-namespace.svc.cluster-domain.example。 對無頭服務,該記錄會被解析成多個結果,服務對應的每個后端 Pod 各一個; 其中包含 Pod 端口號和形為 auto-generated-name.my-svc.my-namespace.svc.cluster-domain.example 的域名。

Pods

A/AAAA 記錄

一般而言,Pod 會對應如下 DNS 名字解析:

pod-ip-address.my-namespace.pod.cluster-domain.example

例如,對於一個位於 default 名字空間,IP 地址為 172.17.0.3 的 Pod, 如果集群的域名為 cluster.local,則 Pod 會對應 DNS 名稱:

172-17-0-3.default.pod.cluster.local.

Deployment 或通過 Service 暴露出來的 DaemonSet 所創建的 Pod 會有如下 DNS 解析名稱可用:

pod-ip-address.deployment-name.my-namespace.svc.cluster-domain.example.

Pod 的 hostname 和 subdomain 字段

當前,創建 Pod 時其主機名取自 Pod 的 metadata.name 值。

Pod 規約中包含一個可選的 hostname 字段,可以用來指定 Pod 的主機名。 當這個字段被設置時,它將優先於 Pod 的名字成為該 Pod 的主機名。 舉個例子,給定一個 hostname 設置為 "my-host" 的 Pod, 該 Pod 的主機名將被設置為 "my-host"。

Pod 規約還有一個可選的 subdomain 字段,可以用來指定 Pod 的子域名。 舉個例子,某 Pod 的 hostname 設置為 “foo”,subdomain 設置為 “bar”, 在名字空間 “my-namespace” 中對應的完全限定域名(FQDN)為 “foo.bar.my-namespace.svc.cluster-domain.example”。

示例:

apiVersion: v1
kind: Service
metadata:
  name: default-subdomain
spec:
  selector:
    name: busybox
  clusterIP: None
  ports:
  - name: foo # 實際上不需要指定端口號
    port: 1234
    targetPort: 1234
---
apiVersion: v1
kind: Pod
metadata:
  name: busybox1
  labels:
    name: busybox
spec:
  hostname: busybox-1
  subdomain: default-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: default-subdomain
  containers:
  - image: busybox:1.28
    command:
      - sleep
      - "3600"
    name: busybox

如果某無頭服務與某 Pod 在同一個名字空間中,且它們具有相同的子域名, 集群的 DNS 服務器也會為該 Pod 的全限定主機名返回 A 記錄或 AAAA 記錄。 例如,在同一個名字空間中,給定一個主機名為 “busybox-1”、 子域名設置為 “default-subdomain” 的 Pod,和一個名稱為 “default-subdomain” 的無頭服務,Pod 將看到自己的 FQDN 為 "busybox-1.default-subdomain.my-namespace.svc.cluster-domain.example"。 DNS 會為此名字提供一個 A 記錄或 AAAA 記錄,指向該 Pod 的 IP。 “busybox1” 和 “busybox2” 這兩個 Pod 分別具有它們自己的 A 或 AAAA 記錄。

Endpoints 對象可以為任何端點地址及其 IP 指定 hostname。

說明:
因為沒有為 Pod 名稱創建 A 記錄或 AAAA 記錄,所以要創建 Pod 的 A 記錄 或 AAAA 記錄需要 hostname。
沒有設置 hostname 但設置了 subdomain 的 Pod 只會為 無頭服務創建 A 或 AAAA 記錄(default-subdomain.my-namespace.svc.cluster-domain.example) 指向 Pod 的 IP 地址。 另外,除非在服務上設置了 publishNotReadyAddresses=True,否則只有 Pod 進入就緒狀態 才會有與之對應的記錄。

Pod 的 setHostnameAsFQDN 字段

FEATURE STATE: Kubernetes v1.20 [beta]

前置條件:SetHostnameAsFQDN 特性門控 必須在 API 服務器 上啟用。

當你在 Pod 規約中設置了 setHostnameAsFQDN: true 時,kubelet 會將 Pod 的全限定域名(FQDN)作為該 Pod 的主機名記錄到 Pod 所在名字空間。 在這種情況下,hostname 和 hostname --fqdn 都會返回 Pod 的全限定域名。

說明:
在 Linux 中,內核的主機名字段(struct utsname 的 nodename 字段)限定 最多 64 個字符。
如果 Pod 啟用這一特性,而其 FQDN 超出 64 字符,Pod 的啟動會失敗。 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)." (無法基於 Pod 主機名和集群域名構造 FQDN,FQDN long-FQDN 過長,至多 64 字符,請求字符數為 70)。 對於這種場景而言,改善用戶體驗的一種方式是創建一個 准入 Webhook 控制器, 在用戶創建頂層對象(如 Deployment)的時候控制 FQDN 的長度。

Pod 的 DNS 策略

DNS 策略可以逐個 Pod 來設定。目前 Kubernetes 支持以下特定 Pod 的 DNS 策略。 這些策略可以在 Pod 規約中的 dnsPolicy 字段設置:

  • "Default": Pod 從運行所在的節點繼承名稱解析配置。參考 相關討論 獲取更多信息。
  • "ClusterFirst": 與配置的集群域后綴不匹配的任何 DNS 查詢(例如 "www.kubernetes.io") 都將轉發到從節點繼承的上游名稱服務器。集群管理員可能配置了額外的存根域和上游 DNS 服務器。 參閱相關討論 了解在這些場景中如何處理 DNS 查詢的信息。
  • "ClusterFirstWithHostNet":對於以 hostNetwork 方式運行的 Pod,應顯式設置其 DNS 策略 "ClusterFirstWithHostNet"。
  • "None": 此設置允許 Pod 忽略 Kubernetes 環境中的 DNS 設置。Pod 會使用其 dnsConfig 字段 所提供的 DNS 設置。 參見 Pod 的 DNS 配置節。

說明: "Default" 不是默認的 DNS 策略。如果未明確指定 dnsPolicy,則使用 "ClusterFirst"。

下面的示例顯示了一個 Pod,其 DNS 策略設置為 "ClusterFirstWithHostNet", 因為它已將 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 配置

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 最多允許 6 個搜索域。

  • 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:
      - 1.2.3.4
    searches:
      - ns1.svc.cluster-domain.example
      - my.dns.search.suffix
    options:
      - name: ndots
        value: "2"
      - name: edns0

創建上面的 Pod 后,容器 test 會在其 /etc/resolv.conf 文件中獲取以下內容:

nameserver 1.2.3.4
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 fd00:79:30::a
search default.svc.cluster-domain.example svc.cluster-domain.example cluster-domain.example
options ndots:5

功能的可用性

Pod DNS 配置和 DNS 策略 "None" 的可用版本對應如下所示。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM