k3s coredns 持久化配置域名解析方案
一、结论
使用 k3s 原生支持的 coredns-custom ConfigMap 配置自定义域名解析,将 ep-223rer700dc089123123.dashscope.cn-bejing.privatelink.aliyuncs.com 解析到内网 IP 10.150.140.1。该配置独立于 k3s 内置清单管理范围,k3s 重启后配置不丢失**,为官方推荐的持久化自定义 DNS 方案。
核心操作仅两步:
- 创建名为
coredns-custom的 ConfigMap(key 以.override结尾,hosts 块内含目标解析条目与fallthrough) -
kubectl rollout restart deployment coredns -n kube-system重载生效
二、背景与问题
场景:私有化环境中,集群内业务需访问 DashScope PrivateLink 终端节点,要求将域名 ep-223rer700dc089123123.dashscope.cn-bejing.privatelink.aliyuncs.com 解析到内网 IP 10.150.140.1。
直接修改 coredns ConfigMap 不可行:
- k3s 通过 AddonController 机制管理内置组件,每次启动时会重新 apply 内置清单
/var/lib/rancher/k3s/server/manifests/coredns.yaml - 通过
kubectl edit cm coredns -n kube-system手动追加的解析条目,在 k3s 重启后会被内置清单覆盖还原 - 该行为是 k3s 的设计预期,不是缺陷,因此必须使用官方预留的扩展入口
三、方案原理
3.1 coredns-custom 扩展入口
k3s 内置的 CoreDNS Corefile 中预置了两条 import 指令:
import /etc/coredns/custom/*.override
import /etc/coredns/custom/*.server
该路径挂载的是名为 coredns-custom 的可选(optional)ConfigMap:
- key 以
.override结尾:内容注入 CoreDNS 主 server 块(.:53)内部,用于追加插件配置(如 hosts) - key 以
.server结尾:内容作为独立 server 块,用于自定义特定域名的完整处理逻辑
coredns-custom 不在内置清单管理范围内,AddonController 重新 apply coredns.yaml 时不会触碰该 ConfigMap,因此配置天然持久化。
3.2 CoreDNS 插件链与 fallthrough
CoreDNS 按插件链顺序处理查询请求,本方案涉及的关键链路为:
hosts(自定义静态解析)→ kubernetes(Service/Pod 域名)→ forward(上游 DNS)
fallthrough 的作用:hosts 插件默认对所有查询"终结"响应——命中返回记录,未命中直接返回 NXDOMAIN,不再交给后续插件。加上 fallthrough 后,hosts 表未命中的域名会放行给 kubernetes 与 forward 插件继续处理。
不加 fallthrough 的后果:除自定义条目外,全集群 DNS 解析失败,包括 Service 发现(*.svc.cluster.local)与全部外网域名。
| 查询域名 | 有 fallthrough | 无 fallthrough |
|---|---|---|
ep-xxx.privatelink.aliyuncs.com(hosts 命中) |
返回 10.150.140.1 | 返回 10.150.140.1 |
xxx.svc.cluster.local(Service 发现) |
kubernetes 插件正常解析 | NXDOMAIN,解析失败 |
www.aliyun.com(外网域名) |
forward 转发上游正常解析 | NXDOMAIN,解析失败 |
四、实施步骤
步骤 1:创建 coredns-custom ConfigMap
kubectl apply -f - <<'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns-custom
namespace: kube-system
data:
dashscope.override: |
hosts {
10.150.140.1 ep-223rer700dc089123123.dashscope.cn-bejing.privatelink.aliyuncs.com
fallthrough
}
EOF
步骤 2:重载 CoreDNS
kubectl rollout restart deployment coredns -n kube-system
kubectl rollout status deployment coredns -n kube-system
步骤 3:验证解析
方式一:在现有 Pod 中执行(任选一个含 nslookup 的 Pod):
kubectl exec -it <pod-name> -n <namespace> -- \
nslookup ep-223rer700dc089123123.dashscope.cn-bejing.privatelink.aliyuncs.com
方式二:启动 busybox 临时 Pod 验证:
kubectl run dns-test --rm -it --image=busybox:1.36 --restart=Never -- \
nslookup ep-223rer700dc089123123.dashscope.cn-bejing.privatelink.aliyuncs.com
预期结果:返回 10.150.140.1。
步骤 4:重启持久性验证
systemctl restart k3s
# 等待节点与 CoreDNS 就绪后复验
kubectl run dns-test --rm -it --image=busybox:1.36 --restart=Never -- \
nslookup ep-223rer700dc089123123.dashscope.cn-bejing.privatelink.aliyuncs.com
预期结果:k3s 重启后解析仍返回 10.150.140.1,配置未被覆盖。
关键约束要点
| 项目 | 要求 | 违反后果 |
|---|---|---|
| ConfigMap 名称 | 必须为 coredns-custom |
不会被挂载,配置不生效 |
| data key 命名 |
必须以 .override 结尾(本方案场景) |
import 不匹配,配置不生效 |
fallthrough |
必须保留在 hosts 块内 | 全集群 DNS 解析失败 |
五、后续维护
追加域名:
kubectl edit cm coredns-custom -n kube-system
在 hosts 块内按 IP 域名 格式追加新行(保持 fallthrough 位于块末尾),保存后执行:
kubectl rollout restart deployment coredns -n kube-system
六、方案对比(附录)
| 方案 | 持久性 | 维护性 | 结论 |
|---|---|---|---|
| coredns-custom ConfigMap | k3s 重启不丢失,独立于内置清单 | k3s 原生支持,官方预留扩展入口,可随时增删条目 | 推荐 |
| 直接修改 coredns ConfigMap | k3s 重启后被内置清单覆盖还原 | 每次重启需重新修改,不可运维 | 不可用 |
创建 coredns.yaml.skip 跳过内置清单 |
持久,但 CoreDNS 完全脱离 k3s 管理 | 失去 k3s 升级时对 CoreDNS 的版本维护,需自行管理全量清单 | 不推荐 |