Skip to content

RKE2 集群通过 CoreDNS hosts 插件配置静态域名解析

在 Rancher 创建的 RKE2 集群中,经常遇到这样的需求:集群内的 Pod 需要把某个特定域名(最典型的就是 Rancher Server 自己的域名 rancher.example.com)解析到一个固定 IP,而不是走外部 DNS。比如集群节点无法访问企业 DNS、或希望集群内访问 Rancher 时绕过 LB 直接指向某台固定服务器。

这种场景不需要改每个 Pod 的 hostAliases,也不需要在每个节点改 /etc/hosts 后逐个维护,标准做法是直接修改 RKE2 内置 CoreDNS 的 Corefile,注入 hosts 插件,让整个集群的 DNS 解析层统一返回静态映射。本文基于生产环境的实际操作整理,覆盖 Corefile 修改、滚动重启、Pod 内验证以及 ConfigMap 被 Helm 管理时的持久化注意事项。

一、应用场景与整体思路

典型场景:

  • 通过 Rancher 创建下游 RKE2 集群后,下游集群的 agent(cattle-cluster-agent 等)需要持续访问 Rancher Server 域名。
  • 企业内网 DNS 尚未收录该域名,或希望集群内对该域名的解析固定指向 192.168.10.140
  • 宿主机层面可以在 /etc/hosts 里加映射解决节点自身的解析,但 Pod 的 DNS 查询走的是 CoreDNS,不会读宿主机 hosts 文件,必须在 CoreDNS 层处理。

整体思路:

  1. 编辑 kube-system 命名空间下的 CoreDNS ConfigMap,在 Corefile 中加入 hosts 插件块,写入「IP 域名」映射。
  2. 滚动重启 CoreDNS Deployment 使配置生效。
  3. 在 Pod 内用 nslookup 验证解析结果。

二、修改 CoreDNS ConfigMap

2.1 准备 kubectl 环境

登录 RKE2 的 master 节点宿主机,配置 kubeconfig 和 kubectl:

bash
mkdir -p ~/.kube
cp /etc/rancher/rke2/rke2.yaml ~/.kube/config
ln -sf /var/lib/rancher/rke2/bin/kubectl /usr/local/bin/kubectl

2.2 编辑 ConfigMap 注入 hosts 插件

bash
kubectl edit configmap rke2-coredns-rke2-coredns -n kube-system

说明:RKE2 通过 Helm chart 部署 CoreDNS,ConfigMap 名称在不同 RKE2 版本上可能是 rke2-coredns-rke2-corednsrke2-coredns,以 kubectl get cm -n kube-system | grep coredns 实际查到的为准。

在 Corefile 中 .:53 区块内加入 hosts 插件,修改后的完整 Corefile 示例如下:

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: rke2-coredns-rke2-coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        health {
            lameduck 10s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
            pods insecure
            fallthrough in-addr.arpa ip6.arpa
            ttl 30
        }
        hosts {
            192.168.10.140 rancher.example.com
            fallthrough
        }
        prometheus 0.0.0.0:9153
        forward . /etc/resolv.conf
        cache 30
        loop
        reload
        loadbalance
    }

配置要点:

  • hosts 块内每行一条映射,格式为 IP 域名,与 /etc/hosts 语法一致,可写多行。
  • fallthrough 表示未匹配到的域名继续交给后续插件(这里是 forward)处理,必须保留,否则只有映射表内的域名能解析,其他域名全部失败。
  • hosts 块外,其余插件保持 RKE2 默认配置不动,不要增删。

2.3 滚动重启 CoreDNS

CoreDNS 虽然配置了 reload 插件支持热加载,但 RKE2 场景下建议显式滚动重启,确保所有副本加载到新 Corefile:

bash
kubectl -n kube-system rollout restart deploy/rke2-coredns-rke2-coredns
kubectl -n kube-system rollout status deploy/rke2-coredns-rke2-coredns

三、验证解析生效

起一个临时 Pod 验证集群内解析:

bash
kubectl run dns-test --rm -it --image=harbor.example.com/library/busybox:1.28 --restart=Never -- nslookup rancher.example.com

预期输出中 Address 指向配置的静态 IP:

text
Server:    10.43.0.10
Address 1: 10.43.0.10 kube-dns.kube-system.svc.cluster.local

Name:      rancher.example.com
Address 1: 192.168.10.140

同时验证正常域名解析未受影响(确认 fallthrough 生效):

bash
kubectl run dns-test2 --rm -it --image=harbor.example.com/library/busybox:1.28 --restart=Never -- nslookup kubernetes.default.svc.cluster.local

四、注意事项

4.1 ConfigMap 被 Helm 管理时的持久化问题

RKE2 的 CoreDNS 是通过 Helm chart(rke2-coredns)部署的,ConfigMap 上带有 Helm 的元数据标签。这带来一个风险:直接 kubectl edit 修改的 Corefile 属于"带外修改",当 RKE2 升级或 Helm chart 被重新 reconcile 时,ConfigMap 可能被 chart 的默认值覆盖,hosts 映射丢失。

持久化的正确做法是通过 HelmChartConfig 资源覆盖 chart 的 values,把自定义 Corefile 写进 chart 配置:

bash
kubectl apply -f - <<EOF
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: rke2-coredns
  namespace: kube-system
spec:
  valuesContent: |-
    global:
      clusterDNS: 10.43.0.10
    servers:
    - zones:
      - zone: .
      port: 53
      plugins:
      - name: errors
      - name: health
        configBlock: |-
          lameduck 10s
      - name: ready
      - name: kubernetes
        parameters: cluster.local in-addr.arpa ip6.arpa
        configBlock: |-
          pods insecure
          fallthrough in-addr.arpa ip6.arpa
          ttl 30
      - name: hosts
        configBlock: |-
          192.168.10.140 rancher.example.com
          fallthrough
      - name: prometheus
        parameters: 0.0.0.0:9153
      - name: forward
        parameters: . /etc/resolv.conf
      - name: cache
        parameters: 30
      - name: loop
      - name: reload
      - name: loadbalance
EOF

说明:

  • 如果不确定 chart values 结构,一个稳妥的折中办法是:先 kubectl edit 改 ConfigMap 验证功能,确认生效后再把同样的内容落到 HelmChartConfig 中固化;同时在变更台账里登记"Corefile 有自定义 hosts 映射,RKE2 升级后需复核"。
  • 每次 RKE2 版本升级后,执行 kubectl get cm rke2-coredns-rke2-coredns -n kube-system -o jsonpath='{.data.Corefile}' | grep hosts 确认映射还在。

4.2 其他注意事项

  • hosts 映射中的 IP 变更后需要同步修改 Corefile 并重启 CoreDNS,这类静态映射要登记台账,避免 IP 漂移后集群内解析悄悄指向旧地址。
  • 宿主机 /etc/hosts 的映射(解决节点自身解析)与 CoreDNS 的 hosts 插件(解决 Pod 解析)是两套独立机制,如两侧都需要,应同时维护并保持一致。
  • hosts 插件在 Corefile 中的位置建议放在 kubernetes 之后、forward 之前,确保静态映射优先于上游转发。

五、故障速查表

故障现象可能原因排查与处理
Pod 内 nslookup 域名返回 NXDOMAINhosts 块缺少 fallthrough,或映射行格式错误检查 Corefile 中 hosts 块语法;确认 IP 域名 之间是空格而非其他字符
修改 ConfigMap 后解析未生效CoreDNS 未重启,或改错了 ConfigMap(集群里同时存在 coredns 与 rke2-coredns 两个 cm)kubectl get cm -n kube-system | grep coredns 确认生效的 cm;执行 rollout restart
所有域名都无法解析,CoreDNS Pod CrashLoopBackOffCorefile 语法错误(缩进、花括号不匹配)kubectl logs -n kube-system deploy/rke2-coredns-rke2-coredns 看报错行;修正后重启
RKE2 升级后静态解析丢失ConfigMap 被 Helm chart 重新渲染覆盖按 4.1 节用 HelmChartConfig 固化自定义 Corefile
静态域名可以解析,其他外部域名解析失败hosts 块误删了 fallthrough,或 forward 插件被改动对比第二章的完整 Corefile 示例恢复默认插件链
宿主机上能解析,Pod 里不能解析只改了宿主机 /etc/hosts,未改 CoreDNS按本文修改 CoreDNS ConfigMap;宿主机 hosts 对 Pod 无效