Helm应用包管理器
一.Helm基本概述
1.为什么需要Helm
K8S上的应用对象,都是由特定的资源描述组成的,包括deployment、service等。都保存在各自的文件中或者集中写到一个配置文件里。然后使用kubectl apply -f命令进行部署。
如果应用只由一个或几个这样的服务组成,上面部署方式足够了。
而对于一个复杂的应用,会有很多类似上面的资源描述文件,例如微服务架构应用,组成应用的服务可能多达十个,几十个。如果有更新或回滚应用的需求,可能要修改和维护所涉及的大量资源文件,而这种组织和管理应用的方式就显得力不从心了。
且由于缺少对发布过的应用版本管理和控制,使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
的删除
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仓库
- 微软仓库(http://mirror.azure.cn/kubernetes/charts/)这个仓库强烈推荐,基本上官网有的chart这里都有。
- 阿里云仓库(https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts)
- 官方仓库(https://hub.kubeapps.com/charts/incubator) 官方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使用对应如下