内网kubernetes dns解析失败主因是coredns默认继承节点/etc/resolv.conf作为上游,而内网节点常无有效dns;解法是编辑coredns configmap,将forward . /etc/resolv.conf替换为可信内网dns地址,并验证上游可达性。

内网部署 Kubernetes 时,DNS 解析失败几乎必然发生——不是因为配置错了,而是默认设计就依赖外部 DNS,而内网节点通常没有连通公网的 /etc/resolv.conf 或上游解析能力。核心解法不是“修 Pod”,而是切断对不可控外部 DNS 的隐式依赖。
确认 CoreDNS 是否在用节点的 resolv.conf 做上游转发
这是绝大多数内网 DNS 失败的根源:CoreDNS 启动时会读取所在节点的 /etc/resolv.conf,并把里面所有 nameserver 当作上游。如果节点本身 resolv.conf 是空的、写的是 127.0.0.53(systemd-resolved 回环)、或指向一个内网根本不存在的 DNS 服务器,CoreDNS 就会卡在转发环节,日志里反复出现 i/o timeout 或 unreachable backend。
验证方式:
- 进任意一个
corednsPod:kubectl exec -it -n kube-system coredns-xxxx -- sh - 检查它的
/etc/resolv.conf:cat /etc/resolv.conf—— 如果看到127.0.0.53或空内容,问题已定位 - 查 CoreDNS 日志:
kubectl logs -n kube-system -l k8s-app=kube-dns | grep -i "timeout\|unreachable"
强制 CoreDNS 使用可控的上游 DNS(非节点继承)
不要指望修改节点的 /etc/resolv.conf——内网节点可能成百上千,且 systemd-resolved 行为难以统一。正确做法是让 CoreDNS 忽略节点配置,直接指定可信上游。
编辑 coredns ConfigMap:
kubectl edit configmap coredns -n kube-system
在 .:53 块中,将原来的 forward . /etc/resolv.conf 替换为明确地址,例如:
forward . 10.10.10.1 10.10.10.2
其中 10.10.10.1 是你内网部署的可信 DNS 服务(如 dnsmasq、bind 或 Windows AD DNS),不能是 127.0.0.1 或未监听 UDP 53 的地址。
评估 Kubernetes 集群安全态势,覆盖 RBAC、工作负载安全、网络策略、基础设施即代码(IaC)、运行时监控和密钥管理等 30 项控制项……
注意:
- 若内网无 DNS 服务,可临时用
forward . 8.8.8.8测试,但生产环境必须收敛到内网可控源 - 修改后 CoreDNS Pod 会自动滚动更新,无需手动重启
- 确保该上游 DNS 服务器允许来自 CoreDNS Pod 所在节点网段的 UDP 53 请求
避免 ndots 和 search 导致的无效查询放大
Pod 默认的 resolv.conf 含 options ndots:5 和多个 search 域,导致像 curl my-service 这类短域名会先拼出 my-service.default.svc.cluster.local. 等共 5 次查询。一旦某次拼接后域名恰好存在(比如内网有 my-service.internal),就会返回错误 IP;更糟的是,若上游 DNS 响应慢,整个解析会卡满 5 秒超时。
缓解方法(按优先级):
- 在关键业务 Pod 中显式设置
dnsConfig,关闭冗余搜索:dnsConfig: options: - name: ndots value: "1" - 若集群全局控制,可 patch CoreDNS 的
Corefile,加rewrite stop插件拦截无效搜索,但需谨慎评估兼容性 - 避免在应用代码中使用不带点的短域名(如
redis),改用redis.default.svc或完整 FQDN
NodeLocalDNS 不是银弹,内网部署前需验证其上游链路
很多团队启用 NodeLocalDNS 是为了加速,但它只是缓存代理,仍依赖底层 CoreDNS 转发。如果 CoreDNS 的 upstream 不通,NodeLocalDNS 的 169.254.25.10 地址只会更快地返回 NXDOMAIN 或 timeout。
验证要点:
- 查 NodeLocalDNS Pod 日志:
kubectl logs -n kube-system -l k8s-app=nodelocaldns | grep -i "refused\|timeout" - 从 NodeLocalDNS 容器内直连 CoreDNS:
dig @10.96.0.10 kubernetes.default.svc.cluster.local(用实际 CoreDNS ClusterIP) - 若这步失败,说明问题仍在 CoreDNS 层,NodeLocalDNS 配置再正确也无意义
真正关键的不是加了多少层 DNS 组件,而是每一层的上游是否指向一个稳定、低延迟、可审计的内网 DNS 实例——这个实例本身不应再依赖外部网络。










