只有单向,成不了真相之源
一句话总结
只有实现双向控制,才能声称 Git 是唯一 source of truth。只启用 automated 时仍是单向,Git 与集群会悄悄分离。
为什么必须双向
GitOps 的核心主张只有一个:Git 是唯一 source of truth,集群是它的副本。
要让这项主张成立,必须是双向的。
| 设置 | 作用 |
|---|---|
automated |
修改 Git 后,集群跟随变化 |
selfHeal |
直接修改集群后,自动恢复 |
prune |
从 Git 删除的对象,也从集群删除 |
只启用 automated 时仍是单向。通过 kubectl 直接修改的内容会保留下来,Git 与集群悄悄分离。 通常起因是紧急故障:凌晨通过 kubectl scale 扩容,早晨却忘记更新 Git。下一次部署时,差异就会一次性被恢复。
sync 与 health 表达不同含义
sync——Git 与集群是否相同health——已部署内容是否正常运行
应用可以 OutOfSync 却同时 Healthy,例如有人手动修改,而该状态运行良好。反过来,也可能 Synced 却 Degraded。
selfHeal 有代价
它会妨碍紧急手动处置。并且手动修改会不留痕迹地消失,修改者不知道自己的变更为何丢失。因此,团队必须预先达成“紧急处置也要经过 Git”的共识。
它还会与 HPA 冲突。如果 Git 中写有 replicas,HPA 每次扩容都会被 Argo 恢复。
OutOfSync 无法消失时
这是最常见的运维问题。Git 与集群看似相同,却一直显示 OutOfSync,原因通常是某个主体自动填入了字段。
| 填入主体 | 示例 | 应对方式 |
|---|---|---|
| admission webhook | sidecar 注入、默认 label | 使用 ignoreDifferences 排除相应路径 |
| controller | HPA 的 replicas、clusterIP |
从 Git 删除相应字段 |
| API server default | imagePullPolicy、terminationGracePeriodSeconds |
在 Git 中明确写入以保持一致 |
# Application 스펙
spec:
ignoreDifferences:
- group: apps
kind: Deployment
jsonPointers:
- /spec/replicas # HPA 가 관리한다
- group: ""
kind: Service
jsonPointers:
- /spec/clusterIP # API 서버가 정한다
应使用命令而不是 UI 查看具体差异。
argocd app diff <앱> --local ./manifests # 로컬과 클러스터
argocd app get <앱> -o json | jq '.status.resources[] | select(.status!="Synced")'
同步顺序与 wave
一次 apply 所有 resource 会产生顺序问题,例如 CRD 尚不存在就 apply CR,或者 application 在 DB 启动前就运行。Argo 使用 sync wave 决定顺序。
metadata:
annotations:
argocd.argoproj.io/sync-wave: "-1" # 작을수록 먼저
Argo 先应用默认顺序(namespace → CRD → 其余),再在其中检查 wave。wave 之间会等待前一 wave 的 resource 全部变为 Healthy。因此,如果把没有 Health 判定的 custom resource 放在前一个 wave,可能会永远等待。此时应使用 Hook、health check Lua script,或合并 wave。
App of Apps 与 project
application 达到数十个后,会用 Git 管理 Application 自身(app of apps)。这样,添加新服务就变成 commit 一张 manifest。
再通过 AppProject 设置围栏,限制可以从哪个 repository、向哪个 cluster 的哪个 namespace 创建哪些 resource kind。没有它时,某个 Application 就可能修改 kube-system。
spec:
sourceRepos: ["https://git.internal/labhub/*"]
destinations:
- namespace: "labhub-*"
server: https://kubernetes.default.svc
clusterResourceWhitelist: [] # 클러스터 범위 리소스는 아예 금지
实务中真正重要的事
启用 selfHeal 之前,应先约定紧急处置流程。 手动修改会不留痕迹地消失,修改者不知道自己的变更为何消失。在尚未形成“紧急处置也经过 Git”共识的团队中启用它,会让凌晨故障发生两次。
使用 HPA 的 workload 必须从 Git 删除 replicas。 否则 HPA 每次扩容都会被 Argo 恢复,两个 controller 会在负载上升期间互相争夺。
不能把 Synced 绿灯理解成部署完成。 sync 只表示与 Git 一致,health 才表示运行正常,因此 Synced 且 Degraded 的状态真实存在。判断部署结果时必须同时查看二者。
下一项实验会在真实 Argo CD 上连同 Git server 一起搭建,并亲自制造这些现象。