搭出 GitOps 仓库的骨架
目标
亲手创建 GitOps 配置仓库的标准布局,并直观看到同一个 base 在不同环境中渲染为不同的最终清单。最后,以文件形式完成将该仓库接入 Argo CD 所需的 Application、AppProject 和 app-of-apps 根对象。
为什么这很重要
在 GitOps 中,仓库结构不是个人喜好,而是决定运维成本的设计。如果 base 与 overlay 划分合理,从 stage 晋升到 prod 的 PR diff 就只需变更一行镜像标签,评审者可以直观看出“配置保持不变,仅版本升级”。反之,如果为每个环境完整复制一份 YAML,每次晋升 PR 都会改动数十行,没有人能分辨哪些差异是有意为之。本实验中的 Application 和 AppProject 因实验环境没有 Argo CD CRD,所以只需写成文件,评分也会读取这些文件。在实际生产环境中,这些文件同样是提交到 Git 的产物,因此准确掌握其结构就是直接掌握实际工作方式。
步骤
- 创建目录
/root/cgoa-repo/apps/checkout/base、/root/cgoa-repo/apps/checkout/overlays/dev、/root/cgoa-repo/apps/checkout/overlays/stage、/root/cgoa-repo/apps/checkout/overlays/prod、/root/cgoa-repo/bootstrap。 - 在
base/deployment.yaml中编写 Deploymentcheckout——spec.replicas: 1,选择器和 Pod 标签均为app: checkout,容器名称为app,镜像为ghcr.io/labhub/checkout:1.4.0,containerPort 为8080。在base/service.yaml中编写 Servicecheckout——spec.ports[0].port: 80、targetPort: 8080,选择器为app: checkout。在base/kustomization.yaml的resources中列出这两个文件。 - 在
overlays/dev/kustomization.yaml中写入resources: [../../base]、namespace: cgoa-dev、namePrefix: dev-。在overlays/stage/kustomization.yaml中写入resources: [../../base]、namespace: cgoa-stage、namePrefix: stage-,并通过replicas将checkout指定为2。 - 在
overlays/prod/kustomization.yaml中写入resources: [../../base]、namespace: cgoa-prod、namePrefix: prod-,通过replicas将checkout指定为3,并通过images将ghcr.io/labhub/checkout的newTag指定为1.5.0。 - 将
kubectl kustomize /root/cgoa-repo/apps/checkout/overlays/prod的输出保存到/root/cgoa-repo/render-prod.yaml。 - 在
/root/cgoa-repo/bootstrap/app-checkout-prod.yaml中编写 Argo CD Application——apiVersion: argoproj.io/v1alpha1、kind: Application、metadata.name: checkout-prod、metadata.namespace: argocd、spec.project: checkout、spec.source.repoURL: http://10.0.0.200/labhub/gitops.git、spec.source.path: apps/checkout/overlays/prod、spec.source.targetRevision: main、spec.destination.server: https://kubernetes.default.svc、spec.destination.namespace: cgoa-prod、spec.syncPolicy.automated.prune: true、spec.syncPolicy.automated.selfHeal: true,并将spec.syncPolicy.syncOptions的第一项设为CreateNamespace=true。 - 在
/root/cgoa-repo/bootstrap/root-app.yaml中编写 app-of-apps 根 Application——名称为root,namespace 为argocd,spec.project: checkout、spec.source.path: bootstrap、spec.source.directory.recurse: true、spec.destination.namespace: argocd,启用自动同步(prune 与 selfHeal 均为 true)。 - 在
/root/cgoa-repo/bootstrap/project-checkout.yaml中编写 AppProjectcheckout——metadata.namespace: argocd,spec.sourceRepos第一项为http://10.0.0.200/labhub/gitops.git,spec.destinations[0].server: https://kubernetes.default.svc,spec.destinations[0].namespace: cgoa-*,spec.clusterResourceWhitelist[0]的 group 为""、kind 为Namespace。
参考
- 使用
kubectl kustomize <경로>检查渲染结果。与kubectl apply -k不同,它不会修改集群。 - kustomization.yaml 的
replicas采用- name: checkout/count: 3的形式,images采用- name: <이미지>/newTag: "1.5.0"的形式。 - 常见错误 1:在 overlay 的
resources中重新列出文件名,而不是引用../../base,从而复制了 base。这样晋升 PR 就无法只改一行。 - 常见错误 2:把
namePrefix放在 base 中。base 应与环境无关,因此前缀属于 overlay。
仓库目录骨架
创建目录 /root/cgoa-repo/apps/checkout/base、/root/cgoa-repo/apps/checkout/overlays/dev、/root/cgoa-repo/apps/checkout/overlays/stage、/root/cgoa-repo/apps/checkout/overlays/prod、/root/cgoa-repo/bootstrap。
需要一个 base、一组环境 overlay,以及一个用于集中存放 Application 清单的 bootstrap 目录。请使用能够一次创建全部上级路径的 mkdir 选项。
base 清单与 kustomization
在 base/deployment.yaml 中编写 Deployment checkout——spec.replicas: 1,选择器和 Pod 标签均为 app: checkout,容器名称为 app,镜像为 ghcr.io/labhub/checkout:1.4.0,containerPort 为 8080。在 base/service.yaml 中编写 Service checkout——spec.ports[0].port: 80、targetPort: 8080,选择器为 app: checkout。在 base/kustomization.yaml 的 resources 中列出这两个文件。
base 只应包含与环境无关的公共部分。最好不要在这里决定 namespace 或 replicas。请在 kustomization.yaml 的 resources 中列出文件名。
dev 与 stage overlay
在 overlays/dev/kustomization.yaml 中写入 resources: [../../base]、namespace: cgoa-dev、namePrefix: dev-。在 overlays/stage/kustomization.yaml 中写入 resources: [../../base]、namespace: cgoa-stage、namePrefix: stage-,并通过 replicas 将 checkout 指定为 2。
overlay 的 resources 通过相对路径指向 base。可以在 kustomization.yaml 中指定防止名称冲突的前缀字段和 namespace 字段。
prod overlay——replicas 与镜像标签
在 overlays/prod/kustomization.yaml 中写入 resources: [../../base]、namespace: cgoa-prod、namePrefix: prod-,通过 replicas 将 checkout 指定为 3,并通过 images 将 ghcr.io/labhub/checkout 的 newTag 指定为 1.5.0。
kustomize 提供了按名称修改 replicas 的字段,也提供了查找镜像名称并只修改标签的字段。无需 patch 文件,直接在 kustomization.yaml 中即可完成。
使用 kubectl kustomize 保存渲染结果
将 kubectl kustomize /root/cgoa-repo/apps/checkout/overlays/prod 的输出保存到 /root/cgoa-repo/render-prod.yaml。
kubectl kustomize <디렉터리> 会将应用 overlay 后的最终清单输出到标准输出。无需应用到集群,也能直观看到期望状态。
Argo CD Application 清单
在 /root/cgoa-repo/bootstrap/app-checkout-prod.yaml 中编写 Argo CD Application——apiVersion: argoproj.io/v1alpha1、kind: Application、metadata.name: checkout-prod、metadata.namespace: argocd、spec.project: checkout、spec.source.repoURL: http://10.0.0.200/labhub/gitops.git、spec.source.path: apps/checkout/overlays/prod、spec.source.targetRevision: main、spec.destination.server: https://kubernetes.default.svc、spec.destination.namespace: cgoa-prod、spec.syncPolicy.automated.prune: true、spec.syncPolicy.automated.selfHeal: true,并将 spec.syncPolicy.syncOptions 的第一项设为 CreateNamespace=true。
Application 由 source(来源)、destination(目标位置)和 syncPolicy(同步方式)三部分组成。请确认自动同步、自愈及自动创建 namespace 的选项分别放在哪里。
app-of-apps 根 Application
在 /root/cgoa-repo/bootstrap/root-app.yaml 中编写 app-of-apps 根 Application——名称为 root,namespace 为 argocd,spec.project: checkout、spec.source.path: bootstrap、spec.source.directory.recurse: true、spec.destination.namespace: argocd,启用自动同步(prune 与 selfHeal 均为 true)。
根对象的 source.path 指向包含子 Application 文件的目录,并设置为递归读取该目录。destination 是 Argo CD 自身所在的 namespace。
使用 AppProject 划定边界
在 /root/cgoa-repo/bootstrap/project-checkout.yaml 中编写 AppProject checkout——metadata.namespace: argocd,spec.sourceRepos 第一项为 http://10.0.0.200/labhub/gitops.git,spec.destinations[0].server: https://kubernetes.default.svc,spec.destinations[0].namespace: cgoa-*,spec.clusterResourceWhitelist[0] 的 group 为 ""、kind 为 Namespace。
AppProject 限制该项目的 Application 可以使用哪些仓库、部署到哪些集群和 namespace,以及创建哪些集群作用域资源。其名称必须与第 6 步所建 Application 的 project 值一致。