LabHub
学习 学习路径 课程

GitOps 与 Argo CD

用 base 与 overlay 做出环境差异

在 LabHub 中继续学习

目标

从一个 base 生成 dev、prod 两个环境,并能将这些 overlay 连接为 ArgoCD Application 的源。

为什么重要

按环境复制 YAML 管理,必然会逐渐分叉;分叉后无人知道哪边才正确,“dev 明明可以”也由此开始。overlay 让公共部分只写一次,仅把差异保留为文件,从结构上阻止分叉。本实验尤其要观察 configMapGenerator 的哈希后缀:配置内容变化时 ConfigMap 名称改变,引用它的 Pod 模板也改变,从而自动触发 rollout。没有哈希时,只更新 ConfigMap,Pod 却继续使用旧配置,这是最难排查的事故之一。最后还会了解 ArgoCD 处理 Helm 的方式:ArgoCD 不执行 helm install,而是在 repo-server 中用 helm template 渲染后 apply。因此集群中运行 helm list 看不到内容,回滚依靠 git 提交而不是 Helm revision。

步骤

  1. base 指令文件为 /root/gitops/kustomize/base/kustomization.yaml。把 /opt/lab/fixtures/gitops/seed/deployment.yamlservice.yaml 复制到 /root/gitops/kustomize/base/,在同一目录创建 kustomization.yaml。写入 apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization,并在 resources 中列出两个文件名。base 的 spec.replicas 设为 2(设为 1 将失败)。
  2. kustomize build /root/gitops/kustomize/base > /root/gitops/kustomize/out/base.yaml 保存结果。结果必须包含 kind: Deploymentkind: Service,不得包含 kind: Kustomization
  3. 在 base 的 kustomization.yaml 中加入 namePrefix: labhub-,并添加公共标签 app.kubernetes.io/part-of: labhub-platformlabels: 下的 - pairs: 形式或 commonLabels: 均可)。重新构建并更新 out/base.yaml 后,Deployment 名称应为 labhub-web,Service 的 metadata.labels 也应包含该标签。
  4. 创建 /root/gitops/kustomize/overlays/dev/kustomization.yamlresources 第一项为 ../../basenamespacegitops-devnameSuffix-dev。使用 kustomize build /root/gitops/kustomize/overlays/dev > /root/gitops/kustomize/out/dev.yaml 保存。
  5. 在 dev overlay 中放置战略合并补丁文件(如 patch-deployment.yaml),并在 kustomization.yamlpatches 中写入路径。补丁须把 Deployment 的 spec.replicas 降为 1,并为容器 web 添加环境变量 LOG_LEVEL=debug。补丁的 metadata.name 使用base 中的原始名称 web。base 的 replicas 仍须为 2。重新构建并更新 out/dev.yaml
  6. 在 dev overlay 的 kustomization.yaml 中使用 configMapGenerator 创建名为 app-config 的 ConfigMap(如在 literals 中写 LOG_FORMAT=json)。再在第 5 步补丁中让容器 web 通过 envFromconfigMapRef.name: app-config 引用它。重新构建后,ConfigMap 名称末尾应有内容哈希,Deployment 引用名也应更新为带哈希的名称。在 /root/gitops/kustomize/out/hash-note.txt 中用中文说明哈希后缀使配置变更触发 Pod rollout。
  7. argocd 命名空间创建 kind: Applicationmetadata.name: platform-helm。在 spec.source.helm.valueFiles 中加入 values-prod.yaml;在 spec.source.helm.parameters 中加入名称 image.tag 和一个值(如 1.27.3);spec.source.targetRevision 使用非 HEAD 的固定值(如 v1.4.0)。
  8. 创建 /root/gitops/kustomize/overlays/prod/ overlay:resources../../basenamespacegitops-prod,用补丁把 spec.replicas 设为 3 或更大,并通过 images 把镜像标签改成与 dev 不同的值(如 name: nginxnewTag: 1.27.3)。将构建结果保存到 /root/gitops/kustomize/out/prod.yaml。随后在 argocd 命名空间创建 kind: Applicationmetadata.name: web-devspec.source.path 必须包含 overlays/devspec.source.kustomize.images 至少包含一个镜像覆盖项。

参考

配置 kustomize base

base 指令文件为 /root/gitops/kustomize/base/kustomization.yaml。把 /opt/lab/fixtures/gitops/seed/deployment.yamlservice.yaml 复制到 /root/gitops/kustomize/base/,在同一目录创建 kustomization.yaml。写入 apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization,并在 resources 中列出两个文件名。base 的 spec.replicas 设为 2(设为 1 将失败)。

kustomization.yaml 是指令文件而非清单。resources 中列出的名称必须真实存在于同一目录。

保存 base 构建结果

kustomize build /root/gitops/kustomize/base > /root/gitops/kustomize/out/base.yaml 保存结果。结果必须包含 kind: Deploymentkind: Service,不得包含 kind: Kustomization

kustomize build 디렉터리 的标准输出写入文件。结果中不应混入指令文件本身,因为它不是产物。

添加名称前缀与公共标签

在 base 的 kustomization.yaml 中加入 namePrefix: labhub-,并添加公共标签 app.kubernetes.io/part-of: labhub-platformlabels: 下的 - pairs: 形式或 commonLabels: 均可)。重新构建并更新 out/base.yaml 后,Deployment 名称应为 labhub-web,Service 的 metadata.labels 也应包含该标签。

名称变换和标签都在 base kustomization 中声明。可使用新版 labelspairs 或旧版 commonLabels。修改后必须重新构建,结果文件才会变化。

创建 dev overlay

创建 /root/gitops/kustomize/overlays/dev/kustomization.yamlresources 第一项为 ../../basenamespacegitops-devnameSuffix-dev。使用 kustomize build /root/gitops/kustomize/overlays/dev > /root/gitops/kustomize/out/dev.yaml 保存。

overlay 通过相对路径把 base 放入 resources。命名空间和名称后缀由 overlay 决定,构建结果单独保存为 dev 文件。

用补丁覆盖 base

在 dev overlay 中放置战略合并补丁文件(如 patch-deployment.yaml),并在 kustomization.yamlpatches 中写入路径。补丁须把 Deployment 的 spec.replicas 降为 1,并为容器 web 添加环境变量 LOG_LEVEL=debug。补丁的 metadata.name 使用base 中的原始名称 web。base 的 replicas 仍须为 2。重新构建并更新 out/dev.yaml

不要修改 base。补丁文件使用 base 中的原始名称,且容器名称必须正确才能合并。

连接配置生成器与哈希后缀

在 dev overlay 的 kustomization.yaml 中使用 configMapGenerator 创建名为 app-config 的 ConfigMap(如在 literals 中写 LOG_FORMAT=json)。再在第 5 步补丁中让容器 web 通过 envFromconfigMapRef.name: app-config 引用它。重新构建后,ConfigMap 名称末尾应有内容哈希,Deployment 引用名也应更新为带哈希的名称。在 /root/gitops/kustomize/out/hash-note.txt 中用中文说明哈希后缀使配置变更触发 Pod rollout。

生成器创建的名称末尾带内容哈希。工作负载引用该 ConfigMap 时,引用名也会同步更新——理解它为何有用是本步骤的核心。

编写使用 Helm 源的 Application

argocd 命名空间创建 kind: Applicationmetadata.name: platform-helm。在 spec.source.helm.valueFiles 中加入 values-prod.yaml;在 spec.source.helm.parameters 中加入名称 image.tag 和一个值(如 1.27.3);spec.source.targetRevision 使用非 HEAD 的固定值(如 v1.4.0)。

环境值文件与每次部署变化的单独参数位于不同位置。若 revision 指向分支最新值,同一声明在不同时刻会部署不同内容。

创建基于 overlay 的 Application 与 prod 构建

创建 /root/gitops/kustomize/overlays/prod/ overlay:resources../../basenamespacegitops-prod,用补丁把 spec.replicas 设为 3 或更大,并通过 images 把镜像标签改成与 dev 不同的值(如 name: nginxnewTag: 1.27.3)。将构建结果保存到 /root/gitops/kustomize/out/prod.yaml。随后在 argocd 命名空间创建 kind: Applicationmetadata.name: web-devspec.source.path 必须包含 overlays/devspec.source.kustomize.images 至少包含一个镜像覆盖项。

prod overlay 使用与 dev 相同的 base,但命名空间、副本数和镜像标签必须不同。Application 中也有专门替换镜像标签的位置。