Helm Chart 维护
指导 Agent 组织 Chart.yaml、values.schema.json、可覆盖模板与 hook 生命周期,并保持 appVersion 与 Chart 版本语义一致;PR 中固化 lint、template 与(可选)kubeconform。
SKILL 要求 values.yaml 默认值可开箱、README 列出关键 values;模板中避免硬编码镜像 tag,用 values 与 global 段统一注入。
子 chart 与 library chart 的依赖版本范围;升级时注明 CRD 与 hook 顺序风险;密钥与敏感配置走 External Secrets / SealedSecrets 等引用方式,不在 chart 内明文提交。
Chart 发布流水线(本地 → CI → 集群)
[ Chart 目录与版本 bump ]
│
▼
┌─────────────┐ Chart.yaml / values / schema 一致;README 同步
│ 本地校验 │──── helm lint、helm template(+ kubeconform 可选)
└─────────────┘
│
▼
┌─────────────┐ ct lint、kind 安装矩阵、artifact 推送
│ CI / CD │──── 版本 semver;breaking 时 major 与迁移说明
└─────────────┘
│
▼
┌─────────────┐ install / upgrade;历史与 rollback 注释对齐发布技能
│ 集群 release │──── hook 与 CRD 顺序在 runbook 中写明
└─────────────┘
合流前:模板渲染结果可 diff;生产覆盖文件(如 values-prod.yaml)只写差异项,禁止把密钥写进仓库。
Helm Chart 目录结构说明:
mychart/
├── Chart.yaml # Chart 元数据(name、version、appVersion)
├── values.yaml # 默认值(可开箱,文档化所有对外 key)
├── values.schema.json # 类型约束与必填校验
├── README.md # 关键 values 说明与使用示例
├── charts/ # 子 chart 依赖(helm dependency update 填充)
├── templates/
│ ├── _helpers.tpl # 命名模板(全名、标准标签)
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── configmap.yaml
│ ├── hpa.yaml
│ ├── pdb.yaml
│ ├── serviceaccount.yaml
│ ├── NOTES.txt # install/upgrade 后打印的使用提示
│ └── tests/
│ └── test-connection.yaml # helm test 测试 Pod
├── ci/ # chart-testing 使用的 CI values 文件
│ └── ci-values.yaml
└── .helmignore # 排除不需要打包进 Chart 的文件
Values 与 schema
用 values.schema.json 约束类型与必填项;默认值应适合最小演示环境。跨子 chart 共享配置放在 global,并在 README 说明覆盖优先级(-f 顺序、--set)。
- 镜像:
repository+tag分离,tag 通常由环境 values 注入而非写死在模板。 - 资源与副本:prod/stage 用独立 values 文件,文档列出「禁止在 prod 打开」的开关(如 debug)。
- 文档:每个对外暴露的 value 一行说明;breaking 改名时保留一期别名或迁移注释。
values.yaml 设计原则(必填/可选/环境差异)示例:
# values.yaml — 默认值可开箱运行(最小演示环境)
# 必须由外部覆盖的值,默认填 "" 并在 schema 标为 required
image:
repository: myregistry/myapp # 必填:由 CI 注入
tag: "" # 必填:由环境 values 覆盖(不写死 latest)
pullPolicy: IfNotPresent
replicaCount: 1 # 开发环境默认 1;生产 values 覆盖为 3+
service:
type: ClusterIP
port: 80
ingress:
enabled: false # 默认关闭;生产 values 开启
className: nginx
host: "" # 必须由环境 values 提供
tls: false
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
autoscaling:
enabled: false # 生产建议开启
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 70
# debug: false # 禁止在生产开启!见 values-prod.yaml 注释
---
# values-prod.yaml — 仅写差异项
# image.tag 由 CI pipeline 以 --set image.tag=1.2.3 注入
replicaCount: 3
ingress:
enabled: true
host: myapp.example.com
tls: true
autoscaling:
enabled: true
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: "1"
memory: 1Gi
模板与参数化
使用 {{ .Values }}、required、default 与 tpl 保持 DRY;标签与选择器引用同一组变量,避免字符串漂移。可抽 _helpers.tpl 定义全名与标准标签。
推荐
include渲染命名模板;注释说明 chart 内约定- Probe、resources、
securityContext可配置化 - 仅渲染需要的资源;条件块与能力检测写清(如 API 版本)
避免
- 在模板里写死环境名或完整镜像 URI(无 tag 变量)
- 忽略
nindent与 YAML 缩进导致的多余空行/非法结构 - 在未文档化情况下依赖 Helm 未公开的内部对象
_helpers.tpl 中的 helper 函数示例(全名、标准标签、selector):
{{/*
_helpers.tpl — mychart 的命名模板
mychart.fullname:Chart name + release name,截断至 63 字符
*/}}
{{- define "mychart.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
mychart.labels:所有资源的标准标签集
*/}}
{{- define "mychart.labels" -}}
helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 }}
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Values.image.tag | default .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
mychart.selectorLabels:Deployment selector(不含 version,避免更新时冲突)
*/}}
{{- define "mychart.selectorLabels" -}}
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/* 在 deployment.yaml 中使用 */}}
{{/*
metadata:
name: {{ include "mychart.fullname" . }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
spec:
selector:
matchLabels:
{{- include "mychart.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "mychart.selectorLabels" . | nindent 8 }}
*/}}
依赖、Hook 与密钥
Chart.yaml 的 dependencies 使用兼容版本范围;子 chart 升级后在 CHANGELOG 标明。Hook 注明 hook-weight 与删除策略;与 CRD 安装顺序冲突时在技能或 runbook 中单列一节。
- 测试:chart-testing(ct)与 kind 上的 install 冒烟矩阵。
- 回滚:
helm rollback与 release 历史注释与发布技能对齐。 - 多环境:
values-prod.yaml覆盖原则与禁止项(如 dev 端点)。
CI 校验与多环境
PR 必跑:helm lint、helm template;若对接 kubeconform,固定 Kubernetes 版本列表与 CRD 来源。将「渲染后清单」作为 artifact 便于审查 diff。
与原生清单技能对齐:渲染结果应满足同一套标签、探针与安全基线约定。
Helm 命令片段实验室
填写 chart 路径与 release 名,勾选 values 文件与选项,生成可粘贴的 helm lint / helm template 片段(按本机 Helm 版本微调标志)。
helm template 默认输出到 stdout;可追加 | tee /tmp/rendered.yaml 再跑 kubeconform。安装/升级命令请结合集群凭证与 --atomic 等团队策略单独维护。
---
name: helm-chart-maintenance
description: 维护可 lint、可模板化、多环境的 Helm Chart
tags: [helm, kubernetes, devops, chart]
---
# 目录结构
1. templates/_helpers.tpl 定义 fullname、labels、selectorLabels 命名模板
2. values.schema.json 约束类型与必填项(helm install 时自动校验)
3. ci/ 目录存放 chart-testing 使用的最小 CI values 文件
# Values 设计
4. 默认值可开箱:最小演示环境不需要额外 -f 文件
5. image.tag 由环境 values 注入(--set image.tag=)而非写死
6. 环境差异文件:values-dev.yaml / values-staging.yaml / values-prod.yaml 仅写差异项
7. 禁止在 values-prod.yaml 中写密钥;用 External Secrets / SealedSecrets 引用
# 模板最佳实践
8. 所有资源标签引用 include "mychart.labels" 保持 DRY
9. selector 与 template.labels 引用同一 selectorLabels,不手写字符串
10. 条件渲染:{{ if .Values.ingress.enabled }} 按需生成 Ingress
11. required "message" .Values.image.repository 让缺失必填项立即报错
# 测试与 CI
12. helm lint + helm template | kubeconform 在每个 PR 中必跑
13. helm unittest(helm plugin install https://github.com/helm-unittest/helm-unittest)单元测试模板渲染
14. chart-testing(ct)+ kind 集群做 install/upgrade 冒烟测试
# 升级与回滚
15. Chart.yaml version 遵循 semver;breaking 变更升 major 并写迁移说明
16. helm upgrade --atomic 失败自动回滚;配合 --timeout 防止挂起
17. hook weight 与删除策略写明,CRD 安装顺序在 runbook 单列