前幾天,在ucloud上搭建的k8s集羣(搭建教程後續會發出)。今天發現域名解析不了。前端
組件版本:k8s 1.15.0,coredns:1.3.1java
首先用如下yaml文件建立了一個nginx服務python
apiVersion: v1 kind: Service metadata: name: nginx-svc-old labels: app: nginx-svc spec: selector: app: nginx ports: - protocol: TCP port: 80 targetPort: 80 --- apiVersion: apps/v1beta1 kind: Deployment metadata: name: nginx-old spec: replicas: 1 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80
建立好以後:
因只部署了一個master節點。在master宿主機上直接執行如下命令:nginx
nslookup nginx-svc-old.default.svc
發現不能解析域名。事先也在宿主機上/etc/resolv.conf裏配置了nameserver {coredns的podIP}
這樣一來,就覺得多是coredns有問題。。git
而後用如下yaml建立了一個busybox做爲調試工具:github
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: busybox-deployment spec: replicas: 1 template: metadata: labels: app: busybox spec: restartPolicy: Always containers: - name: busybox command: - sleep - "3600" image: busybox
這裏用的是截止2019/07/20,busybox的最新鏡像。建立好以後,exec進入容器,執行測試命令
發現解析不了:面試
/ # nslookup nginx-svc-old.default.svc Server: 10.96.0.10 Address: 10.96.0.10:53 ** server can't find nginx-svc-old.default.svc: NXDOMAIN *** Can't find nginx-svc-old.default.svc: No answer
根據coredns解析集羣內域名原理可知:spring
服務 a 訪問服務 b,對於同一個 Namespace下,能夠直接在 pod 中,經過 curl b 來訪問。對於跨 Namespace 的狀況,服務名後邊對應 Namespace便可,好比 curl b.default。DNS 如何解析,依賴容器內 resolv 文件的配置。docker
查看busybox容器內的resolve.conf文件:編程
[root@liabio nginx]# kubectl exec -ti busybox-deployment-59755c8c6d-rmrfq sh / # nslookup nginx-svc-old.default.svc Server: 10.96.0.10 Address: 10.96.0.10:53 ** server can't find nginx-svc-old.default.svc: NXDOMAIN *** Can't find nginx-svc-old.default.svc: No answer / # cat /etc/resolv.conf nameserver 10.96.0.10 search default.svc.cluster.local svc.cluster.local cluster.local options ndots:5 / #
這個文件中,配置的 DNS Server,通常就是 K8S 中,kubedns 的 Service 的 ClusterIP,這個IP是虛擬IP,沒法ping,但能夠訪問。
在容器內發請求時,會根據 /etc/resolv.conf 進行解析流程。選擇 nameserver 10.96.0.10 進行解析,而後用nginx-svc-old ,依次帶入 /etc/resolve.conf 中的 search 域,進行DNS查找,分別是:
search 內容相似以下(不一樣的pod,第一個域會有所不一樣)
search default.svc.cluster.local svc.cluster.local cluster.local
nginx-svc-old.default.svc.cluster.local -> nginx-svc-old.svc.cluster.local -> nginx-svc-old.cluster.local
直到找到爲止。因此,咱們執行 ping nginx-svc-old,或者執行 ping nginx-svc-old.default,均可以完成DNS請求,這2個不一樣的操做,會分別進行不一樣的DNS查找步驟。
根據以上原理,查看到busybox內的域名/etc/resolv.conf沒有問題,nameserver指向正確的kube-dns的service clusterIP。
這下更加懷疑core-dns有問題了。
但查看coredns日誌,能夠看到並無報錯:
那就說明不是coredns問題了。。
把busybox裏報的錯誤,進行搜索google
*** Can't find nginx-svc-old.default.svc: No answer
查到了如下兩個issue:
https://github.com/kubernetes...
https://github.com/easzlab/ku...
發現都說是busybox鏡像的問題,從1.28.4之後的鏡像都存在這問題。把鏡像換成1.28.4試試?修改yaml版本號:
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: busybox-deployment spec: replicas: 1 template: metadata: labels: app: busybox spec: restartPolicy: Always containers: - name: busybox command: - sleep - "3600" image: busybox:1.28.4
從新apply後,進入容器:
確實能夠成功解析域名了。
那爲何宿主機上直接執行測試命令,域名不能解析呢?
繼續google,知道resolver域名解析器:
nameserver關鍵字,若是沒指定nameserver就找不到DNS服務器,其它關鍵字是可選的。nameserver表示解析域名時使用該地址指定的主機爲域名服務器。其中域名服務器是按照文件中出現的順序來查詢的,且只有當第一個nameserver沒有反應時才查詢下面的nameserver,通常不要指定超過3個服務器。
而我在宿主上/etc/resolv.conf中nameserver以下:
且前三個域名解析服務器後能夠通。
如今試着把coredns的其中一個podIP:192.168.155.73放到第一個nameserver:
能夠看到如今能夠解析了。
其實最好把kube-dns service的clusterIP放到/etc/resolv.conf中,這樣pod重啓後也能夠解析。
Linux中/etc/resolv.conf文件簡析
https://blog.csdn.net/lcr_hap...
CoreDNS系列1:Kubernetes內部域名解析原理、弊端及優化方式
https://hansedong.github.io/2...
本公衆號免費提供csdn下載服務,海量IT學習資源,若是你準備入IT坑,勵志成爲優秀的程序猿,那麼這些資源很適合你,包括但不限於java、go、python、springcloud、elk、嵌入式 、大數據、面試資料、前端 等資源。同時咱們組建了一個技術交流羣,裏面有不少大佬,會不定時分享技術文章,若是你想來一塊兒學習提升,能夠公衆號後臺回覆【2】,免費邀請加技術交流羣互相學習提升,會不按期分享編程IT相關資源。
掃碼關注,精彩內容第一時間推給你