追踪 Kubernetes 中的 DNS 查询路径
  cKmdazbX85Xz 2023年11月02日 91 0

DNS 的解析流程

追踪 Kubernetes 中的 DNS 查询路径_服务器

简化版的 DNS 处理流程:

  1. DNS 客户端(如浏览器、应用程序或者设备)发送域名 example.com 的查询请求。
  2. DNS 解析器收到请求,查询本地缓存,如果本地有记录且未过期会返回本地的记录。
  3. 如果本地缓存未命中,DNS 解析器将从 DNS 根服务器开始向下查询,首先是顶级域名(Top Level Domain, TLD) DNS 服务器(这里是 .com),一直向下直到可以解析 example.com 的服务器。
  4. 能够解析 example.com 的服务器成为权威 DNS 名称服务器(Authoritative DNS name server),解析器访问该服务器并收到 IP 地址等相关信息,然后返回给给客户端。解析完成。

从流程来看非常重要的一项配置就是上游 DNS 服务器,该配置位于 Pod 中。这里 Kubernetes 的集群 DNS 服务器正是扮演上游 DNS 服务器的角色,比如 kube-dns[2]CoreDNS[3],二者均实现了 Kubernetes 的基于 DNS 的服务发现规范[4]。对 CoreDNS 感兴趣的,可以参考上一篇文章 浅析 CoreDNS 的工作机制[5]

追踪 Kubernetes 中的 DNS 查询路径_DNS_02


Pod DNS 配置

在 解析 kubelet 源码[6] 一文中,我们曾分析了 kubelet 创建 pod 的流程。kubelet 创建 pod sandbox 配置时[7] ,其中重要的一项配置就是准备 pod 的 DNS 配置[8](Pod 的 DNS 配置由 pod 的 dnsPolicy 和 dnsConfig 字段进行操作,这里不展开,下面的部分按照 dnsPolicy=ClusterFirst 情况进行说明)。

配置的内容包括如下三个部分:

  • DNS 服务器 nameserver:来自 kubelet 配置(通常位于 /var/lib/kubelet/config.yaml)的 clusterDNS 字段
  • 搜索域 search:包含四种域:命名空间域、服务域、集群域,以及节点 /etc/resolv.conf 中定义的搜索域。集群域来自 kubelet 配置的 clusterDomain 字段,默认为 cluster.local;命名空间域 NS.svc.cluster.local;服务域 svc.cluster.local
  • 选项 options:默认为 ndots:5

然后 kubelet 调用 CRI 接口创建容器,由 CRI 的实现将 DNS 配置写入到容器文件(默认地址 /etc/resolv.conf)中,如 Containerd[9] 的 pkg/cri/server/sandbox_run_linux.go#L272[10]

我们查看命名空间 default 下某个 pod 的 DNS 配置:

cat /etc/resolv.conf
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.96.0.10
options ndots:5

这里的 nameserver 正是 Service kube-dns 的 cluster IP 地址,也就是集群的 DNS 服务器,即 dnsPolicy=ClusterFirst 的结果。

search 与 ndots

search 用于指定默认的搜索域。当你在使用不完全限定域名(例如,只提供主机名而没有域名)进行域名解析时,系统会尝试在搜索域中找到匹配的完全限定域名。搜索域按照出现的顺序进行搜索,直到找到匹配的域名或搜索完所有的域名。

ndots 用于指定在进行域名解析时,系统自动添加域名的点号个数阈值。当提供的域名中点号的个数达到或超过这个阈值时,系统会将其视为完全限定域名,而不再使用搜索域进行搜索。默认为 1,这里将其设置为 5

注:ndots FQDN 进行服务访问,以及将 ndots 改为更小的值。

Pod DNS 解析

当在 Pod 中执行 DNS 解析时,查询请求被发到本地(pod 中)的 DNS 解析器。这个解析器先在缓存中查询,如果未命中,则会根据 /etc/resolv.conf 中的配置,将请求发到上游的 DNS 服务器,即集群 DNS 服务器 10.96.0.10 完成域名解析。

根据前面的介绍,假如我们要解析的域名是 foo.bar,会依次进行如下的查询:

  • foo.bar.default.svc.cluster.local
  • foo.bar.svc.cluster.local(匹配到结果)

当我们使用 foo.barfoo.bar.svc 都可以完成解析,但 foo.bar.svc.cluster 不行,因为追加了搜索域后无法匹配到结果。假如请求方与目标服务在同一个命名空间下,只用 foo 也是可以的。

参考资料

[1] 

追踪过 Kubernetes 中的网络数据包: https://atbug.com/tracing-network-packets-in-kubernetes/

[2] 

kube-dns: https://github.com/kubernetes/dns

[3] 

CoreDNS: https://coredns.io

[4] 

Kubernetes 的基于 DNS 的服务发现规范: https://github.com/kubernetes/dns/blob/master/docs/specification.md

[5] 

浅析 CoreDNS 的工作机制: https://atbug.com/analysis-of-the-working-mechanism-of-coredns/

[6] 

解析 kubelet 源码: https://atbug.com/how-kubelete-container-runtime-work-with-cni/#创建-pod

[7] 

创建 pod sandbox 配置时: https://github.com/kubernetes/kubernetes/blob/release-1.24/pkg/kubelet/kuberuntime/kuberuntime_manager.go#L861

[8] 

pod 的 DNS 配置: https://github.com/kubernetes/kubernetes/blob/release-1.24/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go#L93

[9] 

Containerd: https://github.com/containerd/containerd

[10] 

pkg/cri/server/sandbox_run_linux.go#L272: https://github.com/containerd/containerd/blob/a05d175400b1145e5e6a735a6710579d181e7fb0/pkg/cri/server/sandbox_run_linux.go#L272

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
cKmdazbX85Xz
作者其他文章 更多