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

GitOps 与 Argo CD

把运维中手动做的三件事变成按钮

在 TT Lab 中继续学习

目标

在 argocd-cm 的 resource.customizations.actions.<그룹>_<종류>(占位符依次为组、类型)中编写 discovery.lua 和操作定义来创建资源操作,根据情况让按钮变灰,并把操作产生的变更真正应用到 kwok 集群。

为什么重要

GitOps 做得好的话,生产环境里靠手工完成的事情应该消失,但有几件事会一直保留下来——暂时暂停、重新拉起、增加一个副本。如果让人用 kubectl 去做,仓库和集群就会分叉;如果干脆禁止,又会催生更危险的绕行办法。资源操作就是这样一种装置:只把这几件事做成界面上的按钮,并纳入权限与审计记录的管辖之下。 其设计要点有两个。第一,操作不会修改仓库——所以如果自动同步是开启的,下一次调谐时就会被还原。第二,要把什么做成按钮,都集中在 discovery.lua 这一处。根据状态开启或关闭的判断由这段代码而不是界面来做,所以可以通过设计避免对已经暂停的东西再次暂停这类事故。

步骤

  1. 在 /root/ga-actions/deploy.yaml 中创建 ga-actions 命名空间的 Deployment web——spec.replicas 为 2,一个容器(web,镜像 nginx:1.25),选择器和标签为 app: web。/root/ga-actions/argocd-cm.yaml 是 data: {} 的空 ConfigMap。把 argocd admin settings resource-overrides list-actions /root/ga-actions/deploy.yaml --argocd-cm-path /root/ga-actions/argocd-cm.yaml 的输出保存到 /root/ga-actions/none.txt。
  2. 在 /root/ga-actions/w-running.yaml 中创建 example.com/v1 的 Widget——名称为 w-running,命名空间为 ga-actions,spec.size 为 3,status.phase 为 Running。在 /root/ga-actions/argocd-cm-pause.yaml 中放置键 resource.customizations.actions.example.com_Widget,让 discovery.lua 只给出一个 pause,并在 definitions 中写下该操作的 action.lua(把 spec.paused 设为真)。把 list-actions 的输出保存到 /root/ga-actions/list-pause.txt。
  3. 把 argocd admin settings resource-overrides run-action /root/ga-actions/w-running.yaml pause --argocd-cm-path /root/ga-actions/argocd-cm-pause.yaml 的输出保存到 /root/ga-actions/run-pause.txt。输出中必须能看到新增了 paused: true。
  4. 创建 /root/ga-actions/w-paused.yaml——名称为 w-paused,spec.size 为 3,spec.paused 为真,status.phase 为 Paused。在 /root/ga-actions/argocd-cm-toggle.yaml 中放置 pause 和 resume 两个操作,并让 discovery.lua 根据 spec.paused 的值,只让两者之一可用,方法是加上 disabled。把针对这两个样本的 list-actions 输出分别保存到 /root/ga-actions/list-running.txt 和 /root/ga-actions/list-paused.txt。
  5. 在 /root/ga-actions/argocd-cm-scale.yaml 中,在第 4 步的两个操作之外再加一个 scale-up——把 spec.size 增加 1。对于已暂停的 Widget,这个操作也必须变灰。把对 w-running.yaml 运行 scale-up 的输出保存到 /root/ga-actions/run-scale.txt。必须能看到 3 变成 4。
  6. 在 /root/ga-actions/argocd-cm-full.yaml 中原样保留第 5 步的 Widget 操作,再创建一个键 resource.customizations.actions.apps_Deployment。操作名称为 pin-image,把第一个容器的镜像改为 nginx:1.27-hardened。把对 deploy.yaml 运行这个操作的输出保存到 /root/ga-actions/run-pin.txt。
  7. 在 kwok 集群中创建命名空间 ga-actions 并应用 deploy.yaml。然后创建并应用 /root/ga-actions/deploy-pinned.yaml,它是反映了第 6 步操作所指出变更的清单——集群中 web 容器的镜像必须变成操作所指定的值。
  8. 在 /root/ga-actions/actions-matrix.tsv 中写至少四行 <샘플파일이름>\t<동작이름>\t<바뀐 필드에서 찾을 글자>(占位符依次为样本文件名、操作名称、要在被修改字段中查找的字符)——必须出现三种以上的操作名称。/root/ga-actions/check-actions.sh 读取这张表,用 /root/ga-actions/argocd-cm-full.yaml 运行每个操作,输出中有该字符则输出 OK …,没有则输出 MISMATCH …,只写到标准输出,只要有一行不匹配就必须以非 0 退出码结束。把它的输出保存到 /root/ga-actions/actions-result.txt。

参考

这条命令只看 ConfigMap

在 /root/ga-actions/deploy.yaml 中创建 ga-actions 命名空间的 Deployment web——spec.replicas 为 2,一个容器(web,镜像 nginx:1.25),选择器和标签为 app: web。/root/ga-actions/argocd-cm.yaml 是 data: {} 的空 ConfigMap。把 argocd admin settings resource-overrides list-actions /root/ga-actions/deploy.yaml --argocd-cm-path /root/ga-actions/argocd-cm.yaml 的输出保存到 /root/ga-actions/none.txt。

在 Argo CD 界面上,Deployment 会显示 restart 之类的按钮。但这条命令的输出不同——想一想这条命令读取的是什么,就能明白原因。后面的步骤会一直把这两个文件当作材料。

决定显示哪些按钮的代码

在 /root/ga-actions/w-running.yaml 中创建 example.com/v1 的 Widget——名称为 w-running,命名空间为 ga-actions,spec.size 为 3,status.phase 为 Running。在 /root/ga-actions/argocd-cm-pause.yaml 中放置键 resource.customizations.actions.example.com_Widget,让 discovery.lua 只给出一个 pause,并在 definitions 中写下该操作的 action.lua(把 spec.paused 设为真)。把 list-actions 的输出保存到 /root/ga-actions/list-pause.txt。

一个键的值中包含 discovery.lua 和 definitions 两项。discovery 返回以名称为键的表,definitions 是带有名称和 action.lua 的列表。没有 spec 的资源也可能传进来,所以请在 action.lua 中检查。

运行操作就会得到被修改的字段

把 argocd admin settings resource-overrides run-action /root/ga-actions/w-running.yaml pause --argocd-cm-path /root/ga-actions/argocd-cm-pause.yaml 的输出保存到 /root/ga-actions/run-pause.txt。输出中必须能看到新增了 paused: true。

这条命令不会把修改后的资源整个返回,而只显示改了什么。因此可以一眼确认操作除了预期的修改之外还动了什么——编写操作时最需要小心的正是这一点。

根据情况让按钮变灰

创建 /root/ga-actions/w-paused.yaml——名称为 w-paused,spec.size 为 3,spec.paused 为真,status.phase 为 Paused。在 /root/ga-actions/argocd-cm-toggle.yaml 中放置 pause 和 resume 两个操作,并让 discovery.lua 根据 spec.paused 的值,只让两者之一可用,方法是加上 disabled。把针对这两个样本的 list-actions 输出分别保存到 /root/ga-actions/list-running.txt 和 /root/ga-actions/list-paused.txt。

在 discovery.lua 返回的表的值中放入 {["disabled"] = true},该操作就会变灰。对已经暂停的东西再次暂停的按钮会招来事故,所以根据状态开启或关闭的工作由这段代码而不是界面来做。

读取值并计算的操作

在 /root/ga-actions/argocd-cm-scale.yaml 中,在第 4 步的两个操作之外再加一个 scale-up——把 spec.size 增加 1。对于已暂停的 Widget,这个操作也必须变灰。把对 w-running.yaml 运行 scale-up 的输出保存到 /root/ga-actions/run-scale.txt。必须能看到 3 变成 4。

action.lua 可以读取资源并进行计算。这里要注意的是值不存在的情况——给 nil 加 1 会让脚本崩溃。本实验的样本里 size 总是存在,但如果是真正要使用的规则,就应该加入检查。

也给内置类型添加自己的操作

在 /root/ga-actions/argocd-cm-full.yaml 中原样保留第 5 步的 Widget 操作,再创建一个键 resource.customizations.actions.apps_Deployment。操作名称为 pin-image,把第一个容器的镜像改为 nginx:1.27-hardened。把对 deploy.yaml 运行这个操作的输出保存到 /root/ga-actions/run-pin.txt。

Lua 的数组下标不是从 0 开始,而是从 1 开始——containers[1] 是第一个容器。给内置类型添加自定义操作后,界面上会多出一个按钮,而内置操作仍然保留。

把操作产生的结果应用到真实集群

在 kwok 集群中创建命名空间 ga-actions 并应用 deploy.yaml。然后创建并应用 /root/ga-actions/deploy-pinned.yaml,它是反映了第 6 步操作所指出变更的清单——集群中 web 容器的镜像必须变成操作所指定的值。

run-action 不会保存修改后的资源,只会告知会改变什么。在真正的 Argo CD 中,这个结果由控制器来应用,而在这里,则由人把同样的变更写进清单再应用。如果命名空间不存在,应用会失败。

把操作所做的事整理成表,做回归检查

在 /root/ga-actions/actions-matrix.tsv 中写至少四行 <샘플파일이름>\t<동작이름>\t<바뀐 필드에서 찾을 글자>(占位符依次为样本文件名、操作名称、要在被修改字段中查找的字符)——必须出现三种以上的操作名称。/root/ga-actions/check-actions.sh 读取这张表,用 /root/ga-actions/argocd-cm-full.yaml 运行每个操作,输出中有该字符则输出 OK …,没有则输出 MISMATCH …,只写到标准输出,只要有一行不匹配就必须以非 0 退出码结束。把它的输出保存到 /root/ga-actions/actions-result.txt。

操作是写一次就会被遗忘的代码,资源 schema 改变的那天,它会悄悄开始修改不该动的字段。有了这张表,当天就会亮起红灯。如果脚本自己去写文件,评分器再次运行时就会覆盖学员的产出文件,所以请只输出到标准输出。