LabHub
学习 学习路径 课程

CGOA — GitOps 认证助理

制造漂移、观察它、再撤回

在 LabHub 中继续学习

目标

亲手完成一个完整循环:主动制造漂移、计算差异并保存到文件,再恢复到声明状态。随后编写 sync wave 和 PreSync hook 清单,并检查集群以判断 prune 对象。

为什么这很重要

Argo CD 的协调循环并非魔法,它只是默认每 180 秒重复本实验中的操作:重新渲染、读取 live 状态、进行比较,并在策略允许时应用。亲手执行一次这个循环,就能切身体会 refreshsync 为何是不同的操作,以及启用 selfHeal 会对运维纪律提出什么要求。判断 prune 对象也是如此——代理不会删除集群中的所有资源,而只会删除那些被标记为由它创建、且已从 Git 中消失的资源。如果不了解这一边界,就既无法解释“为什么那个没有被删除”,也无法解释“为什么这个被删除了”。本环境没有 Argo CD CRD,因此 wave 和 hook 需要以文件形式编写,评分也会读取这些文件。

步骤

  1. /root/cgoa-drift/desired/orders.yaml 中编写 Deployment orders——namespace 为 cgoa-driftspec.replicas: 2,选择器和 Pod 标签为 app: orders,容器名称为 app,镜像为 nginx:1.27-alpine。创建 namespace cgoa-drift,并使用 kubectl apply -f 应用该文件。
  2. 保持文件不变,只将集群中 orders 的 replicas 改为 5 以制造漂移。然后用 kubectl get ... -o jsonpath 读取变更后的 live 值,并保存到 /root/cgoa-drift/live-replicas.txt(稍后恢复后仍将其保留为证据)。
  3. kubectl diff -f /root/cgoa-drift/desired/orders.yaml 的输出保存到 /root/cgoa-drift/drift.txt。文件中应显示 replicas 的差异。
  4. 重新应用原始清单,将 replicas 恢复为 2
  5. /root/cgoa-drift/wave/ 中创建三个文件。namespace.yaml——Namespace cgoa-wave,注解 argocd.argoproj.io/sync-wave: "-2"config.yaml——ConfigMap orders-wave-config(namespace 为 cgoa-wave,data 中任意一个键),注解 argocd.argoproj.io/sync-wave: "-1"app.yaml——Deployment orders-wave(namespace 为 cgoa-wave),注解 argocd.argoproj.io/sync-wave: "1"
  6. /root/cgoa-drift/hooks/db-migrate.yaml 中编写 Job db-migrate——namespace 为 cgoa-drift,注解 argocd.argoproj.io/hook: PreSyncargocd.argoproj.io/hook-delete-policy: BeforeHookCreationargocd.argoproj.io/sync-wave: "-1"spec.backoffLimit: 1,Pod 的 restartPolicy: Never,容器名称为 migrate
  7. 判断 prune 对象。先在 /root/cgoa-drift/desired/config.yaml 中声明并应用 ConfigMap orders-config(namespace 为 cgoa-drift,data 中任意一个键)。然后以命令式方式创建名为 legacy-config 的 ConfigMap,位置是 namespace cgoa-drift不要使用文件。最后,在 /root/cgoa-drift/prune-candidates.txt 中逐行写入 namespace cgoa-drift 内那些未在 desired/ 目录任何位置声明的 ConfigMap 名称。(Kubernetes 自动创建的 kube-root-ca.crt 不属于管理对象,因此应排除。)

参考

声明并应用期望状态

/root/cgoa-drift/desired/orders.yaml 中编写 Deployment orders——namespace 为 cgoa-driftspec.replicas: 2,选择器和 Pod 标签为 app: orders,容器名称为 app,镜像为 nginx:1.27-alpine。创建 namespace cgoa-drift,并使用 kubectl apply -f 应用该文件。

以声明式方式应用后,对象的注解中会保留最后应用的配置。以命令式方式创建则没有该注解——评分会检查这一差异。

手动修改以制造漂移

保持文件不变,只将集群中 orders 的 replicas 改为 5 以制造漂移。然后用 kubectl get ... -o jsonpath 读取变更后的 live 值,并保存到 /root/cgoa-drift/live-replicas.txt(稍后恢复后仍将其保留为证据)。

必须保持文件不变,只修改集群。可以使用一个用于更改副本数的命令式子命令。请用 jsonpath 提取变更后的 live 值并保存到文件中——恢复后它仍可作为证据。

计算差异并保存到文件

kubectl diff -f /root/cgoa-drift/desired/orders.yaml 的输出保存到 /root/cgoa-drift/drift.txt。文件中应显示 replicas 的差异。

kubectl diff -f <파일> 会向服务器发起 dry-run,以显示实际差异。存在差异时退出码为 1,因此重定向输出时要避免命令因此中断。

恢复到声明状态

重新应用原始清单,将 replicas 恢复为 2

这是手动执行代理的 selfHeal 所做的工作。直接重新应用原始文件即可。

三个 sync wave 注解

/root/cgoa-drift/wave/ 中创建三个文件。namespace.yaml——Namespace cgoa-wave,注解 argocd.argoproj.io/sync-wave: "-2"config.yaml——ConfigMap orders-wave-config(namespace 为 cgoa-wave,data 中任意一个键),注解 argocd.argoproj.io/sync-wave: "-1"app.yaml——Deployment orders-wave(namespace 为 cgoa-wave),注解 argocd.argoproj.io/sync-wave: "1"

wave 编号要写成字符串。请分配编号,使基础设施最先、配置其次、工作负载最后。

PreSync hook Job

/root/cgoa-drift/hooks/db-migrate.yaml 中编写 Job db-migrate——namespace 为 cgoa-drift,注解 argocd.argoproj.io/hook: PreSyncargocd.argoproj.io/hook-delete-policy: BeforeHookCreationargocd.argoproj.io/sync-wave: "-1"spec.backoffLimit: 1,Pod 的 restartPolicy: Never,容器名称为 migrate

hook 类型和删除策略使用不同的注解键。为了便于评审,最好明确写出默认删除策略。

判断 prune 对象

判断 prune 对象。先在 /root/cgoa-drift/desired/config.yaml 中声明并应用 ConfigMap orders-config(namespace 为 cgoa-drift,data 中任意一个键)。然后以命令式方式创建名为 legacy-config 的 ConfigMap,位置是 namespace cgoa-drift不要使用文件。最后,在 /root/cgoa-drift/prune-candidates.txt 中逐行写入 namespace cgoa-drift 内那些未在 desired/ 目录任何位置声明的 ConfigMap 名称。(Kubernetes 自动创建的 kube-root-ca.crt 不属于管理对象,因此应排除。)

prune 对象是“存在于集群中,但不存在于声明目录中”的资源。请记住,由集群自动创建的对象不属于此范围。