kube-dns配置注意及問題排查
基礎的k8s集群可以通過flannel的網絡ip地址工作,但要擴展addons的service,都要通過域名來連通,因為各個鏡像的配置文件中是不可能把ip寫死在文件中的,但域名是可以不變的。因此,一個k8s集群中kube-dns的配置是必要的。
下面介紹配置kube-dns,需要注意的地方,驗證及問題排查過程。
在/etc/resolv.conf文件中配置短域補齊,比如cluster.local,這里必須要與skydns-rc.yaml.sed文件中的domain參數一致。
1、看kube-dns的pod內3個容器是否全部running
kubectl get pods --namespace=kube-system -l k8s-app=kube-dns
2、如果全部running,看日志是否有異常
可以通過命令,也可以通過kube dashboard。
3、若日志無明顯異常,驗證healthz是否能夠解析完整域和短域
完整域
kubectl exec -n kube-system -ti kube-dns-v20-xxxxx -c healthz -- nslookup kube-dns.kube-system.svc.cluster.local
短域
kubectl exec -n kube-system -ti kube-dns-v20-xxxxx -c healthz -- nslookup kube-dns
4、如果完整域可以解析,短域不可以解析
查看/etc/resolv.conf文件,是否補齊cluster.local
kubectl exec -n kube-system -ti kube-dns-v20-xxxxx -c healthz cat /etc/resolv.conf
一般文件內容為:
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 172.17.26.52 #kube-dns service clusterIp
options ndots:5
這個是從宿主機的/etc/resolv.conf文件中繼承的。
這些都可以通過官網doc可以查看到Troubleshooting Tips
5、在node上的修改
修改/etc/kubernetes/kubelet文件:
KUBELET_ARGS="--cluster-dns=172.17.26.52 --cluster-domain=cluster.local --log_dir=/var/log/kubernetes"
修改之后要重啟kubelet
systemctl restart kubelet
修改宿主機的/etc/resolv.conf:
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 172.17.26.52 #kube-dns service clusterIp
5、遇到的問題,這里也比較關鍵
<1>、手動指定的clusterIp不能解析
在實際操作中,由于kube-dns的特殊性,需要手動指定kube-dns service的clusterIp(在各種“教程”中全都在說手動指定,他們竟然都沒遇到問題),然后創建svc,結果使用healthz的nslookup驗證時卻不能解析。
幸好suzhen經驗豐富,嘗試把clusterIp注釋掉,讓k8s自動為kube-dns分配一個ip。然后再手動指定這個ip,重新創建svc。或者直接拿這個ip用就可以了。
按道理說指定的clusterIp在k8s限定的范圍之內都是可以的,但是不知道隨機指定了一個ip就不行。。。就這么不巧。。。具體原因目前還不清楚。
<2>、命令可解析,healthz自帶的參數不能解析
這個問題也是非常詭異的,把healthz的cmd參數單獨拿出來用命令解析可以,但是它自己卻不能解析,命令一模一樣,完全沒道理。。。
命令:
kubectl exec -n kube-system -ti kube-dns-v20-xxxxx -c healthz -- nslookup kubernetes.default.svc.cluster.local 127.0.0.1
日志:
can't resolve "kubernetes.default.svc.cluster.local"
healthz是負責dns的健康的,根據創建rc時的yaml文件,healthz容器定時向kubedns容器查詢
kubernetes.default.svc.cluster.local 127.0.0.1及kubernetes.default.svc.cluster.lcoal 127.0.0.1:10053,
即(因為這個奇怪的問題把原args都注釋了,暫時這樣解決了):
- name: healthz
image: gcr.io/google_containers/exechealthz-amd64:1.2
...
args:
#- --cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1 >/dev/null
- --cmd=ping 127.0.0.1
#- --url=/healthz-dnsmasq
#- --cmd=nslookup kubernetes.default.svc.cluster.lcoal 127.0.0.1:10053 >/dev/null
#- --url=/healthz-kubedns
#- --port=8080
#- --quiet
如果一段時間healthz一直解析不過,就會發送一個terminated信號給kubedns,這時即使kubedns本身正常(可以通過kubedns直接執行nslookup進行解析驗證),也會自毀,此時該pod就會變的不正常。
<3>、BTW
官網太簡單,網上教程太雜,經驗很重要,謹慎。
附skydns-rc.yaml.sed修改的地方:
spec:
#nodeName: k8s-nod5
containers:
- name: kubedns
image: gcr.io/google_containers/kubedns-amd64:1.8
...
args:
# command = "/kube-dns"
- --domain=cluster.local.
- --dns-port=10053
- --kube-master-url=http://100.101.69.252:8080
...
- name: healthz
image: gcr.io/google_containers/exechealthz-amd64:1.2
...
args:
#- --cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1 >/dev/null
- --cmd=ping 127.0.0.1
#- --url=/healthz-dnsmasq
#- --cmd=nslookup kubernetes.default.svc.cluster.lcoal 127.0.0.1:10053 >/dev/null
#- --url=/healthz-kubedns
#- --port=8080
#- --quiet