TT Lab
开始
学习 学习路径 课程

GitOps 与 Argo CD

亲手写 Application 与 AppProject

在 TT Lab 中继续学习

目标

亲自编写 ArgoCD 的 Application 和 AppProject,用声明表达“从哪里读取什么,以什么顺序和策略应用到何处”。

为什么重要

把部署建模为对象而非脚本,会带来三项能力:可向集群查询“当前正在接收什么部署”;自动获得 RBAC 和审计日志;还能将声明本身提交回 git。本实验填写的每个字段都对应真实事故:prune 能把一次仓库路径拼写错误变成大规模删除;没有 retry.backoff 时,失败同步会以固定间隔持续冲击 API 服务器;没有 ignoreDifferences 时,HPA 与 ArgoCD 会反复争夺 replicas。但本环境并未运行 ArgoCD 控制器。你可以注册 CRD 并创建自定义资源,但它们不会自行变为 Synced/Healthy。因此评分检查的是声明是否准确;真实控制器会如何执行这些声明,已在前面的阅读材料和最后一个模块中说明。

步骤

  1. 在 /opt/crds/ 下的离线 CRD 包中查找包含 ArgoCD CRD 的文件(grep -l applications.argoproj.io /opt/crds/*.yaml),用 kubectl apply -f 应用。必须创建 applications.argoproj.io 与 appprojects.argoproj.io 两个 CRD,且 Established 条件为 True;还须存在命名空间 argocd。将已注册类型列表保存到 /root/gitops/app/out/crds.txt(必须包含字符串 applications)。
  2. 在 argocd 命名空间创建 kind: Application、metadata.name: web 的对象。spec.source.repoURL 为 file:///root/gitops/repo,spec.source.path 为 apps/web,spec.source.targetRevision 为 main,spec.destination.server 为 https://kubernetes.default.svc,spec.destination.namespace 为 gitops-lab,spec.project 为 platform。
  3. 为 web 添加 spec.syncPolicy.automated,设置 prune: true、selfHeal: true。在 /root/gitops/app/out/prune-note.txt 中用两三行中文说明启用 prune 的风险:一个指向错误路径的提交可能导致大规模删除。
  4. 在 web 的 spec.syncPolicy.syncOptions 中加入 CreateNamespace=true 和 ServerSideApply=true;在 spec.syncPolicy.retry 中设置 limit: 3、backoff.duration: 10s、backoff.factor: 2、backoff.maxDuration: 5m。
  5. 若仓库 /root/gitops/repo 尚不存在,先创建它:将 /opt/lab/fixtures/gitops/seed/ 中的 deployment.yaml 和 service.yaml 复制到 /root/gitops/repo/apps/web/,执行 git init 后提交。随后为 /root/gitops/repo/apps/web/ 中的 service.yaml 添加 argocd.argoproj.io/sync-wave: "-1" 注解,为 deployment.yaml 添加 argocd.argoproj.io/sync-wave: "0"。值必须是用双引号包裹的字符串。在 /root/gitops/app/out/wave-note.txt 中说明,同一 wave 内按资源种类(kind)的默认顺序应用。
  6. 在 /root/gitops/repo/apps/web/presync-job.yaml 创建 kind: Job 的钩子资源。添加注解 argocd.argoproj.io/hook: PreSync 和 argocd.argoproj.io/hook-delete-policy: BeforeHookCreation;容器名为 migrate,spec.backoffLimit 为 1,Pod 的 restartPolicy 为 Never。该目录中带钩子注解的文件必须只有这一个。
  7. 在 argocd 命名空间创建 kind: AppProject、metadata.name: platform。spec.sourceRepos 只能包含 file:///root/gitops/repo(禁止 *);spec.destinations[0] 包含 server https://kubernetes.default.svc 和 namespace gitops-lab(禁止 *);spec.clusterResourceWhitelist 包含 group "" / kind Namespace;spec.namespaceResourceBlacklist 包含 group "" / kind ResourceQuota 与 group "" / kind LimitRange。Application web 的 spec.project 必须为 platform。
  8. 为 web 添加 spec.ignoreDifferences:group apps、kind Deployment,jsonPointers 中包含 /spec/replicas(由 HPA 所有)。将 spec.revisionHistoryLimit 设为 5。最后创建 /root/gitops/app/out/gitops-report.json:applications 是包含 argocd 命名空间全部 Application、形式为 {"name": "..."} 的数组;project 为 "platform";self_heal 为 true。

参考

注册 ArgoCD API 类型

在 /opt/crds/ 下的离线 CRD 包中查找包含 ArgoCD CRD 的文件(grep -l applications.argoproj.io /opt/crds/*.yaml),用 kubectl apply -f 应用。必须创建 applications.argoproj.io 与 appprojects.argoproj.io 两个 CRD,且 Established 条件为 True;还须存在命名空间 argocd。将已注册类型列表保存到 /root/gitops/app/out/crds.txt(必须包含字符串 applications)。

由于没有互联网,请使用离线 CRD 包。不要死记文件名,而应按内容搜索——可用 grep 查找哪个文件包含 applications.argoproj.io。

定义 Application 的源与目标

在 argocd 命名空间创建 kind: Application、metadata.name: web 的对象。spec.source.repoURL 为 file:///root/gitops/repo,spec.source.path 为 apps/web,spec.source.targetRevision 为 main,spec.destination.server 为 https://kubernetes.default.svc,spec.destination.namespace 为 gitops-lab,spec.project 为 platform。

Application 对象自身所在位置与部署目标命名空间不同。source 必须同时说明从哪里、读取哪里以及使用哪个修订版本。

启用自动同步、清理与自愈

为 web 添加 spec.syncPolicy.automated,设置 prune: true、selfHeal: true。在 /root/gitops/app/out/prune-note.txt 中用两三行中文说明启用 prune 的风险:一个指向错误路径的提交可能导致大规模删除。

automated 下两个开关承担不同职责:一个处理从仓库删除的资源,另一个纠正集群中的漂移。还必须写明其中危险的一项是什么。

添加同步选项与重试退避

在 web 的 spec.syncPolicy.syncOptions 中加入 CreateNamespace=true 和 ServerSideApply=true;在 spec.syncPolicy.retry 中设置 limit: 3、backoff.duration: 10s、backoff.factor: 2、backoff.maxDuration: 5m。

syncOptions 是 키=값 字符串数组。重试不能只有次数,还需要三个让间隔逐渐拉长的值。

用 sync wave 创建部署顺序

若仓库 /root/gitops/repo 尚不存在,先创建它:将 /opt/lab/fixtures/gitops/seed/ 中的 deployment.yaml 和 service.yaml 复制到 /root/gitops/repo/apps/web/,执行 git init 后提交。随后为 /root/gitops/repo/apps/web/ 中的 service.yaml 添加 argocd.argoproj.io/sync-wave: "-1" 注解,为 deployment.yaml 添加 argocd.argoproj.io/sync-wave: "0"。值必须是用双引号包裹的字符串。在 /root/gitops/app/out/wave-note.txt 中说明,同一 wave 内按资源种类(kind)的默认顺序应用。

wave 值是注解,必须写成用双引号包裹的字符串,而非数字。应先创建的资源使用更小的值,必要时可用负数。要体现顺序,至少需要两个文件。

编写 PreSync 钩子 Job

在 /root/gitops/repo/apps/web/presync-job.yaml 创建 kind: Job 的钩子资源。添加注解 argocd.argoproj.io/hook: PreSync 和 argocd.argoproj.io/hook-delete-policy: BeforeHookCreation;容器名为 migrate,spec.backoffLimit 为 1,Pod 的 restartPolicy 为 Never。该目录中带钩子注解的文件必须只有这一个。

钩子本质上是普通 Job。需要两个注解:一个决定所处阶段,一个决定何时清理。遗漏清理策略会使钩子资源不断累积。

用 AppProject 划定边界

在 argocd 命名空间创建 kind: AppProject、metadata.name: platform。spec.sourceRepos 只能包含 file:///root/gitops/repo(禁止 *);spec.destinations[0] 包含 server https://kubernetes.default.svc 和 namespace gitops-lab(禁止 *);spec.clusterResourceWhitelist 包含 group "" / kind Namespace;spec.namespaceResourceBlacklist 包含 group "" / kind ResourceQuota 与 group "" / kind LimitRange。Application web 的 spec.project 必须为 platform。

白名单表示“只允许列出的内容”,黑名单表示“只禁止列出的内容”。仓库和命名空间若使用 *,项目隔离就失去意义。也不要忘记把应用归入该项目。

指定忽略字段并创建配置报告

为 web 添加 spec.ignoreDifferences:group apps、kind Deployment,jsonPointers 中包含 /spec/replicas(由 HPA 所有)。将 spec.revisionHistoryLimit 设为 5。最后创建 /root/gitops/app/out/gitops-report.json:applications 是包含 argocd 命名空间全部 Application、形式为 {"name": "..."} 的数组;project 为 "platform";self_heal 为 true。

若连其他控制器所有的字段也强行回滚,就会形成无限同步。报告中的应用数量不要手工统计,而应查询集群生成,才能始终与实际一致。