Argo CD Argo CD

按环境部署 Helm Chart 与 Kustomize Overlay

为 dev 和 prod 组织同一个仓库,并避开 ConfigMap 滚动发布的陷阱。

15 min 中级

真实的应用会运行在多个环境中,这些环境之间只有细微差别:副本数、主机名、配置值。Argo CD 可以从纯 YAML、Helm chart 或 Kustomize 部署,并能自动识别文件夹使用的是哪一种。本指南展示如何用 Kustomize overlay 和 Helm values 文件,为多个环境组织同一个仓库,并介绍一个在修改配置时容易踩到的坑。本指南基于前面指南中的 webapp 示例。

选择布局:用文件夹,而不是分支

你可以把环境建模为长期存在的分支(dev、staging、main),但这会让升级变成一次次合并,也会让各环境逐渐漂移。单一分支加每个环境一个文件夹的方式更容易理解:所有环境并排可见,对其中一个的修改就是一次普通的 diff。

Kustomize 正是为此而设计:一个共享的 base,加上每个环境一个小小的 overlay,只修改有差异的部分。

构建 Kustomize base 与 overlay

webapp-config/
├── base/
│   ├── deployment.yaml
│   ├── service.yaml
│   └── kustomization.yaml
└── overlays/
    ├── dev/
    │   └── kustomization.yaml
    └── prod/
        └── kustomization.yaml

base/kustomization.yaml 列出共享资源:

resources:
  - deployment.yaml
  - service.yaml

在 base/deployment.yaml 中,让容器从一个 ConfigMap 读取设置,该 ConfigMap 将由各个 overlay 生成:

          envFrom:
            - configMapRef:
                name: webapp-config

overlays/dev/kustomization.yaml:

resources:
  - ../../base
namespace: webapp-dev
replicas:
  - name: webapp
    count: 2
configMapGenerator:
  - name: webapp-config
    literals:
      - HEADER=Hello from dev

overlays/prod/kustomization.yaml 与之类似,只是 namespace: webapp-prod、count: 4,并且有自己的 HEADER 值。

让每个环境对应一个 Application

Argo CD 会检测路径中的 kustomization.yaml 并为你构建。为每个环境创建一个 Application:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: webapp-dev
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/your-org/webapp-config.git
    targetRevision: HEAD
    path: overlays/dev
  destination:
    server: https://kubernetes.default.svc
    namespace: webapp-dev
  syncPolicy:
    syncOptions:
      - CreateNamespace=true
    automated:
      prune: true

对于 webapp-prod,修改名称、路径(overlays/prod)和命名空间,并考虑去掉 automated,这样生产环境的同步就需要人工批准。

对于 Helm,形式相同,只是来源是 chart,并且你要选择某个环境的 values 文件:

  source:
    repoURL: https://github.com/your-org/webapp-config.git
    targetRevision: HEAD
    path: charts/webapp
    helm:
      valueFiles:
        - values-dev.yaml

valueFiles 的路径相对于 chart 文件夹,后面的文件会覆盖前面的。

有意识地处理配置变更

在某个环境中修改 HEADER 的值,然后比较两种工具的行为:

  • Kustomize 会在生成的 ConfigMap 名称后附加内容哈希。新的值会产生新的 ConfigMap(webapp-config-<hash>),并更新 Deployment 的引用,从而触发 Pod 滚动发布。旧的 ConfigMap 变成孤儿资源,所以在被清理之前应用会显示 OutOfSync。启用 prune: true 后,它会被自动清理。
  • Helm 会原地更新现有的 ConfigMap。Deployment 的 spec 没有变化,因此运行中的 Pod 保留旧值,没有任何机制通知 Argo CD 或 Kubernetes 去重启它们。

Helm 的标准解决办法是把 ConfigMap 的校验和放入 Pod 模板,这样配置变化就会改变模板并滚动 Pod。在 templates/deployment.yaml 中:

  template:
    metadata:
      annotations:
        checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}

手动重启 Deployment 也能奏效一次,但这并没有记录在 Git 中,违背了初衷。

在各环境之间升级变更

采用这种布局,升级就是一连串普通的提交。先修改 dev overlay(例如,在 overlays/dev 中运行 kustomize edit set image webapp=nginx:1.26 来升级镜像),让自动同步应用它,然后验证。接着对 overlays/prod 做同样的修改并同步,如果你保留了生产环境的把关,则手动同步。CI 流水线可以自动完成 dev 的提交,而拉取请求或审批则可以把关生产环境的提交。若要从一处管理许多集群或环境,可以了解 Argo CD 的 ApplicationSet,它能根据模板生成 Application 资源。

热门指南