一、开篇:从"单 Chart"到"应用栈"
上篇我们聊了 Helm 的基础概念、values.yaml 配置管理和 Release 回滚机制。但真实世界远比单个 Chart 复杂:
一个典型的微服务应用栈,可能包含:
- 前端
- 后端 API(Spring Boot)
- 数据库
- 缓存(Redis Cluster)
- 消息队列
- 监控
如果用 6 个独立 Chart 分别管理,启动顺序、配置依赖、环境隔离都是噩梦。这就是 Helm Chart 依赖管理要解决的核心问题。
今天这篇,我们深入 Helm 的进阶能力:依赖管理、子 Chart、测试框架、CI/CD 集成,以及我们团队在落地过程中总结的最佳实践。
二、Chart 依赖管理:从"手动编排"到"声明式依赖"
Helm 3 支持 Chart 依赖声明,类似 npm 的 package.json 或 Maven 的 pom.xml。
Chart.yaml 中声明依赖:
yaml
apiVersion: v2
name: myapp-stack
version: 1.0.0
dependencies:
- name: redis
version: "17.x.x"
repository: "https://charts.bitnami.com/bitnami"
condition: redis.enabled
tags:
- cache
- name: postgresql
version: "12.x.x"
repository: "https://charts.bitnami.com/bitnami"
condition: postgresql.enabled
alias: db # 在模板中用 .Values.db 访问
- name: myapp-backend
version: "1.2.0"
repository: "file://charts/backend" # 本地 Chart
关键参数解释:
| 参数 | 作用 | 示例 |
|---|---|---|
condition |
条件启用,可通过 values 控制是否安装 | redis.enabled: false 跳过 Redis |
tags |
批量控制一组依赖 | tags: [cache] 可统一开关 |
alias |
重命名依赖,避免冲突 | 两个不同版本的 Redis 用不同别名 |
下载依赖并构建 charts/ 目录:
bash
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 控制依赖启用:
yaml
# 不安装 Redis,用外部托管服务
redis:
enabled: false
# 启用 PostgreSQL,覆盖默认配置
postgresql:
enabled: true
auth:
password: "prod-db-password-2026"
primary:
persistence:
size: 100Gi
storageClass: ssd-gold
# 后端服务配置
backend:
image:
repository: myregistry/myapp-backend
tag: "2.1.4"
env:
DATABASE_URL: "postgresql://db:5432/myapp"
三、子 Chart 的值传递:父 Chart 如何控制子 Chart
这是 Helm 依赖管理中最容易踩坑的地方:values 是如何从父 Chart 传递到子 Chart 的?
规则很简单但容易被忽略:
- 父 Chart 的
values.yaml中,以子 Chart 名称为 key 的部分,会传递给子 Chart - 子 Chart 只能看到自己命名空间下的值
示例:父 values.yaml
yaml
# 全局配置(所有子 Chart 可见)
global:
imageRegistry: myregistry.io
imagePullSecrets:
- name: registry-secret
# 传递给 redis 子 Chart
redis:
auth:
password: "redis-prod-pass"
replica:
replicaCount: 3
# 传递给 postgresql 子 Chart(注意 alias)
db: # 用 alias 名,不是原名
auth:
password: "pg-prod-pass"
# 后端应用配置(非子 Chart,直接在本 Chart 模板使用)
backend:
image:
tag: "2.1.4"
子 Chart(redis)收到的 values:
yaml
# redis 子 Chart 的 values.yaml + 父 Chart 传入的覆盖
auth:
password: "redis-prod-pass"
replica:
replicaCount: 3
# global 是特殊字段,所有子 Chart 自动继承
global:
imageRegistry: myregistry.io
imagePullSecrets:
- name: registry-secret
踩坑记录: 我们第一次用依赖管理时,把 redis.auth.password 写在 values.yaml 根级别,结果 Redis 一直用默认密码启动。排查半天才发现:必须放在 redis: 下面,Helm 才会把值传给子 Chart。
四、Chart 测试框架:安装后自动验证
Helm 内置了测试框架,可以在安装/升级后自动运行验证脚本,确保应用真正可用。
定义测试 Pod(templates/tests/):
yaml
# templates/tests/test-connection.yaml
apiVersion: v1
kind: Pod
metadata:
name: "{{ .Release.Name }}-test-connection"
annotations:
"helm.sh/hook": test
"helm.sh/hook-delete-policy": hook-succeeded
spec:
containers:
- name: wget
image: busybox
command: ['wget']
args: ['{{ .Release.Name }}:{{ .Values.service.port }}']
restartPolicy: Never
运行测试:
bash
helm test my-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,测试失败则自动回滚。
进阶测试:数据库连通性验证
yaml
# templates/tests/test-db-connection.yaml
apiVersion: v1
kind: Pod
metadata:
name: "{{ .Release.Name }}-test-db"
annotations:
"helm.sh/hook": test
spec:
containers:
- name: pg-test
image: postgres:15
command: ['psql']
args:
- '-c'
- 'SELECT 1'
env:
- name: PGHOST
value: "{{ .Release.Name }}-db"
- name: PGUSER
value: "postgres"
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-db-postgresql"
key: password
restartPolicy: Never
五、CI/CD 集成:从手动部署到自动化流水线
Helm 天然适合 CI/CD 集成。我们团队用 GitLab CI + Helm 实现了一套完整流程:
.gitlab-ci.yml 核心片段:
yaml
stages:
- lint
- test
- package
- deploy
# 阶段 1:语法检查
helm-lint:
stage: lint
image: alpine/helm:3.12.0
script:
- helm lint charts/myapp/
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
# 阶段 2:模板渲染验证(dry-run)
helm-template:
stage: test
image: alpine/helm:3.12.0
script:
- helm template myapp charts/myapp/ -f values/dev.yaml > /dev/null
- helm template myapp charts/myapp/ -f values/prod.yaml > /dev/null
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
# 阶段 3:打包并推送到 Chart 仓库
helm-package:
stage: package
image: alpine/helm:3.12.0
script:
- helm dependency update charts/myapp/
- helm package charts/myapp/ --version $CI_COMMIT_TAG
- helm push myapp-$CI_COMMIT_TAG.tgz oci://$OCI_REGISTRY/charts
rules:
- if: $CI_COMMIT_TAG
# 阶段 4:部署到 staging
deploy-staging:
stage: deploy
image: alpine/helm:3.12.0
environment: staging
script:
- 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-staging
rules:
- 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: deploy
image: alpine/helm:3.12.0
environment: production
script:
- 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-prod
rules:
- if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+$/
when: manual
allow_failure: false
关键设计点:
- lint + template 双重验证:语法正确不代表渲染正确,必须两步都过
- OCI Registry:Helm 3 支持 OCI 协议,直接推送到 Docker Registry,不需要单独的 ChartMuseum
- 语义化版本规则 :
v1.2.3-rc.1自动部署 staging,v1.2.3需手动审批上生产 - 测试失败自动回滚 :
after_script中判断任务状态,失败则回滚
六、Chart 仓库:从本地文件到企业级托管
Helm 支持多种 Chart 仓库方案:
| 方案 | 适用场景 | 优缺点 |
|---|---|---|
| 本地文件系统 | 开发测试 | 简单但无法团队共享 |
| HTTP 服务器 | 中小团队 | 需自建,维护成本中等 |
| ChartMuseum | 企业私有仓库 | 功能完善,支持多存储后端 |
| OCI Registry | 现代方案 | 复用 Docker Registry,无需额外服务 |
| Artifact Hub | 开源 Chart 发现 | 公开仓库,类似 npm registry |
OCI Registry 方式(推荐):
bash
# 登录 Registry
helm registry login registry.example.com -u myuser -p mytoken
# 推送 Chart
helm push myapp-1.2.0.tgz oci://registry.example.com/charts
# 安装
helm install myapp oci://registry.example.com/charts/myapp --version 1.2.0
我们团队的选择: 用 Harbor 作为私有 Registry,同时托管 Docker 镜像和 Helm Chart,一套权限体系管理所有制品。
七、Helm Diff 插件:升级前预览变更
helm upgrade 最大的痛点是不知道具体改了什么。Helm Diff 插件解决了这个问题:
bash
# 安装插件
helm plugin install https://github.com/databus23/helm-diff
# 升级前预览变更
helm diff upgrade myapp bitnami/nginx -f values/prod.yaml
# default, myapp-nginx (Deployment) spec.template.spec.containers[0].image
# - image: nginx:1.20
# + image: nginx:1.21
CI/CD 中集成 Diff:
yaml
helm-diff:
stage: test
script:
- helm diff upgrade myapp charts/myapp/ -f values/prod.yaml || true
artifacts:
paths:
- diff-output.txt
我们团队规定:生产环境任何 helm upgrade,必须先跑 diff 并在 MR 中展示变更内容。
八、敏感信息管理:从明文到加密
Chart 中经常包含数据库密码、API Key 等敏感信息。直接写 values.yaml 会进入 Git 仓库,存在安全风险。
方案 1:Sealed Secrets(推荐)
yaml
# values.yaml 中引用加密 Secret
postgresql:
auth:
existingSecret: "myapp-db-secret"
用 kubeseal 加密 Secret:
bash
kubectl create secret generic myapp-db-secret --from-literal=password=prod-pass-2026 --dry-run=client -o yaml | kubeseal -o yaml > sealed-secret.yaml
方案 2:Helm Secrets 插件
bash
# 安装插件
helm plugin install https://github.com/jkroepke/helm-secrets
# 加密 values 文件
helm secrets encrypt values/prod-secrets.yaml
# 部署时自动解密
helm secrets upgrade myapp charts/myapp/ -f values/prod.yaml -f values/prod-secrets.yaml
我们团队的选择: CI/CD 中用 Helm Secrets,本地开发用 Sealed Secrets。两种方案各有优劣,但核心原则一致:敏感信息不入 Git。
九、我们落地 Helm 依赖管理的几个关键坑
坑 1:循环依赖导致无限递归。
A 依赖 B,B 又依赖 A。Helm 会直接报错,但排查时容易忽略。规范:依赖图必须是无环有向图(DAG)。
坑 2:子 Chart 版本不兼容。
父 Chart 声明 redis: "17.x.x",但某个子 Chart 又依赖 redis: "16.x.x",版本冲突。解决方案:用 helm dependency list 检查版本树,确保兼容。
坑 3:charts/ 目录忘记提交。
helm dep up 生成的 .tgz 文件应该提交到 Git(除非用 CI/CD 自动构建)。我们团队规定:charts/ 目录必须纳入版本控制,保证任何时间点都能完整复现发布。
坑 4:global 值污染。
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 基础,进阶探讨依赖管理与自动化集成。