☰
深入理解kubernetes - 第五章 Kubernetes DNS
2026/9/27 5:43:09 网站建设 项目流程

在这个实验环境中,我们将学习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.local
  • CoreDNS应答针对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-worker2<none><none>multitool-1-hnkl41/1 Running02d2h192.168.131.131 calico-ipam-worker<none><none>multitool-1-nh4qg1/1 Running02d2h192.168.18.73 calico-ipam-control-plane<none><none>multitool-2-6jbdt1/1 Running02d2h192.168.131.132 calico-ipam-worker<none><none>multitool-2-jql6b1/1 Running02d2h192.168.18.72 calico-ipam-control-plane<none><none>multitool-2-zlm2k1/1 Running02d2h192.168.112.130 calico-ipam-worker2<none><none>nginx-deployment-55d7bb4b86-j5q5j1/1 Running025h192.168.112.132 calico-ipam-worker2<none><none>nginx-deployment-55d7bb4b86-lqswq1/1 Running025h192.168.131.133 calico-ipam-worker<none><none>

确认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.10<none>53/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-app=kube-dns kubernetes.io/cluster-service=true kubernetes.io/name=CoreDNS Annotations: endpoints.kubernetes.io/last-change-trigger-time:2026-09-23T04:00:29Z Subsets: Addresses:192.168.18.67,192.168.18.71 NotReadyAddresses:<none>Ports: 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-app=kube-dns-owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES coredns-5dd5756b68-m4g7n1/1 Running03d3h192.168.18.67 calico-ipam-control-plane<none><none>coredns-5dd5756b68-p9p4r1/1 Running03d3h192.168.18.71 calico-ipam-control-plane<none><none>
master ✗ $ 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:43Z"name: coredns namespace: kube-system resourceVersion:"271"uid: a5741f28-799b-4f9a-acac-f551b44bbbd7

CoreDNS 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 endpoints
  • prometheus :9153: 公开用于数据爬取的指标信息
  • reload: 会监控Corefile中的变化,并重新加载CoreDNS的配置,而无需重启Pod。这样就能让配置更加迅速生效
  • loadbalance: 随机排列A/AAAA记录的顺序,并轮换上游节点,以使客户端负载在各个端点上分布得更均衡。
  • loop: 能够检测并打破DNS递归循环(例如,由于配置错误导致的CoreDNS将请求转发给另外一个resolver,而该resolver又再次将请求转发会CoreDNS的情况),这样可以避免堆栈溢出和过高的CPU使用率。

检查Host/Node解析器

master ✗ $dockerexec-itcalico-ipam-worker /bin/bash root@calico-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: internal
  • nameserver 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:5
  • search domains: 搜索域用于名称解析的自动域名补全,这些域会自动附加到短名称域名后面,例如从default命名空间中,nginx会展开为nginx.default.svc.cluster.local,然后是nginx.svc.cluster.local,接着是nginx.cluster.local
  • namserver: 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.20<<>>nginx-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.20<<>>+search 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:135
  • +search: 指示 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.20<<>>+search 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.20<<>>+search 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.local
  • CoreDNS将该FQDN解析为Service的ClusterIP
  • 要点:短名称通过搜索域依赖于当前活动命名空间;包含命名空间或使用完整的FQDN可得到确定性的结果。

总结

  • Kubelet 配置每个 Pod 的/etc/resolv.conf,使其使用kube-dnsClusterIP(CoreDNS),并注入命名空间作用域的搜索域。
  • CoreDNS 提供集群 DNS 记录(Service,以及经由无头 Service 的 Pod A 记录),并将外部查询转发给上游解析器。
  • 使用ndots:5这样的解析器选项驱动搜索展开;短名称通过搜索后缀在命名空间内解析
  • 跨命名空间查询需要带上命名空间或完整的FQDN(例如:service.ns.svc.cluster.local)

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询