告别手工管理 Argo CD Application:ApplicationSet 批量编排实战指南
当你需要把同一套应用部署到 10 个集群、为每个分支创建预览环境,或者管理几百个微服务时,手动维护 Application 资源会变成噩梦。Argo CD ApplicationSet 就是为这种批量场景而生。本文带你吃透它的核心原理、生成器机制和实战用法。
目录
-
单个 Application 的局限
-
什么是 ApplicationSet?
-
核心机制:模板 + 生成器
-
七大生成器详解
-
4.1 List 生成器
-
4.2 Cluster 生成器
-
4.3 Git 生成器(目录/文件)
-
4.4 SCM Provider 生成器
-
4.5 Pull Request 生成器
-
4.6 Matrix 与 Merge 生成器
-
-
ApplicationSet vs App of Apps:区别与组合
-
实战:用 ApplicationSet 部署多集群 AI 推理服务
-
最佳实践与避坑指南
-
总结
1. 单个 Application 的局限
在上一篇 Argo CD 文章中,我们学会了如何创建一个 Application 来同步一个 Git 仓库中的应用。但现实中的需求往往更复杂:
-
多集群部署:同一套应用要部署到 dev、staging、prod 等多个集群,每个集群的 Application 参数稍有不同(namespace、集群地址等)。
-
多环境差异化:每个分支需要独立的预览环境,Application 需要动态指向不同分支或目录。
-
大规模微服务:几十上百个微服务,每个都需要一个 Application,手动管理会疯掉。
你当然可以用 App of Apps 模式,即写一个根 Application 来管理一堆子 Application 的 YAML。但那些子 Application 的 YAML 还是要你自己维护,而且当集群数量、环境数量增加时,静态文件会急剧膨胀。
ApplicationSet 正是为解决这种"模板化 + 批量生成"问题而生的。
2. 什么是 ApplicationSet?
ApplicationSet 是 Argo CD 的一个 CRD(自定义资源) ,它利用 模板(Template) 和 生成器(Generator) 自动创建多个 Application 资源。
简单来说:
-
模板:定义了一个 Application 的"骨架",其中部分参数用变量表示。
-
生成器:负责产生多组变量值,每组值渲染出一个完整的 Application。
一个 ApplicationSet 可以生成几十、几百个 Application,你只需维护这个 ApplicationSet 资源即可。
ApplicationSet 控制器内置于 Argo CD(从 v2.3 开始稳定),无需额外安装。
3. 核心机制:模板 + 生成器
来看一个最小示例,感受一下它的运作方式:
yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: guestbook
namespace: argocd
spec:
generators:
- list:
elements:
- cluster: engineering-dev
url: https://kubernetes.default.svc
- cluster: engineering-prod
url: https://prod-cluster.example.com
template:
metadata:
name: 'guestbook-{{cluster}}'
spec:
project: default
source:
repoURL: https://github.com/argoproj/argocd-example-apps.git
targetRevision: HEAD
path: guestbook
destination:
server: '{{url}}'
namespace: guestbook
这个 ApplicationSet 会生成两个 Application:
-
guestbook-engineering-dev→ 部署到https://kubernetes.default.svc -
guestbook-engineering-prod→ 部署到https://prod-cluster.example.com
模板里的 {``{cluster}} 和 {``{url}} 就是从 List 生成器的元素中取值的。
控制器的行为 :ApplicationSet 控制器会监测生成器的输入变化,并动态创建、更新或删除 Application。当删除 ApplicationSet 时,默认不会级联删除其生成的 Application,但可通过设置 .spec.syncPolicy.preserveResourcesOnDeletion: false 来改变。
4. 七大生成器详解
生成器是 ApplicationSet 的灵魂。Argo CD 提供了多种生成器,可单独使用,也可通过 Matrix/Merge 组合。
4.1 List 生成器
最直接:提供一个固定列表,每个元素是一组 key-value。
yaml
generators:
- list:
elements:
- env: dev
cluster: dev-cluster
namespace: myapp-dev
- env: prod
cluster: prod-cluster
namespace: myapp-prod
模板中使用 {``{env}}、{``{cluster}}、{``{namespace}}。
适用于环境数量固定、差异不大的场景。
4.2 Cluster 生成器
自动从 Argo CD 已连接的集群列表生成参数。它会查询所有已注册的集群,输出 name、server、metadata.labels 等字段。
yaml
generators:
- clusters:
selector:
matchLabels:
env: staging
Argo CD 中任何带有 env: staging 标签的集群都会被选中,模板里可以用 {``{name}}、{``{server}} 以及集群标签作为变量。这使得动态添加新集群时,应用会自动部署过去,真正实现"集群即服务"。
4.3 Git 生成器
Git 生成器根据 Git 仓库中的目录结构或文件内容生成参数,分为两种子类型:
4.3.1 目录生成器(Git Directory)
扫描 Git 仓库中指定路径下的子目录,每个子目录生成一个 Application。
yaml
generators:
- git:
repoURL: https://github.com/example/apps.git
revision: HEAD
directories:
- path: apps/*
假设仓库结构为:
text
apps/
frontend/
kustomization.yaml
backend/
kustomization.yaml
则会生成两个 Application,{``{path}} 变量分别是 apps/frontend 和 apps/backend,同时还有 {``{path.basename}}(目录名)等派生变量。
这正是 微服务批量管理 的最佳实践:每新增一个服务,只需在仓库中新建目录并放入配置,ApplicationSet 会自动生成对应的 Application。
4.3.2 文件生成器(Git File)
读取仓库中的 JSON/YAML 文件,每个文件条目作为一个参数。比如有一个 envs.json:
json
[
{ "env": "dev", "cluster": "dev-cluster" },
{ "env": "prod", "cluster": "prod-cluster" }
]
生成器配置:
yaml
generators:
- git:
repoURL: https://github.com/example/config.git
revision: HEAD
files:
- path: envs.json
每个 JSON 对象会渲染出一个 Application。适合将环境配置集中到单个文件中。
4.4 SCM Provider 生成器
与 Git 目录生成器类似,但它是直接从 Git 组织/仓库中查找所有符合条件的仓库,并为每个仓库生成 Application。支持 GitHub、GitLab、Bitbucket 等。
yaml
generators:
- scmProvider:
github:
organization: my-org
# 可选过滤
allBranches: true
cloneProtocol: https
这常用于 组织级仓库发现:公司有几十个微服务仓库,每个仓库根目录都有 Kustomize/Helm 配置,ApplicationSet 会自动为每个仓库创建一个 Application。
4.5 Pull Request 生成器
当 Git 仓库有新的 PR(Pull Request)创建时,自动生成一个临时 Application 用于预览环境。
yaml
generators:
- pullRequest:
github:
owner: my-org
repo: my-app
requeueAfterSeconds: 180
生成的 Application 会包含 PR 编号、分支、head SHA 等变量,可以部署到独立的 namespace(如 pr-{``{number}})。PR 合并或关闭后,ApplicationSet 会自动删除对应的 Application,实现预览环境的全生命周期管理。
4.6 Matrix 与 Merge 生成器
当单一生成器无法满足需求时,可用 Matrix 和 Merge 组合多个生成器。
-
Matrix :取两个子生成器的笛卡尔积 。例如,将 List(环境)和 Cluster(集群)组合,生成
{dev}×{cluster-a}、{dev}×{cluster-b}等所有组合。 -
Merge :将两个子生成器生成的项目进行一对一合并(类似 SQL JOIN),要求两个生成器产出的数量相等,按索引合并。用于从不同来源提取属性合并到同一个参数集中。
yaml
generators:
- matrix:
generators:
- list:
elements:
- env: dev
- env: prod
- clusters:
selector:
matchLabels:
env: '{{env}}' # 这里不能直接引用上层变量,需注意作用域
Matrix 生成器有一些作用域限制,使用时建议仔细阅读官方文档。
5. ApplicationSet vs App of Apps:区别与组合
很多人会困惑:ApplicationSet 和 App of Apps 都是批量管理 Application,它们有何不同?
| 对比维度 | App of Apps | ApplicationSet |
|---|---|---|
| 原理 | 手动编写多个 Application YAML,由一个根 Application 统一 apply | 用生成器动态创建 Application |
| 扩展性 | 新增服务需要新增 YAML 文件 | 新增目录/集群/PR 自动生成 |
| 配置量 | 较多,每个 Application 一份 | 很少,只需一个模板 |
| 参数化能力 | 较弱,可用 Helm/Kustomize 辅助 | 内建模板变量,非常灵活 |
| 动态感知 | 弱,需手动更新 Git | 强,自动感知集群/仓库变化 |
最佳组合:
-
用 ApplicationSet 动态生成和管理 Application,作为"工厂"。
-
用 一个 App of Apps 类型的 ApplicationSet 来管理多个 ApplicationSet(即管理管理者的管理者),不过这种模式通常直接用 ApplicationSet 的嵌套即可,或者将 ApplicationSet 本身放入 Git,并用 App of Apps apply 进去。
更实用的组合:使用 ApplicationSet(Git 目录生成器) 来替代静态的 App of Apps,让服务数量自由扩展。
6. 实战:用 ApplicationSet 部署多集群 AI 推理服务
回顾我们之前的文章,我们有一个 vLLM 推理服务部署到 Kubernetes。假设现在我们要把同一个推理服务部署到三个不同的集群(dev、staging、prod),每个集群的 GPU 类型和副本数略有不同。
我们可以这样设计 ApplicationSet:
yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: vllm-inference
namespace: argocd
spec:
generators:
- list:
elements:
- env: dev
server: https://dev-cluster.example.com
replicas: "1"
gpu: "nvidia-t4"
- env: staging
server: https://staging-cluster.example.com
replicas: "2"
gpu: "nvidia-a10"
- env: prod
server: https://prod-cluster.example.com
replicas: "4"
gpu: "nvidia-a100"
template:
metadata:
name: 'vllm-{{env}}'
spec:
project: default
source:
repoURL: https://github.com/my-org/ai-services.git
targetRevision: HEAD
path: vllm
helm:
parameters:
- name: replicas
value: '{{replicas}}'
- name: gpu.type
value: '{{gpu}}'
destination:
server: '{{server}}'
namespace: ai-inference
syncPolicy:
automated:
prune: true
selfHeal: true
这里我们用了 Helm 参数化 ,vllm 目录下的 Helm Chart 读取 replicas 和 gpu.type,每个环境生成不同的配置。
如果你想为每个环境添加不同的模型版本,还可以在 List 元素中加入 modelVersion 字段,然后在 Helm 参数中传递。
如果后续 dev 集群被移除,只需从 List 中删除对应元素,ApplicationSet 控制器会负责清理对应的 Application(前提是 .spec.syncPolicy.preserveResourcesOnDeletion 设为 false)。
7. 最佳实践与避坑指南
-
避免生成的 Application 命名冲突 :模板中的
name必须是唯一的,通常使用组合变量,如'myapp-{``{env}}-{``{cluster}}'。 -
谨慎设置资源清理策略 :默认删除 ApplicationSet 不会删除已生成的 Application。如果希望级联删除,设置
syncPolicy.preserveResourcesOnDeletion: false。 -
使用项目(Project)做权限隔离 :在模板中指定
project,利用 Argo CD 的 Project 限制可访问的仓库和集群。 -
不要滥用 Matrix 生成器:组合爆炸可能产生大量 Application,给 Kubernetes API 和 Argo CD 控制器带来压力。建议生成总数控制在几百以内。
-
测试新生成器:先在一个测试集群上验证生成逻辑,确保模板变量没有拼写错误。
-
结合 GitOps 管理 ApplicationSet 自身:把 ApplicationSet 的 YAML 也放在 Git 仓库中,用 App of Apps 或手动 apply 的方式部署它,实现自举。
-
监控 ApplicationSet 控制器的日志 :如果生成的 Application 一直不出现,检查
argocd-applicationset-controller的日志,通常能找到原因(如模板变量未定义)。
8. 总结
ApplicationSet 是 Argo CD 进入"规模化 GitOps"的关键拼图。它让你从一个个手工创建 Application 的繁琐劳动中解放出来,用 模板 + 生成器 的声明式方法,自动应对多集群、多环境、多服务的复杂部署需求。
从今天开始,请检查一下你的 Argo CD 中是否还躺着一堆静态的 Application YAML。如果是,不妨把它们重构成一个 ApplicationSet,感受一下"一个 CR 管所有"的畅快。
如果本文帮你理清了 ApplicationSet 的用法,欢迎点赞、收藏。你有哪些独家的生成器组合玩法?评论区聊聊!