Helm应用包管理器

一.Helm基本概述

1.为什么需要Helm

K8S上的应用对象,都是由特定的资源描述组成的,包括deployment、service等。都保存在各自的文件中或者集中写到一个配置文件里。然后使用kubectl apply -f命令进行部署。

file

如果应用只由一个或几个这样的服务组成,上面部署方式足够了。
而对于一个复杂的应用,会有很多类似上面的资源描述文件,例如微服务架构应用,组成应用的服务可能多达十个,几十个。如果有更新或回滚应用的需求,可能要修改和维护所涉及的大量资源文件,而这种组织和管理应用的方式就显得力不从心了。
且由于缺少对发布过的应用版本管理和控制,使Kubernetes上的应用维护和更新等面临诸多的挑战,主要面临以下问题:

1.如何将这些服务作为一个整体管理
2.这些资源文件如何高效复用
3.不支持应用级别的版本管理


2.Helm介绍

Helm是一个Kubernetes的包管理工具,就像Linux下的包管理器,如yum/apt等, 可以很方便的将之前打包好的yaml文件部署到kubernetes上。

Helm有三个重要概念:

  • helm: 一个命令行客户端工具,主要用于Kubernetes应用chart的创建、打包、发布和管理。
  • Chart: 应用描述,一系列用于描述k8s资源相关文件的集合。
  • Release: 基于Chart的部署实体, 一个chart被Helm运行后将会生成对应的一个release; 将在k8s中创建出真实运行的资源对象。

3.Helm v3变化

2019年11月13日,Helm团队发布了helm v3的第一个稳定版本

该版本的主要变化:

1.架构变化

最明显的变化是Tiller的删除

file

2.Release名称可以在不同命名空间重用

3.支持将Chart推送至Docker镜像仓库当中

4.使用JSON Schema验证chart values

5.其他

1) 为了更好地协调其他包管理者的措辞Helm Cli个别更名

helm delete  更名为 helm uninstall
helm inspect 更名为 helm show
helm fetch   更名为 helm pull

# 但更名前命令当前仍能使用

2)移除了用于本地临时搭建Chart Repository的helm serve命令。

3)自动创建名称空间
在不存在的命名空间中创建发行版时,Helm 2创建了命名空间。Helm 3遵循其他Kubernetes对象的行为,如果
命名空间不存在则返回错误。

4)不再需要requir ements .yam1 ,依赖关系是直接在chart .yam中定义。

二.Helm客户端部署与使用

1.部署安装Helm

Helm客户端下载地址: TP

1.下载helm安装包

wget https://get.helm.sh/helm-v3.0.0-linux-amd64.tar.gz

2.解压

tar zxvf helm-v3.0.0-linux-amd64.tar.gz

3.将命令移动到/usr/bin目录下

mv linux-amd64/helm usr/bin/

2.Helm常用命令

命令 描述
create 创建一个chart并指定名字
dependency 管理chart的依赖
get 下载一个releses。可用子命令:all、hooks、manifest、notes、values
history 获取release历史
install 安装一个chart
list 列出release
package 将chart目录打包到chart存档文件中
pull 从远程仓库中下载chart并解压到本地 #helm pull stable/myqsl --untar
repo 添加,列出,移除,更新和索引chart仓库。可用子命令:add、index、list、remove、update
rollback 从之前版本回滚
search 根据关键字搜索chart。可用子命令:hub、repo
show 查看chart详细信息。可用子命令:all、chart、readme、values
status 显示已命名版本的状态
template 本地呈现模板
uninstall 卸载一个release
upgrade 更新一个release
version 查看helm客户端版本

3.配置国内Chart仓库

添加存储库:

[root@k8s-m01 ~]# helm repo add stable http://mirror.azure.cn/kubernetes/charts/
"stable" has been added to your repositories

[root@k8s-m01 ~]# helm repo add aliyun https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
"aliyun" has been added to your repositories

[root@k8s-m01 ~]# helm  repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "aliyun" chart repository
...Successfully got an update from the "stable" chart repository
...Successfully got an update from the "bitnami" chart repository
Update Complete. ⎈Happy Helming!⎈

查看配置的存储库:

[root@k8s-m01 ~]# 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

[root@k8s-m01 ~]# helm search repo stable
NAME                                    CHART VERSION   APP VERSION             DESCRIPTION                                       
stable/acs-engine-autoscaler            2.2.2           2.1.1                   DEPRECATED Scales worker nodes within agent pools 
stable/aerospike                        0.3.5           v4.5.0.5                DEPRECATED A Helm chart for Aerospike in Kubern...
stable/airflow                          7.13.3          1.10.12                 DEPRECATED - please use: https://github.com/air...
stable/ambassador                       5.3.2           0.86.1                  DEPRECATED A Helm chart for Datawire Ambassador   

删除存储库:

[root@k8s-m01 ~]# helm repo remove sh
"sh" has been removed from your repositories

三.Helm基本使用

主要有三个命令:

  • chart install
  • chart upgrade
  • chart rollback

1.使用chart部署一个应用

这里通过helm部署一个MySQL进行示例

查找chart信息

[root@k8s-m01 ~]# helm search repo

[root@k8s-m01 ~]# helm search repo mysql
NAME                                CHART VERSION   APP VERSION DESCRIPTION                                       
aliyun/mysql                        0.3.5                       Fast, reliable, scalable, and easy to use open-...
bitnami/mysql                       9.4.4           8.0.31      MySQL is a fast, reliable, scalable, and easy t...
stable/mysql                        1.6.9           5.7.30      DEPRECATED - Fast, reliable, scalable, and easy...

查看包的相关信息

[root@k8s-m01 ~]# helm show chart stable/mysql

部署安装包

[root@k8s-m01 ~]# helm install db stable/mysql 
WARNING: This chart is deprecated
NAME: db
LAST DEPLOYED: Fri Dec  9 09:35:15 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
MySQL can be accessed via port 3306 on the following DNS name from within your cluster:
db-mysql.default.svc.cluster.local

To get your root password run:

    MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace default db-mysql -o jsonpath="{.data.mysql-root-password}" | base64 --decode; echo)

To connect to your database:

1. Run an Ubuntu pod that you can use as a client:

    kubectl run -i --tty ubuntu --image=ubuntu:16.04 --restart=Never -- bash -il

2. Install the mysql client:

    $ apt-get update && apt-get install mysql-client -y

3. Connect using the mysql cli, then provide your password:
    $ mysql -h db-mysql -p

To connect to your database directly from outside the K8s cluster:
    MYSQL_HOST=127.0.0.1
    MYSQL_PORT=3306

    # Execute the following command to route the connection:
    kubectl port-forward svc/db-mysql 3306

    mysql -h ${MYSQL_HOST} -P${MYSQL_PORT} -u root -p${MYSQL_ROOT_PASSWORD}

查看应用的状态

[root@k8s-m01 ~]# helm list
NAME    NAMESPACE   REVISION    UPDATED                                 STATUS      CHART       APP VERSION
db      default     1           2022-12-09 09:35:15.651775388 +0800 CST deployed    mysql-1.6.9 5.7.30   

[root@k8s-m01 ~]# kubectl get pods -A
NAMESPACE     NAME                                       READY   STATUS    RESTARTS   AGE
default       db-mysql-7f4fdddfd5-pg8wq                  0/1     Pending   0          2m17s
default       nginx-deployment-5d59d67564-snnwq          1/1     Running   0          19h

我们会发现部署的mysql处于pending状态,我们可以查看事件

[root@k8s-m01 ~]# kubectl describe pod   db-mysql-7f4fdddfd5-pg8wq 

Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  5m8s  default-scheduler  0/3 nodes are available: 3 pod has unbound immediate PersistentVolumeClaims.
  Warning  FailedScheduling  5m6s  default-scheduler  0/3 nodes are available: 3 pod has unbound immediate PersistentVolumeClaims.

# 没有pv可绑定,查看pvc
[root@k8s-m01 ~]#  kubectl get pvc
NAME       STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
db-mysql   Pending                                                     6m32s

创建pv

[root@k8s-m01 ~]# vim pv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0003
spec:
  capacity:
    storage: 8Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"

## 创建pv
[root@k8s-m01 ~]# kubectl apply -f pv.yaml 
persistentvolume/pv0003 created

查看绑定状态

[root@k8s-m01 ~]# kubectl get pv,pvc
NAME                      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM              STORAGECLASS   REASON   AGE
persistentvolume/pv0003   8Gi        RWO            Retain           Bound       default/db-mysql                           42m

NAME                             STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/db-mysql   Bound    pv0003   8Gi        RWO                           96m

查看Pod状态

[root@k8s-m01 ~]# kubectl get pods -A
NAMESPACE     NAME                                       READY   STATUS    RESTARTS   AGE
default       db-mysql-7f4fdddfd5-pg8wq                  1/1     Running   0          97m

根据helm给的方式进行验证

[root@k8s-m01 ~]# helm status db
NAME: db
LAST DEPLOYED: Fri Dec  9 09:35:15 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
MySQL can be accessed via port 3306 on the following DNS name from within your cluster:
db-mysql.default.svc.cluster.local

To get your root password run:

    MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace default db-mysql -o jsonpath="{.data.mysql-root-password}" | base64 --decode; echo)

To connect to your database:

1. Run an Ubuntu pod that you can use as a client:

    kubectl run -i --tty ubuntu --image=ubuntu:16.04 --restart=Never -- bash -il

2. Install the mysql client:

    $ apt-get update && apt-get install mysql-client -y

3. Connect using the mysql cli, then provide your password:
    $ mysql -h db-mysql -p

To connect to your database directly from outside the K8s cluster:
    MYSQL_HOST=127.0.0.1
    MYSQL_PORT=3306

    # Execute the following command to route the connection:
    kubectl port-forward svc/db-mysql 3306

    mysql -h ${MYSQL_HOST} -P${MYSQL_PORT} -u root -p${MYSQL_ROOT_PASSWORD}

## 也可以直接进入到部署的mysql容器里面进行验证
[root@k8s-m01 ~]# kubectl get pods -A
NAMESPACE     NAME                                       READY   STATUS    RESTARTS   AGE
default       db-mysql-7f4fdddfd5-pg8wq                  1/1     Running   0          113m

[root@k8s-m01 ~]# kubectl exec -it db-mysql-7f4fdddfd5-pg8wq -- bash

root@db-mysql-7f4fdddfd5-pg8wq:/# mysql -uroot -p4LdQlEqomf

2.构建一个Helm Chart

上面变示例了通过helm部署一个应用(MySQL)。我们也可以进行自行构建Chart进行部署。

1.Chart目录结构说明

mychart/
├── charts                          # 目录里存放这个 chart 依赖的所有子 chart。
├── Chart.yaml                      # 用于描述这个 Chart 的基本信息,包括名字、描述信息以及版本等
├── templates                       # 目录里面存放所有的 yaml 模板文件。
│   ├── deployment.yaml
│   ├── _helpers.tpl                # 放置模板助手的地方,可以在整个 chart 中重复使用
│   ├── hpa.yaml
│   ├── ingress.yaml
│   ├── NOTES.txt                   # 用于介绍 Chart 帮助信息,helm install 部署后展示给用户;例如:如何使用这个Chart,列出缺省的设置等。
│   ├── serviceaccount.yaml
│   ├── service.yaml
│   └── tests
│       └── test-connection.yaml
└── values.yaml                     # 用于存储 templates 目录中模板文件中用到的变量的值。 

2.构建Chart

1.首先通过create生成chart模板样式,进行修改即可,这里采用完全自定义,所以我们将用不到的yaml文件进行删除

[root@k8s-m01 ~]# helm create mychart
Creating mychart

[root@k8s-m01 ~]# tree -L 1 mychart/
mychart/
├── charts
├── Chart.yaml
├── templates
└── values.yaml

2 directories, 2 files

2.修改Chart.yaml文件,定义版本和名字等

[root@k8s-m01 ~]# cd mychart/
[root@k8s-m01 mychart]# vim Chart.yaml 

apiVersion: v2
name: mychart
description: A Helm chart for Kubernetes
type: application
version: 0.1.0
appVersion: "1.16.0"

这里部署通过部署一个web站点nginx进行示例,首先通过kubectl create 生产一个deployment 模板进行修改,下面yaml文件中将 副本数(replicas)、name、image定义为了变量进行传递

[root@k8s-m01 mychart]# kubectl create deployment deployment --image=nginx:1.12 --dry-run -o yaml > templates/deployment.yaml
W1209 15:59:23.032329   67118 helpers.go:557] --dry-run is deprecated and can be replaced with --dry-run=client.

[root@k8s-m01 mychart]# vim templates/deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: deployment
  name: {{ .Values.Name }}
spec:
  replicas: {{ .Values.replicas }}
  selector:
    matchLabels:
      app: deployment
  template:
    metadata:
      labels:
        app: deployment
    spec:
      containers:
      - image: {{ .Values.image }}
        name: nginx

编写变量文件

[root@k8s-m01 mychart]# vim values.yaml 

Name: mychart-deploy-demo
replicas: 3
image: nginx:1.18.0

其实上面这两个文件的内容就已经算是一个可以安装的chart包了。

进行安装

[root@k8s-m01 ~]# helm install web mychart/
NAME: web
LAST DEPLOYED: Fri Dec  9 16:28:00 2022
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=mychart,app.kubernetes.io/instance=web" -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-m01 ~]# helm list
NAME    NAMESPACE   REVISION    UPDATED                                 STATUS      CHART           APP VERSION
db      default     1           2022-12-09 09:35:15.651775388 +0800 CST deployed    mysql-1.6.9     5.7.30       
web     default     1           2022-12-09 16:28:00.504944368 +0800 CST deployed    mychart-0.1.0   1.16.0     

[root@k8s-m01 ~]# kubectl get pods -o wide 
NAME                                  READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES
db-mysql-7f4fdddfd5-pg8wq             1/1     Running   0          6h57m   10.244.58.197   k8s-node02   <none>           <none>
mychart-deploy-demo-8488cd749-78ndv   1/1     Running   0          4m15s   10.244.58.199   k8s-node02   <none>           <none>
mychart-deploy-demo-8488cd749-jchzd   1/1     Running   0          4m15s   10.244.85.198   k8s-node01   <none>           <none>
mychart-deploy-demo-8488cd749-x9tql   1/1     Running   0          4m15s   10.244.85.199   k8s-node01   <none>           <none>

3.升级

1.首先进行访问测试,可以看到访问结果nginx版本为1.18.0

[root@k8s-m01 ~]# curl -I 10.244.58.199 
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Fri, 09 Dec 2022 08:35:03 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 21 Apr 2020 14:09:01 GMT
Connection: keep-alive
ETag: "5e9efe7d-264"
Accept-Ranges: bytes

2.发布新版本的chart时,或者当要更改发布的配置时,可以使用helm upgrade命令,比如这里升级镜像为1.19.0

[root@k8s-m01 ~]# helm upgrade --set image=nginx:1.19.0 web mychart
Release "web" has been upgraded. Happy Helming!
NAME: web
LAST DEPLOYED: Fri Dec  9 16:37:15 2022
NAMESPACE: default
STATUS: deployed
REVISION: 2
NOTES:

[root@k8s-m01 ~]# kubectl get pods -o wide
NAME                                   READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES
db-mysql-7f4fdddfd5-pg8wq              1/1     Running   0          7h5m    10.244.58.197   k8s-node02   <none>           <none>
mychart-deploy-demo-5459db777d-97g7r   1/1     Running   0          2m33s   10.244.85.200   k8s-node01   <none>           <none>
mychart-deploy-demo-5459db777d-df29f   1/1     Running   0          80s     10.244.85.201   k8s-node01   <none>           <none>
mychart-deploy-demo-5459db777d-nt7gl   1/1     Running   0          3m19s   10.244.58.200   k8s-node02   <none>           <none>

# 访问测试
[root@k8s-m01 ~]# curl -I 10.244.85.200
HTTP/1.1 200 OK
Server: nginx/1.19.0
Date: Fri, 09 Dec 2022 08:41:23 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 26 May 2020 15:00:20 GMT
Connection: keep-alive
ETag: "5ecd2f04-264"
Accept-Ranges: bytes

可以看到已经升级镜像版本为1.19.0版本,如果有大量的改动,那么可以修改values文件,然后通过如下命令进行更新

[root@k8s-m01 ~]# helm upgrade -f values.yaml web mychart

4.回滚

如果在发布后没有达到预期的效果,则可以使用helm rollback回滚到之前的版本。通过helm history命令可以查看发布版本记录

[root@k8s-m01 ~]# helm history web
REVISION    UPDATED                     STATUS      CHART           APP VERSION DESCRIPTION     
1           Fri Dec  9 16:28:00 2022    superseded  mychart-0.1.0   1.16.0      Install complete
2           Fri Dec  9 16:37:15 2022    deployed    mychart-0.1.0   1.16.0      Upgrade complete

比如这里我们要回滚到第一个版本:

[root@k8s-m01 ~]# helm rollback web 1
Rollback was a success! Happy Helming!

在通过helm history命令进行查看,可以看到后面的 DESCRIPTION还有详细版本说明。

[root@k8s-m01 ~]# helm history web
REVISION    UPDATED                     STATUS      CHART           APP VERSION DESCRIPTION     
1           Fri Dec  9 16:28:00 2022    superseded  mychart-0.1.0   1.16.0      Install complete
2           Fri Dec  9 16:37:15 2022    superseded  mychart-0.1.0   1.16.0      Upgrade complete
3           Fri Dec  9 16:44:11 2022    deployed    mychart-0.1.0   1.16.0      Rollback to 1   

还可以通过helm get manifest命令查看模板被渲染过后的资源文件

[root@k8s-m01 ~]# helm get manifest web
---
# Source: mychart/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: web-mychart
  labels:
    helm.sh/chart: mychart-0.1.0
    app.kubernetes.io/name: mychart
    app.kubernetes.io/instance: web
    app.kubernetes.io/version: "1.16.0"
    app.kubernetes.io/managed-by: Helm
---
# Source: mychart/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: web-mychart
  labels:
    helm.sh/chart: mychart-0.1.0
    app.kubernetes.io/name: mychart
    app.kubernetes.io/instance: web
    app.kubernetes.io/version: "1.16.0"
    app.kubernetes.io/managed-by: Helm
spec:
  type: ClusterIP
  ports:
    - port: 80
      targetPort: http
      protocol: TCP
      name: http
  selector:
    app.kubernetes.io/name: mychart
    app.kubernetes.io/instance: web
---
# Source: mychart/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: deployment
  name: mychart-deploy-demo
spec:
  replicas: 3
  selector:
    matchLabels:
      app: deployment
  template:
    metadata:
      labels:
        app: deployment
    spec:
      containers:
      - image: nginx:1.18.0
        name: nginx

5.打包

如果我们需要将构建的Chart打包保存,并推送到charts仓库共享别人使用,则可以通过helm package命令进行打包

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

四.安装前自定义chart配置选项

我们发现上面的mysql示例要配置pv才能运行成功,所以并不是所有的chart都能按照默认配置运行成功,可能会需要一些环境依赖,例如PV。

所以我们需要自定义chart配置选项,按照过程中有两种方法可以传递配置数据:

  • --values(或-f):指定带有覆盖的YAML文件。这可以多次指定,最右边的文件优先
  • --set:在命令行上指定替代。如果两者都用,--set优先级高

1.配置文件定义配置项

--values使用,先将修改的变量写到一个文件中

通过上面查看默认的变量中,我们进行自定义MySQL root用户密码,并安装完成自动创建一个应用用户及设置密码,并创建一个应用数据库helm;同事设定了不启用persistence

# 查看Chart默认value
[root@k8s-m01 ~]# helm show values stable/mysql

# 将配置重定向到一个db_config.yaml文件中
[root@k8s-m01 ~]# helm show values stable/mysql > db_config.yaml

# 修改db_config.yaml文件,修改成我们预设值的需求
[root@k8s-m01 ~]# vim db_config.yaml
mysqlRootPassword: testing
mysqlUser: k8s
mysqlPassword: k8s123
mysqlDatabase: k8s
persistence:
  enabled: False

# 创建pod并指定文件
[root@k8s-m01 ~]# helm install db2 -f db_config.yaml stable/mysql

[root@k8s-m01 ~]# kubectl get pods -A
NAMESPACE     NAME                                       READY   STATUS    RESTARTS   AGE
default       db2-mysql-8697b7fb94-ff95r                 1/1     Running   0          4m29s

以上将创建具有名称的默认MySQL用户k8s,并授予此用户访问新创建的k8s数据库的权限,但将接受该图标的所有其余默认值

2.命令行替代变量

[root@k8s-m01 ~]# helm install db3 --set mysqlRootPassword=te123,mysqlUser=helm,mysqlPassword=helm123,mysqlDatabase=helm,persistence.enabled=false mysql-test stable/mysql

更多values yaml与set使用对应如下

file


山林不向四季起誓 荣枯随缘