Cilium ClusterMesh MCS-API 之 CoreDNS 自动配置:clustermesh-apiserver mcsapi-coredns-cfg 命令深度解析
【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium
Cilium 的 ClusterMesh 通过 Multi-Cluster Services API(MCS-API)将多个 Kubernetes 集群中的服务导出并合并为全局可访问的服务,而这一切依赖 CoreDNS 对clusterset.local域名的解析能力。clustermesh-apiserver mcsapi-coredns-cfg是 clustermesh-apiserver 内置的一条子命令,用于自动检测并改写 CoreDNS 的 Corefile 配置、写入备份并触发滚动更新,从而一键打通跨集群服务发现。读完本文,你将掌握该命令的每个命令行参数、它的自动配置工作流与幂等逻辑、Corefile 的改写规则,以及如何通过 Helm 开关或手动方式在 Cilium 集群中启用 MCS-API DNS 解析。
命令概览:一句话说明它做什么
mcsapi-coredns-cfg的官方定位是 "Automatically configure CoreDNS with recommended MCS-API settings",即自动为 CoreDNS 施加 MCS-API 推荐配置。它由 root.go 中的NewCmd构建,命令名称为mcsapi-coredns-cfg,属于 clustermesh-apiserver 的子命令。基本调用形式为:
clustermesh-apiserver mcsapi-coredns-cfg [flags]命令实际执行的是一个由 Cilium Hive 框架驱动的"一次性任务"(OneShot job):从 Kubernetes 集群中读取 CoreDNS 的 ConfigMap 与 Deployment,校验版本,改写 Corefile,更新 ConfigMap 并触发 Deployment 滚动更新。由于它基于 Hive,还可通过clustermesh-apiserver mcsapi-coredns-cfg hive子命令查看 hive 运行图。
参数清单:所有 flags 及其默认值
以下是该命令支持的完整参数列表(来自 命令参考文档,默认值常量定义于 cell.go):
| 参数 | 说明 | 默认值 |
|---|---|---|
--coredns-cluster-domain string | CoreDNS 使用的集群域名(cluster domain) | cluster.local |
--coredns-clusterset-domain string | CoreDNS 使用的集群集域名(clusterset domain) | clusterset.local |
--coredns-configmap-name string | CoreDNS 的 ConfigMap 名称 | coredns |
--coredns-deployment-name string | CoreDNS 的 Deployment 名称 | coredns |
--coredns-namespace string | CoreDNS 所在的命名空间 | kube-system |
--enable-k8s | 是否启用 k8s clientset | true |
--enable-k8s-api-discovery | 是否启用 Kubernetes API 组与资源的 discovery 发现 | 关闭 |
-h, --help | 显示 mcsapi-coredns-cfg 的帮助信息 | — |
--k8s-api-server-urls strings | Kubernetes API server 的 URL 列表 | — |
--k8s-client-burst int | K8s client 允许的突发(burst)值 | 20 |
--k8s-client-connection-keep-alive duration | K8s client 连接的 keep alive 时长,设为 0 则禁用该 client | 30s |
--k8s-client-connection-timeout duration | K8s client 连接的超时时长,设为 0 则禁用该 client | 30s |
--k8s-client-qps float32 | K8s client 每秒查询数(QPS)上限 | 10 |
--k8s-heartbeat-timeout duration | 与 api-server 心跳的超时,设为 0 可禁用 | 30s |
--k8s-kubeconfig-path string | Kubernetes kubeconfig 文件的绝对路径 | — |
其中--coredns-*五个参数由 cell.go 中的coreDNSConfig.Flags()注册,它们直接决定自动配置程序去"找谁、改什么"。其余--k8s-*参数则来自k8sClient.Cell,用于构造访问集群所需的 clientset,例如--k8s-client-qps/--k8s-client-burst控制 client-go 的限速令牌桶,--k8s-kubeconfig-path指定非默认位置的 kubeconfig。
自动配置工作流:从读取 ConfigMap 到触发滚动更新
命令启动后,root.go 中的configureCoreDNS被以 Hive 单元(cell)方式注入执行(见 cell.go 中的cell.Invoke(configureCoreDNS)),整体流程分为六个步骤:
- 校验 clientset 是否启用:若
client.IsEnabled()为 false,直接报错 "Kubernetes client is not enabled, cannot configure CoreDNS" 并退出。 - 读取 CoreDNS ConfigMap 与 Deployment:通过
client.CoreV1().ConfigMaps(config.CoreDNSNamespace).Get(...)和client.AppsV1().Deployments(...).Get(...)分别获取指定命名空间下、指定名称的两个资源;任一获取失败都会终止任务。 - 校验 CoreDNS 版本:从 Deployment 首个容器的镜像 tag 解析语义化版本(semver),低于
v1.12.2则报错终止(详见下文"版本校验"一节)。 - 改写 Corefile:取出 ConfigMap
data中Corefile字段,调用updateCorefile注入 multicluster 配置。 - 备份并更新 ConfigMap:将原
Corefile内容复制到Corefile.cilium.bak键,再写入改写后的 Corefile,然后调用 ConfigMap 的Update接口提交。 - 触发 CoreDNS 滚动更新:通过
restartCoreDNS为 Deployment 的 PodTemplate 打上时间戳注解并 Apply,触发滚动重启加载新配置。
整个任务在一个job.OneShot中运行,执行完毕后无论成败都会调用shutdowner.Shutdown结束进程,因此它是一次性配置命令而非常驻控制器。
幂等与安全性设计
updateCorefile(root.go)在改写前先做两个检查:
- 已配置则跳过:若 Corefile 中已包含 clusterset 域名或
multicluster字样,说明之前已执行过,函数返回空字符串,主流程记录 "CoreDNS might already have MCS-API configuration, skipping configuration" 并安全退出。这是命令幂等性的关键。 - 找不到 kubernetes 插件则报错:用正则
(?m)^\s*kubernetes.*%s.*\{(其中 cluster domain 中的.被转义为\.)匹配 Corefile,若不存在匹配,说明该 CoreDNS 未以指定 cluster domain 配置 kubernetes 插件,报错终止,避免盲目改写。
Corefile 改写规则:注入 multicluster 插件
改写逻辑本身并不复杂,却非常精确(root.go):
- 将 Corefile 中所有
cluster.local字样替换为cluster.local clusterset.local,使 kubernetes 插件同时监听两个域名后缀; - 用正则
(?m)^(\s*)kubernetes(.*)\{定位 kubernetes 插件块的开头行,在其下一行缩进一级插入multicluster <clusterset-domain>指令,启用 CoreDNS 的 multicluster 插件并把查询路由到 clusterset 域。
以一个典型的 Corefile 为例,改写前:
.:53 { errors health { lameduck 5s } ready kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure fallthrough in-addr.arpa ip6.arpa ttl 30 } prometheus :9153 forward . 1.1.1.1 { max_concurrent 1000 } cache 30 { disable success cluster.local disable denial cluster.local } loop reload loadbalance log }改写后:
.:53 { errors health { lameduck 5s } ready kubernetes cluster.local clusterset.local in-addr.arpa ip6.arpa { multicluster clusterset.local pods insecure fallthrough in-addr.arpa ip6.arpa ttl 30 } prometheus :9153 forward . 1.1.1.1 { max_concurrent 1000 } cache 30 { disable success cluster.local clusterset.local disable denial cluster.local clusterset.local } loop reload loadbalance log }注意改写不只发生在 kubernetes 插件块内:cache插件的disable success/disable denial参数同样从cluster.local扩展为cluster.local clusterset.local,这是为了保证新域名不被缓存插件错误地禁用。上述两组改动在 root_test.go 的TestUpdateCorefiles中都有对应的输入输出用例(normal corefile 场景),并被 testdata/configure.txtar 里的端到端脚本(k8s/add → hive start → 校验 ConfigMap 与 Deployment 注解)完整验证。
multicluster是 CoreDNS 官方插件(v1.12.2 起引入),它监听 ServiceImport 资源并回答clusterset.local域下的 DNS 查询。这正是改写必须要求 CoreDNS 版本不低于 1.12.2 的原因。
版本校验:为什么要求 CoreDNS >= 1.12.2
validateCoreDNSVersion(root.go)从镜像 tag 解析版本号:先以:取 tag 部分,再去掉@后的 digest 和-后的自定义构建信息,最后去掉v前缀后用blang/semver解析。若解析失败只给出警告(不影响执行,例如自定义镜像 tag),若解析成功但版本低于v1.12.2,则报错 "CoreDNS version is too old for MCS-API auto configuration, please use v1.12.2 or newer" 并终止。
TestValideCoreDNSVersion 覆盖了多种镜像形态:
registry.k8s.io/coredns/coredns:v1.12.0—— 版本过旧,报错;registry.k8s.io/coredns/coredns:v1.12.2与带@sha256:...digest 的同版本 —— 通过;v1.13.0等更新版本 —— 通过;public.ecr.aws/eks-distro/coredns/coredns:v1.12.2-eks-1-33-latest—— 剥离-eks-*后缀后通过;mycompany.org/coredns:v1.12.2+1—— 带构建元数据也可解析;mycompany.org/coredns:mycustomversion—— 无法解析,仅告警不阻塞。
因此该命令适用于任意合规镜像,包括 EKS distro 与私有镜像仓库的 CoreDNS。
滚动更新机制:autoPatchedAt 注解
改写 Corefile 并更新 ConfigMap 后,还需要让 CoreDNS 重新加载配置。restartCoreDNS(root.go)先检查 Deployment 是否处于 paused 状态(paused 时直接报错跳过),然后以FieldManager: "mcsapi-coredns-autocfg"和Force: true执行 server-side Apply,为 PodTemplate 注入注解:
clustermesh.cilium.io/autoPatchedAt: <RFC3339 时间戳>该注解的键定义于 pkg/annotation/k8s.go(ClusterMeshPrefix + "/autoPatchedAt"),注释明确说明其用途是"在补丁 CoreDNS 配置以启用 MCS-API 支持后触发 CoreDNS 滚动更新"。每次写入不同的时间戳都会改变 PodTemplate,从而驱动 Deployment 滚动重启。同时,这个注解也相当于配置生效的"证据":testdata/configure.txtar 的端到端测试正是通过grep 'clustermesh.cilium.io/autoPatchedAt:'来断言滚动更新被正确触发。
如何启用与手动替代方案
通过 Helm 一键启用
在 MCS-API 使用指南 中,Cilium 提供了两条路径:若设置 Helm 参数clustermesh.mcsapi.corednsAutoConfigure.enabled=true,Cilium 会以本命令为底层实现,自动完成 CoreDNS 配置与滚动更新。前提是先有可用的 Cluster Mesh 环境,且 CoreDNS 版本不低于 1.12.2(Kubernetes 1.35 起默认安装)。安装时启用:
helm install cilium cilium/cilium --namespace kube-system --set clustermesh.mcsapi.enabled=true对已有安装启用:
helm upgrade cilium cilium/cilium --namespace kube-system --reuse-values --set clustermesh.mcsapi.enabled=true手动配置 CoreDNS(未开启自动配置时)
若未开启自动配置,可参照 MCS-API 指南 手动执行等价的四步操作:
# (可选) 安装 MCS-API CRDs kubectl apply -f vendor/sigs.k8s.io/mcs-api/config/crd/multicluster.x-k8s.io_serviceexports.yaml kubectl apply -f vendor/sigs.k8s.io/mcs-api/config/crd/multicluster.x-k8s.io_serviceimports.yaml # 为 CoreDNS 授予读取 ServiceImports 的 RBAC 权限 kubectl create clusterrole coredns-mcsapi \ --verb=list,watch --resource=serviceimports.multicluster.x-k8s.io kubectl create clusterrolebinding coredns-mcsapi \ --clusterrole=coredns-mcsapi --serviceaccount=kube-system:coredns # 改写 Corefile:注入 clusterset.local 与 multicluster 插件 kubectl get configmap -n kube-system coredns -o yaml | \ sed -e 's/cluster\.local/cluster.local clusterset.local/g' | \ sed -E 's/^(.*)kubernetes(.*)\{/\1kubernetes\2{\n\1 multicluster clusterset.local/' | \ kubectl replace -f- # 滚动重启 CoreDNS 加载新配置 kubectl rollout deployment -n kube-system coredns可以对照发现:mcsapi-coredns-cfg自动模式所做的正是把上述sed改写逻辑固化为经过充分测试的 Go 代码,并额外增加了版本校验、Corefile.cilium.bak备份和基于注解的滚动更新,比手工sed更安全可靠。
使用前提与限制
- 依赖 Cluster Mesh:该命令的最终目的是让 CoreDNS 解析 MCS-API 导出的服务,因此需要先搭建可用的 Cluster Mesh 环境(见 load-balancing 文档 与 MCS-API 指南的前提章节)。
- 版本硬约束:CoreDNS 必须为 v1.12.2 或更新版本,否则自动配置会直接失败;这是 CoreDNS
multicluster插件引入版本的硬性要求。 - 命名与路径假设:命令默认寻找
kube-system命名空间下名为coredns的 ConfigMap/Deployment,并假定 Corefile 中已按cluster.local配置 kubernetes 插件。非标准部署需通过--coredns-*参数显式指定。 - paused Deployment:CoreDNS Deployment 处于暂停状态时不会执行滚动更新,而是报错提示。
- 执行语义:它是"执行一次即退出"的配置命令,重复执行是安全的(幂等跳过),但若集群中 Corefile 已包含
multicluster或 clusterset 域,将不会重复改写。
从源码结构看它的定位
从代码组织看,mcsapi-coredns-cfg 目录本身就是一个独立的自包含模块:root.go定义命令与全部业务逻辑,cell.go以 Hive 单元形式注册配置项与依赖(复用 pkg/k8s/client 的Cell),root_test.go提供纯函数级单元测试,script_test.go配合 testdata/configure.txtar 提供基于 Fake Client 的端到端场景测试。这种"命令 + Hive 单元 + 脚本测试"的形态也印证了它作为 ClusterMesh 服务导出能力中 DNS 侧关键一环的工程定位:将 Kubernetes 生态里繁琐、易错的 CoreDNS 手动配置流程,收敛成一个可参数化、可测试、可幂等执行的子命令。
【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考