Argo 为什么被拆成四个
一句话总结
Argo 不是一个部署工具,而是一组包含四个 CNCF 项目的套件。Argo CD 解决“集群是否与 Git 保持相同状态”,Workflows 解决“按指定顺序把这些任务全部执行完”,Events 解决“外部发生某件事时再触发”,Rollouts 解决“以多慢的速度发布新版本”。它们没有合并为一个项目,是因为各自处理的时间性质不同。
为什么需要它
GitOps 之前的部署大多采用 push。CI server 完成构建后执行 kubectl apply。这种结构隐藏了三项代价。第一,CI server 必须持有 production 集群的 credential。一台 Jenkins 被攻陷,所有集群都可能失守。第二,应用配置后,即使有人手动修改 replicas,也无人知晓。Git 只是部署时的记录,不是当前状态的依据。第三,一旦有多个集群,pipeline 数量会随集群数量增加。
Pull 模型一次颠覆了这三点。运行在集群内的 controller 读取 Git,并自行使实际状态与其一致。credential 不会离开集群;controller 持续比较,因此 drift 会呈现为状态;即使集群增多,也可以继续使用一个 Git repository。Argo CD 所做的正是这些,其余三个项目则像卫星一样围绕这条主轴。
工作原理
| 项目 | 解决的问题 | 时间性质 |
|---|---|---|
| Argo CD | 持续消除声明状态与实际状态的差异 | 永不结束的 loop(默认周期 180 秒) |
| Argo Workflows | 将多个 container task 组织为 DAG,并完整执行一次 | 有开始与结束的有限执行 |
| Argo Events | 接收外部 signal 并启动某项操作 | 无法预知何时到来的 event |
| Argo Rollouts | 观察指标,逐步扩大新版本比例 | 包含人工判断的数分钟至数小时 |
由此可以看出没有合并的原因。Argo CD 会运行到“差异为 0”,本身没有完成概念;Workflows 恰恰相反,完成就是它的全部。如果把两者放进一个 controller,重试含义、失败处理和 metric 名称都会冲突。Events 独立存在也是同样原因。如果开始向 Argo CD 添加 webhook 处理,GitHub、S3、Kafka、calendar 都会进入 deployment controller。Events 则把这种 adapter 困境抽离成 EventSource → Sensor → Trigger 这条独立轴线。
Argo CD 是 CNCF Graduated 项目。毕业等级对实际工作的含义是“该 API 不会在下个季度被彻底推翻”,因此可以放心把 Application manifest 作为组织标准。
现场会遇到的情况
作者的家庭实验室由 3 台 control plane 与 4 台 GPU worker 组成,共 7 个节点。MetalLB 通过 L2 分配 10.0.0.200~215,其上 Gitea 使用 10.0.0.200,ArgoCD 使用 10.0.0.201,Harbor 使用 10.0.0.202。source、GitOps controller 与 registry 并列运行在同一地址网段,而这种布局的真正价值,在故障发生时才显现。
该集群的 controlPlaneEndpoint 不是 VIP,而被固定为第一台 control plane 的物理 IP。etcd 有三个 member,quorum 完全正常,但只要该节点故障,kubectl 与 kubelet 都无法连接。control plane 仍然存活,却无人能找到入口。从中得到两项教训:一是“状态为 Ready”与“真实可用”是两个不同命题;二是即使整个集群都不可见,Git repository 中仍保留期望状态。如果使用 push pipeline,恢复步骤可能变成“重新构建 pipeline”;使用 pull 模型,则在集群复活的瞬间,controller 会自行追赶到目标状态。很多文章用部署便利性解释引入 GitOps 的理由,但它真正体现价值的时刻,正是这种恢复场景。
四个项目实际重叠的位置
Argo 的四个项目可以独立使用,但组合使用时,也会出现边界模糊的位置。考试和实际工作都会在这里区分理解深浅。
CD 与 Rollouts 会发生所有权冲突。 Rollouts 执行 canary 期间,Deployment 的 replicas 或 image 会变化,而 CD 会将其视为相对 Git 的差异。如果不用 ignoreDifferences 排除相应字段,就会形成CD 把 canary 回滚的循环。
Workflows 与 Events 的区别在于“什么是触发器”。 Workflows 是运行多步骤任务的 engine;Events 则是接收外部事件(webhook、queue message、schedule)并调用该 engine 的一层。没有 Events,只用 Workflows 时需要人工启动;没有 Workflows,只用 Events 时,收到事件后能执行的操作会比较简单。
需要同步顺序时,使用 hook 与 wave。 必须先创建 namespace,才能安装 CRD;有了 CRD,才能创建使用它的 resource。如果不指定顺序,首次同步会失败,之后可能因 retry 偶然成功。使用 argocd.argoproj.io/sync-wave 指定顺序,migration 等只应运行一次的操作则放在 PreSync hook 中。
创建应用的应用(App of Apps)很方便,但难以回滚。 删除 parent app 时,child 是否随之删除取决于 finalizer。不了解这一点就执行删除,可能导致整个集群被清空,这种事故真实发生过。因此,应明确规定 parent 与 child 的删除策略。
无论使用哪个项目,真正困难的都是权限。 如果 CD 要向多个集群部署,就必须持有这些集群的权限,这意味着攻陷 CD 就可能攻陷全部集群。因此,通过 AppProject 按项目限制目标 namespace 与 resource kind,不是可选项,而是基础配置。
下一项测验要确认什么
本模块只讨论概念。紧接着的模块会要求直接编写 Application manifest,亲手确认刚才所说的“持续消除差异的 loop”由哪些字段组成。