dns解析流程
我们可以通过抓包来理顺dns解析的流程
关于怎么找到pod的pid,请看【k8s运维】pod name与pid互查 (qq.com)
1 | # 进入 dns container 的 network namespace |
nsenter -n 是指定进入network命名空间,-t指定pid
53端口为 DNS服务器的服务端口。
另起一个pod进行nslookup
1 | nslookup baidu.com dns_container的ip |

因为我的集群有多个coredns容器。nslookup的时候指定一下dns_container的ip。这样可以抓全。

可以看到进行了4次dns查询
1 | 1、 baidu.com.default.svc.cluster.local. |
/etc/resolv.conf
为什么会查询这些?原因就是容器的/etc/resolv.conf的配置
1 | /# cat /etc/resolv.conf |
查看下我们dns svc,确实是这个ip

FQDN
要完全理解dns解析过程,首先要指导一个名词FQDN。Fully qualified domain name,全限定域名。(以下简称全域名)
全域名要求以.结束。所以你看到上面的dns查询最后都带着.
baidu.com这不是一个fqdn,baidu.com.这才是一个fqdn。
那是不是fqdn有什么关系呢?
规则是,如果是一个fqdn,那么就转发给DNS服务器进行解析。也就是 nameserver 1x.xx.0.10
如果不是一个fqdn,那么这个域名就要和search中的项组合成一个全域名去搜索。
在这里就是
1 | 1、 baidu.com.default.svc.cluster.local. |
这三个。
options ndots:5
这又是什么东西呢?
这个意思是说域名里的点号大于等于这个数字的话就是个全域名fqdn
比如 a.b.c.d.baidu.com 就算不是以点号结尾的,它也是个全域名。会直接交给DNS服务器进行解析。
总之
不管是内部服务名还是外部域名,最终都是交给DNS服务器进行解析。只不过对于非全域名来说要先经过和search域的组装,然后交给DNS服务器进行解析。我们可以利用这一点,对外部域名要用.结束,避免多次无效的dns解析。
另外一点,对于同一namespace下的svc调用,使用直接的svc名字调用,要比svc名.ns名的效率更高。因为svc名.ns名要经过第二次组装才能查询到,而直接的svc名字是第一次查询解析到了。
k8s的dns策略
k8s提供了4种DNS策略,如下:
Default: Pod 从运行所在的节点继承名称解析配置。其实就是使用宿主机的 /etc/resolv.conf 来进行解析ClusterFirst: Pod 内的 DNS 优先会使用 k8s 集群内的 DNS 服务,也就是会使用 kubedns 或者 coredns 进行域名解析。如果解析不成功,才会使用宿主机的 DNS 配置进行解析ClusterFirstWithHostNet:对于以 hostNetwork 方式运行的 Pod,这个 POD 中的所有容器都会使用宿主机的 /etc/resolv.conf 配置进行 DNS 查询,但是如果在 Pod 中仍然还想继续使用 k8s 集群 的 DNS 服务时,就需要将 dnsPolicy 设置为应显式设置其 DNS 策略ClusterFirstWithHostNet。None: 不会使用集群和宿主机的 DNS 策略。需要和dnsConfig一起配合使用
查看
1 | kubectl -n kube-system get deploy coredns -oyaml |

目前使用的是Default策略
关于core-dns和kube-dns
CoreDNS 和 Kube-DNS 都是 Kubernetes 集群的 DNS 服务提供者,作用上是完全相同的。
那选谁呢?
主要看性能差异,根据资料来看CoreDNS 更优。
从 Kubernets 1.11 开始,CoreDNS 达到了 GA,kubeadm 使用它来默认安装 Kubernetes。
从Kubernetes 1.13开始,CoreDNS就成了Kubernetes的默认DNS服务器
但是
1 | kubectl -n kube-system get svc |
看到的却是kube-dns
这是因为容器镜像使用 coredns 而服务名是 kube-dns,这是为了保证应用从 Kube-DNS 迁移到 coredns 时的后向兼容性。
所以我们集群里用的是coreDns。
看deploy的名字就是coredns。