
背景
近期接触的微服务项目是基于DNS实现服务的注册与发现,整体项目半容器化。如项目全部容器化并迁移至kubernetes集群,假设在不使用kubernetes集群中的DNS做服务注册与发现的前提下,引出一个思考——Kubernetes集群中是如何解析外部域名的?
kubernetes DNS简述
Kuberentes通过将Service注册到DNS中,可以为我们提供一种简单的服务注册发现与负载均衡方式。
CoreDNS是第四个从CNCF毕业的项目,是一个通用、权威的DNS服务,从Kubernetes 1.11版本开始正式GA,替代KubeDNS成为默认的DNS,CoreDNS提供与Kubernetes后向兼容且可扩展的集成。它解决了kube-dns所遇到的问题,并提供了许多独特的功能,可以解决各种各样的用例。kube-dns和CoreDNS的差异可以去社区了解下。
Kubernetes中域名是如何解析的
Kubernetes内部域名解析,依赖容器内resolv.conf文件的配置。Pod运行后,kubelet会自动在容器中创建域名解析配置。
# cat /etc/resolv.conf
nameserver 10.254.0.2
search default.svc.cluster.local. svc.cluster.local. cluster.local.
options ndots:5
#
配置中DNS Server是CoreDNS的ClusterIP,在容器内,会根据resolve.conf配置进行解析,例如有一个nginx的service,DNS解析时用字符'nginx'依次带入resolve.conf中的 search 域,进行DNS查找,即
nginx.default.svc.cluster.local -> nginx.svc.cluster.local -> nginx.cluster.local ,直到找到为止。
配置中ndots:5表示如果查询的域名包含的点".",在Kubernetes中默认值为5,是因为Kubernetes认为内部域名最长为5,要保证内部域名的请求优先走集群内部的DNS,而不是将内部域名的DNS解析请求有外网的机会,ndots的值为5是一个比较合理的值。
| <5 | 先走search域,最后将其视为绝对域名进行查询 |
| >=5 | 直接视为绝对域名进行查找,只有当查询不到的时候,才继续走search域 |
对于跨Namespace的情况,服务名后边对应Namespace即可,如edgecontroller.kubeedge
/ # nslookup edgecontroller.kubeedge
Server: 10.254.0.2
Address 1: 10.254.0.2 kube-dns.kube-system.svc.cluster.local
Name: edgecontroller.kubeedge
Address 1: 10.254.67.34 edgecontroller.kubeedge.svc.cluster.local
/ #
~ # curl https://edgecontroller.kubeedge:10000 -k
404 page not found
~ #
所以在同个Namespace下,执行 curl nginx,或者执行 curl nginx.default,都可以完成DNS请求:
~ # curl nginx
Welcome to nginx
~ #
~ # curl nginx.default
Welcome to nginx
~ #
这2个不同的操作,会分别进行不同的DNS查找步骤:
#curl nginx ,可以一次性找到(nginx + default.svc.cluster.local)
nginx.default.svc.cluster.local
#curl nginx.default,第一次找不到( nginx.default + default.svc.cluster.local)
nginx.default.default.svc.cluster.local
#第二次查找( nginx.default + svc.cluster.local),可以找到
nginx.default.svc.cluster.local
So,curl nginx要比curl nginx.default效率高,当执行带有Namespace的内部域名时,容器的第一个DNS请求是default.svc.cluster.local。
Kubernetes中外部域名走search域吗
以请求www.baidu.com为例,通过抓包的方式,看一看在某个容器中访问www.baidu.com,进行的DNS查找的过程,都产生了什么样的数据包。
#1、找到DNS容器ID,并打印它的NS ID
docker ps | grep k8s_coredns | awk '{print $1}' | xargs docker inspect --format "{{.State.Pid}}"
#2、进入此容器的网络Namespace
nsenter -n -t 54438
#3、抓DNS包
[root@kube-master ~]# tcpdump -i eth0 udp dst port 53|grep baidu
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
15:40:01.105204 IP 192.168.59.2.46993 > kube-master.domain: 3+ AAAA? www.baidu.com. (31)
15:40:01.105530 IP kube-master.44160 > gateway.domain: 3+ AAAA? www.baidu.com. (31)
15:40:02.556701 IP 192.168.59.2.49297 > kube-master.domain: 4+ A? www.baidu.com. (31)
15:40:02.556942 IP kube-master.44160 > gateway.domain: 4+ A? www.baidu.com. (31)1
可以看到访问外部域名不走search域。CoreDNS通过apiserver+etcd来获得内部Service的A记录以区分内外部域名,访问外部域名时,CoreDNS通常会获取当前node的resolv.conf的配置进行解析,当node的resolv.conf中没有配置dns时,会使用8.8.8.8和8.8.4.4。
当node的resolv.conf配置无法解析域名时,CoreDNS会在search域进行查找
[root@kube-master ]# tcpdump udp dst port 53 |grep ww.k10s.com
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
16:23:03.774024 IP 192.168.59.2.43274 > kube-master.domain: 3+ AAAA? www.k10s.com. (30)
16:23:03.774383 IP kube-master.56700 > gateway.domain: 3+ AAAA? www.k10s.com. (30)
16:23:05.774764 IP kube-master.45589 > gateway.domain: 3+ AAAA? www.k10s.com. (30)
16:23:07.775035 IP kube-master.52035 > gateway.domain: 3+ AAAA? www.k10s.com. (30)
16:23:07.900422 IP 192.168.59.2.55185 > kube-master.domain: 4+ AAAA? www.k10s.com.default.svc.cluster.local. (56)
16:23:07.900814 IP 192.168.59.2.49646 > kube-master.domain: 5+ AAAA? www.k10s.com.svc.cluster.local. (48)
16:23:07.901088 IP 192.168.59.2.46749 > kube-master.domain: 6+ AAAA? www.k10s.com.cluster.local. (44)
16:23:07.901324 IP 192.168.59.2.48158 > kube-master.domain: 7+ A? www.k10s.com. (30)
16:23:07.901486 IP kube-master.52035 > gateway.domain: 7+ A? www.k10s.com. (30)
16:23:08.588050 IP 192.168.59.2.35448 > kube-master.domain: 8+ A? www.k10s.com.default.svc.cluster.local. (56)
16:23:08.588377 IP 192.168.59.2.39284 > kube-master.domain: 9+ A? www.k10s.com.svc.cluster.local. (48)
16:23:08.588591 IP 192.168.59.2.41323 > kube-master.domain: 10+ A? www.k10s.com.cluster.local. (44)
对于局域网或特殊域名,可以在Corefile配置文件指定的DNS,如
master.open.com:53 {
errors
cache 30
proxy . 192.168.59.1
}




