k8s集群-CoreDNS配置踩坑
记录时间:2026-10-28
环境:K8s 1.28.15 二进制部署集群(host51-56,arm64);CoreDNS 1.10.1(kube-dns Service 10.96.0.2)
一、背景
CoreDNS 在我们集群里管的是集群内部 Service 名称解析,部署方式是二进制部署 K8s 1.28 时手工 apply 的 kube-system 资源,不走 kubeadm,所以配置全在自己手上。最近看了一篇讲 CoreDNS hosts 插件坑点的文章,翻出来对照我们集群的配置核对了一遍:文章里的坑我们恰好避开了,但那个坑的杀伤力是整个集群 DNS 解析挂掉,值得把机制和验证方法记下来。
二、我们集群的 CoreDNS 部署形态
由一份 coredns.yaml 管理(kubectl apply -f coredns.yaml),内容分四块:
| 资源 | 作用 |
|---|---|
| ServiceAccount + ClusterRole/Binding | CoreDNS 访问 endpoints/services/pods/namespaces(含 endpointslices) |
| ConfigMap(coredns) | Corefile 主配置 |
| Deployment(coredns,kube-system) | 实例,2 副本 |
| Service(kube-dns) | ClusterIP 10.96.0.2,53 UDP/TCP + 9153 metrics |
Deployment 里几处是刻意这么写的:
| 配置 | 值 | 为什么这么写 |
|---|---|---|
replicas |
2 | 单副本时 readiness 失败会摘掉唯一 endpoint,kube-dns 无后端,全集群解析直接失败(不是变慢) |
podAntiAffinity |
required(topologyKey hostname) | 2 副本必须分散到不同节点,preferred 不保证,节点抖动时会一起挂 |
priorityClassName |
system-cluster-critical | 调度优先级 |
tolerations |
CriticalAddonsOnly | 允许调度到带该污点的节点 |
| 镜像 | coredns/coredns:1.10.1 | 离线环境每节点都要有镜像,缺镜像的节点 ImagePullBackOff |
现行 Corefile(重点看插件顺序):
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
fallthrough in-addr.arpa ip6.arpa
}
hosts {
192.168.111.156 reg-hub.example.cn
fallthrough
}
template IN PTR 111.168.192.in-addr.arpa {
rcode NXDOMAIN
}
template IN PTR 120.168.192.in-addr.arpa {
rcode NXDOMAIN
}
prometheus :9153
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
三、hosts 插件的那个坑
文章里的故障是这样的:部署 ArgoCD 后 argocd-server 连不上 argocd-redis,日志报:
redis: connection pool: failed to dial after 5 attempts: dial tcp: lookup argocd-redis on 10.43.0.10:53: server misbehaving
排查时有个特别迷惑的点:自定义 hosts 域名解析一切正常(dig 返回预期 IP),CoreDNS 日志里也看不出任何异常,但 Service 域名就是 SERVFAIL:
dig argocd-redis.argocd.cluster.local @10.43.0.10
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL
根因在 Corefile 的插件链上。CoreDNS 的插件按 Corefile 从上到下形成处理链,文章的配置里 hosts 写在 kubernetes 之前,而且 hosts 块里没写 fallthrough。于是任何不在 hosts 记录里的查询(比如所有 Service 域名)走到 hosts 就中断返回失败,后面的 kubernetes 插件和 forward 插件永远执行不到。官方文档写得很明白:”If you want to pass the request to the rest of the plugin chain if there is no match in the hosts plugin, you must specify the fallthrough option.”
出错的配置(文章原样):
.:53 {
...
hosts {
192.168.111.156 reg-hub.example.cn
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
...
forward . /etc/resolv.conf
}
修好的配置(文章原样):
.:53 {
...
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
hosts {
192.168.111.156 reg-hub.example.cn
fallthrough
}
...
forward . /etc/resolv.conf
}
两条修复:给 hosts 加 fallthrough;把 hosts 挪到 kubernetes 后面(防御性,防以后手改 hosts 再出问题)。
我拿这两条核对了我们的 Corefile,都对得上:hosts 块在 kubernetes 后面,fallthrough 也写了。躲开了,但这个顺序和 fallthrough 的组合以后动 Corefile 时不能拆。
文章还有个教训我很认同:排查 DNS 问题必须验证 K8s Service 域名。只测自定义域名”解析正常”就认为 CoreDNS 没问题,正是这次排查绕远路的起点,因为 hosts 记录恰好能解析,掩盖了 kubernetes 解析路径已断的事实。
四、我们集群 CoreDNS 的其他配置要点
- hosts 记录的用途和边界:Corefile 里的
hosts { 192.168.111.156 reg-hub.example.cn }是刻意配置,内网 harbor 域名没有权威 DNS,靠 CoreDNS hosts 让 Pod 内能解析它。注意它只作用于 Pod:kubelet/containerd 拉镜像走的是节点的/etc/resolv.conf(加/etc/hosts),不经 CoreDNS。harbor IP 变更时这里要同步改。 - 两处 template IN PTR:内网 111/120 网段的反向解析直接返回 NXDOMAIN,防止私网 PTR 查询被 forward 到公网 DNS 空等超时(这个问题我之前在别的机器上遇到过,CoreDNS 日志刷
i/o timeout)。 - 扩容/调整走这条线(不重建):
kubectl -n kube-system scale deploy coredns --replicas=2
kubectl -n kube-system edit deploy coredns # anti-affinity 改为 required
kubectl get pods -n kube-system -l k8s-app=kube-dns -o wide
- 集群规模上去后可以部署 dns-autoscaler 接管副本数,我们暂时固定 2 副本。
五、验证
部署或改动 Corefile 后,三类解析都要测,缺一不可:
# 1. 公网域名(forward 路径)
dig -t a www.baidu.com @10.96.0.2
# 2. Service 域名(kubernetes 路径,最容易被漏测、也最容易挂)
dig -t a kubernetes.default.svc.cluster.local @10.96.0.2
# 3. hosts 记录域名(hosts 路径)
dig -t a reg-hub.example.cn @10.96.0.2
Pod 内部验证更贴近真实场景:起一个带 nslookup 的容器,解析 kubernetes.default.svc.cluster.local 和业务 Service 名。2 副本要分布在不同节点:kubectl get pods -n kube-system -l k8s-app=kube-dns -o wide。
六、注意事项
- hosts 插件两件事必须同时做:加 fallthrough、放 kubernetes 插件之后。只做其一都不保险,以后手动加 hosts 记录时先看 Corefile 的位置对不对。
- 动完 Corefile 忘记验证 Service 域名是最常见的假阳性验证。自定义域名正常 ≠ CoreDNS 正常。
- 单副本 CoreDNS 是可用性红线:readiness 失败一次就是全集群 DNS 断供,2 副本加 required 反亲和不是可选项。
- 离线环境给 coredns 换 Harbor 镜像时,要在 kube-system 建好 imagePullSecrets 并加到 Deployment,否则 ImagePullBackOff。
forward . /etc/resolv.conf的解析行为跟着节点 resolv.conf 走,节点上 DNS 配置不干净(比如配了不通的公网 DNS)会把超时带到集群里。
七、参考资料
- CoreDNS hosts 插件坑点解析(CNCF Stack)
- CoreDNS hosts 插件官方文档
- 本仓库相关笔记:
kubernetes/二进制部署K8s1.28集群(arm64版).md(CoreDNS 部署章节)