最近在部署一些解決方案時,碰到了關於名稱解析上的一些問題,雖然有時候不難解決,但我發現如果清楚K8S有關於名稱解析的概念,會對除錯的時間與過程有很大的幫助。
透過本篇文章,除了幫自已留下問題查找的過程,同時也希望利用文章來整理自已對CoreDNS元件的一些觀念,同時也可以分享給大家參考。
以下是本文所將提到的章節:
本文為心得記錄,內容比較長,感謝大家願意花時間觀看。
首先不免俗的還是來一個官方的說法:
CoreDNS也是DNS server的一種,用Go語言開發。
與其他DNS(ex. BIND…)不同,它非常彈性、並且幾乎所有的功能都全部都被放成Plugin的型式。
這些Plugin可以各別運行或是全部放在一起運行來實現DNS的功能。
透過官方的說法,我們可以利用CoreDNS的特性來選擇與組合這些Plugin(CoreDNS Plugin API),變成自訂版本的DNS解決方式。預設的CoreDNS安裝完就會帶有約30個Plugin一起安裝進系統。其他額外的Plugin可以到以下網址去找到自已需要的:
https://coredns.io/explugins/?source=post_page-----71d255e39548--------------------------------
簡短說完CoreDNS的來歷,接下來說明kubernetes中,如何解析domain name的。
在K8S內,如果Pod在訪問在同一個Namespace下的Service,只要執行:
# curl aa-svc
可是如果訪問的對象在不同的namespace呢? 此時就要再加上domain的部分,如下:
# curl aa-svc.domain
由此可知,只要離開自已的namespace範圍時,就會需要做名稱解析了。
不管是不是在K8S cluster內,基本上DNS解析基本上會使用到:
在訪問時,Pod會先查找/etc/resolv.conf的內容,裡面就是指定DNS server的位置,而內容則是由設定好dnspolicy: ClusterFirst的情況下,自動生成出來。裡面nameserver的IP則是DNS service的cluster IP。所以這個Pod內所有的解析都會與這個cluster IP傳送(不管是不是同一個namespace)。
預設的search domain(搜尋時會依序進行查找):
最後簡單說明K8S的DNS Policies,一共有以下四種:
本章節簡單說明二者的不同。
(1) Kube-DNS: 同樣提供DNS名稱解析的功能,但K8S 1.21版之後,kubeadm移除了對Kube-DNS的支援,只支援CoreDNS。而以下圖為Kube-DNS的基本架構圖:
以下簡單說明主要的三個元件:
(2) CoreDNS: 請參閱上述內容,就不重覆內容。
(3) 優缺點:
※ Kube-DNS
※ CoreDNS
#---------------------------------------------
# S3-1. 部署dnsutils
#---------------------------------------------
[master]# vim dnsutils.yaml
apiVersion: v1
kind: Pod
metadata:
name: dnsutils
namespace: default
spec:
containers:
- name: dnsutils
image: registry.k8s.io/e2e-test-images/jessie-dnsutils:1.3
command:
- sleep
- "infinity"
securityContext:
capabilities:
add:
- NET_RAW
imagePullPolicy: IfNotPresent
restartPolicy: Always
[master]# kubectl create -f dnsutils.yaml -n default
[master]# kubectl get podils.yaml -n default
[master]# kubectl get pod
#----------------------------------------------------
# S3-2. Ping
#----------------------------------------------------
[master]# kubectl exec -it dnsutils /bin/sh
/# ping kubernetes.default
/# ping default.svc.cluster.localster.local
#----------------------------------------------------
# S3-3. 確認是否有將namespace的svc內容打入環境變數
#----------------------------------------------------
[master]# kubectl exec -it dnsutils -n default -- env | grep KUBERNETESRNETES
#----------------------------------------------------
# S3-4. nslookup
#----------------------------------------------------
/# nslookup kubernetes.default
/# nslookup default.svc.cluster.local
;; connection timed out; no servers could be reachedbe reached
#----------------------------------------------------
# S3-5. 確認coredns pod status
#----------------------------------------------------
[master]# kubectl get pods -l k8s-app=kube-dns -n kube-system
=> 均為Running狀態unning狀態
#----------------------------------------------------
# S3-6. 確認coredns pod logs
#----------------------------------------------------
[master]# for p in $(kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o name); do kubectl logs --namespace=kube-system $p; done
=> 沒有錯誤訊息
=> 以下會出現較多訊息的原因是在"kubectl edit configmap coredns -n kube-system" 加入log參數 加入log參數
#----------------------------------------------------
# S3-7. 確認endpoint and pod binding
#----------------------------------------------------
[master]# kubectl get pods -l k8s-app=kube-dns -n kube-system -o wide
[master]# kubectl get endpoints kube-dns -n kube-systeme-system
#----------------------------------------------------
# S3-8. 確認是否為"Pod本身解析" or "Pod ok,但請求送到kube-dns無法轉發"
# 直接修改/etc/resolv.conf的nameserver換成別的
#----------------------------------------------------
Pod /etc/resolv.conf => 指向10.86.0.10 (Service “kube-dns” 的 cluterIP)
[lb01]# kubectl exec -it dnsutils /bin/sh
/# vi /etc/resolv.conf
nameserver 8.8.8.8
/# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=56 time=2.774 ms
64 bytes from 8.8.8.8: seq=1 ttl=56 time=2.571 ms
64 bytes from 8.8.8.8: seq=2 ttl=56 time=2.625 ms
64 bytes from 8.8.8.8: seq=3 ttl=56 time=2.512 ms
/# ping www.google.com
ping: bad address 'www.google.com'address 'www.google.com'
#----------------------------------------------------
# S3-9. 確認kube-proxy是否有問題
#----------------------------------------------------
[master]# kubectl logs kube-proxy-6kdj2 --tail=5 -n kube-system
=> 確認是否有error是否有error
根據以下流程圖,可以發現Pod會先往CoreDNS(10.96.0.10)查詢,然後再轉送到外部進行解析。
#--------------------------------------------
# S3-10. 確認Pod是否可以正確轉送到外部解析
#--------------------------------------------
[master]# kubectl exec -it nginx-quic-deployment-c5f8b8b44-8hwm9 -- bash
/# yum updatem update
最後請注意,在Pod內能Ping的IP不能是Service的Cluster IP,它是Virtual IP,如果要Ping其他服務IP時,請照以下方式:
master]# kubectl describe pod <pod_name> => find IP
[master]# kubectl exec -it nginx-quic-deployment-c5f8b8b44-8hwm9 -- bash
/# ping 192.168.35.935.9
終於完成關於DNS解析的文章,當初看了非常多文件來了解到底Kubernetes內部名稱解析在做些什麼事,從以上文章可以了解到許多服務之間的溝通真的非常依賴CoreDNS,所以了解CoreDNS的運作方式,對於想要管理K8S cluster的管理者是至關重要的。
最後如果現在是使用Kube-dns方案的Cluster,官方在升級K8S時提供一個轉換成CoreDNS的支援,參考網址如下:
References: