CoreDNS 在 Kubernetes 集群中承担着内部服务发现的角色,所有 Pod 的域名解析请求都会先经过它。如果 CoreDNS 配置不当,轻则解析延迟增加,重则服务之间无法通过 Service 名称通信。理解 Corefile 的语法和插件链机制,是排查和优化 DNS 问题的第一步。

CoreDNS 的核心配置文件 Corefile 怎么编写
Corefile 是 CoreDNS 的主配置文件,采用类似 Caddy 的语法。一个 Corefile 可以包含多个服务器块,每个块由一组地址和区域开头,后跟大括号包裹的插件列表。例如监听 53 端口并处理所有区域的基础块写作 . :53,其中点号代表根区域,即匹配所有域名查询。插件按顺序排列,查询请求会依次经过每个插件,直到某一个插件返回响应或最终落入转发逻辑。
每个插件都有自己独立的参数,但整体结构非常直观。常见的插件包括 errors 用于记录错误日志、log 输出每条查询、health 提供健康检查端点、ready 提供就绪检查、kubernetes 实现集群服务发现、prometheus 暴露指标、forward 将请求转发到上游 DNS、cache 缓存查询结果、loop 检测转发环路、reload 支持配置热加载、loadbalance 在多个 A 记录之间做轮询。
下面是一个最小可用的 Corefile 示例:
.:53 {
errors
log
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
}其中 kubernetes 插件监听了 cluster.local 以及反向解析区域 in-addr.arpa 和 ip6.arpa。pods insecure 表示允许解析 Pod IP 对应的域名,但不验证 Pod 是否存在;fallthrough 表示当插件无法在该区域内找到记录时,将请求传递给下一个插件,而不是直接返回 NXDOMAIN。这个配置适合大多数标准集群,但生产环境往往需要根据实际网络拓扑做调整。
Kubernetes 中 CoreDNS 的运维配置
在 Kubernetes 集群中,CoreDNS 通常以 Deployment 方式运行,其配置文件存储在名为 coredns 的 ConfigMap 中。修改 ConfigMap 后,可以通过 kubectl rollout restart deployment/coredns -n kube-system 或等待 reload 插件自动加载。官方推荐启用 reload 插件,这样在 ConfigMap 变化后无需重启 Pod,CoreDNS 会自动检测并重新加载 Corefile。
当集群需要访问内部私有域名或者使用特定的上游 DNS 服务器时,可以在 Corefile 中增加专门的服务器块。例如企业内网有一个私有域 internal.ipipp.com,所有该区域的查询应转发到内网 DNS 服务器 10.0.0.53,而其他域名仍走默认上游。配置片段可以写成:
internal.ipipp.com:53 {
errors
log
forward . 10.0.0.53
cache 30
}这种区域级别的转发块需要放在根区域块之前,因为 CoreDNS 会优先匹配更具体的区域。同时,根区域块中的 forward . /etc/resolv.conf 保持默认上游,私有域请求则被专门的块拦截。如果私有域解析失败,CoreDNS 会返回 SERVFAIL,而不会回退到根区域块,所以上游地址必须保证可达。
此外,还可以通过 hosts 插件将固定域名映射到特定 IP,适用于少量静态记录的场景。例如在 Corefile 中加入:
.:53 {
hosts {
192.168.1.100 gitlab.internal
192.168.1.101 registry.internal
fallthrough
}
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
forward . /etc/resolv.conf
cache 30
}这里 hosts 插件先匹配静态记录,fallthrough 表示如果没有命中则继续交给后续插件处理,避免影响集群内部服务发现。需要注意的是,hosts 插件的记录不会自动同步到所有节点,只对经过 CoreDNS 的查询生效,因此必须保证所有 Pod 的 DNS 请求都指向 CoreDNS 服务。
forward、cache 与负载均衡配置详解
forward 插件是 CoreDNS 与外部 DNS 通信的关键,它支持同时配置多个上游服务器,并按照指定策略分发请求。常用策略包括 random 随机选择、round_robin 轮询,以及 sequential 顺序尝试。例如同时使用两个公共 DNS 和两个内部 DNS:
forward . 223.5.5.5 114.114.114.114 10.0.0.53 {
policy random
max_fails 3
expire 10s
health_check 5s
}这里 max_fails 3 表示连续三次健康检查失败后将该上游标记为不可用,expire 10s 指定失败状态持续 10 秒后重新尝试,health_check 5s 每 5 秒探测一次上游。如果上游 DNS 响应缓慢,可以调整 policy 为 round_robin 来均衡负载,但要注意不同上游返回的记录可能不一致,对于需要依赖地理位置解析的场景需要谨慎。
cache 插件可以显著降低外部 DNS 查询延迟,并减少上游服务器压力。其配置格式为 cache [TTL] [ZONES...],例如 cache 30 表示缓存成功响应 30 秒,失败响应默认缓存 5 秒。更精细的控制可以写成:
cache {
success 9984 30
denial 9984 5
prefetch 5
serve_stale
}success 和 denial 的第一个参数是缓存容量,单位是条目数,第二个参数是 TTL 秒数。prefetch 5 表示在缓存过期前 5 秒主动刷新热门记录,serve_stale 允许在上游不可用时返回过期的缓存内容,能有效提高可用性。不过缓存也会带来污染风险,如果上游记录频繁变更,需要适当调低 TTL 或针对特定区域关闭缓存。
对于集群内部的 Service 解析,loadbalance 插件可以对返回的多个 A 记录进行轮询,避免所有 Pod 都连到同一个后端。它默认对 kubernetes 插件返回的结果生效,无需额外参数。如果使用 forward 插件解析外部域名并希望也做负载均衡,可以在 forward 块内单独启用 loadbalance,但需要确认上游返回的记录是否适合轮询。
排查 CoreDNS 解析故障的实用方法
当 Pod 无法解析 Service 名称时,第一步是确认 CoreDNS 自身的健康状态。执行 kubectl get pods -n kube-system -l k8s-app=kube-dns 检查 Pod 是否 Running,再使用 kubectl logs -n kube-system -l k8s-app=kube-dns 查看日志。如果日志中大量出现 i/o timeout 或 no upstream host,说明 CoreDNS 无法连接到上游 DNS,需要检查节点网络和 /etc/resolv.conf 中的上游地址是否正确。
接着验证 Pod 的 DNS 配置。进入一个测试 Pod,执行 cat /etc/resolv.conf,确认 nameserver 指向 CoreDNS 的 ClusterIP,并且 search 中包含正确的命名空间和集群域。如果 nameserver 指向了宿主机的 DNS 或公网 DNS,会导致 Service 名称解析失败。这通常是因为 kubelet 启动参数 --cluster-dns 没有正确设置,或者 Pod 的 dnsPolicy 设置为了 Default。
在 Corefile 中启用 prometheus 插件后,可以通过 curl http://coredns-service:9153/metrics 查看请求量、错误率、缓存命中率等指标。如果发现 coredns_dns_request_duration_seconds 的 P99 延迟持续升高,可能是缓存容量不足或上游 DNS 响应慢。可以通过增加 cache 容量、调整 forward 策略、限制单个客户端的 QPS 来缓解。ratelimit 插件可以按 IP 或前缀限制请求速率,保护 CoreDNS 不被突发流量打垮。
另一个值得注意的问题是 CoreDNS 的副本数和资源限制。生产环境建议至少运行两个副本,并配置 Pod 反亲和性,避免多个副本调度到同一节点。资源方面,请求和限制至少设置为 CPU 100m、内存 128Mi,具体数值可以根据集群规模调整。当副本数不足或资源被限流时,DNS 请求会排队甚至超时,表现为服务间调用间歇性失败,因此监控 CoreDNS 自身的 CPU 节流和内存使用同样重要。

