K3s pod 内部 resolv.conf 被覆盖导致 DNS 解析异常

11次阅读

K3s覆盖/etc/resolv.conf是为启用Coredns+dnsmasq本地DNS代理,设nameserver 127.0.0.1,但基础镜像常无dnsmasq导致解析失败;需显式配置dnsPolicy或挂载自定义resolv.conf修复。

K3s pod 内部 resolv.conf 被覆盖导致 DNS 解析异常

在 K3s 集群中,Pod 启动后 /etc/resolv.conf 被覆盖为仅含 nameserver 127.0.0.1(或指向 CoredNS 的本地代理),但实际 CoreDNS 并未监听该地址,或 Pod 网络无法访问该地址,从而导致 DNS 解析失败。

为什么 K3s 会覆盖 resolv.conf?

K3s 默认使用 CoreDNS + dnsmasq 插件(通过 k3s-agent 内置的轻量 DNS 代理)提供集群 DNS 服务。它会自动将 Pod 的 resolv.conf 设置为:

  • nameserver 127.0.0.1(指向 Pod 内部的 dnsmasqcoredns 本地监听)
  • search .svc.cluster.local svc.cluster.local cluster.local
  • options ndots:5

但这个机制依赖两个前提:Pod 必须运行在支持 hostNetwork: false + dnsPolicy: ClusterFirst 的标准 CNI 网络下,且容器内需有 dnsmasq 或能响应 127.0.0.1:53 的 DNS 代理进程——而大多数基础镜像(如 Alpine、BusyBox、Distroless)并不自带,也**不会自动注入**。

常见触发场景

以下情况容易暴露该问题:

  • 使用 hostNetwork: true 的 Pod:K3s 不会注入 127.0.0.1,但可能仍覆盖原有 resolv.conf 为错误内容
  • 自定义镜像未安装 dnsmasqcoredns,却继承了 K3s 的默认 dnsPolicy
  • 使用 initContainer 或多阶段构建时,resolv.conf 被挂载覆盖或写入失败
  • K3s 版本升级后,dnsPolicy 行为变更(如 v1.25+ 对 hostNetwork Pod 的处理更严格)

快速修复方法

根据实际需求选择一种或组合使用:

  • 显式指定 DNS 配置:在 Pod spec 中设置 dnsPolicy: None 并手动提供 dnsConfig
  • 回退到集群 DNS:改用 dnsPolicy: ClusterFirstWithHostNet(仅限 hostNetwork: true 场景)
  • 跳过自动覆盖:挂载只读空文件覆盖 /etc/resolv.conf,例如:
    volumeMounts:
    - name: resolv-conf
      mountPath: /etc/resolv.conf
      readOnly: true
    volumes:
    - name: resolv-conf
      configMap:
        name: custom-resolv
    其中 custom-resolv 包含你期望的 nameserver 10.43.0.10(K3s CoreDNS ClusterIP)
  • 验证 CoreDNS 可达性:进入 Pod 执行 nslookup kubernetes.default.svc.cluster.local 10.43.0.10,确认 CoreDNS 是否正常响应

长期建议

避免“覆盖即生效”的隐式行为:

  • 所有生产 Pod 显式声明 dnsPolicy,不依赖默认值
  • 基础镜像中预装 dnsmasq(仅当需 127.0.0.1:53 代理)或统一使用 ClusterFirst + 10.43.0.10
  • 通过 kubectl get svc -n kube-system 确认 CoreDNS Service 的 ClusterIP(通常是 10.43.0.10),并在文档中标注为集群 DNS 地址
  • 若使用 hostNetwork,优先考虑 dnsPolicy: Default(复用宿主机 resolv.conf),并确保宿主机 DNS 可用
text=ZqhQzanResources