为了能高效的训练机器学习模型,最近在调研kubeflow结合kubernetes实现模型的多机多卡分布式训练,在部署kubeflow环境时,用到了kube-dns这个组件,便准备深入的了解下kube-dns的安装及原理。

DNS 介绍

DNS 为域名系统(Domain Name System)的缩写。DNS是一种组织成域层结构的计算机和网络服务命名系统,用于TCP/IP网络,主要用来寻找Internet域名 (如www.baidu.com) 并转化为IP地址 (如:10.1.1.1) 以定位相应的计算机和服务。

关于DNS原理的介绍,请看阮老师的: DNS 原理入门

kube-dns 介绍

kubernetes DNS 的主要作用是为集群提供一种服务发现机制,让集群中的DNS Pod通过访问Service Name的方式去访问目标期望的Pod服务。

  • 如果访问的Service Name是正常的,则DNS pod会解析/etc/resolv.conf文件找到DNS Server,并获取Service Name对用的IP记录。通过这个IP记录去访问该IP(Service Cluster IP)下的某一个具体的Pod IP。
  • 如果访问的Service Name是Headless Service,同样DNS Pod会解析/etc/resolv.conf文件找到DNS Server,但是会被直接解析到该Service下的某一个指定的Pod IP。

当前kuberntes支持的DNS格式:

  • Service
    • A record: 生成my-svc.my-namespace.svc.cluster.local,解析IP分为两种情况
      • 普通的Service 解析为Cluster IP
      • Headless Service 解析为指定的Pod IP列表
  • Pod
    • A record: pod-ip-address.my-namespace.pod.cluster.local
    • 指定 hostname 和 subdomain: hostname.custom-subdomain.default.svc.cluster.local

关于 kube-dns 的详细内容: DNS for Services and Pods
关于 Service 的详细内容: Service

kube-dns 安装

官方安装文档: kube-dns

下载kube-dns.yaml文件,并修改文件中的$DNS_SERVER_IP$DNS_DOMAIN参数:

1
2
3
4
# wget https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/dns/kube-dns/kube-dns.yaml.sed -O kube-dns.yaml

# sed -i 's/$DNS_SERVER_IP/192.168.0.2/gi' kube-dns.yaml
# sed -i 's/$DNS_DOMAIN/cluster.local/gi' kube-dns.yaml

同时需要将kubernetes集群中所有的计算节点的kubelet配置增加如下两个参数:

  • cluster-dns: DNS服务器IP(如:192.168.0.2)
  • cluster-domain: 设置成cluster.local即可。

当上面的准备工作完成之后,开始创建kube-dns服务,并检查服务是否正常启动:

1
2
3
4
# kubectl create -f kube-dns.yaml
# kubectl get deployment -n kube-system
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
kube-dns 1 1 1 1 2d7h

ok, kube-dns 启动成功后,kube-dns Pod中会包含3个容器:

  • kube-dns: kube-dns 进程监视 kubernetes master中的Service和Endpoint的变化,并维护内存查找结构来服务DNS请求。
  • dnsmasq: dnsmasq 容器添加DNS缓存以提高性能。
  • healthz: healthz 容器在执行双重健康检查(针对dnsmasqkube-dns)时提供单个健康检查端点。

验证kube DNS 服务

当kube-dns服务创建成功之后,验证kube DNS服务是否能正常工作。

1.根据dp.yaml文件创建一个deployment资源对象,并检查服务是否创建成功:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: ngnix-deployment-15
spec:
revisionHistoryLimit: 3
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
1
2
3
4
5
6
7
8
9
# kubectl  create -f dp.yaml 
deployment "ngnix-deployment-15" created
# kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
ngnix-deployment-15 2 2 2 2 101s
# kubectl get pods
NAME READY STATUS RESTARTS AGE
ngnix-deployment-15-55bd7c9fd-bm5vg 1/1 Running 0 101s
ngnix-deployment-15-55bd7c9fd-lz75v 1/1 Running 0 101s

2.根据svc.yaml文件创建service资源对象,并检查服务是否创建成功:

1
2
3
4
5
6
7
8
9
10
11
12
kind: Service
apiVersion: v1
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
1
2
3
4
5
6
# kubectl  create -f svc.yaml 
service "nginx-service" created
# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 192.168.0.1 <none> 443/TCP 3d4h
nginx-service ClusterIP 192.168.212.156 <none> 80/TCP 11s

当deployment和service创建成功之后,进入一个容器中查看/etc/resolv.conf文件是否生效:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# kubectl  exec -it ngnix-deployment-15-55bd7c9fd-bm5vg bash
root@ngnix-deployment-15-55bd7c9fd-bm5vg:/# cat /etc/resolv.conf
nameserver 192.168.0.2
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

root@ngnix-deployment-15-55bd7c9fd-bm5vg:/# nslookup kubernetes.default
Server: 192.168.0.2
Address: 192.168.0.2#53

Name: kubernetes.default.svc.cluster.local
Address: 192.168.0.1

root@ngnix-deployment-15-55bd7c9fd-bm5vg:/# curl http://kubernetes:443


ok,接下来我们创建另一个pod,并通过这个pod以Service Name的方式去访问名称为: ngnix-deployment-15-55bd7c9fd-bm5vg 的Pod,看看是否能通:

pod.yaml测试文件:

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80

查看pod是否创建成功,如果成功,则进入到容器中,通过该容器访问关联在另一个Service下的Pod:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# kubectl  get pods
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 4s
# kubectl exec -it nginx bash
root@nginx:/# cat /etc/resolv.conf
nameserver 192.168.0.2
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

oot@nginx:/# curl http://nginx-service:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

ok,一切正常:)

参考