4. 编写第一个 Helm Chart:创建 Chart、定义 Deployment 模板、定义 Service 模板、使用 helm install 部署
本章将带领你从零开始编写第一个 Helm Chart。你将掌握 helm create 命令生成的目录结构,理解核心模板文件(Deployment 与 Service)的编写逻辑,并最终通过 helm install 将应用部署到 Kubernetes 集群中。这是后续学习升级、回滚与配置管理的基础。
4.1 使用 helm create 创建 Chart 骨架
Helm 提供了 helm create 命令,可以快速生成一个符合最佳实践的 Chart 目录结构。执行以下命令创建一个名为 my-first-app 的 Chart:
helm create my-first-app
执行后,Helm 会在当前目录下生成如下结构:
my-first-app/
├── Chart.yaml # Chart 元数据(名称、版本、描述等)
├── charts/ # 存放子 Chart(依赖包)
├── templates/ # Kubernetes 资源模板目录
│ ├── NOTES.txt # 部署后的使用说明
│ ├── _helpers.tpl # 模板辅助函数
│ ├── deployment.yaml # Deployment 模板
│ ├── hpa.yaml # 水平自动扩缩容模板
│ ├── ingress.yaml # Ingress 模板
│ ├── service.yaml # Service 模板
│ ├── serviceaccount.yaml # 服务账户模板
│ └── tests/ # 测试模板
│ └── test-connection.yaml
└── values.yaml # 默认配置值文件
关键点:初学者应重点关注
templates/deployment.yaml、templates/service.yaml 和 values.yaml 三个文件。它们是定义应用运行形态的核心。
4.2 理解 Chart 的核心文件
在开始修改模板之前,需要先了解两个关键文件的作用:
| 文件 | 作用 | 必填 |
|---|---|---|
Chart.yaml |
定义 Chart 的名称、版本、API 版本、描述等元数据 | 是 |
values.yaml |
提供默认配置值,模板通过 .Values 对象引用 |
是 |
templates/ |
存放 Go 模板文件,渲染后生成 Kubernetes 资源清单 | 是 |
charts/ |
存放子 Chart 的目录(依赖管理) | 否 |
NOTES.txt |
部署成功后打印给用户的使用提示 | 否 |
4.3 定义 Deployment 模板
Deployment 是 Kubernetes 中最常用的工作负载资源,负责管理 Pod 的副本、更新策略和自愈能力。下面是一个精简且完整的 Deployment 模板示例,位于 templates/deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "my-first-app.fullname" . }}
labels:
{{- include "my-first-app.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "my-first-app.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "my-first-app.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "my-first-app.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
模板语法要点:
{{ .Values.replicaCount }}:从values.yaml中读取副本数。{{ include "my-first-app.fullname" . }}:调用_helpers.tpl中定义的命名模板,生成统一的资源名称。{{- with .Values.imagePullSecrets }}:条件判断,仅在配置了拉取密钥时才渲染该字段。nindent:在换行后添加指定数量的缩进,保持 YAML 格式正确。
4.4 定义 Service 模板
Service 为 Pod 提供稳定的网络访问入口。以下是一个 ClusterIP 类型的 Service 模板,位于 templates/service.yaml:
apiVersion: v1
kind: Service
metadata:
name: {{ include "my-first-app.fullname" . }}
labels:
{{- include "my-first-app.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "my-first-app.selectorLabels" . | nindent 4 }}
注意:
targetPort: http 引用了 Deployment 模板中定义的端口名称 name: http。使用命名端口可以避免硬编码端口号,增强模板的可读性和可维护性。
4.5 配置 values.yaml
values.yaml 是 Chart 的配置中心。以下是与上述模板匹配的默认值配置:
# 副本数
replicaCount: 1
# 镜像配置
image:
repository: nginx
tag: "1.25.3"
pullPolicy: IfNotPresent
# 服务配置
service:
type: ClusterIP
port: 80
# 资源限制
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
# 自动扩缩容(默认关闭)
autoscaling:
enabled: false
# 其他配置(节点选择、容忍、亲和性等)
nodeSelector: {}
tolerations: []
affinity: {}
4.6 使用 helm install 部署 Chart
完成模板和 values 文件的编写后,即可使用 helm install 命令将 Chart 部署到 Kubernetes 集群。基本语法如下:
helm install [RELEASE_NAME] [CHART_PATH] [flags]
部署 my-first-app Chart 的示例:
# 使用默认 values.yaml 部署
helm install my-release ./my-first-app
# 使用自定义 values 文件覆盖默认配置
helm install my-release ./my-first-app -f custom-values.yaml
# 通过命令行直接设置单个参数
helm install my-release ./my-first-app --set replicaCount=3 --set image.tag=1.26.0
常见错误:
- Release 名称冲突:在同一命名空间下,Release 名称必须唯一。如果已存在同名 Release,需先卸载或使用不同的名称。
- 模板语法错误:使用
helm lint ./my-first-app预先检查模板语法,避免部署时失败。 - values 类型不匹配:确保
values.yaml中的值与模板中期望的类型一致(例如端口号应为数字,而非字符串)。
4.7 验证部署结果
部署完成后,可以通过以下命令验证资源是否正常创建:
# 查看 Release 状态
helm list
# 查看 Release 详细信息
helm status my-release
# 查看 Kubernetes 资源
kubectl get pods,svc -l app.kubernetes.io/instance=my-release
如果一切正常,你将看到类似如下的输出:
NAME READY STATUS RESTARTS AGE
pod/my-release-my-first-app-7d8f9c6b9-abcde 1/1 Running 0 30s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/my-release-my-first-app ClusterIP 10.96.123.45 <none> 80/TCP 30s
4.8 第一个 Chart 的完整工作流程
下图展示了从创建 Chart 到部署完成的完整流程:
4.9 本章小结
通过本章的学习,你已经完成了以下关键任务:
- 使用
helm create快速生成标准 Chart 目录结构。 - 编写了 Deployment 模板,定义了 Pod 的副本数、镜像、探针和资源限制。
- 编写了 Service 模板,为应用提供了稳定的 ClusterIP 访问入口。
- 配置了
values.yaml,实现了配置与模板的分离。 - 使用
helm install成功将 Chart 部署到 Kubernetes 集群。