Kubernetes DNS 架构基础:CoreDNS 工作原理、Pod DNS 解析流程、Service 与 DNS 记录
在 Kubernetes 集群中,DNS 是服务发现的核心基础设施。理解 CoreDNS 的工作原理、Pod 的 DNS 解析流程以及 Service 与 DNS 记录的映射关系,是诊断和规避 DNS 故障的前提。本节将拆解这三层结构,为后续的故障域划分提供理论支撑。
2.1 CoreDNS 工作原理
CoreDNS 是 Kubernetes 1.13 及之后版本的默认 DNS 组件,以 Deployment 形式运行在 kube-system 命名空间下,通常由两个副本构成高可用对。它通过 插件链(Plugin Chain) 处理 DNS 查询请求,每个插件负责一个独立的逻辑功能。
| 插件名称 | 功能职责 | 配置示例(Corefile 片段) |
|---|---|---|
| errors | 将 DNS 错误日志输出到标准输出 | errors |
| health | 提供 HTTP 健康检查端点(默认 :8080/health) | health |
| kubernetes | 将集群内的 Service/Pod 名称解析为 Cluster IP | kubernetes cluster.local in-addr.arpa ip6.arpa |
| prometheus | 暴露 DNS 请求量、延迟等 Prometheus 指标 | prometheus :9153 |
| forward | 将集群外域名(如 baidu.com)转发到上游 DNS |
forward . /etc/resolv.conf |
| cache | 对 DNS 响应进行缓存,降低上游压力 | cache 30 |
| loop | 检测并阻止 DNS 解析环路 | loop |
| reload | 自动加载 Corefile 配置变更 | reload |
| loadbalance | 对 A/AAAA 记录返回顺序做轮询 | loadbalance |
关键设计点: CoreDNS 的
kubernetes 插件直接读取 API Server 中的 Service 和 Pod 资源,无需额外配置 DNS 记录。当 Service 或 Pod 发生变化时,CoreDNS 自动更新内部记录,无需重启。
CoreDNS 的默认 Corefile 配置如下:
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
故障域提示: 当 CoreDNS Pod 所在节点发生网络分区时,
forward 插件可能无法到达上游 DNS,导致集群外域名解析失败;但 kubernetes 插件仍可正常解析集群内 Service,因为其数据源来自本地 API Server 缓存。
2.2 Pod DNS 解析流程
Pod 内的 DNS 解析行为由 dnsPolicy 字段控制,默认值为 ClusterFirst。解析流程分为以下步骤:
- 本地
resolv.conf构造:kubelet 在创建 Pod 时,根据dnsPolicy和dnsConfig生成/etc/resolv.conf文件。 - 查询发起:Pod 内进程调用
gethostbyname或getaddrinfo,向nameserver(即 CoreDNS 的 Cluster IP)发起 DNS 查询。 - CoreDNS 处理:CoreDNS 根据查询域名后缀决定由
kubernetes插件处理(集群内域名)还是由forward插件转发(集群外域名)。 - 响应返回:CoreDNS 将解析结果返回给 Pod,Pod 内的
nscd或应用层缓存可能对结果进行二次缓存。
故障场景: 当 CoreDNS 的 Cluster IP 对应的 Service Endpoint 全部不可用时(例如 CoreDNS Pod 被驱逐),Pod 的
resolv.conf 中配置的 nameserver 将无法响应,导致所有 DNS 解析超时。此时即使集群内其他组件正常,服务发现也会完全中断。
不同 dnsPolicy 的对比:
| dnsPolicy | nameserver 指向 | search 域 | 适用场景 |
|---|---|---|---|
| ClusterFirst | CoreDNS Cluster IP | <ns>.svc.cluster.local svc.cluster.local cluster.local |
默认策略,适用于大多数应用 |
| Default | 节点 /etc/resolv.conf |
继承节点配置 | 需要直接使用节点 DNS 的场景 |
| None | 由 dnsConfig 自定义 |
由 dnsConfig 自定义 |
完全自定义 DNS 配置 |
| ClusterFirstWithHostNet | CoreDNS Cluster IP | <ns>.svc.cluster.local svc.cluster.local cluster.local |
使用主机网络(hostNetwork: true)的 Pod |
2.3 Service 与 DNS 记录
Kubernetes 为每个 Service 自动创建 DNS 记录,格式遵循 RFC 1123 规范。DNS 记录的命名规则决定了 Pod 如何通过域名访问 Service。
| Service 类型 | DNS 记录格式 | 解析结果 | 示例 |
|---|---|---|---|
| ClusterIP | <svc>.<ns>.svc.cluster.local |
Cluster IP(A 记录) | my-svc.default.svc.cluster.local → 10.96.0.50 |
| Headless | <svc>.<ns>.svc.cluster.local |
所有 Pod IP 列表(A 记录集合) | my-headless.default.svc.cluster.local → 10.244.1.5, 10.244.2.6 |
| ExternalName | <svc>.<ns>.svc.cluster.local |
CNAME 记录指向外部域名 | my-ext.default.svc.cluster.local → my-db.example.com |
| NodePort / LoadBalancer | <svc>.<ns>.svc.cluster.local |
Cluster IP(A 记录) | my-lb.default.svc.cluster.local → 10.96.0.100 |
除了标准的 Service 记录,CoreDNS 还会为 Pod 生成 DNS 记录(当 pods insecure 或 pods verified 开启时):
# Pod DNS 记录格式(需开启 pods 插件)
10-244-1-5.default.pod.cluster.local → 10.244.1.5
故障域关键点: 当 Service 的 Cluster IP 对应的 Endpoint 全部不可用时,DNS 记录仍然存在,但访问该 Cluster IP 会导致连接超时。这种“DNS 成功但连接失败”的场景是 DNS 故障域中最隐蔽的问题之一。
Service 的 DNS 记录生命周期与 Service 资源绑定:
- 创建:Service 创建后,CoreDNS 在 30 秒(默认 TTL)内自动添加 A 记录。
- 更新:Service 的 Cluster IP 或 Selector 变更时,CoreDNS 自动更新记录。
- 删除:Service 删除后,CoreDNS 在 TTL 过期后移除记录。
- 故障:CoreDNS 与 API Server 连接中断时,DNS 记录停留在最后一次同步状态,可能导致“DNS 缓存污染”。
架构适配建议: 在 Helm Chart 中为 Service 设置
publishNotReadyAddresses: true,可以确保即使 Pod 未就绪,DNS 记录仍然包含其 IP。这在故障转移场景中可减少 DNS 缓存延迟。