2. Kubernetes DNS 架构基础:CoreDNS 工作原理、Pod DNS 解析流程、kubelet DNS 缓存机制
在深入排查证书轮换引发的 DNS 故障之前,必须首先理解 Kubernetes 集群内 DNS 的完整工作链路。本章将拆解三个核心组件:CoreDNS(集群 DNS 服务端)、Pod DNS 解析流程(客户端请求路径)以及 kubelet DNS 缓存机制(节点级缓存策略)。这三者构成了 Pod 访问 Service 名称或外部域名的全部依赖链。
2.1 CoreDNS 工作原理
CoreDNS 是 Kubernetes 1.13 及之后版本的默认集群 DNS 组件,以 Deployment 形式运行在 kube-system 命名空间下,通常由两个副本构成高可用。其核心架构基于插件链(Plugin Chain),每个 DNS 查询请求会依次经过多个插件处理。
Corefile 配置插件栈,每个插件负责一个独立功能(如 Kubernetes 服务发现、缓存、转发、健康检查)。
CoreDNS 的 kubernetes 插件负责将 Service 名称解析为 Cluster IP。它支持三种查询类型:
- Service 查询:
my-svc.my-namespace.svc.cluster.local→ Cluster IP - Pod 查询:
10-244-1-5.my-namespace.pod.cluster.local→ Pod IP - ExternalName 查询:返回 CNAME 记录
kubernetes 插件将无法响应查询。此时应检查 CoreDNS 的 whoami 插件日志,确认请求是否到达插件链。
2.2 Pod DNS 解析流程
每个 Pod 内的 DNS 解析行为由 /etc/resolv.conf 控制,该文件由 kubelet 在 Pod 启动时注入。解析流程遵循标准的 ndots 规则和 search 域 列表。
| 配置项 | 默认值 | 说明 |
|---|---|---|
nameserver |
10.96.0.10(Cluster IP of kube-dns) | Pod 发送 DNS 查询的目标地址 |
search |
<ns>.svc.cluster.local svc.cluster.local cluster.local |
自动追加的域名后缀列表 |
ndots |
5 | 域名中点数少于该值时,优先尝试 search 域 |
timeout |
5 | 单次查询超时时间(秒) |
attempts |
2 | 查询失败后的重试次数 |
当 Pod 内应用执行 curl http://my-svc 时,glibc 解析器会按以下顺序尝试:
- 检查
my-svc是否包含足够多的点(.)。由于默认ndots=5,而my-svc只有 0 个点,因此优先拼接 search 域。 - 依次查询
my-svc.<ns>.svc.cluster.local、my-svc.svc.cluster.local、my-svc.cluster.local。 - 如果所有 search 域查询均返回 NXDOMAIN,最后查询
my-svc(域名形式)。 - 每次查询都发送 UDP 请求到
10.96.0.10:53(CoreDNS Service IP)。
ndots 值较大时(如默认 5),短域名(如 my-svc)会触发最多 4 次 DNS 查询(3 次 search 域 + 1 次域名)。如果 CoreDNS 响应缓慢或丢包,应用层会感受到明显的延迟累积。证书轮换期间,kubelet 资源争抢可能加剧这一延迟。
2.3 kubelet DNS 缓存机制
kubelet 在节点上运行一个 本地 DNS 缓存(通常以 node-cache 或 kube-dns 缓存形式部署),其核心目的是减少对 CoreDNS 的直接压力,并降低 DNS 查询延迟。在证书轮换场景下,kubelet 的资源争抢可能直接影响缓存进程的健康状态。
Kubernetes 社区推荐的 NodeLocal DNSCache 架构在节点上以 DaemonSet 形式运行一个缓存代理,监听 169.254.20.10:53(或类似链路本地地址),Pod 的 resolv.conf 中的 nameserver 被修改为指向该缓存地址。
| 缓存模式 | 部署方式 | 缓存位置 | 对 CoreDNS 的影响 |
|---|---|---|---|
| 无缓存(默认) | Pod 直接请求 CoreDNS Cluster IP | 无 | CoreDNS 承受全部查询压力 |
| NodeLocal DNSCache | DaemonSet + iptables/IPVS 重定向 | 节点本地(内存) | 缓存命中时 CoreDNS 零负载;未命中时转发 |
| kubelet 内置缓存(实验性) | kubelet 启动参数 --dns-cache-ttl |
kubelet 进程内存 | 仅缓存 kubelet 自身发起的 DNS 查询 |
NodeLocal DNSCache 的典型工作流程如下:
- Pod 发起 DNS 查询,目标为
169.254.20.10:53(链路本地地址)。 - 节点上的
node-cache进程检查本地缓存: - 缓存命中:直接返回响应,TTL 剩余时间递减。
- 缓存未命中:向上游 CoreDNS(
10.96.0.10:53)发起查询,缓存结果后返回。 - 缓存条目遵循 TTL 过期策略,默认与上游 DNS 响应中的 TTL 一致。
node-cache 的指标(如 dns_cache_hits_total、dns_cache_misses_total)。如果命中率突然下降且 CoreDNS 负载飙升,说明缓存层可能已失效。同时检查 kubelet 的 --dns-cache-ttl 参数是否被意外覆盖。