
在这个实验环境中我们将学习kubernetes集群中的DNS的工作原理以及为什么DNS对服务发现和网络连接非常的重要。了解kubelet如何配置Pod的DNS设置CoreDNS如何负责集群名的解析Pod如何执行对服务、其他Pod以及外部域名的查询在kubernetes中DNS是一项基础服务它实现了可靠的服务到服务的通信并简化了应用程序相互发现的方式实现集群内部的服务发现与名称解析Pod使用DNS名称而非硬编码的IP因为Pod/Service的IP会随着扩容和重启而变化kubelet配置每个Pod的/et/resolv.conf 使其使用集群DNS服务通过kube-dns提供的CoreDNS添加集群搜索域eg.ns.svc.cluster.local使得像nginx这样的短名称能够被解析为nginx.svc.cluster.localCoreDNS应答针对Service和Pod查询并将为止域名转发给上游解析器同时支持集群内查询服务发现以及来自Pod的外部DNS解析实验环境实验环境的clab topo复用IPAM的topo检查 ContainerLab拓扑结构确认默认命名空间中容器和服务是否都正常master ✗ $ kubectl get pod-owide1↵ NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES multitool-1-h5z551/1 Running02d2h192.168.112.131 calico-ipam-worker2nonenonemultitool-1-hnkl41/1 Running02d2h192.168.131.131 calico-ipam-workernonenonemultitool-1-nh4qg1/1 Running02d2h192.168.18.73 calico-ipam-control-planenonenonemultitool-2-6jbdt1/1 Running02d2h192.168.131.132 calico-ipam-workernonenonemultitool-2-jql6b1/1 Running02d2h192.168.18.72 calico-ipam-control-planenonenonemultitool-2-zlm2k1/1 Running02d2h192.168.112.130 calico-ipam-worker2nonenonenginx-deployment-55d7bb4b86-j5q5j1/1 Running025h192.168.112.132 calico-ipam-worker2nonenonenginx-deployment-55d7bb4b86-lqswq1/1 Running025h192.168.131.133 calico-ipam-workernonenone确认DNS是否设置正确我们通过检查kub-dns Service(Pod作为其nameserver的IP)以及查看CoreDNS Corefile(它定义了集群内名称如何解析、外部查询如何转发)来验证集群DNS是否已启动并正确配置。验证kube-dns服务master ✗ $ kubectl get services-nkube-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)AGE kube-dns ClusterIP10.96.0.10none53/UDP,53/TCP,9153/TCP 3d1h确认集群内DNS服务(kube-dns)正以ClusterIP形式运行 10.96.0.10。Pod在53/UDP和53/TCP端口使用此IP作为DNS nameserver;9153/TCP暴漏CoreDNS的prometheus指标。检查支撑该服务的Endpoints端点master ✗ $ kubectl describe endpoints kube-dns-nkube-system Name: kube-dns Namespace: kube-system Labels: k8s-appkube-dns kubernetes.io/cluster-servicetrue kubernetes.io/nameCoreDNS Annotations: endpoints.kubernetes.io/last-change-trigger-time:2026-09-23T04:00:29Z Subsets: Addresses:192.168.18.67,192.168.18.71 NotReadyAddresses:nonePorts: Name Port Protocol ---- ---- -------- dns-tcp53TCP dns53UDP metrics9153TCP Events:none列出了Pod实际达到的、kub-dns Service背后的Endpoints(即CoreDNS Pod)。Addresses:192.168.18.67,192.168.18.71是本基金群众正在运行的CoreDNS Pod的IP。Readiness:NotReadyAddresses: none表示所有CoreDNS端点都已就绪可以提供查询服务。Ports: 在53端口通过UDP/TCP提供DNS服务并在9153/TCP提供prometheus指标Takeaway(要点)kube-dns的ClusterIP会负载均衡到这些CoreDNS端点如果解析失败首先应该检查这些地址就绪状态。验证coredns Pod接下来让我们看看coredns这些容器master ✗ $ kubectl get pods-nkube-system-lk8s-appkube-dns-owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES coredns-5dd5756b68-m4g7n1/1 Running03d3h192.168.18.67 calico-ipam-control-planenonenonecoredns-5dd5756b68-p9p4r1/1 Running03d3h192.168.18.71 calico-ipam-control-planenonenonemaster ✗ $ kubectl get configmap-nkube-system coredns-oyaml apiVersion: v1 data: Corefile:|.:53{errors health{lameduck 5s}ready kubernetes cluster.local in-addr.arpa ip6.arpa{pods insecure fallthrough in-addr.arpa ip6.arpa ttl30}prometheus :9153 forward./etc/resolv.conf{max_concurrent1000}cache30loop reload loadbalance}kind: ConfigMap metadata: creationTimestamp:2026-09-23T03:28:43Zname: coredns namespace: kube-system resourceVersion:271uid: a5741f28-799b-4f9a-acac-f551b44bbbd7CoreDNS Corefile中的关键字:53: 在所有区域中通过端口53提供DNS服务kubenetes cluster.local ...: 处理集群记录pods insecrure: 为容器IP地址启用A记录ttl 30: 设置TTL为30s; fallthrough: 将未匹配的反向查询结果传递给下一个插件处理。forward . /etc/resolv.conf: 将非集群查询发送到节点的resolv.conf文件中所指定的上游解析器进行处理。cache 30: 缓存答案持续30s以减少延迟和负载。health, ready: 暴漏由k8s探针使用的 health/readiness endpointsprometheus :9153: 公开用于数据爬取的指标信息reload: 会监控Corefile中的变化并重新加载CoreDNS的配置而无需重启Pod。这样就能让配置更加迅速生效loadbalance: 随机排列A/AAAA记录的顺序并轮换上游节点以使客户端负载在各个端点上分布得更均衡。loop: 能够检测并打破DNS递归循环例如由于配置错误导致的CoreDNS将请求转发给另外一个resolver而该resolver又再次将请求转发会CoreDNS的情况这样可以避免堆栈溢出和过高的CPU使用率。检查Host/Node解析器master ✗ $dockerexec-itcalico-ipam-worker /bin/bash rootcalico-ipam-worker:/# cat /etc/resolv.conf# Generated by Docker Engine.# This file can be edited; Docker Engine will not make further changes once it# has been modified.nameserver192.168.48.1 search.options edns0 trust-ad ndots:0# Based on host file: /etc/resolv.conf (internal resolver)# ExtServers: [host(127.0.0.53)]# Overrides: []# Option ndots from: internalnameserver 192.168.48.1: Node/container DNS 指向docker网桥网关宿主机解析器路径。search .: 别给我加任何后缀我给什么域名你就查什么一个字都别多拼。如果是云厂商提供的云主机一般这里会跟着云厂商的上级域名options edns0 trust-ad ndots:0启用了EDNS信任AD位ndots:0将名称视为绝对名称不进行搜索域展开检查Pod DNS配置使用exec进入到一个正在运行的Pod中查看其解析设置。master ✗ $ kubectlexec-itmultitool-1-hnkl4 --sh/# cat /etc/resolv.confsearch default.svc.cluster.local svc.cluster.local cluster.local nameserver10.96.0.10 options ndots:5search domains: 搜索域用于名称解析的自动域名补全这些域会自动附加到短名称域名后面例如从default命名空间中nginx会展开为nginx.default.svc.cluster.local然后是nginx.svc.cluster.local接着是nginx.cluster.localnamserver: kube-dns 服务的ClusterIP(CoreDNS)。所有的Pod DNS查询都会发送到这里options ndots:5: 点数少于5的域名将会被视为相对域名解析系统会先尝试使用后缀进行搜索然后尝试使用绝对FQDN进行解析。这样对于那些较短的外部域名来说可以生成更多的查询语句。Kubernetes 会引入集群搜索域名机制并将容器指向 CoreDNS 进行解析因此集群内部使用的简短名称可以自动完成解析而ndots:5这样的简短外部名称则可能优先使用这些后缀进行解析。andrew•~»dockernetwork inspect kind[15:24:08][{Name:kind,........IPAM:{Driver:default,Options:{},Config:[{Subnet:fc00:f853:ccd:e793::/64},{Subnet:192.168.48.0/20,Gateway:192.168.48.1}]},........}]服务名称解析示例/# dig nginx-service;DiG9.16.20nginx-service;;global options: cmd;;Got answer:;;-HEADER-opcode: QUERY, status: SERVFAIL, id:15427;;flags: qr rd;QUERY:1, ANSWER:0, AUTHORITY:0, ADDITIONAL:1;;WARNING: recursion requested but not available;;OPT PSEUDOSECTION:;EDNS: version:0, flags:;udp:4096;COOKIE: 684ad39f0022a274(echoed);;QUESTION SECTION:;nginx-service. IN A;;Query time:123msec;;SERVER:10.96.0.10#53(10.96.0.10);;WHEN: Sat Sep2607:57:52 UTC2026;;MSG SIZE rcvd:54查询裸名称nginx-service未应用Pod的搜索域dig显示最终的问题为绝对名称nginx-service未附加任何后缀公共/根DNS中不存在该记录因此 10.96.0.10 上的CoreDNS返回SERVFAIL。在 Kubernetes 中短 Service 名称需要结合集群搜索后缀例如nginx-service.namespace.svc.cluster.local才能解析或者使用dig search nginx-service来应用/etc/resolv.conf中的搜索域。使用dig解析时如果使用search会使用/etc/resolv.conf中指定的域名后缀/# dig search nginx-service;DiG9.16.20search nginx-service;;global options: cmd;;Got answer:;;WARNING: .local is reservedforMulticast DNS;;You are currently testing what happens when an mDNS query is leaked to DNS;;-HEADER-opcode: QUERY, status: NOERROR, id:61546;;flags: qr aa rd;QUERY:1, ANSWER:1, AUTHORITY:0, ADDITIONAL:1;;WARNING: recursion requested but not available;;OPT PSEUDOSECTION:;EDNS: version:0, flags:;udp:4096;COOKIE: 870917ebc77d0341(echoed);;QUESTION SECTION:;nginx-service.default.svc.cluster.local. IN A;;ANSWER SECTION: nginx-service.default.svc.cluster.local.30IN A10.96.102.172;;Query time:0msec;;SERVER:10.96.0.10#53(10.96.0.10);;WHEN: Sat Sep2608:08:17 UTC2026;;MSG SIZE rcvd:135search: 指示 dig使用/etc/resolv.conf的Pod搜索域短名称nginx-service被展开为nginx-service.default.svc.cluster.local(位于default命名空间)CoreDNS返回该Service的ClusterIP展示了通过该命名空间搜索后缀实现的集群服务发现。跨命名空间域名解析接下来我们进入foo命名空间的 mutitool-3 中的Pod检查它的DNS配置master ✗ $ kubectlexec-itmultitool-3-92ztr-nfoo --sh1↵ /# cat /etc/resolv.confsearch foo.svc.cluster.local svc.cluster.local cluster.local nameserver10.96.0.10 options ndots:5基于命名空间搜索在命名空间foo中运行时会将第一个搜索后缀设置为foo.svc.cluster.local而不是default.svc.cluster.local短名称解析向nginx这样的名称首先会被解析为nginx.foo.svc.cluster.local, 之后才会使用更通用的集群后缀表示resolve target:nameserver 10.96.0.10是所有Pod所使用的CoreDNS服务的IP地址kube-dns。ndots行为对所有ndots:5的域名会先尝试使用搜索后缀来匹配少于包含五个点的名称只有在无法匹配结果的情况下才会将其视为绝对的FQDN。/# dig search nginx-service;DiG9.16.20search nginx-service;;global options: cmd;;Got answer:;;-HEADER-opcode: QUERY, status: SERVFAIL, id:50872;;flags: qr rd;QUERY:1, ANSWER:0, AUTHORITY:0, ADDITIONAL:1;;WARNING: recursion requested but not available;;OPT PSEUDOSECTION:;EDNS: version:0, flags:;udp:4096;COOKIE: 6a6460267effaa75(echoed);;QUESTION SECTION:;nginx-service. IN A;;Query time:1msec;;SERVER:10.96.0.10#53(10.96.0.10);;WHEN: Sat Sep2608:26:06 UTC2026;;MSG SIZE rcvd:54在命名空间foo中通过短名称nginx-service查询 default 中的服务搜索行为Resolver首先尝试查找nginx-service.foo.svc.cluster.local但发现它不存在随后尝试查找绝对名称nginx-service.结果nginx-service.不是一个有效的公共/根DNS记录因此CoreDNS返回了SERVFAIL修复需要在命名空间中包含该名称(nginx-service.default)或者使用完整的FQDNnginx-service.default.svc.cluster.local/# dig search nginx-service.default;DiG9.16.20search nginx-service.default;;global options: cmd;;Got answer:;;WARNING: .local is reservedforMulticast DNS;;You are currently testing what happens when an mDNS query is leaked to DNS;;-HEADER-opcode: QUERY, status: NOERROR, id:54538;;flags: qr aa rd;QUERY:1, ANSWER:1, AUTHORITY:0, ADDITIONAL:1;;WARNING: recursion requested but not available;;OPT PSEUDOSECTION:;EDNS: version:0, flags:;udp:4096;COOKIE: 00d55dc943077c3c(echoed);;QUESTION SECTION:;nginx-service.default.svc.cluster.local. IN A;;ANSWER SECTION: nginx-service.default.svc.cluster.local.30IN A10.96.102.172;;Query time:0msec;;SERVER:10.96.0.10#53(10.96.0.10);;WHEN: Sat Sep2608:31:50 UTC2026;;MSG SIZE rcvd:135添加.default命名空间为解析器提供了足够的上下文将名称展开为nginx-service.default.svc.cluster.localCoreDNS将该FQDN解析为Service的ClusterIP要点短名称通过搜索域依赖于当前活动命名空间包含命名空间或使用完整的FQDN可得到确定性的结果。总结Kubelet 配置每个 Pod 的/etc/resolv.conf使其使用kube-dnsClusterIPCoreDNS并注入命名空间作用域的搜索域。CoreDNS 提供集群 DNS 记录Service以及经由无头 Service 的 Pod A 记录并将外部查询转发给上游解析器。使用ndots:5这样的解析器选项驱动搜索展开短名称通过搜索后缀在命名空间内解析跨命名空间查询需要带上命名空间或完整的FQDN例如service.ns.svc.cluster.local