【架构实战】Helm Chart 进阶:依赖管理、测试与 CI/CD 集成

【架构实战】Helm Chart 进阶:依赖管理、测试与 CI/CD 集成 一、开篇从单 Chart到应用栈上篇我们聊了 Helm 的基础概念、values.yaml 配置管理和 Release 回滚机制。但真实世界远比单个 Chart 复杂一个典型的微服务应用栈可能包含前端后端 APISpring Boot数据库缓存Redis Cluster消息队列监控如果用 6 个独立 Chart 分别管理启动顺序、配置依赖、环境隔离都是噩梦。这就是 Helm Chart 依赖管理要解决的核心问题。今天这篇我们深入 Helm 的进阶能力依赖管理、子 Chart、测试框架、CI/CD 集成以及我们团队在落地过程中总结的最佳实践。二、Chart 依赖管理从手动编排到声明式依赖Helm 3 支持 Chart 依赖声明类似 npm 的 package.json 或 Maven 的 pom.xml。Chart.yaml 中声明依赖apiVersion:v2name:myapp-stackversion:1.0.0dependencies:-name:redisversion:17.x.xrepository:https://charts.bitnami.com/bitnamicondition:redis.enabledtags:-cache-name:postgresqlversion:12.x.xrepository:https://charts.bitnami.com/bitnamicondition:postgresql.enabledalias:db# 在模板中用 .Values.db 访问-name:myapp-backendversion:1.2.0repository:file://charts/backend# 本地 Chart关键参数解释参数作用示例condition条件启用可通过 values 控制是否安装redis.enabled: false跳过 Redistags批量控制一组依赖tags: [cache]可统一开关alias重命名依赖避免冲突两个不同版本的 Redis 用不同别名下载依赖并构建 charts/ 目录helm dependency update myapp-stack/# 或简写helm dep up myapp-stack/执行后会在charts/目录生成.tgz压缩包myapp-stack/ ├── Chart.yaml ├── charts/ │ ├── redis-17.3.0.tgz │ ├── postgresql-12.1.0.tgz │ └── backend/ └── values.yaml通过 values.yaml 控制依赖启用# 不安装 Redis用外部托管服务redis:enabled:false# 启用 PostgreSQL覆盖默认配置postgresql:enabled:trueauth:password:prod-db-password-2026primary:persistence:size:100GistorageClass:ssd-gold# 后端服务配置backend:image:repository:myregistry/myapp-backendtag:2.1.4env:DATABASE_URL:postgresql://db:5432/myapp三、子 Chart 的值传递父 Chart 如何控制子 Chart这是 Helm 依赖管理中最容易踩坑的地方values 是如何从父 Chart 传递到子 Chart 的规则很简单但容易被忽略父 Chart 的values.yaml中以子 Chart 名称为 key的部分会传递给子 Chart子 Chart 只能看到自己命名空间下的值示例父 values.yaml# 全局配置所有子 Chart 可见global:imageRegistry:myregistry.ioimagePullSecrets:-name:registry-secret# 传递给 redis 子 Chartredis:auth:password:redis-prod-passreplica:replicaCount:3# 传递给 postgresql 子 Chart注意 aliasdb:# 用 alias 名不是原名auth:password:pg-prod-pass# 后端应用配置非子 Chart直接在本 Chart 模板使用backend:image:tag:2.1.4子 Chartredis收到的 values# redis 子 Chart 的 values.yaml 父 Chart 传入的覆盖auth:password:redis-prod-passreplica:replicaCount:3# global 是特殊字段所有子 Chart 自动继承global:imageRegistry:myregistry.ioimagePullSecrets:-name:registry-secret踩坑记录我们第一次用依赖管理时把redis.auth.password写在 values.yaml 根级别结果 Redis 一直用默认密码启动。排查半天才发现必须放在redis:下面Helm 才会把值传给子 Chart。四、Chart 测试框架安装后自动验证Helm 内置了测试框架可以在安装/升级后自动运行验证脚本确保应用真正可用。定义测试 Podtemplates/tests/# templates/tests/test-connection.yamlapiVersion:v1kind:Podmetadata:name:{{ .Release.Name }}-test-connectionannotations:helm.sh/hook:testhelm.sh/hook-delete-policy:hook-succeededspec:containers:-name:wgetimage:busyboxcommand:[wget]args:[{{ .Release.Name }}:{{ .Values.service.port }}]restartPolicy:Never运行测试helmtestmy-release# NAME: my-release# LAST DEPLOYED: Mon Jul 27 15:00:00 2026# NAMESPACE: default# STATUS: deployed# TEST SUITE: my-release-test-connection# Last Started: Mon Jul 27 15:01:00 2026# Last Completed: Mon Jul 27 15:01:05 2026# Phase: Succeeded我们团队的实践所有 Chart 必须包含至少一个测试用例验证核心服务可访问性。CI/CD 流程中helm upgrade后自动跑helm test测试失败则自动回滚。进阶测试数据库连通性验证# templates/tests/test-db-connection.yamlapiVersion:v1kind:Podmetadata:name:{{ .Release.Name }}-test-dbannotations:helm.sh/hook:testspec:containers:-name:pg-testimage:postgres:15command:[psql]args:--c-SELECT 1env:-name:PGHOSTvalue:{{ .Release.Name }}-db-name:PGUSERvalue:postgres-name:PGPASSWORDvalueFrom:secretKeyRef:name:{{ .Release.Name }}-db-postgresqlkey:passwordrestartPolicy:Never五、CI/CD 集成从手动部署到自动化流水线Helm 天然适合 CI/CD 集成。我们团队用 GitLab CI Helm 实现了一套完整流程.gitlab-ci.yml 核心片段stages:-lint-test-package-deploy# 阶段 1语法检查helm-lint:stage:lintimage:alpine/helm:3.12.0script:-helm lint charts/myapp/rules:-if:$CI_PIPELINE_SOURCE merge_request_event# 阶段 2模板渲染验证dry-runhelm-template:stage:testimage:alpine/helm:3.12.0script:-helm template myapp charts/myapp/-f values/dev.yaml/dev/null-helm template myapp charts/myapp/-f values/prod.yaml/dev/nullrules:-if:$CI_PIPELINE_SOURCE merge_request_event# 阶段 3打包并推送到 Chart 仓库helm-package:stage:packageimage:alpine/helm:3.12.0script:-helm dependency update charts/myapp/-helm package charts/myapp/--version $CI_COMMIT_TAG-helm push myapp-$CI_COMMIT_TAG.tgz oci://$OCI_REGISTRY/chartsrules:-if:$CI_COMMIT_TAG# 阶段 4部署到 stagingdeploy-staging:stage:deployimage:alpine/helm:3.12.0environment:stagingscript:-helm upgrade--install myapp oci://$OCI_REGISTRY/charts/myapp--version $CI_COMMIT_TAG-f values/staging.yaml-n myapp-staging--create-namespace-helm test myapp-n myapp-stagingrules:-if:$CI_COMMIT_TAG ~ /^v[0-9]\.[0-9]\.[0-9]-rc\.[0-9]$/after_script:-|if [ $CI_JOB_STATUS failed ]; then helm rollback myapp -n myapp-staging fi# 阶段 5部署到 production需要手动审批deploy-production:stage:deployimage:alpine/helm:3.12.0environment:productionscript:-helm upgrade--install myapp oci://$OCI_REGISTRY/charts/myapp--version $CI_COMMIT_TAG-f values/production.yaml-n myapp-prod--create-namespace-helm test myapp-n myapp-prodrules:-if:$CI_COMMIT_TAG ~ /^v[0-9]\.[0-9]\.[0-9]$/when:manualallow_failure:false关键设计点lint template 双重验证语法正确不代表渲染正确必须两步都过OCI RegistryHelm 3 支持 OCI 协议直接推送到 Docker Registry不需要单独的 ChartMuseum语义化版本规则v1.2.3-rc.1自动部署 stagingv1.2.3需手动审批上生产测试失败自动回滚after_script中判断任务状态失败则回滚六、Chart 仓库从本地文件到企业级托管Helm 支持多种 Chart 仓库方案方案适用场景优缺点本地文件系统开发测试简单但无法团队共享HTTP 服务器中小团队需自建维护成本中等ChartMuseum企业私有仓库功能完善支持多存储后端OCI Registry现代方案复用 Docker Registry无需额外服务Artifact Hub开源 Chart 发现公开仓库类似 npm registryOCI Registry 方式推荐# 登录 Registryhelm registry login registry.example.com-umyuser-pmytoken# 推送 Charthelm push myapp-1.2.0.tgz oci://registry.example.com/charts# 安装helminstallmyapp oci://registry.example.com/charts/myapp--version1.2.0我们团队的选择用 Harbor 作为私有 Registry同时托管 Docker 镜像和 Helm Chart一套权限体系管理所有制品。七、Helm Diff 插件升级前预览变更helm upgrade最大的痛点是不知道具体改了什么。Helm Diff 插件解决了这个问题# 安装插件helm plugininstallhttps://github.com/databus23/helm-diff# 升级前预览变更helmdiffupgrade myapp bitnami/nginx-fvalues/prod.yaml# default, myapp-nginx (Deployment) spec.template.spec.containers[0].image# - image: nginx:1.20# image: nginx:1.21CI/CD 中集成 Diffhelm-diff:stage:testscript:-helm diff upgrade myapp charts/myapp/-f values/prod.yaml||trueartifacts:paths:-diff-output.txt我们团队规定生产环境任何 helm upgrade必须先跑 diff 并在 MR 中展示变更内容。八、敏感信息管理从明文到加密Chart 中经常包含数据库密码、API Key 等敏感信息。直接写 values.yaml 会进入 Git 仓库存在安全风险。方案 1Sealed Secrets推荐# values.yaml 中引用加密 Secretpostgresql:auth:existingSecret:myapp-db-secret用 kubeseal 加密 Secretkubectl create secret generic myapp-db-secret --from-literalpasswordprod-pass-2026 --dry-runclient-oyaml|kubeseal-oyamlsealed-secret.yaml方案 2Helm Secrets 插件# 安装插件helm plugininstallhttps://github.com/jkroepke/helm-secrets# 加密 values 文件helm secrets encrypt values/prod-secrets.yaml# 部署时自动解密helm secrets upgrade myapp charts/myapp/-fvalues/prod.yaml-fvalues/prod-secrets.yaml我们团队的选择CI/CD 中用 Helm Secrets本地开发用 Sealed Secrets。两种方案各有优劣但核心原则一致敏感信息不入 Git。九、我们落地 Helm 依赖管理的几个关键坑坑 1循环依赖导致无限递归。A 依赖 BB 又依赖 A。Helm 会直接报错但排查时容易忽略。规范依赖图必须是无环有向图DAG。坑 2子 Chart 版本不兼容。父 Chart 声明redis: 17.x.x但某个子 Chart 又依赖redis: 16.x.x版本冲突。解决方案用helm dependency list检查版本树确保兼容。坑 3charts/ 目录忘记提交。helm dep up生成的.tgz文件应该提交到 Git除非用 CI/CD 自动构建。我们团队规定charts/ 目录必须纳入版本控制保证任何时间点都能完整复现发布。坑 4global 值污染。global字段会传递给所有子 Chart但很多新人不知道。我们在规范里明确global 只放真正全局的值如 imageRegistry环境特定配置必须放在对应子 Chart 命名空间下。十、写在最后Helm 的依赖管理和 CI/CD 集成本质上是在解决应用栈的标准化交付问题。从单 Chart 到多 Chart 依赖从手动 helm install 到 GitLab CI 自动化流水线从明文密码到 Helm Secrets 加密——这套工程化能力的演进映射着我们从能跑就行到可复现、可追溯、可回滚的架构成熟度提升。我们团队现在的标准任何应用栈上线必须提供 Helm Chart CI/CD 流水线 测试用例。Chart 即文档流水线即流程测试即保障。下一站我们可以聊聊ArgoCD Helm看看在 GitOps 体系下Helm Chart 如何成为声明式部署的核心载体。关注我架构路上不迷路。—— 本文是《100 篇架构实战》系列第 90 篇承接上篇 Helm 基础进阶探讨依赖管理与自动化集成。