作者 | 江小南
来源 | 江小南和他的小伙伴们
引言
说到DNS域名解析,大家想到最多的可能就是/etc/hosts
文件,并没有什么错,但是/etc/hosts
只能做到本机域名解析,如果跨机器的解析就有点捉襟见肘了。
在服务器中还有一个配置值得大家注意,/etc/resolv.conf
,这个文件用于配置DNS服务器,使域名解析可以扩展到本机以外。
kubernetes集群使用到的就是这种机制。
原理
当kubernetes初始化完成后,在kube-system名称空间下会出现kube-dns的service服务与coredns的pod。
[root@k8s-master etc]# kubectl get svc -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 14d
[root@k8s-master etc]# kubectl get pod -n kube-system -o wide| grep coredns
coredns-5897cd56c4-7ps2n 1/1 Running 9 14d 192.168.235.220 k8s-master <none> <none>
coredns-5897cd56c4-j7psj 1/1 Running 9 14d 192.168.235.221 k8s-master <none> <none>
[root@k8s-master etc]#
CoreDNS是一个DNS解析的组件,作为集群内的DNS服务器,为集群内部提供域名解析服务。比如说一个前端pod要通过service name访问后端pod,前端pod会先通过自身的dns文件(/etc/resolv.conf)指向dns服务器,由dns服务器做域名解析转换成对用的ip,然后通过ip访问到后端pod。
配置策略
在yaml中,通过dnsPolicy
字段配置DNS策略,共有4种策略:
ClusterFirst:默认策略,表示使用集群内部的CoreDNS来做域名解析。
Default:Pod直接继承集群node节点的域名解析配置,也就是,Pod会直接使用宿主机上的/etc/resolv.conf文件内容。
None:忽略k8s集群环境中的DNS设置,Pod会使用其dnsConfig字段所提供的DNS配置。
ClusterFirstWithHostNet:宿主机与 Kubernetes 共存,这种情况下的POD,既能用宿主机的DNS服务,又能使用kube-dns的Dns服务,注意的是需要将hostNetwork打开。
部署验证
首先说明一点,CoreDNS本身具有解析集群外域名的能力,但是集群外的DNS服务器并不一定具有解析集群内域名的能力。基于这个认识,我们做下列的测试。
ClusterFirst
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginx-deployname: nginx-deploy
spec:replicas: 2selector:matchLabels:app: nginx-deploytemplate:metadata:labels:app: nginx-deployspec:restartPolicy: Alwayscontainers:- name: mynginximage: nginximagePullPolicy: IfNotPresentdnsPolicy: ClusterFirst
[root@k8s-master test]# kubectl apply -f deployment.yaml
deployment.apps/nginx-deploy created
[root@k8s-master test]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deploy-6d79d74f76-qp8pr 1/1 Running 0 77s
nginx-deploy-6d79d74f76-tjcxt 1/1 Running 0 77s
[root@k8s-master test]#
# 进入到容器内部
[root@k8s-master test]# kubectl exec -it nginx-deploy-6d79d74f76-qp8pr -c mynginx -- /bin/bash
root@nginx-deploy-6d79d74f76-qp8pr:/# cat /etc/resolv.conf
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local pek3.qingcloud.com
options ndots:5
root@nginx-deploy-6d79d74f76-qp8pr:/#
# 访问service成功
root@nginx-deploy-6d79d74f76-qp8pr:/# curl nginx-deploy.default.svc:8000
<!DOCTYPE html>
<html>
...
<body>
<h1>Welcome to nginx!</h1>
...
</body>
</html>
root@nginx-deploy-6d79d74f76-qp8pr:/#
可以发现NDS服务器为10.96.0.10
,这个地址我们在上面原理部分获取到的kube-dns
的地址一致。说明ClusterFirst的策略使用集群内部的CoreDNS来做域名解析,并且成功解析了service域名。
Default
将yaml中的dnsPolicy: ClusterFirst
修改为dnsPolicy: Default
。
[root@k8s-master test]# kubectl apply -f deployment.yaml
deployment.apps/nginx-deploy created
[root@k8s-master test]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deploy-85bd9d5f4c-js6fv 1/1 Running 0 5s
nginx-deploy-85bd9d5f4c-q8pxb 1/1 Running 0 5s
[root@k8s-master test]#
# 进入到容器内部
[root@k8s-master test]# kubectl exec -it nginx-deploy-85bd9d5f4c-js6fv -c mynginx -- /bin/bash
root@nginx-deploy-85bd9d5f4c-js6fv:/# cat /etc/resolv.conf
nameserver 100.64.9.5
search pek3.qingcloud.com
root@nginx-deploy-85bd9d5f4c-js6fv:/#
# 查看本机的 /etc/resolv.conf
[root@k8s-master test]# cat /etc/resolv.conf
# Generated by NetworkManager
search pek3.qingcloud.com
nameserver 100.64.9.5
[root@k8s-master test]#
# 访问service不成功
root@nginx-deploy-85bd9d5f4c-js6fv:/# curl nginx-deploy.default.svc:8000
curl: (6) Could not resolve host: nginx-deploy.default.svc
root@nginx-deploy-85bd9d5f4c-js6fv:/#
# 访问百度成功
root@nginx-deploy-85bd9d5f4c-js6fv:/# curl www.baidu.com
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn"></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必读</a> <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a> 京ICP证030173号 <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>
root@nginx-deploy-85bd9d5f4c-js6fv:/#
说明使用Default策略,Pod会直接使用宿主机上的/etc/resolv.conf文件内容,当然解析service域名是不能成功的。
None
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginx-deployname: nginx-deploy
spec:replicas: 2selector:matchLabels:app: nginx-deploytemplate:metadata:labels:app: nginx-deployspec:restartPolicy: Alwayscontainers:- name: mynginximage: nginximagePullPolicy: IfNotPresentdnsPolicy: NonednsConfig:nameservers: ["172.31.0.3","172.31.0.4"]searches:- default.svc.cluster.local- svc.cluster.local- cluster.localoptions:- name: ndotsvalue: "5"
[root@k8s-master test]# kubectl apply -f deployment.yaml
deployment.apps/nginx-deploy created
[root@k8s-master test]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deploy-6699fcc589-7nrn7 1/1 Running 0 7s
nginx-deploy-6699fcc589-8sk8p 1/1 Running 0 7s
[root@k8s-master test]#
# 进入到容器内部
[root@k8s-master test]# kubectl exec -it nginx-deploy-6699fcc589-7nrn7 -c mynginx -- /bin/bash
root@nginx-deploy-6699fcc589-7nrn7:/# cat /etc/resolv.conf
nameserver 172.31.0.3
nameserver 172.31.0.4
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
root@nginx-deploy-6699fcc589-7nrn7:/#
说明None策略Pod会使用其dnsConfig字段所提供的DNS配置。nameserver最多可配置3个ip。域名解析能力视DNS服务器的解析能力而定。
ClusterFirstWithHostNet
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginx-deployname: nginx-deploy
spec:replicas: 2selector:matchLabels:app: nginx-deploytemplate:metadata:labels:app: nginx-deployspec:restartPolicy: Alwayscontainers:- name: mynginximage: nginximagePullPolicy: IfNotPresentdnsPolicy: ClusterFirstWithHostNethostNetwork: true
[root@k8s-master test]# kubectl apply -f deployment.yaml
deployment.apps/nginx-deploy created
[root@k8s-master test]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deploy-74bd47ccdd-cjbmv 1/1 Running 0 4s
nginx-deploy-74bd47ccdd-m6bm6 1/1 Running 0 4s
[root@k8s-master test]#
[root@k8s-master test]# kubectl exec -it nginx-deploy-74bd47ccdd-cjbmv -c mynginx -- /bin/bash
root@k8s-worker2:/# cat /etc/resolv.conf
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local pek3.qingcloud.com
options ndots:5
root@k8s-worker2:/#
# 访问service成功
root@k8s-worker2:/# curl nginx-deploy.default.svc:8000
<!DOCTYPE html>
<html>
...
<body>
<h1>Welcome to nginx!</h1>
...
</html>
root@k8s-worker2:/#
# 访问百度成功
root@k8s-worker2:/# curl www.baidu.com
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn"></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必读</a> <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a> 京ICP证030173号 <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>
root@k8s-worker2:/#
能同时访问service和百度,说明此配置既能使用集群内部的CoreDNS来做域名解析,又可以使用宿主机的DNS做域名解析。
注意点:我们有时也会看到如下的配置。
dnsPolicy: ClusterFirst
hostNetwork: true
hostNetwork表示与宿主机共享网络空间。但是只有dnsPolicy: ClusterFirstWithHostNet时生效。而此处配置的ClusterFirst由于打开了hostNetwork为true,会自动转换为Default,那么此时解析集群内的域名是不能成功的。
往期推荐
Docker 那些事儿:如何安全地停止、删除容器?
容器跑不动网络可不背锅!
云原生时代,开发者应具备这5大能力
实战 Kubectl 创建 Deployment 部署应用
点分享
点收藏
点点赞
点在看