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 缓存。
CoreDNS 插件链处理流程 CoreDNS 插件链处理流程 Pod DNS 请求 errors health kubernetes cache forward 上游 DNS DNS 响应 说明:集群内域名(如 svc.cluster.local)由 kubernetes 插件直接响应;集群外域名由 forward 插件转发至上游 DNS。

2.2 Pod DNS 解析流程

Pod 内的 DNS 解析行为由 dnsPolicy 字段控制,默认值为 ClusterFirst。解析流程分为以下步骤:

  1. 本地 resolv.conf 构造:kubelet 在创建 Pod 时,根据 dnsPolicy 和 dnsConfig 生成 /etc/resolv.conf 文件。
  2. 查询发起:Pod 内进程调用 gethostbyname 或 getaddrinfo,向 nameserver(即 CoreDNS 的 Cluster IP)发起 DNS 查询。
  3. CoreDNS 处理:CoreDNS 根据查询域名后缀决定由 kubernetes 插件处理(集群内域名)还是由 forward 插件转发(集群外域名)。
  4. 响应返回: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
Pod DNS 解析流程 Pod DNS 解析流程 Pod /etc/resolv.conf nameserver 10.96.0.10 search default.svc.cluster.local CoreDNS Service ClusterIP: 10.96.0.10 CoreDNS Pod 副本 1 (10.244.1.2) 副本 2 (10.244.2.3) kube-system 命名空间 API Server Service/Pod 资源数据 DNS 响应返回 Pod 说明:Pod 通过 ClusterIP 10.96.0.10 访问 CoreDNS,CoreDNS 从 API Server 获取 Service/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 缓存延迟。