跳至主要内容

[12] 為什麼 CoreDNS 可以解析 VPC endpoint 及外部 DNS

預設 EKS1 使用了 CoreDNS2 作為 Kubernetes 內部 DNS 服務器,我們也可以根據 kubectl get deploy 命令查看 CoreDNS 資源:

$ kubectl -n kube-system get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
coredns 2/2 2 2 12d

於 Day 3 所提及於 EKS node bootstrap script 內提供了 --dns-cluster-ip 設定 CoreDNS service IP。但是這部分僅能了解 Pods 使用此 IP 作為 resolver,那為什麼 CoreDNS Pod 不會繼承此 CoreDNS Service Cluster IP,倘若繼承了此 IP 豈不是也造成了遞迴無法解析 VPC endpoint 及外部 DNS 域名。

故本文將探討 CoreDNS 設定及 EKS DNS 解析流程。

kubelet 設定檔

再次複習一下 EKS AMI Build Specification bootstrap.sh3 中,取得 --dns-cluster-ip 變數設定後更新至 kubelet 設定檔 clusterDNS flag。

echo "$(jq ".clusterDNS=[\"$DNS_CLUSTER_IP\"]" $KUBELET_CONFIG)" > $KUBELET_CONFIG

我們也可以於 EKS worker node 上檢視相應設定,預設為 10.100.0.10

[ec2-user@ip-192-168-3-47 ~]$ jq .clusterDNS /etc/kubernetes/kubelet/kubelet-config.json
[
"10.100.0.10"
]

根據 kubelet4 文件 --cluster-dns,為 DNS IP 地址 list,適用於每個 dnsPolicy=ClusterFirst 的 Pod。

Pod's DNS Policy

Kubernetes Pod DNS Policy4 有以下四種:

  • Default:Pod 繼承所在的 node 上的 DNS 解析設定。
  • ClusterFirst:與預設 cluster domain suffix 不相符時,如 cluster.local,則會轉發至 node 所繼承的上游 DNS 服務器。
  • ClusterFirstWithHostNet:對於已設定 hostNetwork 的 Pod,則應該設置此 DNS 策略 ClusterFirstWithHostNet
  • None:此設定允許 Pod 忽略 Kubernetes 環境中的 DNS 設定。

驗證測試

預設 Pod

透過 kubectl run 執行啟用一個 aws-cli Pod 並無額外設定。

$ kubectl run aws-cli --image="amazon/aws-cli" --command sleep infinity
pod/aws-cli created

檢視 dnsPolicy 確認預設使用 ClusterFirst。這邊需要注意的是 Default 並非預設值,而 Kubernetes dnsPolicy 預設值為 ClusterFirst

$ kubectl get po aws-cli -o yaml | grep "dnsPolicy"
dnsPolicy: ClusterFirst

同時,檢視 Pods resolver 設定檔 /etc/resolv.conf 也能確認 nameserver設定為 10.100.0.10

$ kubectl exec -it aws-cli -- cat /etc/resolv.conf
nameserver 10.100.0.10
search default.svc.cluster.local svc.cluster.local cluster.local eu-west-1.compute.internal
options ndots:5

CoreDNS

同理,檢視 CoreDNS 所使用 dnsPolicy 為 Default。換言之,CoreDNS 繼承使用 /etc/resolv.conf 為 EKS node 上的設定檔。

$ kubectl -n kube-system get deploy -o yaml | grep "dnsPolicy"
......
dnsPolicy: Default

不過由於 CoreDNS image 並未提供 shell 環境可以執行,以下透過設定 dnsPolicy=Default 驗證:

$ kubectl run aws-cli-2 --image="amazon/aws-cli" --command sleep infinity --overrides='{ "spec": { "dnsPolicy": "Default" } }'
pod/aws-cli-2 created

$ kubectl get po aws-cli-2 -o yaml | grep "dnsPolicy"
dnsPolicy: Default

可觀察到 Pod 使用的 nameserver 並非 10.100.0.10 而是預設 VPC DNS resolver .2 IP 地址。

$ kubectl exec -it aws-cli-2 -- cat /etc/resolv.conf
nameserver 192.168.0.2
search eu-west-1.compute.internal
options timeout:2 attempts:5

倘若登入 EKS worker node,也能觀察到相同的設定。

[ec2-user@ip-192-168-3-47 ~]$ cat /etc/resolv.conf
; generated by /usr/sbin/dhclient-script
search eu-west-1.compute.internal
options timeout:2 attempts:5
nameserver 192.168.0.2

流程

  1. 預設 Pod 使用 ClusterFirst,其 namesever 設定(/ect/resolve.conf) 是由 kubelet --cluster-dns 參數設定,預設為 10.100.0.10
  2. CoreDNS deployment 預設 replicaset 數量為 2。因此 kube-dns Service Cluster IP 將會由 iptable 路由規則轉發至對應 CoreDNS Pod。
  3. CoreDNS Pod 進行 DNS 解析,倘若 domain name 為預設 Kubernetes domain cluster.local 則會回應對應 Service 及 Pod DNS 紀錄。反之,沒有找到對應 domain name 則會回應 NXDOMAIN
  4. 對於外部 domain 來說,DNS query 則會轉發至 VPC DNS resolver 也就是 VPC 預設 .2 IP address。
  5. 其中 VPC DNS resolver .25 可以與 VPC 中關聯的服務,如 VPC endpoint 或是 Route 53 Private hosted Zone 溝通。此外,也負責將向外部進行 DNS query 。

https://ithelp.ithome.com.tw/upload/images/20220927/20151040JZlFpZxYds.png

Pod resolv.conf

讓我們再看一下其中有幾個有趣的設定:

$ kubectl exec -it aws-cli -- cat /etc/resolv.conf
nameserver 10.100.0.10
search default.svc.cluster.local svc.cluster.local cluster.local eu-west-1.compute.internal
options ndots:5
  • search:host-name lookup list。
  • ndots 為 5:ndots 預設值為 1,對於一個 domain name 若不是 absolute name 結尾,只要 domain name 包含的 . 數量少於 ndots 定義數量,則會依照 serach list 內順序進行解析,若 . 大於或等於 5 則會直接進行解析。

因此我們也可以在 Pods 內使用 host 命令檢視此流程:


$ kubectl exec -it aws-cli -- bash

bash-4.2# yum install bind-utils -y

bash-4.2# host -av goole.com
Trying "goole.com.default.svc.cluster.local"
Trying "goole.com.svc.cluster.local"
Trying "goole.com.cluster.local"
Trying "goole.com.eu-west-1.compute.internal"
Trying "goole.com"
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 26185
;; flags: qr rd ra; QUERY: 1, ANSWER: 8, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;goole.com. IN ANY

;; ANSWER SECTION:
goole.com. 30 IN NS ns1083.ui-dns.org.
goole.com. 30 IN NS ns1083.ui-dns.de.
goole.com. 30 IN NS ns1083.ui-dns.com.
goole.com. 30 IN NS ns1083.ui-dns.biz.
goole.com. 30 IN SOA ns1083.ui-dns.de. hostmaster.1and1.co.uk. 2017062801 28800 7200 604800 300
goole.com. 30 IN A 217.160.0.201
goole.com. 30 IN MX 10 mx01.1and1.co.uk.
goole.com. 30 IN MX 10 mx00.1and1.co.uk.

Received 376 bytes from 10.100.0.10#53 in 61 ms

若希望優化 DNS query 次數,我們可以於 dnsPolicy 調整 ndots 數量。此外,若對於 Kubernetes 預設 ndots 設定數值為 5,也可以參考 GitHub issue #33554

結論

CoreDNS 預設使用 dnsPolicy 為 host 繼承 node 上的 /etc/resolv.conf 設定檔。而在 node 上預設使用了 VPC DNS resolver .2 IP,因此可以解析 VPC 內部資源,如 VPC endpoint 及 Route53 Private Zone。

參考文件

Footnotes

  1. Managing the CoreDNS add-on - https://docs.aws.amazon.com/eks/latest/userguide/managing-coredns.html

  2. CoreDNS: DNS and Service Discovery - https://coredns.io/

  3. https://github.com/awslabs/amazon-eks-ami/blob/master/files/bootstrap.sh#L518

  4. DNS for Services and Pods | Pod's DNS Policy - https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy 2

  5. Resolving DNS queries between VPCs and your network - https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resolver.html