Argo CD ApplicationSet 实战指南:用 ApplicationSet 控制器自动批量生成 Application
【免费下载链接】argo-cdDeclarative Continuous Deployment for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/ar/argo-cd
本文围绕 Argo CD 的 ApplicationSet 控制器(ApplicationSet controller)展开,讲解它如何基于ApplicationSet自定义资源(CR)自动批量生成 Argo CDApplication,覆盖 List/Cluster/Git/Matrix 等生成器的参数注入机制、模板渲染流程与多集群目标选择方案,并补充源码级的生成、对账与安全边界说明。读完后,你可以用单个清单文件管理面向多集群、多应用的 Application 集合,并理解其背后的生成器接口与调和逻辑。
1. ApplicationSet 控制器解决什么问题
ApplicationSet 控制器是一个 Kubernetes 控制器,为 Argo CD 引入ApplicationSetCRD(自 Argo CD v2.3 起随 Argo CD 一同捆绑发布)。它面向三类典型场景(见 ApplicationSet 介绍文档):
- 用一份Kubernetes 清单同时把应用部署到多个Kubernetes 集群;
- 用一份清单从一个或多个 Git 仓库部署多个应用(对 monorepo 尤其友好,在 Argo CD 语境下,monorepo 指单个 Git 仓库内定义多个 Application);
- 在多租户集群中让普通租户自助创建 Application,无需集群管理员介入。
最后一点也意味着安全边界问题:官方安全文档明确指出,只应授予管理员创建/更新/删除 ApplicationSet 的权限——因为 ApplicationSet 可以在任意 Project 下创建 Application(包括权限很高的defaultproject),可以高速创建/删除任意数量的 Application,甚至在特定生成器(如 Git generator 的api字段)下泄露 Argo CD 命名空间内 Secret 的信息。因此若要让开发者通过 ApplicationSet 创建 Application,必须先评估这些安全影响。
2. 完整示例:用 List 生成器将 guestbook 部署到三个集群
下面是 用户指南中的 ApplicationSet 示例:ApplicationSet基于 List 生成器,把guestbook应用模板化为面向三个集群的三套部署目标。
apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: guestbook spec: goTemplate: true goTemplateOptions: ["missingkey=error"] generators: - list: elements: - cluster: engineering-dev url: https://1.2.3.4 - cluster: engineering-prod url: https://2.4.6.8 - cluster: finance-preprod url: https://9.8.7.6 template: metadata: name: '{{.cluster}}-guestbook' spec: project: my-project source: repoURL: https://github.com/infra-team/cluster-deployments.git targetRevision: HEAD path: guestbook/{{.cluster}} destination: server: '{{.url}}' namespace: guestbook示例要点逐项说明:
| 字段 | 作用 |
|---|---|
goTemplate: true | 启用 Go Text Template 渲染引擎(而非默认的 fasttemplate),可使用 Go 模板函数 |
goTemplateOptions: ["missingkey=error"] | 推荐选项:模板引用了不存在的参数时直接报错,而不是静默渲染成空值(出于向后兼容,它不是默认行为) |
generators.list.elements | List 生成器的参数源:每个元素是一组键值对,cluster与url两个字段会成为模板参数 |
template | 待渲染的 Application 模板;{{.cluster}}、{{.url}}在渲染时被替换为每个元素对应的值 |
List 生成器把每个元素的url、cluster字段作为{{param}}风格的参数传入模板,最终渲染出三个对应的 Argo CD Application(每个集群一个)。新增或移除目标集群只需修改这个ApplicationSet资源,对应的 Application 会被自动创建或删除;同理,修改template中的任意字段也会自动应用到所有已生成的 Application 上。也就是说:管理一组 Application 与管理单个 ApplicationSet 一样简单。
渲染结果之一(对应engineering-dev集群)是一个完整的 Application:
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: engineering-dev-guestbook spec: source: repoURL: https://github.com/infra-team/cluster-deployments.git targetRevision: HEAD path: guestbook/engineering-dev destination: server: https://1.2.3.4 namespace: guestbook在 Argo CD Web UI 中,三个生成的 Application 会并列展示:
3. 参数替换与调和流程(源码印证)
无论使用哪种生成器,流程都是一致的:生成器产出参数 → 参数替换进template中的{{parameter}}占位 → 每套参数渲染出一次模板 → 每个渲染结果转化为一个Application资源(创建或更新)→ Argo CD 应用控制器接管这些 Application(见 Introduction):
- ApplicationSet 控制器处理 generator 条目,产出一组模板参数;
- 参数被逐套替换进模板;
- 每个渲染后的模板转化为 Argo CD
Application,在 Argo CD 命名空间内创建或更新; - Argo CD 控制器随后被通知并负责这些 Application。
3.1 生成器接口:所有生成器的统一抽象
从源码结构看(applicationset/generators/interface.go),每个生成器都实现统一的Generator接口,只有三个方法:
GenerateParams(...):解释ApplicationSetGenerator配置,产出参数列表([]map[string]any),随后由控制器渲染并与集群中现有 Application 状态对账;GetRequeueAfter(...):控制下一次调和循环的间隔(多生成器时取最小值;NoRequeueAfter表示不重入队)。List 生成器是纯静态数据源,直接返回NoRequeueAfter(见 applicationset/generators/list.go);GetTemplate(...):返回生成器条目内联的模板(如有)。
3.2 List 生成器实现:elements 如何变成参数
applicationset/generators/list.go 的GenerateParams展示了参数生成的具体逻辑:
- 每个
elements条目先被 JSON 反序列化为 map; - 若
goTemplate: true,整个元素对象(含嵌套结构)直接作为参数传入模板,因此模板中可以用{{.values.xxx}}这类嵌套路径; - 若未启用 Go 模板,则仅接受字符串值,
values子映射会被展开为values.<key>扁平键; - 此外还支持
elementsYaml字段:以 YAML 字符串形式提供元素列表,反序列化后追加到参数结果中,适合不便直接内联elements的场景。
3.3 对账主循环:从生成到落盘
调和入口在 applicationset/controllers/applicationset_controller.go 的Reconcile中,可以看到核心链路:
- 若 ApplicationSet 正在被删除,且同步策略不允许删除,则移除生成 Application 上的 ownerReference 并走渐进式删除(progressive sync 的 Reverse 删除序)逻辑;
- 正常路径上,
template.GenerateApplications(...)调用所有注册生成器产出期望的 Application 集合(desiredApplications),再与集群现有状态对账; - 对期望与实际 Application 的规格比较并非简单逐字节对比:applicationset/utils/createOrUpdate.go 中的
SpecsEquivalent先做NormalizeApplicationSpec规范化,再应用ignoreDifferences规则后判断 spec 是否等价,避免忽略项导致的“永远显示待变更”。
这意味着:ApplicationSet 的任何变更(增删生成器元素、修改模板)都会在后续调和中自动传导到对应 Application,无需手动创建或更新 Application。
4. 除 List 之外的生成器
List 生成器只是最基础的起点。ApplicationSet 控制器内置了多种更强大的生成器(完整清单见 Generators 文档,共九种):
- Cluster 生成器:不手写集群列表,而是直接使用 Argo CD 中已定义的集群清单作为参数源,并在集群增删时自动响应;
- Git 生成器:基于 Git 仓库内的文件或目录结构生成参数——JSON 文件会被解析为模板参数,目录路径本身也可作为参数值(适合 monorepo 按目录部署);
- Matrix 生成器:把另外两个生成器产出的参数做组合(笛卡尔积式交叉);
- Merge 生成器:合并两个或多个生成器的参数,附加生成器可覆盖基础生成器的值;
- SCM Provider 生成器:通过 GitHub 等 SCM 提供方 API 自动发现组织/仓库下的仓库;
- Pull Request 生成器:通过 API 自动发现仓库中开放的 PR(常用于预览环境);
- Cluster Decision Resource 生成器:对接自定义 CR,用其内置逻辑决定部署到哪些 Argo CD 集群;
- Plugin 生成器:通过 RPC HTTP 请求获取参数。
此外,所有生成器都可以用 Post Selector 做结果过滤(见 Post Selector)。对于刚接触生成器的读者,官方建议从List和Cluster两种入手,再按需求引入其他生成器。
5. 模板渲染细节与限制
示例中goTemplate: true启用了 Go Text Template,并带来几个实用点:
- 除标准 Go 文本模板函数外,还提供 Sprig 函数库(
env、expandenv、getHostByName除外); - 额外提供
normalize函数(把任意字符串转为合法 DNS 名,非法字符替换为连字符并截断到 253 字符),以及slugify函数(支持最大长度、智能截断等可选参数),对生成 Application 名称尤其有用; - 限制:Go 模板按字段(per-field)作用于字符串字段,不能用于模板化布尔字段或对象字段——例如
helm.useCredentials这类布尔值不能写成{{.useCredentials}}。
关于goTemplateOptions,当前唯一有用的选项就是missingkey=error:它让模板引用未定义参数时报错而非静默通过,官方推荐设置,示例中已启用。
6. 在 Web UI 中管理 ApplicationSet
除了直接操作 Kubernetes 资源,ApplicationSet 也可以通过 Argo CD Web UI 管理,包括创建、编辑与查看生成的 Application,详见 在 Web UI 中管理 ApplicationSet。
7. 小结
- ApplicationSet 控制器让“一份清单 → N 个 Application”成为可能,是 Argo CD 多集群、monorepo 与多租户自助部署场景的核心机制;
- 生成器负责产出参数,
template负责消费参数;List 生成器演示了最直观的参数注入方式,Cluster/Git/Matrix/Merge/SCM Provider/Pull Request/CDR/Plugin 等生成器覆盖更动态的场景; - 从源码看,
Generator接口统一了参数产出、重入队与模板来源三个职责,Reconcile主循环负责将期望 Application 集合与集群实际状态对账,SpecsEquivalent等工具函数保证比较前先规范化并应用ignoreDifferences,确保变更可靠传导; - 安全上务必遵循 Security 文档:仅管理员可操作 ApplicationSet,且
project字段若被模板化,管理员必须控制所有生成器的数据来源。
深入阅读入口:ApplicationSet 概述、生成器总览、Go 模板、安全说明。
【免费下载链接】argo-cdDeclarative Continuous Deployment for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/ar/argo-cd
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考