Helm


1.介绍

如果你曾经发现自己深陷 Kubernetes YAML 文件中——复制、粘贴和调整多个环境的配置——你已经体验到了许多人所说的“YAML 蔓延”。随着微服务的增加,每个微服务都有自己的 Deployment、Service、ConfigMaps 和 Ingress,手动管理这些清单变得容易出错、耗时且难以管理。

1.1 什么是Helm

每个成功的软件平台都有一个优秀的打包系统,比如Debian、Ubuntu的apt,Red Hat、CentOS的yum、Mac的brew。Helm则是Kubernetes上的包管理器,方便我们更好的管理应用。

1.2 为什么需要Helm

为什么Kubernetes需要Helm?

Kubernetes能够很好地组织和编排容器,但它缺少一个更高层次的应用打包工具,而Helm就是来干这件事的。

Helm到底解决了什么问题?

清单地狱问题: 当你刚开始使用 Kubernetes 时,通常会编写大量 YAML 清单。一个微服务可能需要 Deployment、Service、Ingress、ConfigMaps、Secrets 等。在多个环境(开发、 staging、生产)中,每个环境都需要细微调整,很容易积累数百行重复的 YAML。

缺少包管理器: 像 Linux 上的aptyum,或 Node.js 的npm 这样的包管理器简化了软件安装和版本管理。在 Helm 出现之前,没有直接、标准化的方法来打包、版本化、分发和轻松部署 Kubernetes 应用程序。Helm 解决了这个问题。

配置和可重用性: Helm 不仅打包 Kubernetes 对象,还使其可配置。通过将配置外部化为values.yaml 文件,你可以动态生成 Kubernetes 清单。这减少了复制粘贴错误,提高了一致性,并显著简化了跨不同集群或环境的部署。

2. Helm架构

img

Helm2和Helm3架构

Tiller是Helm2的服务端组件,用于管理在Kubernetes集群上的Helm Charts(Helm包)。

Helm3删除了Tiller组件。

2.1 概念介绍

Charts: Helm chart 本质上是一个预配置的 Kubernetes 资源包。它是一个包含模板(带有占位符的 Kubernetes 清单)、默认值、chart 元数据(如Chart.yaml)和一些其他文件(如NOTES.txt 用于发布信息)的目录。

模板和值: Helm 的核心是模板的概念。这些是带有Go 模板语法的 Kubernetes 清单。Helm 从values.yaml 或命令行覆盖中注入值,将模板转换为准备部署的有效 Kubernetes 清单。

发布: 当你将 chart 安装到 Kubernetes 集群时,Helm 会创建一个release,即该 chart 的运行实例。每个 release 都有一个名称(如polar-bearspinning-windmill),并跟踪已安装的 chart 版本以及已部署的清单。

仓库: Helm charts 可以存储在仓库中,就像代码包一样。公共仓库如 Artifact Hub 托管了数千个社区 chart。组织通常维护内部私有仓库,以确保应用程序和组件的一致性。

3. Helm安装

# 1.Helm有个安装脚本可以自动拉取最新的Helm版本并在本地安装。
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod +x get_helm.sh
./get_helm.sh

# 2.局域网可以直接下载helm二进制文件安装
wget http://192.168.3.200/Software/helm-v3.14.4-linux-amd64.tar.gz
tar zxvf helm-v3.14.4-linux-amd64.tar.gz 
cd linux-amd64/
cp helm /usr/local/bin/

# 执行helm命令测试是否安装成功
helm version
-----------------------------------------------------
version.BuildInfo{Version:"v3.14.4", GitCommit:"81c902a123462fd4052bc5e9aa9c513c4c8fc142", GitTreeState:"clean", GoVersion:"go1.21.9"}

更多安装方法,可参见官方文档: https://helm.sh/zh/docs/intro/install/

4. Helm使用

Helm CLI 基础: Helm 命令行界面(helm)是你的主要工具。常见操作包括:

  • helm repo add – 添加 chart 仓库
  • helm search repo – 在仓库中搜索 charts
  • helm install – 将 chart 安装到集群中,创建一个 release
  • helm upgrade – 将 release 升级到 chart 的新版本
  • helm rollback – 将 release 回滚到之前的版本
  • helm uninstall – 从集群中删除 release

4.1 添加仓库

因为Helm3没有默认的存储库,需要手动添加,推荐添加仓库https://charts.bitnami.com/bitnami,使用命令helm repo add来添加仓库,操作如下:

4.1.1 添加

# 添加仓库,并把仓库名设为bitnami
helm repo add bitnami https://charts.bitnami.com/bitnami

4.1.2 查看已添加列表

helm repo list
------------------------------------------------------------------
NAME            URL
bitnami         https://charts.bitnami.com/bitnami
stable          http://mirror.azure.cn/kubernetes/charts
aliyun          https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
incubator       https://charts.helm.sh/incubator

4.2 搜索应用

Helm 自带一个强大的搜索命令,可以用来从两种来源中进行搜索:

  • helm search hub 从 Artifact Hub 中查找并列出 helm chartsArtifact Hub中存放了大量不同的仓库。
  • helm search repo 从你添加(使用 helm repo add)到本地helm 客户端中的仓库中进行查找。该命令基于本地数据进行搜索,无需连接互联网。

通过执行helm search hub 命令可以找到公开可用的charts,如果不进行过滤,helm search hub 命令会展示所有可用的 charts

4.2.1 模糊搜索应用

从已添加的仓库(bitnami)列表中,搜索redis

helm search repo redis
-------------------------------------------------------------------
NAME                                    CHART VERSION   APP VERSION     DESCRIPTION
aliyun/redis                            1.1.15          4.0.8           Open source, advanced key-value store. Itis of...
aliyun/redis-ha                         2.0.1                           Highly available Redis cluster with multiple se...
bitnami/redis                           20.3.0          7.4.1           Redis(R) is an open source, advanced key-value ...
bitnami/redis-cluster                   11.0.8          7.4.1           Redis(R) is an open source, scalable, distribut...
incubator/redis-cache                   0.5.2           4.0.12-alpine   DEPRECATED A pure in-memory redis cache, using ...
stable/prometheus-redis-exporter        3.5.1           1.3.4           DEPRECATED Prometheus exporter for Redis metrics
stable/redis                            10.5.7          5.0.7           DEPRECATED Open source, advanced key-value stor...
stable/redis-ha                         4.4.6           5.0.6           DEPRECATED - Highly available Kubernetes implem...
aliyun/sensu                            0.2.0                           Sensu monitoring framework backed by the Redis ...
bitnami/keydb                           0.1.6           6.3.4           KeyDB is a high performance fork of Rediswith ...
stable/sensu                            0.2.5           0.28            DEPRECATED Sensu monitoring framework backed by...

CHART VERSIONchar的版本,APP VERSIONredis的版本

4.2.2 查看应用版本列表

helm search repo bitnami/redis -l
-----------------------------------------------------------------
NAME                    CHART VERSION   APP VERSION     DESCRIPTION
bitnami/redis           20.3.0          7.4.1           Redis(R) is an open source, advanced key-value ...
bitnami/redis           20.2.2          7.4.1           Redis(R) is an open source, advanced key-value ...
# 内容过多中间省略...
bitnami/redis-cluster   7.6.2           6.2.7           Redis(R) is an open source, scalable, distribut...
bitnami/redis-cluster   7.6.1           6.2.7           Redis(TM) is an open source, scalable, distribu...

4.3 安装应用

通过命令helm install releaseName chartName来安装应用,releaseName指这次运行实例的名称,需要自己定义,chartNamechar对应的仓库名,比如上面的bitnami/redisredischarName

4.3.1 安装redis

# 安装指定版本的redis,这里的version是chart的版本
helm install redis-server bitnami/redis --version=16.13.1
----------------------------------------------------------------
NAME: redis-server
LAST DEPLOYED: Tue Sep 20 12:37:26 2022
NAMESPACE: default # 部署到k8s中的命名空间
STATUS: deployed 
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: redis
CHART VERSION: 16.13.1
APP VERSION: 6.2.7

** Please be patient while the chart is being deployed **

Redis® can be accessed on the following DNS names from within your cluster:

    redis-server-master.default.svc.cluster.local for read/write operations (port 6379)
    redis-server-replicas.default.svc.cluster.local for read-only operations (port 6379)

# 下面是测试访问服务方法
To get your password run:
    # 1.设置环境变量
    export REDIS_PASSWORD=$(kubectl get secret --namespace default redis-server -o jsonpath="{.data.redis-password}" | base64 -d)

To connect to your Redis® server:

1. Run a Redis® pod that you can use as a client:
   # 2. 运行redis-client pod
   kubectl run --namespace default redis-client --restart='Never'  --env REDIS_PASSWORD=$REDIS_PASSWORD  --image docker.io/bitnami/redis:6.2.7-debian-11-r9 --command -- sleep infinity

   Use the following command to attach to the pod:
  # 3. 进入pod
   kubectl exec --tty -i redis-client --namespace default -- bash

4.3.2 查看对应的k8s信息

上面的安装命令,会自动将redis服务部署到Kubernetes中,我们不需要单独在写复杂的Service、Pod、PVC....

# 查看service,发现redis是主从模式
kubectl get service
----------------------------------------------------------------
NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
redis-server-headless   ClusterIP   None            <none>        6379/TCP   2m22s
redis-server-master     ClusterIP   10.111.42.110   <none>        6379/TCP   2m22s
redis-server-replicas   ClusterIP   10.111.214.31   <none>        6379/TCP   2m22s
# 查看 pod
kubectl get pod
----------------------------------------------------------------
NAME                           READY   STATUS    RESTARTS      AGE
redis-server-master-0          1/1     Running   0             4m22s
redis-server-replicas-0        1/1     Running   0             4m22s
redis-server-replicas-1        1/1     Running   0             3m29s
redis-server-replicas-2        1/1     Running   0             2m47s

4.3.3 测试访问服务

# 进入测试端Pod
kubectl exec --tty -i redis-client --namespace default -- bash
# 登录redis
redis-cli -h 10.108.225.221 -a ikcNrFDQr7
---------------------------------------------------------------
# 设置值
10.108.225.221:6379> set test 123
OK

# 登录redis服务端
kubectl exec -it  redis-server-master-0 -- bash
# 登录redis
redis-cli -a ikcNrFDQr7
# 查看信息
127.0.0.1:6379> keys *
1) "test"
127.0.0.1:6379> get test
"123"

4.4 升级应用

4.4.1 查看当前版本

# 进入pod 中的容器
kubectl exec -it redis-server-master-0 -- bash
# 查看redis版本
redis-cli --version
----------------------------
redis-cli 6.2.7

4.4.2 升级

使用命令helm upgrade releaseName charName

helm upgrade redis-server bitnami/redis --version=17.0.1
------------------------------------------------------------
Release "redis-server" has been upgraded. Happy Helming!
NAME: redis-server
LAST DEPLOYED: Tue Sep 20 19:12:24 2022
NAMESPACE: default
STATUS: deployed
REVISION: 2
TEST SUITE: None
NOTES:
CHART NAME: redis
CHART VERSION: 17.0.1
APP VERSION: 7.0.3

** Please be patient while the chart is being deployed **

Redis&reg; can be accessed on the following DNS names from within your cluster:

    redis-server-master.default.svc.cluster.local for read/write operations (port 6379)
    redis-server-replicas.default.svc.cluster.local for read-only operations (port 6379)

To get your password run:

    export REDIS_PASSWORD=$(kubectl get secret --namespace default redis-server -o jsonpath="{.data.redis-password}" | base64 -d)

To connect to your Redis&reg; server:

1. Run a Redis&reg; pod that you can use as a client:

   kubectl run --namespace default redis-client --restart='Never'  --env REDIS_PASSWORD=$REDIS_PASSWORD  --image docker.io/bitnami/redis:7.0.3-debian-11-r0 --command -- sleep infinity

   Use the following command to attach to the pod:

   kubectl exec --tty -i redis-client \
   --namespace default -- bash

2. Connect using the Redis&reg; CLI:
   REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli -h redis-server-master
   REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli -h redis-server-replicas

To connect to your database from outside the cluster execute the following commands:

    kubectl port-forward --namespace default svc/redis-server-master 6379:6379 &
    REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli -h 127.0.0.1 -p 6379

4.4.3 验证

# 进入pod 中的容器
kubectl exec -it redis-server-master-0 -- bash
# 查看redis版本
redis-cli --version
------------------------------------------
redis-cli 7.0.3

4.5 回滚应用

每次对应用的操作(安装、升级、回滚),都会被保存起来,可以通过命令helm history releaseName查看历史操作信息,然后通过命令helm rollback releaseName 版本号来回滚到对应的版本。

4.5.1 查看历史版本

# 查看历史版本
helm history redis-server
--------------------------------------------------------------
REVISION UPDATED                  STATUS     CHART         APP VERSION DESCRIPTION
1        Tue Sep 20 18:09:32 2022 superseded redis-16.13.1 6.2.7       Install complete
2        Tue Sep 20 19:12:24 2022 deployed   redis-17.0.1  7.0.3       Upgrade complete

4.5.2 回滚到指定版本

# 回滚到指定版本,这里回滚到版本1
helm rollback redis-server 1 
-----------------------------------------
Rollback was a success! Happy Helming!
# 查看当前char版本,发现已经回滚到 6.2.7
helm list
-----------------------------------------
NAME         NAMESPACE REVISION    STATUS    CHART           APP VERSION
redis-server default   3         deployed  redis-16.13.1      6.2.7

4.6 卸载应用

通过命令helm uninstall releaseName来卸载应用,执行如下:

# 卸载
helm uninstall redis-server
# 查看redis-server对应的历史操作
helm history redis-server
----------------------------
Error: release: not found

默认卸载应用后会删除与应用相关联的所有发布记录,如果还想继续保留发布记录信息,可以通过helm uninstall releaseName --keep history,保留后的记录,并且依然可以通过helm rollback来回滚到删除前的版本。

5. 构建Chart

chartHelm的核心。除了将它们安装到Kubernetes集群中或管理已安装的chart实例之外,还可以构建新chart或更改现有chart,

  • chart的设计目标:把Kubernetes作为一个有自己独特风格的平台。
  • chart的核心是模板:该模板用于生成可以在集群中安装和管理的Kubernetes清单。

5.1 创建模板

helm create chartName可以轻松创建一个chart模板,里面包含所有必需的chart结构和文件,创建命令如下:

# 创建chart
helm create helloword
-----------------------
Creating helloword

5.2 目录介绍

# 查看目录
$ tree -L 2 helloword
helloword
├── Chart.yaml
├── charts
├── templates
│   ├── NOTES.txt
│   ├── _helpers.tpl
│   ├── deployment.yaml
│   ├── hpa.yaml
│   ├── ingress.yaml
│   ├── service.yaml
│   ├── serviceaccount.yaml
│   └── tests
│       └── test-connection.yaml
└── values.yaml
  • Chart.yaml: 描述chart的概要信息,
  • charts: chart可以依赖于其他chart,被依赖的chart可以放进这个目录,目前这是个空目录。
  • templates: 用于生成Kubernetes清单的模板存储在templates目录中.
  • NOTES.txt: 安装chart时,NOTES.txt文件模板是被渲染和显示到(而不是被安装到)集群中,比如安装成功后的使用提示等。
  • values.yaml: 当Helm渲染清单时传递给模板的默认值位于values.yaml文件中。实例化chart时,可以覆盖这些值。

5.3 修改values.yaml

默认生成的values.yaml里面有很多内容,这里只修改一些满足实例要求的配置信息。

replicaCount: 1 # pod 数量
fullnameOverride: "hello-word-app" # 服务名称
# 镜像信息
image:
  repository: docker.io/liuqinghui/gin-hello # docker镜像
  pullPolicy: IfNotPresent # 不存在则拉取镜像
  tag: "v1" # 镜像tag
# 服务配置信息
service:
  type: NodePort
  port: 80 # ClusterIP监听的端口
  targetPort: 80 # Pod监听的端口
  nodePort: 30001 # 端口范围在 30000~3276

5.4 打包

通过命令helm package path,将chart的文件和目录打包到单个归档文件中,便于后续安装和传输。

5.4.1 命令说明

helm package -h       
---------------------------------------------------------------
...
Usage:
  helm package [CHART_PATH] [...] [flags]
# 部分参数说明
Flags:
  --app-version      # 可用于设置Chart.yaml文件的appVersion属性
  -u, --dependency-update # 创建存档文件之前更新依赖的chart
  -d, --destination  # 设置用于放置chart归档文件的位置
...

5.4.2 执行打包

helm package helloword 
-------------------------------------------------------------
Successfully packaged chart and saved it to: /root/HelmRepo/helloword-0.1.0.tgz

5.5 校验

在开发chart时,尤其是使用YAML模板时,很容易出错或遗漏某些内容。为了帮助你捕捉错误和其他可疑元素,Helm客户端提供了一个代码校验器(linter),使用方式如下:

# 代码信息
ls
---------------------------------------------------------------
drwxr-xr-x  8 root  staff   256  9 23 18:12 helloword
-rw-r--r--  1 root  staff  3943  9 29 11:49 helloword-0.1.0.tgz
# 基于目录校验
helm lint helloword
---------------------------------------------------------------
==> Linting helloword
[INFO] Chart.yaml: icon is recommended

1 chart(s) linted, 0 chart(s) failed

# 基于打包后的文件校验
helm lint helloword-0.1.0.tgz
---------------------------------------------------------------
==> Linting helloword-0.1.0.tgz
[INFO] Chart.yaml: icon is recommended

1 chart(s) linted, 0 chart(s) failed

# 故意写错yaml语法,再次校验
helm lint helloword
---------------------------------------------------------------
==> Linting helloword
[ERROR] Chart.yaml: unable to parse YAML
 error converting YAML to JSON: yaml: line 2: mapping values are not allowed in this context
[ERROR] templates/: cannot load Chart.yaml: error converting YAML to JSON: yaml: line 2: mapping values are not allowed in this context
[ERROR] : unable to load chart
 cannot load Chart.yaml: error converting YAML to JSON: yaml: line 2: mapping values are not allowed in this context

Error: 1 chart(s) linted, 1 chart(s) failed

5.6 安装

5.6.1 基于打包文件安装

# 基于打包文件安装
helm install hello-word helloword-0.1.0.tgz
--------------------------------------------------------------
NAME: hello-word
LAST DEPLOYED: Thu Sep 29 15:24:24 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
  export NODE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services hello-word-app)
  export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath="{.items[0].status.addresses[0].address}")
  echo http://$NODE_IP:$NODE_PORT

5.6.2 查看服务信息

# helm服务列表
helm list
----------------------------------------------------------------
NAME       NAMESPACE REVISION    STATUS      CHART                APP VERSION
hello-word default   1         deployed  helloword-0.1.0        0.1.1
# 查看k8s service
kubectl get svc
----------------------------------------------------------------
NAME             TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
hello-word-app   NodePort    10.101.62.30   <none>        80:30001/TCP   7m11s
# 查看k8s deploy
kubectl get deploy
-----------------------------------------------------------------
NAME            READY   UP-TO-DATE  AVAILABLE   AGE    IMAGES                             ...
hello-word-app   1/1     1           1         7m46s   docker.io/liuqinghui/gin-hello:v1  ...
# 查看k8s pod
kubectl get pod -o wide
-----------------------------------------------------------------
NAME                            READY   STATUS  RESTARTS     IP            NODE    ...
hello-word-app-d467dbcd8-g796n  1/1     Running   0       10.244.104.9     node2   ...

img

Helm 带来的不同

使用 Helm 之前:

  • 每个环境的多组几乎相同的 YAML 文件。
  • 手动更新 YAML,容易出错。
  • 没有原生的版本控制或回滚能力。

使用 Helm 后:

  • 一组模板,多个values.yaml 覆盖。
  • 简单的参数化更改,适用于不同环境。
  • 内置版本控制,轻松升级,无痛回滚。

Helm 将复杂性集中在一个定义良好的结构中,使维护和扩展变得更加容易。

结论:

从原始 YAML 管理到自定义 Helm charts 和预配置解决方案,Helm 改变了 Kubernetes 应用程序的部署方式。无论你是创建自己的 chart 还是利用预配置的 charts,Helm 都简化了复杂性,促进了可重用性,并确保了一致性。今天尝试 Helm,为你的 Kubernetes 工作流注入活力。