CoreDNS是什么
CoreDNS是一個靈活可擴展的DNS服務器,使用Go語言編寫,旨在提供快速、靈活的DNS服務
為什么需要CoreDNS
CoreDNS為Kubernetes集群內部的DNS解析提供服務,使得服務之間能夠通過域名互相通信
Kubernetes集群中, CoreDNS是運行在kube-system這個namespace下的Pod
kubectl -n kube-system get pod coredns-66f779496c-b7mmz
NAME READY STATUS RESTARTS AGE
coredns-66f779496c-b7mmz 1/1 Running 4 (28m ago) 4d23h
k8s集群中的域名是如何解析的
比如服務a訪問服務b:
- 如果a和b在同一個namespace下, 可以直接在pod a中, 通過
curl b
來訪問b - 如果a和b不在同一個namespace下, 在pod a中需要通過
curl b.namespaceb
來訪問b
以下動手測試
測試同一個namespace下的服務間域名解析
創建一個名為foo的namespace, 再創建兩個Flask服務(svca, svcb)
kubectl get all -n foo
NAME READY STATUS RESTARTS AGE
pod/svca-78f6c85d4-sd97h 1/1 Running 0 43s
pod/svcb-5fccb7d86b-mkqg7 1/1 Running 0 43sNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/svca ClusterIP 10.98.115.242 <none> 8000/TCP 24s
service/svcb ClusterIP 10.111.107.194 <none> 8000/TCP 23sNAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/svca 1/1 1 1 24s
deployment.apps/svcb 1/1 1 1 23s
進入pod a, 通過curl http://svcb
訪問 b
kubectl exec -it pod/svca-78f6c85d4-sd97h -n foo -- sh# curl http://svcb:8000
hello foo
測試不同namespace下的服務間域名解析
兩個服務(svca, svcb), svca在foo命名空間, svcb在bar命名空間, 在pod a中訪問b, 使用curl http://svcb.bar
kubectl exec -it pod/svca-78f7c85d4-sd97h -n foo -- sh
# curl http://svcb.bar:8000
hello foo
為什么同一Namespace下, 直接訪問服務名<service-name>
就可以, 不同Namespace下, 必須帶上namespace(<service-name>.<namespace>
?
進入pod a, 查看/etc/resolve.conf
search foo.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.96.0.10
options ndots:5
這里的DNS Server(10.96.0.10)是kube-dns的ClusterIP
# kubectl -n kube-system get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 9d
查看/etc/resolv.conf
, 其中的關鍵點在于search指令和ndots選項:
- search:這個指令定義了一系列的后綴,當DNS查詢失敗時,會依次嘗試將這些后綴附加到原始查詢域名后面,直到找到匹配項或所有后綴都已嘗試過。
- ndots:如果一個域名中包含的點(.)數量小于ndots值,則該域名會被認為是“不完整”的域名。在這種情況下,DNS 客戶端會嘗試將 /etc/resolv.conf 中的 search 路徑逐一追加到該域名后進行解析。如果域名中的點數大于或等于 ndots,則直接將其作為完整的域名進行查詢。
k8s集群中某個服務完整的域名格式是<service-name>.<namespace>.svc.<cluster-domain>
, 驗證一下:
# nslookup svcb.foo.svc.cluster.local 10.96.0.10
Server: 10.96.0.10
Address: 10.96.0.10#53Name: svcb.foo.svc.cluster.local
Address: 10.111.107.194
同一命名空間下的服務訪問
CoreDNS會按照svcb.foo.svc.cluster.local
-> svcb.svc.cluster.local
-> svcb.cluster.local
順序解析, 可以看出第一次解析(svcb.foo.svc.cluster.local
)就會成功
不同命名空間下的服務訪問
必須使用<service-name>.<namespace>
的形式,例如svcb.bar
, CoreDNS會按照 svcb.bar.foo.svc.cluster.local
-> svcb.bar.svc.cluster.local
-> svcb.bar.cluster.local
, 可以看出第二次解析(svcb.bar.svc.cluster.local
)就會成功
訪問外部域名是否走search域 ?
測試一下, 進入pod, 使用nslookup指定coreDNS, 查詢外部域名www.trendmicro.com
kubectl -n bar exec -it svcb-5fccb7d86b-wj6nv -- sh
sh-5.1# nslookup www.trendmicro.com 10.96.0.10
Server: 10.96.0.10
Address: 10.96.0.10#53Non-authoritative answer:
www.trendmicro.com canonical name = ion.trendmicro.com.edgekey.net.
ion.trendmicro.com.edgekey.net canonical name = e3576.a.akamaiedge.net.
Name: e3576.a.akamaiedge.net
Address: 23.217.64.161抓包
# tcpdump -i eth0 udp
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
13:13:54.687483 IP svcb-5fccb7d86b-wj6nv.37345 > kube-dns.kube-system.svc.cluster.local.domain: 44803+ A? www.trendmicro.com.bar.svc.cluster.local. (58)
13:13:54.687791 IP kube-dns.kube-system.svc.cluster.local.domain > svcb-5fccb7d86b-wj6nv.37345: 44803 NXDomain*- 0/1/0 (151)
13:13:54.688531 IP svcb-5fccb7d86b-wj6nv.47832 > kube-dns.kube-system.svc.cluster.local.domain: 45213+ A? www.trendmicro.com.svc.cluster.local. (54)
13:13:54.688671 IP kube-dns.kube-system.svc.cluster.local.domain > svcb-5fccb7d86b-wj6nv.47832: 45213 NXDomain*- 0/1/0 (147)
13:13:54.688877 IP svcb-5fccb7d86b-wj6nv.56239 > kube-dns.kube-system.svc.cluster.local.domain: 52750+ A? www.trendmicro.com.cluster.local. (50)
13:13:54.689073 IP kube-dns.kube-system.svc.cluster.local.domain > svcb-5fccb7d86b-wj6nv.56239: 52750 NXDomain*- 0/1/0 (143)
13:13:54.689225 IP svcb-5fccb7d86b-wj6nv.41094 > kube-dns.kube-system.svc.cluster.local.domain: 46754+ A? www.trendmicro.com. (36)
13:13:54.720336 IP svcb-5fccb7d86b-wj6nv.36285 > kube-dns.kube-system.svc.cluster.local.domain: 55747+ PTR? 10.0.96.10.in-addr.arpa. (41)
13:13:54.721011 IP kube-dns.kube-system.svc.cluster.local.domain > svcb-5fccb7d86b-wj6nv.36285: 55747*- 1/0/0 PTR kube-dns.kube-system.svc.cluster.local. (116)
13:13:54.731442 IP kube-dns.kube-system.svc.cluster.local.domain > svcb-5fccb7d86b-wj6nv.41094: 46754 3/0/0 CNAME ion.trendmicro.com.edgekey.net., CNAME e3576.a.akamaiedge.net., A 23.208.168.135 (202)
13:13:54.735385 IP svcb-5fccb7d86b-wj6nv.37844 > kube-dns.kube-system.svc.cluster.local.domain: 29753+ AAAA? e3576.a.akamaiedge.net. (40)
13:13:54.775441 IP kube-dns.kube-system.svc.cluster.local.domain > svcb-5fccb7d86b-wj6nv.37844: 29753 0/1/0 (131)
————————————————
可以看出, 解析www.trendmicro.com
走了search域, 有3次無用的DNS請求
www.trendmicro.com.bar.svc.cluster.local. -> www.trendmicro.com.svc.cluster.local. -> www.trendmicro.com.cluster.local. -> www.trendmicro.com.
如果我們只用到了同namespace下的訪問、或者跨namespace下的service訪問, 可以把ndots默認值改成2, 減少DNS查詢, 提高性能
Kubernetes DNS 策略
在Kubernetes中,dnsPolicy字段定義了Pod的DNS配置策略,提供了四種不同的策略:ClusterFirst、 ClusterFirstWithHostNet、 Default 和 None
ClusterFirst(默認)
Kubernetes的默認DNS策略, Pod優先使用CoreDNS進行域名解析, 如果CoreDNS無法解析,回退到宿主機的DNS配置進行解析
這是最常見的配置, 適用于需要訪問集群內其他服務的應用
ClusterFirstWithHostNet
這個策略專為使用主機網絡(hostNetwork: true)的Pod設計, 仍然優先使用CoreDNS進行解析
適用于需要直接監聽宿主機上網絡接口, 但仍需訪問集群內其他服務的應用
Default
使用宿主機的DNS設置,完全不使用CoreDNS
適用于主要訪問外部服務的應用, 避免CoreDNS解析外部域名帶來的延遲問題
None
完全忽略Kubernetes和宿主機的DNS配置,要求用戶自行指定DNS設置。 適用于對DNS配置有高度定制需求的應用. 配置示例如下:
apiVersion: v1
kind: Pod
metadata:name: custom-dns-pod
spec:dnsPolicy: NonednsConfig:nameservers:- 8.8.8.8- 8.8.4.4searches:- ns1.svc.cluster.local- mycompany.localoptions:- name: ndotsvalue: "2"- name: edns0
參考
【1】 https://coredns.io/manual/toc/
【2】 https://cloud.tencent.com/developer/article/2126510