LabHub
学习 学习路径 课程

GitOps 与 Argo CD

建清单仓库并抓住漂移

在 LabHub 中继续学习

目标

创建包含清单的 git 仓库并应用到集群,检测手工变更造成的漂移,并按仓库状态恢复。

为什么重要

GitOps 的规则只有一句:**仓库是正确来源,集群跟随仓库。**遵守它之后,“生产环境现在运行什么”就能通过 git log 回答,回滚也变成普通的 git revert。反之,只要仍有直接修改集群的习惯,仓库就会沦为无法说明现实的文档,环境也无法复现。本实验反复使用 kubectl diff 正因为如此:diff 以退出码回答“声明与实际相差多少”,它手工完成的判断与 ArgoCD 界面显示 OutOfSync 完全相同。本环境没有运行 ArgoCD 控制器,因此最后一步将亲自编写脚本,完成控制器本应代劳的工作。

步骤

  1. 创建 /root/gitops/repo 并执行 git init,在该仓库中配置 user.nameuser.email。然后创建 /root/gitops/repo/README.md 并提交首次 commit(至少要有一个 commit)。
  2. /opt/lab/fixtures/gitops/seed/deployment.yamlservice.yaml 复制到 /root/gitops/repo/apps/web/。Deployment 的 metadata.labels 包含 app.kubernetes.io/managed-by: gitopsspec.selector.matchLabelsapp.kubernetes.io/nameweb,并且必须显式指定 spec.replicas,不能依赖默认值(此处从 2 开始)。容器镜像必须像 nginx:1.27 一样使用固定标签:latest 会失败)。README.md 也必须保留。
  3. apps/web/deployment.yamlapps/web/service.yamlREADME.md 三个文件全部执行 git add 使其被跟踪,并用至少 10 个字符的有意义消息提交。完成后 git status --porcelain 输出必须为空。
  4. 使用 kubectl apply -n gitops-lab -f /root/gitops/repo/apps/web/ 应用,并将完整输出保存到 /root/gitops/out/apply.txt。应用后,gitops-lab 命名空间中必须存在 Deployment web 和 Service web,Deployment 具有 app.kubernetes.io/managed-by=gitops 标签。
  5. 将仓库 apps/web/deployment.yaml 中的 spec.replicas 改为 3,用包含单词 replicas 的提交消息提交,再次应用到集群。完成后应至少有 2 个 commit,仓库和集群的 replicas 都为 3,工作树保持干净。
  6. 这次不要修改仓库,运行 kubectl scale deploy web -n gitops-lab --replicas=5 制造漂移。将 kubectl diff -n gitops-lab -f /root/gitops/repo/apps/web/ 的输出保存到 /root/gitops/out/drift-diff.txt,把该命令的退出码保存到 /root/gitops/out/drift-exit.txt。再在 /root/gitops/out/drift-note.txt 中用两三行中文说明手工变更会在下一次应用时被回滚并消失
  7. 重新按仓库状态应用,消除漂移。然后再次运行 kubectl diff -n gitops-lab -f /root/gitops/repo/apps/web/,把此时的退出码保存到 /root/gitops/out/clean-exit.txt。不得把手工设置的 5 写回仓库——仓库 replicas 应为 3,工作树应干净。
  8. 创建 /root/gitops/sync.sh 并赋予执行权限。脚本必须:(a) 用 kubectl diff 检查应用前差异;(b) 用 kubectl apply 应用;(c) 用 git rev-parse HEAD 记录应用了哪个 commit。执行后,在 /root/gitops/out/sync-report.json 中写入三个键:repo_commit(当前 HEAD 的完整哈希)、drift(布尔值 false)、applied(应用的对象数,不小于 2)。

参考

初始化保存声明的仓库

创建 /root/gitops/repo 并执行 git init,在该仓库中配置 user.nameuser.email。然后创建 /root/gitops/repo/README.md 并提交首次 commit(至少要有一个 commit)。

在 GitOps 中,commit 历史就是审计记录。要让仓库记录谁进行了修改,必须在该仓库配置 user.nameuser.email,并且至少存在一个 commit。

创建按应用划分的清单目录

/opt/lab/fixtures/gitops/seed/deployment.yamlservice.yaml 复制到 /root/gitops/repo/apps/web/。Deployment 的 metadata.labels 包含 app.kubernetes.io/managed-by: gitopsspec.selector.matchLabelsapp.kubernetes.io/nameweb,并且必须显式指定 spec.replicas,不能依赖默认值(此处从 2 开始)。容器镜像必须像 nginx:1.27 一样使用固定标签:latest 会失败)。README.md 也必须保留。

复制 fixture 使用,但仓库也需要便于人阅读。不要依赖默认值,应明确数量与镜像标签——若同一 commit 得到不同结果,仓库就没有定义状态。还要确认 selector 与 Pod 标签一致。

用 commit 固化声明

apps/web/deployment.yamlapps/web/service.yamlREADME.md 三个文件全部执行 git add 使其被跟踪,并用至少 10 个字符的有意义消息提交。完成后 git status --porcelain 输出必须为空。

若仍有未跟踪文件,仓库就无法完整定义集群。几个月后,人们会只看这一行提交消息来决定是否回滚,因此消息必须有意义。

将仓库声明应用到集群

使用 kubectl apply -n gitops-lab -f /root/gitops/repo/apps/web/ 应用,并将完整输出保存到 /root/gitops/out/apply.txt。应用后,gitops-lab 命名空间中必须存在 Deployment web 和 Service web,Deployment 具有 app.kubernetes.io/managed-by=gitops 标签。

可一次应用整个目录。清单未写命名空间,因此必须在命令中指定,并把应用结果保存为文件。

经由 commit 应用变更

将仓库 apps/web/deployment.yaml 中的 spec.replicas 改为 3,用包含单词 replicas 的提交消息提交,再次应用到集群。完成后应至少有 2 个 commit,仓库和集群的 replicas 都为 3,工作树保持干净。

顺序是关键:先修改仓库并提交,再应用。先修改集群,那不是变更,而是漂移。

手工修改并制造漂移

这次不要修改仓库,运行 kubectl scale deploy web -n gitops-lab --replicas=5 制造漂移。将 kubectl diff -n gitops-lab -f /root/gitops/repo/apps/web/ 的输出保存到 /root/gitops/out/drift-diff.txt,把该命令的退出码保存到 /root/gitops/out/drift-exit.txt。再在 /root/gitops/out/drift-note.txt 中用两三行中文说明手工变更会在下一次应用时被回滚并消失

这次故意不碰仓库,只修改集群。本步骤的关键是查看差异命令的退出码,而且必须紧接该命令读取。

按仓库状态恢复

重新按仓库状态应用,消除漂移。然后再次运行 kubectl diff -n gitops-lab -f /root/gitops/repo/apps/web/,把此时的退出码保存到 /root/gitops/out/clean-exit.txt。不得把手工设置的 5 写回仓库——仓库 replicas 应为 3,工作树应干净。

把手工值偷偷写入仓库,就是把事故提升为代码。假定仓库正确并让集群与之对齐,再确认没有差异时的退出码。

创建同步脚本与报告

创建 /root/gitops/sync.sh 并赋予执行权限。脚本必须:(a) 用 kubectl diff 检查应用前差异;(b) 用 kubectl apply 应用;(c) 用 git rev-parse HEAD 记录应用了哪个 commit。执行后,在 /root/gitops/out/sync-report.json 中写入三个键:repo_commit(当前 HEAD 的完整哈希)、drift(布尔值 false)、applied(应用的对象数,不小于 2)。

用 shell 模拟控制器的工作:应用前查看将发生什么,执行应用,并记录应用了哪个 commit。若把脚本放进仓库,报告中记录的哈希就会失效。