Appearance
Helm Chart 编写
Helm Chart 本质上是一组带模板语法的 Kubernetes YAML。Chart 编写的重点不是把所有字段都参数化,而是把稳定结构留在模板里,把环境差异、镜像版本、资源规格、入口域名、存储大小这些变化项放到 values 里。
Chart 写得过度灵活会很难维护。业务 Chart 通常只暴露部署时确实会变的字段,其他部分保持固定。平台型 Chart 才需要更强的可配置性。
一、目录结构
创建一个 Chart:
bash
helm create webapp
tree webapp常见结构:
text
webapp/
Chart.yaml
values.yaml
templates/
deployment.yaml
service.yaml
ingress.yaml
_helpers.tpl| 文件 | 说明 |
|---|---|
Chart.yaml | Chart 元信息,名称、版本、应用版本、依赖 |
values.yaml | 默认参数 |
templates/ | 模板目录,渲染后变成 Kubernetes YAML |
_helpers.tpl | 公共模板函数,常用于统一名称和标签 |
Chart.yaml 示例:
yaml
apiVersion: v2
name: webapp
description: Web application chart
type: application
version: 0.1.0
appVersion: "1.0.0"version 是 Chart 自己的版本,appVersion 是应用版本。Chart 模板调整但镜像不变时,version 也应该变化。
二、values 设计
一个简化的 values.yaml:
yaml
replicaCount: 2
image:
repository: registry.example.com/demo/webapp
tag: "1.0.0"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
env:
LOG_LEVEL: infovalues 命名保持稳定很重要。CI/CD、Argo CD、环境 overlay 都会引用这些字段。字段改名等于部署接口变化,需要像代码接口一样谨慎。
三、模板里的对象
Deployment 模板:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "webapp.fullname" . }}
labels:
{{- include "webapp.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "webapp.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "webapp.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: webapp
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 8080
env:
{{- range $name, $value := .Values.env }}
- name: {{ $name }}
value: {{ $value | quote }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}nindent 用来处理缩进,quote 避免 YAML 把某些字符串识别成布尔值或数字。模板错误里最常见的就是缩进错误和空值渲染。
四、helpers 和统一标签
templates/_helpers.tpl 常用于统一命名:
gotemplate
{{- define "webapp.fullname" -}}
{{- printf "%s-%s" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- define "webapp.selectorLabels" -}}
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}
{{- define "webapp.labels" -}}
{{ include "webapp.selectorLabels" . }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
{{- end -}}selector label 创建后不适合随意变化。Deployment 的 selector 是不可变字段,改了会导致升级失败。通常把 selector label 控制在 name 和 instance 这类稳定字段,不把 chart version、app version 放进 selector。
五、条件渲染
可选资源用 if:
yaml
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "webapp.fullname" . }}
spec:
ingressClassName: {{ .Values.ingress.className | quote }}
rules:
- host: {{ .Values.ingress.host | quote }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ include "webapp.fullname" . }}
port:
number: {{ .Values.service.port }}
{{- end }}条件渲染适合开关 Ingress、ServiceMonitor、HPA 这类可选资源。核心 Deployment 不建议做太多条件分支,否则渲染结果会很难预测。
六、schema 校验
values.schema.json 可以限制 values 类型和必填字段:
json
{
"$schema": "https://json-schema.org/schema#",
"type": "object",
"properties": {
"replicaCount": {
"type": "integer",
"minimum": 1
},
"image": {
"type": "object",
"required": ["repository", "tag"]
}
}
}schema 能提前拦住 replicaCount: "two"、漏写镜像 tag 这类问题。平台 Chart、团队共用 Chart 很适合加 schema。
七、检查命令
bash
# 检查 Chart 结构和模板语法
helm lint ./webapp
# 渲染出最终 YAML,检查缩进、名称、标签和资源字段
helm template web ./webapp -n demo -f values.yaml
# 模拟安装,连接集群做校验
helm install web ./webapp -n demo --dry-run模板渲染报错时,优先看报错里的模板文件和行号。渲染成功但集群拒绝时,再看 API Server 的字段校验、不可变字段、RBAC、准入策略。
八、常见问题
| 问题 | 表现 |
|---|---|
| 缩进错误 | 渲染出的 YAML 结构不对,API Server 报字段类型错误 |
| 空值没处理 | image、host、secretName 变成空字符串 |
| selector 标签变化 | Deployment 升级失败,提示 selector 不可变 |
| values 层级太深 | 使用时很难知道该改哪个字段 |
| 把 Secret 明文放 values | values 进入 Git 后泄漏敏感信息 |
| Chart 过度通用 | 模板分支太多,排查渲染结果困难 |
Chart 编写的检查顺序比较固定:helm lint 看结构,helm template 看最终 YAML,kubectl apply --dry-run=server 或 Helm dry-run 看集群是否接受,最后再实际安装或升级。