前言
DNS service 在 k8s cluster 內部負責 service discovery 的重責大任←讓使用者可以跳脫 IP based 的思維,以 domain name 的方式來進行 application 的架構設計。
而 k8s DNS service 其實也是由一個 DNS pod + service 所組成,並且告訴 kubelet 將每個 container 的 DNS resolution 都指向這個 DNS service,藉由此方式,每個 pod 在存取其他 service 時,都會向一開始就安裝好的 DNS pod 進行 domain name 的詢問。
Domain Name 解析規則
要了解 k8s Domain Name 的解析規則,必須清楚知道以下兩件事情:
k8s 中有 namespace 的概念,由於不同的 namespace 中可以有同樣名稱的 service or pod,因此 DNS 解析的部份就需要考慮 namespace
k8s cluster domain name,若是未設定,預設就會是
cluster.local
有了以上兩個概念之後,接著可以繼續往下。
假設目前 k8s 有以下幾個 resource object:
兩個 namespace,分別是
ns1
&ns2
在 ns1 中,有個 service 名稱為
svc1
,與其相關連的 pod 為pod1
在 ns2 中,有個 service 名稱為
svc2
,與其相關連的 pod 為pod2
假設目前有個 pod 位於 ns1 中:
可透過 domain name
svc1
orsvc1.ns1
orsvc1.ns1.svc.cluster.local
存取 svc1可透過 domain name
svc2.ns2
orsvc2.ns2.svc.cluster.local
存取 svc2 (但無法使用svc1
,因為在不同的 namespace 中)
反之亦然。
DNS for Service
準備環境
為了進行後面關於 DNS 的實驗,我們透過以下的 YAML 建立 service:
1 |
|
套用以上設定後,可以看到類似以下資訊:
1 | # 檢視套用上面設定後的結果 |
A records
在以上的範例中(namespace = default
),k8s 會為 service 自動建立 A record 如下:
- svc-cluster.default.svc.cluster.local
一般的 type=ClusterIP 的 service,因此會有一個匹配的 cluster IP
- svc-headless.default.svc.cluster.local
clusterIP: None
,屬於 headless service,因此不會有 cluster IP,解析出來的結果會是其 endpoints 資訊
1 | # 從 host level 使用 nslookup |
SRV records
除了 A record 之外,k8s DNS 還會額外建立相對應的 SRV record,並且用以下的命名規則來產生:
[_my-port-name].[_my-port-protocol].[svc_name].[namespace_name].svc.cluster.local
以下進行實際的查詢來檢視一下 DNS SRV record 產生的結果:
1 | #### 繼續上面的 nslookup 測試 ### |
DNS for Pod
A record
跟 service 相同,每個 pod 在產生的時候也會以下述的格式分配一個 DNS A record 在 k8s DNS service 中:
[pod-ip-address].[namespace-name].pod.cluster.local
因此假設 pod 的 ip 為 1.2.3.4
,namespace 為 default
,且 cluster domain 為 cluster.local
,那就會有 1-2-3-4.default.pod.cluster.local
這筆 A record 產生。
以上的部份是官方文件上提到會有的設定,但實際上實驗結果(k8s version =
1.12.1
)並不是這樣! 並沒有在 k8s DNS service 中看到上述的 A record,因此這個部份還有帶後續釐清
Pod 的 hostname & subdomain
這裡要分成兩個部份來說:
hostname
: 在預設情況下,每個 pod 的 hostname 都會使用在 pod 定義中metadata.name
的值subdomain
:預設情況下不會有這個部份的設定出現
但以上兩個其實都是可以在 pod spec 中定義的,分別是 .spec.hostname
& .spec.subdomain
。
因此假設有個 pod spec 有以下設定:
.spec.hostname
: foo.spec.subdomain
: bar
並新增到 namespace default
中,就會在該 pod 中的 /etc/hosts 中多出 foo.bar.default.svc.cluster.local
& pod IP 的對應記錄,但是並不會出現在 k8s DNS service 中。
不會出現在 k8s DNS service 中的部份,跟官網文件說明有出入,同樣也是待後續釐清
DNS Policy & Config
此外 pod spec 中還可以根據自身的需求,額外設定 DNS policy & config,但在進行這樣的設定之前,建議先把 Linux /etc/resolv.conf
中的相關設定搞清楚,會比較容易理解這一段。
關於 Linux /etc/resolv.conf
的設定說明,可以參考下列文章:
有了以上的 DNS 觀念後,進行 pod DNS policy & config 設定時就會清楚每個設定所產生的效果會是如何了。
而這個部份(pod DNS policy & config)已經有網友有相當詳細的說明,可以參考下列文章: