LabHub
学习 学习路径 课程

CGOA — GitOps 认证助理

只有单向,成不了真相之源

在 LabHub 中继续学习

一句话总结

只有实现双向控制,才能声称 Git 是唯一 source of truth。只启用 automated 时仍是单向,Git 与集群会悄悄分离。

概念图: Git 是唯一 source of truth,集群是它的副本。 · 双向的 · Git 与集群悄悄分离。 · 相同

为什么必须双向

GitOps 的核心主张只有一个:Git 是唯一 source of truth,集群是它的副本。

要让这项主张成立,必须是双向的

设置 作用
automated 修改 Git 后,集群跟随变化
selfHeal 直接修改集群后,自动恢复
prune 从 Git 删除的对象,也从集群删除

只启用 automated 时仍是单向。通过 kubectl 直接修改的内容会保留下来,Git 与集群悄悄分离。 通常起因是紧急故障:凌晨通过 kubectl scale 扩容,早晨却忘记更新 Git。下一次部署时,差异就会一次性被恢复。

sync 与 health 表达不同含义

应用可以 OutOfSync 却同时 Healthy,例如有人手动修改,而该状态运行良好。反过来,也可能 SyncedDegraded

selfHeal 有代价

它会妨碍紧急手动处置。并且手动修改会不留痕迹地消失,修改者不知道自己的变更为何丢失。因此,团队必须预先达成“紧急处置也要经过 Git”的共识。

它还会与 HPA 冲突。如果 Git 中写有 replicas,HPA 每次扩容都会被 Argo 恢复。

OutOfSync 无法消失时

这是最常见的运维问题。Git 与集群看似相同,却一直显示 OutOfSync,原因通常是某个主体自动填入了字段

填入主体 示例 应对方式
admission webhook sidecar 注入、默认 label 使用 ignoreDifferences 排除相应路径
controller HPA 的 replicasclusterIP 从 Git 删除相应字段
API server default imagePullPolicyterminationGracePeriodSeconds 在 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 才表示运行正常,因此 SyncedDegraded 的状态真实存在。判断部署结果时必须同时查看二者。

下一项实验会在真实 Argo CD 上连同 Git server 一起搭建,并亲自制造这些现象。