写在前面
在 Kubernetes 的世界里,部署应用往往涉及复杂的 YAML 文件和多种配置,手动管理不仅容易出错,还不利于团队协作。Helm 作为 Kubernetes 的包管理工具,正是为解决这些痛点而生。它通过 Charts 将应用及其依赖打包,支持模板化配置,让我们可以快速安装、升级、回滚应用。
本篇博客将以实战为主线,带大家从零开始动手使用 Helm:从安装 Helm,到创建自己的 Chart,再到在 Kubernetes 集群上部署、更新和管理应用。每一步都有详细操作示例,保证你不仅能看懂,还能立刻在自己的集群上落地实践。
1. 安装helm
https://github.com/helm/helm/releases
## 上传压缩包并解压,(此处不解压README.MD文档及授权文件信息)
tar xf helm-v3.9.0-linux-amd64.tar.gz -C /usr/local/sbin/ linux-amd64/helm --strip-components=1
## 验证helm 安装成功
[root@k8s231.oldboyedu.com helm]# helm version
## 配置helm命令的自动补全
[root@k8s-master /manifests/helm]# helm completion bash > /etc/bash_completion.d/helm
[root@k8s-master /manifests/helm]# source /etc/bash_completion.d/helm
[root@k8s-master /manifests/helm]# helm # 连续按2次tab键,出现如下内容则成功
completion (generate autocompletion scripts for the specified shell)
create (create a new chart with the given name)
dependency (manage a chart's dependencies)
env (helm client environment information)
get (download extended information of a named release)
help (Help about any command)
...1.1 配置chart仓库
## 1. 添加阿里云的 chart 仓库
[root@k8s-master /manifests/helm]# helm repo add aliyun https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
"aliyun" has been added to your repositories
## 2. 添加 bitnami 的 chart 仓库
[root@k8s-master /manifests/helm]# helm repo add bitnami https://charts.bitnami.com/bitnami
## 3. 更新 chart 仓库
[root@k8s-master /manifests/helm]# helm repo update
## 4. 查看配置的 chart 仓库有哪些
[root@k8s-master /manifests/helm]# helm repo list
NAME URL
bitnami https://charts.bitnami.com/bitnami
aliyun https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
## 5. 删除 chart 仓库地址
[root@k8s-master /manifests/helm]# helm repo remove bitnami
## 6.从指定 chart 仓库地址搜索 chart
[root@k8s-master /manifests/helm]# helm search repo bitnami
[root@k8s-master /manifests/helm]# helm search repo bitnami |grep redis
bitnami/redis 24.0.0 8.4.0 Redis(R) is an open source, advanced key-value ...
bitnami/redis-cluster 13.0.4 8.2.1 Redis(R) is an open source, scalable, distribut...
## 这里的24.0.0 是chart的版本,8.4.0 是默认redis安装的版本。1.2 Helm的基本使用
## 1. 查看 chart 信息 (以阿里云的redis为例子)
[root@k8s-master /manifests/helm/redis]# helm show chart aliyun/redis
apiVersion: v1
appVersion: 4.0.8
description: Open source, advanced key-value store. It is often referred to as a data
structure server since keys can contain strings, hashes, lists, sets and sorted
sets.
home: http://redis.io/
icon: https://bitnami.com/assets/stacks/redis/img/redis-stack-220x234.png
keywords:
- redis
- keyvalue
- database
maintainers:
- email: containers@bitnami.com
name: bitnami-bot
name: redis
sources:
- https://github.com/bitnami/bitnami-docker-redis
version: 1.1.15
## 2. 下载 chart 包到本地
[root@k8s-master /manifests/helm]# helm pull aliyun/redis
## 当前目录下会有一个tar.gz的压缩包
[root@k8s-master /manifests/helm]# tar xzf redis-1.1.15.tgz
[root@k8s-master /manifests/helm]# tree -F redis
redis
├── Chart.yaml* ## chart 的基本信息,包括版本名字之类
├── README.md*
├── templates/ ## 存放 k8s 的部署资源模板,通过渲染变量得到部署文件
│ ├── deployment.yaml*
│ ├── _helpers.tpl* ## 存放能够复用的模板
│ ├── networkpolicy.yaml*
│ ├── NOTES.txt* ## 为用户提供一个关于 chart 部署后使用说明的文件
│ ├── pvc.yaml*
│ ├── secrets.yaml*
│ └── svc.yaml*
└── values.yaml* ## 存放全局变量,templates 下的文件可以调用1.3 部署chart
## 1. helm 部署redis 服务
[root@k8s-master /manifests/helm]# cd redis/
## 2. 修改deployments
[root@k8s-master /manifests/helm/redis]# cat templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
...
## 3. 修改value.yaml,这里我是将数据卷挂载给关掉了,如果需要的话可以自己创建sc 然后将enabled改为true
[root@k8s-master /manifests/helm/redis]# grep -C 3 persistence values.yaml
## - "--repl-backlog-size 1024mb"
redisExtraFlags:
persistence:
enabled: false
## 4. 部署redis
[root@k8s-master /manifests/helm/redis]# helm install redis./
## 5. 基于文件的方式更新
[root@k8s-master /manifests/helm/redis]# helm upgrade redis ./ -f values.yaml
Release "redis" has been upgraded. Happy Helming!
NAME: redis
LAST DEPLOYED: Thu Nov 27 15:37:35 2025
NAMESPACE: default
STATUS: deployed
REVISION: 2
...2. Chart模板
2.1 自定义一个Chart
当我们安装好 helm 之后我们可以开始自定义 chart,那么我们需要先创建出一个模板如下
## 1. 常见Chart
[root@k8s-master /manifests/helm]# helm create nginx
[root@k8s-master /manifests/helm]# tree nginx
nginx
├── charts
├── Chart.yaml
├── templates
│ ├── deployment.yaml
│ ├── _helpers.tpl
│ ├── hpa.yaml
│ ├── httproute.yaml
│ ├── ingress.yaml
│ ├── NOTES.txt
│ ├── serviceaccount.yaml
│ ├── service.yaml
│ └── tests
│ └── test-connection.yaml
└── values.yam
## 2. Chart.yaml 编写规则
## 原生内容
[root@k8s-master /manifests/helm/nginx]# egrep -v '^$|#' Chart.yaml
apiVersion: v2
name: nginx
description: A Helm chart for Kubernetes
type: application
version: 0.1.0
appVersion: "1.16.0"
## Chart.yaml 文件主要用来描述对应 chart 的相关属性信息,
## apiVersion 字段用于描述对应 chart 使用的 api 版本,默认是v2 版本
## name 字段用于描述对应 chart 的名称
## description 字段用于描述对应 chart 的说明简介
## type 字段用户描述对应 chart 是应用程序还是库文件,应用程序类型的chart,它可以运行为一个 release,但库类型的 chart 不能运行为 release,它只能作为依赖被application 类型的 chart 所使用
## version 字段用于描述对应 chart 版本
## appVersion 字段用于描述对应 chart 内部程序的版本信息2.2 go模板文件渲染
[root@k8s-master /manifests/helm/nginx]# cat templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "nginx.fullname" . }}
labels:
{{- include "nginx.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "nginx.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "nginx.labels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "nginx.serviceAccountName" . }}
{{- with .Values.podSecurityContext }}
securityContext:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
{{- with .Values.securityContext }}
securityContext:
{{- toYaml . | nindent 12 }}
{{- end }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
{{- with .Values.livenessProbe }}
livenessProbe:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.readinessProbe }}
readinessProbe:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.volumeMounts }}
volumeMounts:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.volumes }}
volumes:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
## 该部署清单模板文件,主要用 go 模板语言来写的
## {{ include "nginx.fullname" . }}就表示取 nginx 的全名
## {{ .Values.image.repository }}这段代码表示读取当前目录下的 values 文件中的image.repository 字段的值
## nindent 8:表示首行缩进 8 个字母2.3 values.yaml 文件编写
[root@k8s-master /manifests/helm/nginx]# egrep -v '^$|#' values.yaml
replicaCount: 1
image:
repository: nginx
pullPolicy: IfNotPresent
tag: ""
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
serviceAccount:
create: true
automount: true
annotations: {}
name: ""
podAnnotations: {}
podLabels: {}
podSecurityContext: {}
securityContext: {}
service:
type: ClusterIP
port: 80
ingress:
enabled: false
className: ""
annotations: {}
hosts:
- host: chart-example.local
paths:
- path: /
pathType: ImplementationSpecific
tls: []
httpRoute:
enabled: false
annotations: {}
parentRefs:
- name: gateway
sectionName: http
hostnames:
- chart-example.local
rules:
- matches:
- path:
type: PathPrefix
value: /headers
resources: {}
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 100
targetCPUUtilizationPercentage: 80
volumes: []
volumeMounts: []
nodeSelector: {}
tolerations: []
affinity: {}
## 我们要引用 values.yaml 文件中的 image 字段下的 tag 字段的值,我们可以在模板文件中写成{{ .Values.image.tag }}.如果在命令行使用--set 选项来应用我们可以写成 image.tag。默认情况在命令行使用--set 选项给出的值,都会直接被替换,没有给定的值,默认还是使用values.yaml 文件中给定的默认值。2.4 部署release
[root@k8s-master /manifests/helm/nginx]# helm install nginx .
NAME: nginx
LAST DEPLOYED: Thu Nov 27 16:59:38 2025
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=nginx,app.kubernetes.io/instance=nginx" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT
[root@k8s-master /manifests/helm/nginx]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nfs-provisioner-7c7c5bb687-xcgr4 1/1 Running 2 (8h ago) 26h
nginx-7c6448d55b-8w2rh 1/1 Running 0 13s
3. Helm常用命令
## 1. 检查 values 语法格式
[root@k8s-master /manifests/helm]# helm lint nginx/
==> Linting nginx/
[INFO] Chart.yaml: icon is recommended
1 chart(s) linted, 0 chart(s) failed
## 2. upgrade 升级 release
[root@k8s-master /manifests/helm]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.200.0.1 <none> 443/TCP 13d
nginx ClusterIP 10.200.252.247 <none> 80/TCP 3m
[root@k8s-master /manifests/helm/nginx]# helm upgrade --set service.type="NodePort" nginx .
[root@k8s-master /manifests/helm/nginx]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.200.0.1 <none> 443/TCP 13d
nginx NodePort 10.200.252.247 <none> 80:32751/TCP 4m21s
## 更新成功3.1 release 相关操作
## 1. 查看 release 发布状态
[root@k8s-master /manifests/helm/nginx]# helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
nginx default 2 2025-11-27 17:03:44.874112489 +0800 CST deployed nginx-0.1.0 1.16.0
## 2. 删除 release
[root@k8s-master /manifests/helm/redis]# helm delete nginx
release "redis" uninstalled
## 删除 release 会把 release 下对应的资源也删除
## 3. 查看历史版本
[root@k8s-master /manifests/helm/nginx]# helm history nginx
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Thu Nov 27 16:59:38 2025 superseded nginx-0.1.0 1.16.0 Install complete
2 Thu Nov 27 17:03:44 2025 deployed nginx-0.1.0 1.16.0 Upgrade complete
## 4.nginx 回滚到版本 1
[root@k8s-master /manifests/helm/nginx]# helm rollback nginx 1
Rollback was a success! Happy Helming!
[root@k8s-master /manifests/helm/nginx]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.200.0.1 <none> 443/TCP 13d
nginx ClusterIP 10.200.252.247 <none> 80/TCP 10m
## nginx的svc 又变回了clusterIP3.2 打包chart
[root@k8s-master /manifests/helm]# helm package nginx
Successfully packaged chart and saved it to: /manifests/helm/nginx-0.1.0.tgz
评论