在 Kubernetes 中,服务之间通过服务名进行通信,而不是硬编码 IP 地址。这一机制的核心依赖是 Kubernetes DNS 服务。本文将全面解析 K8s 内部 DNS 的工作原理、服务名解析机制、常见配置结构以及如何进行调试,帮助你彻底搞懂:Pod 内访问服务名到底发生了什么?
一、Kubernetes DNS 服务是什么?
Kubernetes DNS 服务是集群内的一个基础设施组件,负责为集群中的 Service、Pod 等对象提供域名解析能力。默认情况下,Kubernetes 会自动部署一个 DNS 解析服务(如 CoreDNS 或 kube-dns),并在所有 Pod 中自动配置 DNS 服务器地址。
默认的 DNS 实现:CoreDNS
- 现代版本的 K8s 默认使用 CoreDNS,其部署在 kube-system 命名空间。
- DNS 服务器的地址通常是:10.96.0.10(取决于 Service CIDR 设置)。
- 所有 Pod 启动时,都会在 /etc/resolv.conf 中配置此地址作为 DNS 服务器。
二、服务名解析的基础结构
Kubernetes 中服务名是有层级结构的 DNS 名称。一个服务在集群中的完整域名(FQDN)格式如下:
<服务名>.<命名空间>.svc.cluster.local举例:
- 服务名:my-svc
- 命名空间:default
- 完整 FQDN:my-svc.default.svc.cluster.local
当 Pod 访问一个服务名如 http://my-svc 时,实际上是通过 DNS 补全为完整域名进行解析的。
三、DNS 补全机制详解
每个 Pod 的 /etc/resolv.conf 文件中,通常包含以下搜索域配置:
search default.svc.cluster.local svc.cluster.local cluster.local这意味着当你在 Pod 中访问 my-svc,DNS 查询会依次尝试以下域名:
- my-svc.default.svc.cluster.local
- my-svc.svc.cluster.local
- my-svc.cluster.local
Kubernetes DNS 服务会尝试解析这些域名,并返回对应的 IP 地址(通常是 ClusterIP)。
四、DNS 是如何解析服务名的?
CoreDNS 使用内置的 kubernetes 插件,动态地将服务名映射为服务 IP。
一个典型的 CoreDNS 配置如下:
.:53 {
errors
health
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}其中,kubernetes cluster.local 表示 CoreDNS 负责解析 *.cluster.local 的域名。
当接收到 DNS 查询时,CoreDNS 会:
- 查询当前服务注册表;
- 根据服务名和命名空间查找对应的服务;
- 返回该服务的 ClusterIP 地址。
五、不同服务类型的 DNS 行为差异
1. ClusterIP 服务
最常见的类型,DNS 记录解析为单个 IP 地址,即 Service 的 ClusterIP。
my-svc.default.svc.cluster.local → 10.96.1.252. Headless Service(无头服务)
当 clusterIP: None 时,CoreDNS 会返回后端 Pod 的 IP 列表,而不是一个虚拟的 Service IP。
apiVersion: v1
kind: Service
metadata:
name: my-headless
spec:
clusterIP: None
selector:
app: backend
ports:
- port: 80DNS 查询将返回每个匹配 Pod 的 A 记录,支持 StatefulSet 中使用 Pod 子域名访问。
pod-1.my-headless.default.svc.cluster.local → Pod IP3. ExternalName 服务
这种服务类型通过 CNAME 把服务名映射到外部域名:
apiVersion: v1
kind: Service
metadata:
name: external-svc
spec:
type: ExternalName
externalName: www.example.comDNS 查询结果为:
external-svc.default.svc.cluster.local → www.example.com(CNAME)六、DNS 在 Pod 中的配置路径
在每个 Pod 中:
- DNS 服务地址:默认由 kubelet 自动注入,指向 CoreDNS 的 ClusterIP;
- 搜索域:确保短名称能自动补全为完整 FQDN;
- 使用顺序:应用程序发起域名查询 → 搜索路径补全 → CoreDNS 响应 IP。
cat /etc/resolv.conf
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5七、实用 DNS 调试命令
当服务间通信失败时,优先排查 DNS 是否解析成功:
1. 查看 DNS 搜索路径
kubectl exec my-pod -- cat /etc/resolv.conf2. 测试 DNS 解析
kubectl exec my-pod -- nslookup my-svc
kubectl exec my-pod -- dig my-svc.default.svc.cluster.local3. 检查 CoreDNS 是否正常运行
kubectl get pods -n kube-system -l k8s-app=kube-dns
kubectl logs -n kube-system -l k8s-app=kube-dns4. 使用 busybox 进行 DNS 测试
kubectl run -it --rm dns-test --image=busybox:1.28 --restart=Never -- nslookup my-svc八、常见问题与排查建议
问题 | 原因 | 排查建议 |
无法解析服务名 | CoreDNS 服务未运行;resolv.conf 配置错误 | 查看 CoreDNS 状态;验证 Pod 内 DNS 配置 |
Headless Service 无法解析 Pod IP | Service selector 不匹配;Pod 标签错误 | 检查 selector、Pod 标签 |
ExternalName 无法访问 | CoreDNS 无外部解析能力;Pod 无网络访问权限 | 验证是否能直接 ping 外部域名 |
延迟高、间歇性失败 | DNS 缓存冲突;CoreDNS 配置错误 | 增加 cache 配置,查看 CoreDNS 负载状态 |
九、进阶:与 Service Mesh(如 Istio)的关系
在引入 Service Mesh(如 Istio)后,DNS 名称依然是服务通信的重要部分,但调用路径会经由 sidecar(如 Envoy)代理处理。
例如:
- 应用访问 my-svc.default.svc.cluster.local
- 请求先被拦截到 Envoy,然后转发到真实 IP
- DNS 仍由 CoreDNS 提供服务名解析
十、总结
Kubernetes DNS 服务是集群中服务发现的基石,它通过 CoreDNS 实现了自动的服务名解析,极大简化了微服务的部署与调用。掌握 DNS 名称结构、补全逻辑和调试方法,是每个 K8s 使用者不可或缺的技能。
当你理解了
my-svc.default.svc.cluster.local 背后的解析机制,你就掌握了 Kubernetes 网络通信的第一道大门。