追踪 Kubernetes 中的 DNS 查询

 张晓辉   2023-07-27 17:18   12078 人阅读  0 条评论

在过去的文章中,我们曾 追踪过 Kubernetes 中的网络数据包[1],这篇文章将追踪 Kubernetes 中的 DNS 查询。

让我们以在 Pod 中解析 Service 完全限定域名(FQDN) foo.bar.svc.cluster.local 为例。

在开始之前,先回顾下 DNS 的解析流程。

DNS 的解析流程

追踪 Kubernetes 中的 DNS 查询  第1张

简化版的 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 查询  第2张

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 的值大小会影响 DNS 解析的性能,为了获得较好的性能,建议使用 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

推荐阅读 点击标题可跳转

《Docker是什么?》

《Kubernetes是什么?》

《Kubernetes和Docker到底有啥关系?》

《教你如何快捷的查询选择网络仓库镜像tag》

《Docker镜像进阶:了解其背后的技术原理》

《教你如何修改运行中的容器端口映射》

《k8s学习笔记:介绍&上手》

《k8s学习笔记:缩扩容&更新》

《Docker 基础用法和命令帮助》

《在K8S上搭建Redis集群》

《灰度部署、滚动部署、蓝绿部署》

《PM2实践指南》

《Docker垃圾清理》

《Kubernetes(k8s)底层网络原理刨析》

《容器环境下Node.js的内存管理》

《MySQL 快速创建千万级测试数据》

《Linux 与 Unix 到底有什么不同?》

《浅谈几种常见 RAID 的异同》

《Git 笔记-程序员都要掌握的 Git》

《老司机必须懂的MySQL规范》

《Docker中Image、Container与Volume的迁移》

《漫画|如何用Kubernetes搞定CICD》

《写给前端的Docker实战教程》

《Linux 操作系统知识地图2.0,我看行》

《16个概念带你入门 Kubernetes》

《程序员因接外包坐牢456天,长文叙述心酸真实经历》

《IT 行业老鸟,有话对你说》

《HTTPS 为什么是安全的?说一下他的底层实现原理?



免责声明:本文内容来源于网络,所载内容仅供参考。转载仅为学习和交流之目的,如无意中侵犯您的合法权益,请及时联系Docker中文社区!



追踪 Kubernetes 中的 DNS 查询  第3张


本文地址:https://docker.ink/?id=335
温馨提示:文章内容系作者个人观点,不代表Docker中文社区对观点赞同或支持。
版权声明:本文为转载文章,来源于 张晓辉 ,版权归原作者所有,欢迎分享本文,转载请保留出处!

 发表评论


表情

还没有留言,还不快点抢沙发?