写在前面

在 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 又变回了clusterIP

3.2 打包chart

[root@k8s-master /manifests/helm]# helm package nginx
Successfully packaged chart and saved it to: /manifests/helm/nginx-0.1.0.tgz