k8s集群-CoreDNS配置踩坑

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 的其他配置要点

  1. 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 变更时这里要同步改。
  2. 两处 template IN PTR:内网 111/120 网段的反向解析直接返回 NXDOMAIN,防止私网 PTR 查询被 forward 到公网 DNS 空等超时(这个问题我之前在别的机器上遇到过,CoreDNS 日志刷 i/o timeout)。
  3. 扩容/调整走这条线(不重建):
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
  1. 集群规模上去后可以部署 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)会把超时带到集群里。

七、参考资料

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇