环境准备

  • 下载k8s包
    https://dl.k8s.io/v1.6.4/kubernetes.tar.gz

  • 解压
    解压后在kubernetes/cluster/addons/dns目录下有kubedns的部署文件

文件说明

  • kubedns-cm.yaml和kubedns-sa.yaml
    kubedns-cm.yaml和kubedns-sa.yaml无须修改,直接使用。

  • kubedns-svc.yaml
    kubedns-svc.yaml有三种类型的模板文件,我们使用kubedns-svc.yaml.sed文件来生成kubedns-svc.yaml文件,替换$DNS_SERVER_IP为指定K8s DNS IP(默认为apiserver ip 加 1,即apiserver中的clusterip),我们使用169.169.0.2。
    cp kubedns-svc.yaml.sed kubedns-svc.yaml
    sed -i 's/$DNS_SERVER_IP/169.169.0.2/g' kubedns-svc.yaml

  • kubedns-controller.yaml
    kubedns-controller.yaml有三种类型的模板文件,我们使用kubedns-controller.yaml.sed文件来生成kubedns-controller.yaml文件,替换$DNS_DOMAIN为cluster.local.(在与kube-apiserver定义的一致)。
    cp kubedns-controller.yaml.sed kubedns-controller.yaml
    sed -i 's/$DNS_DOMAIN/cluster.local./g' kubedns-controller.yaml

启动kubedns服务

  • kubectl create -f kubedns-cm.yaml
  • kubectl create -f kubedns-sa.yaml
  • kubectl create -f kubedns-svc.yaml
  • kubectl create -f kubedns-controller.yaml

启动报错

查看dns报错的方式

  • describe镜像
  • kubectl logs
* kubectl logs -n kube-system  kube-dns-5b58959c58-jfx6w -c kubedns
* kubectl logs -n kube-system kube-dns-5b58959c58-jfx6w  -c sidecar
* kubectl logs -n kube-system kube-dns-5b58959c58-jfx6w  -c dnsmasq

下载镜像失败

通过kubectl describe发现报错为Failed to pull image "gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.14.1": rpc error: code = 2 desc = Get https://gcr.io/v1/_ping: dial tcp 108.177.125.82:443: i/o timeout
* docker pull registry.cn-beijing.aliyuncs.com/yzx/k8s-dns-kube-dns-amd64:1.14.1
* docker tag registry.cn-beijing.aliyuncs.com/yzx/k8s-dns-kube-dns-amd64:1.14.1 gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.14.1
* docker pull registry.cn-beijing.aliyuncs.com/yzx/k8s-dns-dnsmasq-nanny-amd64:1.14.1
* docker tag registry.cn-beijing.aliyuncs.com/yzx/k8s-dns-dnsmasq-nanny-amd64:1.14.1 gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64:1.14.1
* docker pull registry.cn-beijing.aliyuncs.com/yzx/k8s-dns-sidecar-amd64:1.14.1
* docker tag registry.cn-beijing.aliyuncs.com/yzx/k8s-dns-sidecar-amd64:1.14.1 gcr.io/google_containers/k8s-dns-sidecar-amd64:1.14.1

启动报错,分别查看三个容器报错

  • 查看kubedns报错
[root@k8s-master yaml]# kubectl logs -n kube-system --tail=20 kube-dns-5b58959c58-jfx6w -c kubedns
I1111 14:41:28.703893       1 dns.go:49] version: v1.5.2-beta.0+$Format:%h$
F1111 14:41:28.704003       1 server.go:57] Failed to create a kubernetes client: open /var/run/secrets/kubernetes.io/serviceaccount/token: no such file or directory

解决方案:
* apiserver的配置中添加ServiceAccount
* 在controller-manager的配置中添加--root-ca-file=/run/kubernetes/apiserver.crt --service-account-private-key-file=/run/kubernetes/apiserver.key
* 重启apiserver 和 controller-manager
* 重新创建kubedns-sa.yaml和kubedns-controller.yaml

参考:http://dockone.io/question/1412

修改kubelet启动参数

  • kubelet启动参数添加--cluster-dns=169.169.0.2 --cluster-domain=cluster.local
  • 进入某个pod中的容器内查看其/etc/resolv.conf文件
   root@jekins:~# cat /etc/resolv.conf 
   nameserver 10.254.0.2
   search default.svc.cluster.local svc.cluster.local cluster.local
   options ndots:5

如上所示,根据kubelet的启动参数,kubelet会在每个pod中设置DNS域名解析文件/etc/resolv.conf,加入了nameser和search搜索域。最后应用程序就能够像访问网站一样,仅仅通过服务的名字就能访问到服务了。

  • 重新创建pod
  • 在pod中ping服务名已能解析,但是网络不通
root@nginx-deployment-5487769f48-fq6hn:/# ping nginx-service
PING nginx-service.default.svc.cluster.local (169.169.201.158): 48 data bytes

dns解析的为service名,service和pod仅通过label关联,所以service name和与之关联的pod name不一定相同

dns正常网络不通问题

1. 未安装flannel网络服务,多节点间不通

详见 k8s集群搭建之网络处理

2. bad address 'nginx'

[root@localhost deployment]# kubectl exec -it busybox-786cfc6cb7-6trsz sh
/ # wget nginx
wget: bad address 'nginx'

重新创建dns-controller

3. Could not resolve host: nginx

参考

  • k8s node节点上的kube-proxy调整参数,添加proxy-mode=iptables
KUBE_PROXY_ARGS="--master=http://10.254.0.53:8080 --logtostderr=false --log-dir=/var/log/kubernetes --v=2 --proxy-mode=iptables "
  • 重启kube-proxy
  • 重新生成 deployment
  • 重新生成service
  • 若仍不通,则参考文档中在配置文件proxy中添加 --cluster-cidr=169.169.0.0/16
  • 若仍存在问题则执行在node节点上iptables -nvL然后执行iptables -P KUBE-FIREWALL ACCEPT 设置接受
  • 1master 1node时可通过service name连接服务,多node时不可调用

发现去掉proxy-mode=iptables,通过wget仍能够联调其它service

引用1
引用2

4. Failed to list *v1.Endpoints: Unauthorized

kubectl logs kube-dns-5b58959c58-rwzcg -n kube-system kubedns报错

E1118 16:04:24.248560       1 reflector.go:199] k8s.io/dns/vendor/k8s.io/client-go/tools/cache/reflector.go:94: Failed to list *v1.Service: Unauthorized
E1118 16:04:24.250134       1 reflector.go:199] k8s.io/dns/vendor/k8s.io/client-go/tools/cache/reflector.go:94: Failed to list *v1.Endpoints: Unauthorized
I1118 16:04:24.558926       1 dns.go:174] DNS server not ready, retry in 500 milliseconds
F1118 16:04:25.058985       1 dns.go:168] Timeout waiting for initialization

重新创建sa和controller-manager
参考kube-system下的pod只能通过kube-system下的sa请求apiserver

5. 如果容器网络包括访问service ip是正常的,并且dns容器也启动正常

查看kubelet中配置的--cluster-dns是否为dns容器对应的service ip

目前除了 kube-dns的方案还有一个coredns的方案,待以后研究