helm
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseHelm
Helm
Covers the full lifecycle: chart creation, templating, dependency management, validation, OCI distribution, debugging, and release operations.
涵盖完整生命周期:Chart创建、模板编写、依赖管理、验证、OCI分发、调试及版本发布操作。
Chart structure
Chart结构
text
mychart/
Chart.yaml
values.yaml
values.schema.json # optional JSON Schema validation
charts/ # dependencies
crds/ # CRDs (applied before templates)
templates/
NOTES.txt
_helpers.tpl
deployment.yaml
service.yaml
ingress.yaml
configmap.yaml
secret.yaml
hpa.yaml
tests/
test-connection.yaml
.helmignoretext
mychart/
Chart.yaml
values.yaml
values.schema.json # optional JSON Schema validation
charts/ # dependencies
crds/ # CRDs (applied before templates)
templates/
NOTES.txt
_helpers.tpl
deployment.yaml
service.yaml
ingress.yaml
configmap.yaml
secret.yaml
hpa.yaml
tests/
test-connection.yaml
.helmignoreChart.yaml
Chart.yaml
yaml
apiVersion: v2
name: myapp
description: A production-grade web application
type: application
version: 1.0.0
appVersion: "2.0.1"
kubeVersion: ">=1.30.0"
maintainers:
- name: DevOps Team
email: devops@example.com
dependencies:
- name: postgresql
version: "16.x.x"
repository: "oci://registry-1.docker.io/bitnamicharts"
condition: postgresql.enabledyaml
apiVersion: v2
name: myapp
description: A production-grade web application
type: application
version: 1.0.0
appVersion: "2.0.1"
kubeVersion: ">=1.30.0"
maintainers:
- name: DevOps Team
email: devops@example.com
dependencies:
- name: postgresql
version: "16.x.x"
repository: "oci://registry-1.docker.io/bitnamicharts"
condition: postgresql.enabledvalues.yaml
values.yaml
Organize hierarchically; document every field with comments.
yaml
replicaCount: 3
image:
repository: myregistry.io/myapp
tag: ""
pullPolicy: IfNotPresent
imagePullSecrets: []
serviceAccount:
create: true
annotations: {}
name: ""
podAnnotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9090"
podSecurityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: [ALL]
service:
type: ClusterIP
port: 80
targetPort: 8080
ingress:
enabled: false
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: myapp.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: myapp-tls
hosts: [myapp.example.com]
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
autoscaling:
enabled: false
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 70
nodeSelector: {}
tolerations: []
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values: [myapp]
topologyKey: kubernetes.io/hostname
postgresql:
enabled: false按层级组织;为每个字段添加注释说明。
yaml
replicaCount: 3
image:
repository: myregistry.io/myapp
tag: ""
pullPolicy: IfNotPresent
imagePullSecrets: []
serviceAccount:
create: true
annotations: {}
name: ""
podAnnotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9090"
podSecurityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: [ALL]
service:
type: ClusterIP
port: 80
targetPort: 8080
ingress:
enabled: false
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: myapp.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: myapp-tls
hosts: [myapp.example.com]
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
autoscaling:
enabled: false
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 70
nodeSelector: {}
tolerations: []
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values: [myapp]
topologyKey: kubernetes.io/hostname
postgresql:
enabled: falseTemplate helpers (_helpers.tpl
)
_helpers.tpl模板助手(_helpers.tpl
)
_helpers.tplyaml
{{- define "myapp.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "myapp.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 }}
{{- define "myapp.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "myapp.labels" -}}
helm.sh/chart: {{ include "myapp.chart" . }}
{{ include "myapp.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{- define "myapp.selectorLabels" -}}
app.kubernetes.io/name: {{ include "myapp.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{- define "myapp.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "myapp.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}yaml
{{- define "myapp.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "myapp.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 }}
{{- define "myapp.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "myapp.labels" -}}
helm.sh/chart: {{ include "myapp.chart" . }}
{{ include "myapp.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{- define "myapp.selectorLabels" -}}
app.kubernetes.io/name: {{ include "myapp.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{- define "myapp.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "myapp.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}Key template patterns
核心模板模式
Conditional resource:
yaml
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
...
{{- end }}Config checksum (force pod restart on config change):
yaml
annotations:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}Iterate over env list:
yaml
env:
{{- range .Values.env }}
- name: {{ .name }}
value: {{ .value | quote }}
{{- end }}Safe defaults:
yaml
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
replicas: {{ .Values.replicaCount | default 3 }}条件化资源:
yaml
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
...
{{- end }}配置校验和(配置变更时强制重启Pod):
yaml
annotations:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}遍历环境变量列表:
yaml
env:
{{- range .Values.env }}
- name: {{ .name }}
value: {{ .value | quote }}
{{- end }}安全默认值:
yaml
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
replicas: {{ .Values.replicaCount | default 3 }}Validation workflow
验证流程
Always follow this progression:
bash
undefined请始终遵循以下步骤:
bash
undefined1. Static lint
1. 静态检查
helm lint ./mychart --strict
helm lint ./mychart --strict
2. Render templates locally
2. 本地渲染模板
helm template myapp ./mychart --debug --values values.yaml
helm template myapp ./mychart --debug --values values.yaml
3. Server-side dry-run (resolves lookup functions against the real API)
3. 服务端预运行(针对真实API解析查找函数)
helm install myapp ./mychart
--namespace prod
--values values.yaml
--dry-run=server --debug
--namespace prod
--values values.yaml
--dry-run=server --debug
helm install myapp ./mychart
--namespace prod
--values values.yaml
--dry-run=server --debug
--namespace prod
--values values.yaml
--dry-run=server --debug
4. Install
4. 安装
helm install myapp ./mychart
--namespace prod
--values values.yaml
--atomic --wait
--namespace prod
--values values.yaml
--atomic --wait
helm install myapp ./mychart
--namespace prod
--values values.yaml
--atomic --wait
--namespace prod
--values values.yaml
--atomic --wait
5. Post-deploy tests
5. 部署后测试
helm test myapp --namespace prod --logs
Use `--dry-run=server` (not the bare `--dry-run`) when templates contain `lookup` calls that need to resolve against live cluster state.helm test myapp --namespace prod --logs
当模板包含需要针对真实集群状态解析的`lookup`调用时,请使用`--dry-run=server`(而非单纯的`--dry-run`)。Common commands
常用命令
Inspect a deployed release:
bash
helm get manifest myapp -n prod
helm get values myapp -n prod --all
helm status myapp -n prod --show-resourcesUpgrade:
bash
helm upgrade myapp ./mychart -f values.yaml
helm upgrade --install myapp ./mychart
helm upgrade myapp ./mychart --atomic --timeout 5mRollback:
bash
helm history myapp -n prod
helm rollback myapp 3 -n prod --cleanup-on-failDependencies:
bash
helm dependency list ./mychart
helm dependency update ./mychart
helm dependency build ./mychartRepositories:
bash
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm search repo postgresql
helm show values bitnami/postgresql查看已部署的版本:
bash
helm get manifest myapp -n prod
helm get values myapp -n prod --all
helm status myapp -n prod --show-resources升级:
bash
helm upgrade myapp ./mychart -f values.yaml
helm upgrade --install myapp ./mychart
helm upgrade myapp ./mychart --atomic --timeout 5m回滚:
bash
helm history myapp -n prod
helm rollback myapp 3 -n prod --cleanup-on-fail依赖管理:
bash
helm dependency list ./mychart
helm dependency update ./mychart
helm dependency build ./mychart仓库管理:
bash
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm search repo postgresql
helm show values bitnami/postgresqlOCI registry workflow
OCI镜像仓库流程
OCI is the preferred distribution method. No required.
helm repo addbash
undefinedOCI是推荐的分发方式,无需执行。
helm repo addbash
undefinedAuthenticate
认证
helm registry login registry.example.com -u <user>
helm registry login registry.example.com -u <user>
Push a packaged chart
推送打包后的Chart
helm package ./mychart
helm push mychart-1.0.0.tgz oci://registry.example.com/charts
helm package ./mychart
helm push mychart-1.0.0.tgz oci://registry.example.com/charts
Pull
拉取
helm pull oci://registry.example.com/charts/mychart --version 1.0.0
helm pull oci://registry.example.com/charts/mychart --version 1.0.0
Install directly from OCI
直接从OCI安装
helm install myapp oci://registry.example.com/charts/mychart --version 1.0.0
helm install myapp oci://registry.example.com/charts/mychart --version 1.0.0
Template, show, upgrade all work with oci:// refs
模板渲染、查看、升级等操作均支持oci://引用
helm show values oci://registry.example.com/charts/mychart --version 1.0.0
OCI dependencies in `Chart.yaml`:
```yaml
dependencies:
- name: redis
version: "18.x.x"
repository: "oci://registry-1.docker.io/bitnamicharts"helm show values oci://registry.example.com/charts/mychart --version 1.0.0
`Chart.yaml`中的OCI依赖:
```yaml
dependencies:
- name: redis
version: "18.x.x"
repository: "oci://registry-1.docker.io/bitnamicharts"Post-renderers
后处理器
Post-renderers transform rendered manifests before Helm applies them. Common use case: injecting labels/annotations via Kustomize without forking the chart.
bash
helm install myapp ./mychart --post-renderer ./kustomize-labels.sh
helm upgrade myapp ./mychart --post-renderer ./kustomize-labels.sh
helm template myapp ./mychart --post-renderer ./kustomize-labels.shThe executable receives rendered YAML on stdin and must emit valid YAML on stdout. Chain multiple renderers with pipes: .
renderer1 | renderer2后处理器会在Helm应用渲染后的清单前对其进行转换。常见用途:通过Kustomize注入标签/注释,无需fork Chart。
bash
helm install myapp ./mychart --post-renderer ./kustomize-labels.sh
helm upgrade myapp ./mychart --post-renderer ./kustomize-labels.sh
helm template myapp ./mychart --post-renderer ./kustomize-labels.sh可执行文件从标准输入接收渲染后的YAML,并必须向标准输出输出有效的YAML。可通过管道串联多个渲染器:。
renderer1 | renderer2Multi-environment layout
多环境布局
text
mychart/
values.yaml
values-dev.yaml
values-staging.yaml
values-prod.yamlbash
helm install myapp ./mychart -f values-prod.yaml -n productiontext
mychart/
values.yaml
values-dev.yaml
values-staging.yaml
values-prod.yamlbash
helm install myapp ./mychart -f values-prod.yaml -n productionHooks
钩子
Pre-install/pre-upgrade job (e.g., DB migration):
yaml
apiVersion: batch/v1
kind: Job
metadata:
name: {{ include "myapp.fullname" . }}-migration
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-weight": "0"
"helm.sh/hook-delete-policy": before-hook-creation
spec:
template:
spec:
restartPolicy: Never
containers:
- name: migration
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
command: ["./migrate.sh"]Test pod:
yaml
apiVersion: v1
kind: Pod
metadata:
name: {{ include "myapp.fullname" . }}-test
annotations:
"helm.sh/hook": test
spec:
containers:
- name: curl
image: curlimages/curl:latest
command: ['curl']
args: ['{{ include "myapp.fullname" . }}:{{ .Values.service.port }}/health']
restartPolicy: Never预安装/预升级任务(如数据库迁移):
yaml
apiVersion: batch/v1
kind: Job
metadata:
name: {{ include "myapp.fullname" . }}-migration
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-weight": "0"
"helm.sh/hook-delete-policy": before-hook-creation
spec:
template:
spec:
restartPolicy: Never
containers:
- name: migration
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
command: ["./migrate.sh"]测试Pod:
yaml
apiVersion: v1
kind: Pod
metadata:
name: {{ include "myapp.fullname" . }}-test
annotations:
"helm.sh/hook": test
spec:
containers:
- name: curl
image: curlimages/curl:latest
command: ['curl']
args: ['{{ include "myapp.fullname" . }}:{{ .Values.service.port }}/health']
restartPolicy: NeverDebugging reference
调试参考
| Symptom | Likely cause | Fix |
|---|---|---|
| Indentation error | Use |
| Missing value | Add |
| Wrong value type | Use |
| Conflicting release | Uninstall conflicting release or adopt resource |
| Wrong image name or missing pull secret | Fix image ref; create |
| CRD not installed | |
| Readiness probe failure or slow start | Increase |
| Hook job failed | Delete failed job; retry with |
Context safety -- always pass and explicitly to avoid targeting the wrong cluster:
--kube-context-nbash
helm --kube-context=prod-cluster status myapp -n prod
kubectl --context=prod-cluster get pods -n prodVerbose output for template errors:
bash
helm template myapp ./mychart --debug 2>&1 | head -100| 症状 | 可能原因 | 解决方法 |
|---|---|---|
| 缩进错误 | 使用 |
| 值缺失 | 添加 |
| 值类型错误 | 在模板中使用 |
| 版本发布冲突 | 卸载冲突版本或接管资源 |
| 镜像名称错误或缺少拉取密钥 | 修正镜像引用;创建 |
| CRD未安装 | 先执行 |
| 就绪探针失败或启动缓慢 | 增加 |
| 钩子任务执行失败 | 删除失败任务;使用 |
上下文安全 -- 请始终显式传递和参数,避免误操作目标集群:
--kube-context-nbash
helm --kube-context=prod-cluster status myapp -n prod
kubectl --context=prod-cluster get pods -n prod模板错误的详细输出:
bash
helm template myapp ./mychart --debug 2>&1 | head -100Values schema validation
Values Schema验证
json
{
"$schema": "https://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["replicaCount", "image"],
"properties": {
"replicaCount": { "type": "integer", "minimum": 1 },
"image": {
"type": "object",
"required": ["repository"],
"properties": {
"repository": { "type": "string" },
"tag": { "type": "string" }
}
}
}
}json
{
"$schema": "https://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["replicaCount", "image"],
"properties": {
"replicaCount": { "type": "integer", "minimum": 1 },
"image": {
"type": "object",
"required": ["repository"],
"properties": {
"repository": { "type": "string" },
"tag": { "type": "string" }
}
}
}
}Best practices
最佳实践
- Use semantic versioning for both and
version.appVersion - Always define requests and limits.
resources - Never commit secrets to ; use Vault, Sealed Secrets, or External Secrets.
values.yaml - Pin dependency versions explicitly.
- Include with post-install usage instructions.
NOTES.txt - Use to catch misconfiguration early.
values.schema.json - Add annotations to force restarts on ConfigMap changes.
checksum/config - Use for upgrades in CI to auto-rollback on failure.
--atomic - Prefer OCI registries over classic Helm repos for chart distribution.
- Use when templates use
--dry-run=serverto validate against real cluster state.lookup
- 为和
version使用语义化版本控制。appVersion - 始终定义的请求值和限制值。
resources - 切勿将密钥提交到;使用Vault、Sealed Secrets或External Secrets管理密钥。
values.yaml - 显式固定依赖版本。
- 包含文件,提供安装后使用说明。
NOTES.txt - 使用提前捕获配置错误。
values.schema.json - 添加注释,在ConfigMap变更时强制重启Pod。
checksum/config - 在CI中使用参数执行升级,失败时自动回滚。
--atomic - 优先使用OCI镜像仓库而非传统Helm仓库进行Chart分发。
- 当模板使用时,使用
lookup针对真实集群状态进行验证。--dry-run=server
Anti-patterns
反模式
- Hardcoded values in templates instead of references.
.Values.* - Missing resource limits (causes unbounded resource consumption).
- Plain-text secrets in or committed chart files.
values.yaml - Relying on implicit context without
kubectl.--context - Deeply nested logic that makes templates unreadable.
_helpers.tpl - Using bare with
--dry-run-heavy templates -- the lookups return empty withoutlookup.--dry-run=server
- 在模板中使用硬编码值而非引用。
.Values.* - 缺失资源限制(导致资源消耗无上限)。
- 在或已提交的Chart文件中使用明文密钥。
values.yaml - 依赖隐式上下文而不指定
kubectl。--context - 中包含过于复杂的嵌套逻辑,导致模板难以阅读。
_helpers.tpl - 对包含大量的模板使用单纯的
lookup-- 若不使用--dry-run,lookup会返回空值。--dry-run=server