1. 从一次事故说起:Pod的DNS策略为什么值得花一整篇来聊
大概半年前,某公司内部一个微服务系统频繁出现“间歇性连接超时”,A服务调用B服务时,偶尔会卡个十几秒。监控面板上看CPU、内存、磁盘一切正常,网络延迟也低得离谱。折腾了两三天,某团队才在一个很隐蔽的地方找到了真相——某个新入职的同事在部署Pod时,给容器加了一个很不起眼的配置:dnsPolicy: Default。
那是个没有status: hostNetwork的普通Pod,按理说应该用默认的ClusterFirst,让Pod通过CoreDNS去解析集群内部的Service名字。结果这个Pod的/etc/resolv.conf直接沿用了宿主机配置,指向了宿主机的DNS服务器。Service解析时,请求绕了一圈跑到外部DNS去问“gateway-service.default.svc.cluster.local”是谁,外部DNS当然答不上来,于是反复重试、超时、重试……整个链路就像每次打电话都拨错号码,等了好一阵子才收到“您拨打的号码不存在”的提示音。
这件事最后虽然修复了,但给我留下的印象特别深:在Kubernetes网络体系里,DNS策略是最容易被低估、破坏力却极大的隐藏变量。它不像Service、Ingress、CNI那样有明确的组件和面板,而只是每个Pod里一个几行字的小文件,但凡是涉及服务发现、外部访问、多集群互通,都得先过它这一关。
这篇文章就围绕“Kubernetes网络——Pod DNS策略”这个主题,把四个官方策略逐个拆开揉碎讲清楚,再补充上游DNS配置、search domain、排障手段等一整套实战经验。适合刚接触K8s的服务端开发者,也适合正在排查诡异网络问题的运维同学。看完之后,你能准确判断出“什么样的场景该选哪种策略”“为什么某些Pod解析行为这么怪”“出了问题该去哪条链路找根因”。
2. 先理解Kubernetes里DNS是怎么工作起来的
2.1 从kubelet到CoreDNS:一条完整的解析链路
在讨论策略之前,得先知道Kubernetes集群里DNS整体是怎么运转的。
集群里通常会部署一组DNS服务,最常见的是CoreDNS。它本身是几个Pod,用Deployment方式跑着,由Service暴露为集群内部的虚拟IP(一般叫kube-dns或coredns)。所有Pod的/etc/resolv.conf里,nameserver这一项指向的就是这个Service IP。
kubelet在这条链路里扮演的角色是“配置分发器”。每个Pod在启动时,kubelet会根据该Pod的dnsPolicy,决定往/etc/resolv.conf里写什么内容。默认的ClusterFirst策略下,kubelet会把集群DNS的Service IP写进去,同时追加一组search domain,让短名字能自动补全成完整的FQDN。
举个例子,某个Pod的/etc/resolv.conf大概长这样:
search default.svc.cluster.local svc.cluster.local cluster.local nameserver 10.96.0.10 options ndots:5这里有几个关键点:
nameserver 10.96.0.10就是CoreDNS的Service IP。search字段决定了短域名解析时的补齐规则。比如Pod里访问gateway-service,它会依次尝试gateway-service.default.svc.cluster.local、gateway-service.svc.cluster.local、gateway-service.cluster.local,最后是直接查gateway-service。options ndots:5表示域名里点号数量小于5时,先走search domain的补齐流程;如果点号≥5,则先尝试绝对域名查询。
很多初学者不理解“为什么Pod里可以只用服务名访问另一个服务”,背后的核心机制就是search domain和ndots配合的结果。
2.2 为什么Pod里的DNS行为和本机不一样
直觉上,很多人觉得容器就是一个小虚拟机,DNS配置也应该和宿主机一样,但Kubernetes刻意让它们不一样。
如果每个Pod都用宿主机的DNS配置,ClusterFirst这套机制就不存在了。Pod访问同为集群内的Service时,必须用完整的FQDN才能绕过外部DNS解析,但这在容器化场景下既不现实,也是灾难——你不可能要求所有开发人员每次调用都写一长串完整的Service域名。而通过注入集群DNS加search domain,开发人员可以像在本机一样用短名字服务发现,这就是Kubernetes对“开发者体验”的一种定向优化。
但事情的另一面是:如果Pod用了hostNetwork,事情就变得微妙了。宿主机网络空间下的Pod,它的DNS行为受hostNetwork和dnsPolicy的叠加影响,这也是很多人配置出错的重灾区,后面会展开细讲。
3. 四种核心DNS策略:原理、场景、配置实例
3.1 ClusterFirst:默认但不平庸
ClusterFirst是绝大多数普通Pod的默认策略,也是官方推荐的标准做法。kubelet会写入集群DNS地址、search domain和ndots:5,让容器内域名解析优先走集群DNS。
适用场景很明确:Pod需要解析集群内的Service,也可能需要访问外网域名(CoreDNS默认配置下会把外部域名请求转发给上游DNS,比如宿主机的/etc/resolv.conf指向的DNS)。
配置方式很简单:
apiVersion: v1 kind: Pod metadata: name: example-pod spec: containers: - name: app image: nginx dnsPolicy: ClusterFirst实际使用中,ClusterFirst基本不用显式写出来,但我会建议写上,理由是在某些定制的Kubernetes发行版里,默认策略可能被平台层改过,写出来至少能让人一眼看清意图。
一个常见的认知误区是:以为ClusterFirst意味着“永远只走CoreDNS”。实际上CoreDNS本身也支持forward插件,把非集群域名的查询转发到上游DNS。所以CoreDNS请求链路是:Pod → CoreDNS →(如果域名非集群内)上游DNS。Pod的/etc/resolv.conf里看到的永远是集群DNS,真正的“出网”发生在CoreDNS那一跳。
3.2 Default:继承宿主机,最容易被误用的策略
dnsPolicy: Default的含义不是“用Kubernetes默认配置”,而是“让容器继承宿主机的/etc/resolv.conf”。这里的继承动作发生在kubelet从cri(容器运行时)拿到Pod配置时——kubelet会从宿主机读取/etc/resolv.conf,然后把这份文件原样挂载/写入容器对应的位置。
这就带来一个直接后果:容器里的DNS解析行为和宿主机完全一致。宿主机能不能解析某个名字,容器就能不能;宿主机访问某个内网域名走什么DNS,容器也一模一样的路径。
适用场景其实比较窄,最常见的是:
- hostNetwork类型Pod,需要Pod共享宿主机的网络视图,DNS策略也保持和宿主机一致。
- 特殊网络插件或混合环境,比如一些公司自建IDC和公有云混合部署,希望部分Pod直接使用底层网络自带的DNS。
- 对DNS解析要求极简的场景,比如只访问IP、不需要集群内部服务发现的Pod。
踩坑点也很集中。最典型的一个是在普通Pod上误用Default策略,导致集群内Service解析彻底失效。前面提到的事故就是这个原因。另一个坑是宿主机/etc/resolv.conf如果包含某些内网域名配置,Pod启动时间可能变长,甚至因为DNS不可达导致容器健康检查失败。
如果你确实需要宿主机的DNS,但同时又想保留集群Service解析能力,那应该考虑的是ClusterFirstWithHostNet,而不是Default。
3.3 ClusterFirstWithHostNet:hostNetwork场景下的“救星”
hostNetwork: true会让Pod共享宿主机网络命名空间,Pod的IP就是宿主机IP,端口也是宿主机的端口。在这种情况下,如果仍然用ClusterFirst,某些Kubernetes版本不会自动将集群DNS写入容器的/etc/resolv.conf,表现就是Pod内无法通过Service名访问其他服务。这是因为kubelet对于hostNetwork Pod有一套特殊的DNS配置逻辑,不同版本对“继承宿主机的resolv.conf”和“注入集群DNS”的优先级处理不一致。
ClusterFirstWithHostNet就是专门解决这个问题的:它保证即使Pod在宿主机网络空间,依然使用集群DNS进行解析。
配置示例:
apiVersion: v1 kind: Pod metadata: name: host-network-pod spec: hostNetwork: true dnsPolicy: ClusterFirstWithHostNet containers: - name: app image: nginx适合使用这个策略的典型场景包括:
- 部署在节点上的Agent类Pod,比如监控采集器、日志采集器、CNI插件组件等。
- 需要直接绑定端口到宿主机,对外提供服务的Pod。
- 通过节点网络访问集群外部服务,但又要访问集群内部Service的Pod。
实际配置时,我建议只要开了hostNetwork,几乎无脑搭配ClusterFirstWithHostNet。用的是宿主机网络,但解析逻辑还是集群优先,这两者并不冲突。
3.4 None:把resolv.conf的掌控权完全拿回来
dnsPolicy: None意味着Kubernetes完全不管这个Pod的DNS配置,你必须自己通过dnsConfig字段把nameserver、search、options全部指定清楚。
这种策略适合什么场景呢?最典型的是:
- Pod需要固定使用某个外部DNS(比如公有云的DNS服务),不想经过CoreDNS。
- 某些合规要求下,业务侧要求容器内的所有DNS查询必须走指定的私有DNS。
- 需要对DNS行为做非常细粒度的控制,比如自定义
ndots值、特定search domain顺序。
配置方式:
apiVersion: v1 kind: Pod metadata: name: custom-dns-pod spec: dnsPolicy: None dnsConfig: nameservers: - 8.8.8.8 - 1.1.1.1 searches: - ns1.svc.cluster.local - my.dns.search.suffix options: - name: ndots value: "2" containers: - name: app image: nginx有几个细节需要特别注意。
第一个是:一旦用了dnsPolicy: None,dnsConfig是必填的。如果遗漏,Pod会创建失败或处于异常状态,因为kubelet不知道该往resolv.conf里写什么。
第二个是:searches字段的搜索域列表,最多支持6个。超过之后,多余的会被忽略,而且顺序很重要——Kubernetes会先尝试你配置的第一个search domain拼接出来的名字。很多时候你发现问题:“为什么短域名解析要到最后一个search domain才命中?”大概率就是store域列表顺序写得不合理。
第三个是:options里的ndots。在None策略下,ndots的默认值不再自动是5,而是取决于/etc/resolv.conf实际配置或你显式指定的值。ndots:2这种配置适合外部域名点号较多的场景,可以减少无谓的搜索尝试,提升解析效率。
在动手之前,我建议你先通过kubectl exec进入相似Pod,执行cat /etc/resolv.conf,观察默认内容,再据此决定哪些需要定制。别凭感觉乱写nameserver和search,等出问题再排查就晚了。
4. 实操向:不同策略下的Pod DNS配置与验证方法
4.1 通过kubectl快速验证当前生效的resolv.conf
一个很实用的定位思路:先看Pod的spec,再进容器看实际配置,两者比对,能迅速判断策略落地情况。
首先查看Pod的完整定义:
kubectl get pod <pod-name> -o yaml | grep -A 8 'dnsPolicy'这一步能看到策略名称。接着进入容器查看实际生效的文件:
kubectl exec -it <pod-name> -- cat /etc/resolv.conf如果你看到nameserver指向的是10.96.0.10这样的集群DNS IP,且search domain包含svc.cluster.local,说明Pod走的是ClusterFirst;如果nameserver是宿主机网段IP,说明走的是Default或hostNetwork相关的继承逻辑;如果什么都没写或内容异常缺失,则要检查是否用了None且配置不完整。
实际操作中,我还喜欢加一个辅助验证:在容器内用nslookup解析一个集群内服务名和一个外部域名。
kubectl exec -it <pod-name> -- nslookup gateway-service.default.svc.cluster.local kubectl exec -it <pod-name> -- nslookup kubernetes.default.svc.cluster.local有些镜像里没装nslookup,也可以用getent hosts替代:
kubectl exec -it <pod-name> -- getent hosts my-service.default.svc.cluster.local通过对比集群内和外部域名的解析行为,很快能判断问题出在CoreDNS、上游DNS还是search domain的配置上。
4.2 手把手配置一个生产级自定义DNS
假设你有一个业务场景:某数据同步任务需要同时解析集群内Service、外部S3存储域名和公司内网NTP域名。如果直接用ClusterFirst,外部域名会先经由CoreDNS转发,多一跳,延迟略高;如果直接用Default,集群内Service又解析不了。最合适的方案反而是None策略加自定义dnsConfig,精确控制三个解析方向。
具体做法是:
apiVersion: v1 kind: Pod metadata: name: custom-dns-example spec: containers: - name: sync-job image: busybox:1.36 command: ["/bin/sh", "-c", "sleep 3600"] dnsPolicy: None dnsConfig: nameservers: - 10.96.0.10 - 10.20.0.2 searches: - default.svc.cluster.local - svc.cluster.local - cluster.local - corp.internal options: - name: ndots value: "3" - name: timeout value: "3" - name: attempts value: "2"这里第一段nameserver是CoreDNS,第二段是公司内网DNS。search domain里既有集群内的三个标准域,也有内网域。ndots设置为3,使得大部分集群内服务名(如my-service.default.svc.cluster.local有6个点)和部分带点号的内部域名能直接走DNS查询,减少无谓的拼接尝试。timeout和attempts用于控制超时和重试次数,避免某一次DNS慢导致业务超时。
写完之后部署,然后验证:
kubectl apply -f custom-dns-example.yaml kubectl exec -it custom-dns-example -- cat /etc/resolv.conf预期看到的文件内容和dnsConfig里的定义基本一致,顺序也不会被kubelet打乱。然后分别解析三类域名:
kubectl exec -it custom-dns-example -- nslookup my-service.default.svc.cluster.local kubectl exec -it custom-dns-example -- nslookup s3.ap-southeast-1.amazonaws.com kubectl exec -it custom-dns-example -- nslookup ntp.corp.internal三种域名都应能正常返回结果。
这里有一个很容易被忽视的点:dnsConfig里的nameservers最多只能写3个,多了会被截断。不要以为可以像在传统Linux里一样配一堆DNS,Kubernetes在API层面就做了限制。
4.3 宿主机网络场景下DNS策略的选择清单
把hostNetwork和dnsPolicy的搭配情况整理成一张表,方便对照使用:
| Pod是否使用宿主机网络 | 推荐的dnsPolicy | 说明 |
|---|---|---|
| 是 | ClusterFirstWithHostNet | 首选,既用宿主机网络,又保留集群DNS解析能力 |
| 是 | Default | 极少见,明确要求容器完全继承宿主机DNS时考虑 |
| 是 | None | 需要完全自定义DNS时,手动配置dnsConfig |
| 否 | ClusterFirst | 最常用,默认推荐 |
| 否 | Default | 不建议,基本都会出问题 |
| 否 | None | 有精确控制需求时使用 |
这里有一个细节值得强调:当你给hostNetwork Pod使用ClusterFirstWithHostNet时,CoreDNS必须允许其他节点上走宿主网络的Pod来访问。因为正常情况下集群内Pod通过Service IP访问CoreDNS,而hostNetwork Pod使用宿主机IP,网络路径不同。如果CoreDNS部署所在节点的安全组或网络策略有额外限制,可能出现“Pod能通外部,但解析不了集群内Service”的怪问题。排查时,可以先确认CoreDNS Service的endpoint是否有回应。
5. 上游DNS与hostNetwork下的特殊行为
5.1 为什么你的Pod解析公网域名时快时慢
许多场景下,Pod访问外部域名(比如s3.amazonaws.com)的路径是:Pod → CoreDNS → 上游DNS → 公网DNS。CoreDNS的forward插件会读取它自己的Corefile配置,把非集群域名转发给上游。而这个上游默认值通常来自部署CoreDNS时所在节点(或配置项)指定的DNS。
问题往往出在这一层。如果你的CoreDNS所在节点的/etc/resolv.conf里包含多个nameserver,转发目标的延迟和可靠性就会影响集群内所有Pod的外部域名解析。我曾经遇到过一个集群,CoreDNS Pod调度到某个节点后,恰好那台节点上配置了一个响应极其缓慢的内网DNS,结果整个集群的Pod访问外部API都变得时好时坏,而集群内Service解析一切正常。
解决办法有几个思路:
- 显式在CoreDNS的Corefile里指定
forward . 8.8.8.8 1.1.1.1,绕开节点自身的不稳定DNS。 - 给CoreDNS单独设置
nodeSelector,让它只调度到固定且网络稳定的节点。 - 开启
cache插件,减少上游DNS压力。 - 关闭不必要的
loop检测日志干扰,避免误报。
检查当前CoreDNS配置:
kubectl get configmap coredns -n kube-system -o yaml如果看到类似这样的配置:
.:53 { errors health ready kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure fallthrough in-addr.arpa ip6.arpa } forward . /etc/resolv.conf cache 30 }其中forward . /etc/resolv.conf就是“使用CoreDNS所在节点的DNS配置”作为上游,这类配置最容易受节点状态影响。
5.2 hostNetwork Pod访问CoreDNS的几种影响
前面提到了hostNetwork结合ClusterFirstWithHostNet是常规解法,但还有一些变体需要留意。
如果你的Pod使用hostNetwork,同时dnsPolicy为ClusterFirstWithHostNet,Pod的resolv.conf中nameserver指向CoreDNS Service IP。这个Service IP本身是iptables或IPVS转发规则实现的,走宿主机网络也能到达。但需要注意:某些网络插件或网络策略环境下,宿主机到Service IP的访问可能被拦截,导致解析失败。
另一个实际生产中出现的场景是:节点上的kubelet通过hostNetwork方式部署,它自己的DNS解析如果异常,会导致节点上所有Pod在创建时都拿不到正确的resolv.conf。这种情况下排查思路就要调到节点层而不是Pod层。
在hostNetwork的同时还希望完全继承宿主机DNS的少数场景里,用Default策略也可以,但结果就是集群内Service名无法解析。我曾见有人用hostNetwork + Default跑监控采集器,采集器里硬编码了集群内API Server的IP,不开DNS解析,居然也稳定跑了大半年。但这是特例,不推荐模仿。
5.3 dnsConfig里那些容易忽略的options参数
除了nameserver和search,dnsConfig里的options字段对解析行为的影响也很明显,但很多人不怎么关注。
常见的三个参数:
ndots:决定域名中点的数量达到多少时,优先做绝对查询。值太高(比如5)会导致每次解析都要尝试多个search domain拼接,增加DNS查询次数和延迟;值太低(比如1)可能导致有些短名字直接走绝对查询,反而找不到。最常用的值是3或5。timeout:单个DNS请求的超时时间,默认5秒。如果上游DNS慢,适当调低可以让应用更快失败并切换,减少卡顿。attempts:DNS查询失败后的重试次数,默认2次。对于公网解析,适当调高能提高成功率,但也会让单次解析的最长等待时间更久。
我见过一个有意思的case:某业务Pod在集群内访问另一个Service,偶发超时。查了很久,最终发现是它有自定义dnsConfig,把ndots设成了2,同时search domain里保留了svc.cluster.local等域。因为目标Service的完整域名里有6个点,按ndots=2应该直接走绝对查询,但因为/etc/resolv.conf的options中还有一行不显眼的配置,导致glibc解析器对某些情况依然走了搜索域拼接路径,白白多出几次DNS查询。后面把ndots调整为5,超时立刻消失。
这类问题很难从业务日志里直接看出来,只有当你真正理解options与解析器行为的关系,才能在毫秒级别找到原因。
6. 典型问题与排障思路速查
6.1 Pod内无法解析集群内Service名
这是最高频的问题,表现形式是:nslookup my-service能返回IP,但curl http://my-service:8080连接超时;或者是直接解析失败。
排查步骤可以这样走:
- 确认Pod的dnsPolicy:
kubectl get pod <pod-name> -o yaml | grep dnsPolicy- 进入Pod查看实际resolv.conf:
kubectl exec -it <pod-name> -- cat /etc/resolv.conf- 在集群内一个已知正常工作的Pod里对比同样的操作。如果正常Pod能解析、异常Pod不能,问题大概率在策略或dnsConfig配置上;如果所有Pod都不行,重点检查CoreDNS状态:
kubectl get pods -n kube-system -l k8s-app=kube-dns kubectl logs -n kube-system -l k8s-app=kube-dns --tail=50- 若CoreDNS正常,再检查Service
kube-dns的endpoint:
kubectl get endpoints -n kube-system kube-dns常见原因就是这几个:dnsPolicy被误设为Default或None;CoreDNS挂掉;CoreDNS Service的Selector和Pod标签不匹配导致endpoint为空;网络策略拦截了Pod到CoreDNS Service的流量。
6.2 集群内解析正常,但外部域名超时或解析失败
如果nslookup my-service.default.svc.cluster.local正常,nslookup www.baidu.com失败,问题基本可以锁定在上游DNS链路上。
首先检查CoreDNS的forward配置:
kubectl get configmap coredns -n kube-system -o yaml确认上游指向是否合理。很多自建集群默认forward . /etc/resolv.conf,这个文件在CoreDNS Pod里通常指向节点上的DNS配置。节点配的DNS如果只能解析内网域名、对公网域名无回应,那整个集群的Pod外部解析都会挂。
更进一步,可以在CoreDNS Pod里手动执行查询验证:
kubectl exec -n kube-system -l k8s-app=kube-dns -- nslookup www.baidu.com 127.0.0.1如果这个命令能解析,说明CoreDNS本身没问题,问题可能出在Pod访问CoreDNS的链路(比如网络策略);如果解析失败,多半是CoreDNS到上游DNS的网络问题,或上游DNS配置不对。
另外提醒一下:CoreDNS默认的cache时间为30秒,如果你刚修改了Corefile配置并重启了CoreDNS,测试时记得等缓存过期,否则可能会误判。
6.3 Pod的resolv.conf内容和预期不一致
这类问题出现得比较隐蔽。有时候你明明配了dnsPolicy: None,进入容器看到的文件却和你预想的不完全一样——某些search被改了顺序、nameserver只剩一个。这时不必慌,要先检查是不是有webhook、变异控制器之类的组件在Pod创建时改了dnsConfig。大型团队里,平台组为了统一管控,经常会注入全局级别的dnsConfig默认值。
排查手段很简单:查看这个Pod被创建时的原始API请求或审计日志。如果你有权限,kubectl get pod <pod-name> -o yaml看到的dnsConfig就是最终被接受的配置。如果最终配置和你yaml里写的不同,基本可以断定有准入控制器在干预。
还有一类问题是:某些云厂商的Kubernetes托管服务会自动帮你改写dnsPolicy。比如在节点池上启用了私有DNS,平台层会把Default策略的Pod统一改写成某个固定DNS配置。这时候不要徒手kubectl apply试错,直接看节点池或集群层面的DNS相关配置项。
6.4 排障工具箱:命令、日志、行为特征一览
| 故障现象 | 排查命令/手段 | 可能原因 |
|---|---|---|
| Service名解析失败 | kubectl exec <pod> -- nslookup <svc> | dnsPolicy错误、CoreDNS异常 |
| 外部域名解析超时 | kubectl logs -n kube-system -l k8s-app=kube-dns | 上游DNS配置错误、节点DNS故障 |
| 所有Pod无法解析 | kubectl get endpoints -n kube-system kube-dns | kube-dns Service的endpoint为空 |
| 只有hostNetwork Pod解析失败 | 检查节点iptables/网络策略 | ClusterFirstWithHostNet未生效或策略拦截 |
| resolv.conf被篡改 | 查看Pod最终yaml、检查准入控制器 | webhook注入、平台默认策略干预 |
| CoreDNS频繁重启 | kubectl describe pod -n kube-system -l k8s-app=kube-dns | 资源限制、Liveness探针失败 |
另外记录一个比较实用的观察方法:CoreDNS的Prometheus指标里,coredns_dns_request_count_total和coredns_dns_response_size_bytes能反映集群整体的DNS请求状态。如果某个时间点请求量突增,排查思路可以转向业务发布、应用重连等方向。虽然不建议每个人都搭建一套完整监控,但至少可以在出问题时临时看一眼指标,能省去很多盲猜的时间。
7. 从DNS策略延伸:这一层设计背后的底层逻辑
写到这里,回到一个更宏观的问题:为什么Kubernetes要设计四种DNS策略,而不是直接统一成一个?
我个人的理解是,这背后是“平台统一”与“场景差异”之间的取舍。纯集群内应用,用ClusterFirst可以获得最佳的服务发现体验,短名字到处可用;但Kubernetes还要兼容大量历史遗留系统和特殊网络环境,比如需要Pod完全跟着宿主机网络走的监控组件、需要对接传统DNS基础设施的迁移项目,它们需要Default这样“最大限度保持原状”的策略;而网络敏感型或合规要求高的场景,又需要None这种“全权交给用户决定”的极简策略。在Kubernetes的网络抽象里,DNS策略本质上是一把可以调节的旋钮,松开一端,收紧另一端,换取的是对不同部署形态的兼容。
从这个角度看,选择DNS策略时,别只问“哪个最好”,而要问“我这个Pod处在什么网络环境,它依赖哪几种域名解析,允许牺牲哪一部分便利性”。想清楚这三个问题,策略配置自然就定了。
对我个人而言,DNS策略这块还有一个习惯性检查项:每次给Pod写YAML时,都会顺手确认dnsPolicy和hostNetwork是否成对出现。以前踩过一次坑之后,我现在一看到hostNetwork: true,就会条件反射地去看dnsPolicy是不是ClusterFirstWithHostNet。这种“配对检查”用代码写进CI或者模板里,团队协作时能挡住很多低级问题。
8. 最后分享一个小技巧:让Pod快速验证DNS策略是否落地
最后补一个很实用的临时验证方法。当你在测试环境想快速验证不同dnsPolicy的行为,不必反复写繁琐的Deployment,直接用一行kubectl命令起一个临时Pod:
kubectl run dns-test --image=busybox:1.36 --restart=Never --overrides='{"spec":{"dnsPolicy":"ClusterFirstWithHostNet","hostNetwork":true,"containers":[{"name":"dns-test","image":"busybox:1.36","command":["/bin/sh","-c","sleep 3600"],"resources":{}}]}}'启动之后:
kubectl exec -it dns-test -- cat /etc/resolv.conf kubectl exec -it dns-test -- nslookup kubernetes.default.svc.cluster.local测完删除:
kubectl delete pod dns-test这个流程特别适合在排查网络问题时快速验证猜想,不用改任何业务部署文件,也不影响其他Pod。我平时做集群网络巡检时,就经常丢几个这种临时Pod在不同节点上,把各节点的DNS行为横向对比一遍,很多隐性问题立刻显形。
DNS策略这个主题,说明白了几行配置的事,说深了是整个集群网络的一个缩影。希望这篇文章能帮你少走一些我当年走过的弯路。