1.1 为何需要Helm
Kubernetes能够很好地组织和编排容器,但它缺少⼀个更高层次的应用打包工具,而Helm就是来干这件事的。
先来看个例子。
比如对于⼀个MySQL服务,Kubernetes需要部署下面这些对象:
(1)Service,让外界能够访问到MySQL。
(2)Secret,定义MySQL的密码。
(3)PersistentVolumeClaim,为MySQL申请持久化存储空间
(4)Deployment,部署MySQL Pod,并使用上面的这些支持对
象
我们可以将上面这些配置保存到对象各自的文件中,或者集中写进⼀
个配置文件,然后通过kubectl apply -f部署。
如果应用只由⼀个或几个这样的服务组成,上⾯的部署方式完全⾜足够了。但是,如果我们开发的是微服务架构的应用,组成应用的服务可能多达十个甚至几十上百个,这种组织和管理应用的方式就不好使了。Helm帮助Kubernetes成为微服务架构应用理想的部署平台。
1.2 Helm的架构
Helm包含两个组件:Helm客户端和Tiller服务器
Helm是包管理工具,这里的包就是指的chart。Helm能够:
- 从零创建新chart。
- 与存储chart的仓库交互,拉取、保存和更新chart。
- 在Kubernetes集群中安装和卸载release。
- 更新、回滚和测试release。
两个重要概念:
(1)Chart是创建一个应用的信息集合,包括各种K8S对象的配置模板、参数定义等,可以理解为是apt、yum中的软件安装包;
(2)Release是Chart的运行实例,代表了一个正在运行的应用。
1.3 Helm客户端的安装
通常,我们将Helm客户端安装在能够执行kubectl命令的节点上,只需要下面⼀条命令:
curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get | bash
helm有很多子命令和参数,为了提高使用命令行的效率,通常建议安装helm的bash命令补全脚本,方法如下:
cd ~
helm completion bash > .helmrc
echo "source .helmrc" >> .bashrc
Tiller服务器安装非常简单,只需要执行helm init即可。
[root@k8s-master ~]# helm init --upgrade --tiller-image registry.cn-beijing.aliyuncs.com/google_registry/tiller:v2.16.9
Creating /root/.helm/repository/repositories.yaml
Adding stable repo with URL: https://charts.helm.sh/stable
Adding local repo with URL: http://127.0.0.1:8879/charts
$HELM_HOME has been configured at /root/.helm.Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
To prevent this, run `helm init` with the --tiller-tls-verify flag.
For more information on securing your installation see: https://v2.helm.sh/docs/securing_installation/
看到上面的提示信息,代表Helm服务端已经安装成功。
这时,我们可以看看Tiller的Service、Deployment和Pod有没有启动起来:
[root@k8s-master ~]# kubectl get --namespace=kube-system svc tiller-deploy
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
tiller-deploy ClusterIP 10.1.10.122 <none> 44134/TCP 2m53s
[root@k8s-master ~]# kubectl get --namespace=kube-system deployment tiller-deploy
NAME READY UP-TO-DATE AVAILABLE AGE
tiller-deploy 1/1 1 1 3m25s
Pod
[root@k8s-master ~]# kubectl get pods --namespace=kube-system
NAME READY STATUS RESTARTS AGE
tiller-deploy-7b44c4599-vrhxg 1/1 Running 0 6m18s
[root@k8s-master ~]# helm version
Client: &version.Version{SemVer:"v2.17.0", GitCommit:"a690bad98af45b015bd3da1a41f6218b1a451dbe", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.16.9", GitCommit:"8ad7037828e5a0fca1009dabe290130da6368e39", GitTreeState:"dirty"}
1.4 使用Helm
Helm安装好后,我们可以通过以下helm search来查看当前可安装的Chart:
[root@k8s-master ~]# helm search
Kubernetes Helm 配置国内镜像源
1、删除默认的源
helm repo remove stable
2、增加新的国内镜像源
helm repo add stable http://mirror.azure.cn/kubernetes/charts/
3、查看helm源添加情况
helm repo list
4、搜索测试
helm search mysql
为了能够执行install安装,我们还需要事先为Tiller服务器添加集群权限,防止因Tiller服务器的权限不足而无法install。
# 创建serviceaccount资源tiller,属于kube-system命名空间
kubectl create serviceaccount -n kube-system tiller
# 创建 clusterrolebinding资源tiller-cluster-rule,集群角色为cluster-admin,用户为kube-system:tiller
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
# 修改deployment tiller-deploy的配置,增加字段spec.template.spec.serviceAccount
kubectl patch deploy -n kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
这里我们通过以下命令来通过官方仓库安装mysql
[root@k8s-master ~]# helm install stable/mysql
WARNING: This chart is deprecated
NAME: muddled-pug
LAST DEPLOYED: Fri Feb 2 17:57:51 2024
NAMESPACE: default
STATUS: DEPLOYEDRESOURCES:
==> v1/ConfigMap
NAME DATA AGE
muddled-pug-mysql-test 1 0s==> v1/Deployment
NAME READY UP-TO-DATE AVAILABLE AGE
muddled-pug-mysql 0/1 0 0 0s==> v1/PersistentVolumeClaim
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
muddled-pug-mysql Pending 0s==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
muddled-pug-mysql-6645d97f44-2wzb9 0/1 Pending 0 0s==> v1/Secret
NAME TYPE DATA AGE
muddled-pug-mysql Opaque 2 0s==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
muddled-pug-mysql ClusterIP 10.1.107.152 <none> 3306/TCP 0sNOTES:
MySQL can be accessed via port 3306 on the following DNS name from within your cluster:
muddled-pug-mysql.default.svc.cluster.localTo get your root password run:MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace default muddled-pug-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 -il2. Install the mysql client:$ apt-get update && apt-get install mysql-client -y3. Connect using the mysql cli, then provide your password:$ mysql -h muddled-pug-mysql -pTo connect to your database directly from outside the K8s cluster:MYSQL_HOST=127.0.0.1MYSQL_PORT=3306# Execute the following command to route the connection:kubectl port-forward svc/muddled-pug-mysql 3306mysql -h ${MYSQL_HOST} -P${MYSQL_PORT} -u root -p${MYSQL_ROOT_PASSWORD}[root@k8s-master ~]# kubectl get service muddled-pug-mysql
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
muddled-pug-mysql ClusterIP 10.1.107.152 <none> 3306/TCP 6m6s
输出分为三部分:
- chart本次部署的描述信息
- NOTES部分显示的是release的使用方法
- RESOURCES当前release包含的资源
[root@k8s-master ~]# kubectl get pvc muddled-pug-mysql
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
muddled-pug-mysql Pending
[root@k8s-master ~]# helm delete muddled-pug
release "muddled-pug" deleted
由于还没有位mysql准备PV(PersistentVolume),导致当前release不可用,处于Pending状态。接下来我们就要先解决PV的问题,让release能够正常运行起来。
1.5 chart详解
chart是Helm的应用打包格式。chart由⼀系列文件组成,这些文件描述了Kubernetes部署应用时所需要的资源,比如Service、Deployment、PersistentVolumeClaim、Secret、ConfigMap等。
单个的chart可以非常简单,只用于部署⼀个服务,比如Memcached。chart也可以很复杂,部署整个应用,比如包含HTTPServers、Database、消息中间件、Cache等。
chart将这些文件放置在预定义的目录结构中,通常整个chart被打成tar包,而且标注上版本信息,便于Helm部署。
下面我们将详细讨论chart的目录结构以及包含的各类文件。
1.5.1 chart目录结构
以前面MySQLchart为例。⼀旦安装了某个chart,我们就可以在〜/.helm/cache/archive中找到chart的tar包
[root@k8s-master ~]# ls ~/.helm/cache/archive
mysql-0.3.5.tgz mysql-1.6.9.tgz
解压后,MySQL chart目录结构如下:
[root@k8s-master archive]# tree mysql
mysql
├── Chart.yaml
├── README.md
├── templates
│ ├── configurationFiles-configmap.yaml
│ ├── deployment.yaml
│ ├── _helpers.tpl
│ ├── initializationFiles-configmap.yaml
│ ├── NOTES.txt
│ ├── pvc.yaml
│ ├── secrets.yaml
│ ├── serviceaccount.yaml
│ ├── servicemonitor.yaml
│ ├── svc.yaml
│ └── tests
│ ├── test-configmap.yaml
│ └── test.yaml
└── values.yaml
(1)Chart.yaml
YAML文件,描述chart的概要信息
[root@k8s-master mysql]# cat Chart.yaml
apiVersion: v1
appVersion: 5.7.30
deprecated: true
description: DEPRECATED - Fast, reliable, scalable, and easy to use open-source relationaldatabase system.
home: https://www.mysql.com/
icon: https://www.mysql.com/common/logos/logo-mysql-170x115.png
keywords:
- mysql
- database
- sql
name: mysql
sources:
- https://github.com/kubernetes/charts
- https://github.com/docker-library/mysql
version: 1.6.9
name和version是必填项,其他都是可选项。
(2)README.md
Markdown格式的README文件,相当于chart的使用文档,此文件为可选。
(3)LICENSE
文本文件,描述chart的许可信息,此文件为可选。
(4)requirements.yaml
chart可能依赖其他的chart,这些依赖关系可通过 requirements.yaml指定。
mysql这个没有
(5)values.yaml
chart支持在安装时根据参数进行定制化配置,而values.yaml则提供了这些配置参数的默认值
[root@k8s-master mysql]# cat Chart.yaml
apiVersion: v1
appVersion: 5.7.30
deprecated: true
description: DEPRECATED - Fast, reliable, scalable, and easy to use open-source relationaldatabase system.
home: https://www.mysql.com/
icon: https://www.mysql.com/common/logos/logo-mysql-170x115.png
keywords:
- mysql
- database
- sql
name: mysql
sources:
- https://github.com/kubernetes/charts
- https://github.com/docker-library/mysql
version: 1.6.9
[root@k8s-master mysql]# cat values.yaml
## mysql image version
## ref: https://hub.docker.com/r/library/mysql/tags/
##
image: "mysql"
imageTag: "5.7.30"strategy:type: Recreatebusybox:
... 很长
(6)templates目录
各类Kubernetes资源的配置模板都放置在这里。Helm会将values.yaml中的参数值注⼊模板中,生成标准的YAML配置文件。
模板是chart最重要的部分,也是Helm最强大的地方。模板增加了应用部署的灵活性,能够适用不同的环境。
1.6 为MySQL Chart准备PV
vi mysql-pv.yml
apiVersion: v1
kind: PersistentVolume
metadata:name: mysql-pv
spec:capacity:storage: 8GiaccessModes:- ReadWriteOncepersistentVolumeReclaimPolicy: Retain#storageClassName: nfsnfs:path: /edc/k8s/nfsdata/mysql-pvserver: k8s-master
[root@k8s-master ~]# vi mysql-pv.yml
[root@k8s-master ~]# kubectl apply -f mysql-pv.yml
persistentvolume/mysql-pv created
[root@k8s-master ~]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
mysql-pv 8Gi RWO Retain Available
helm有两种方式传递配置参数实现定制化安装,一种是指定自定义的values文件,另一种是通过–set直接传入参数值。这里我们演示通过第二种,这里我们重新安装mysql chart:
helm install stable/mysql --set mysqlRootPassword=abc123456 -n my
mysqlRootPassword=设置密码 -n设置release名称。
通过helm list和helm status可以查看chart的最新状态。
[root@k8s-master ~]# helm list
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
my 1 Sun Feb 4 10:24:03 2024 DEPLOYED mysql-1.6.9 5.7.30 default
[root@k8s-master ~]# helm status my
LAST DEPLOYED: Sun Feb 4 10:24:03 2024
NAMESPACE: default
STATUS: DEPLOYEDRESOURCES:
==> v1/ConfigMap
NAME DATA AGE
my-mysql-test 1 74s==> v1/Deployment
NAME READY UP-TO-DATE AVAILABLE AGE
my-mysql 0/1 1 0 74s==> v1/PersistentVolumeClaim
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
my-mysql Bound mysql-pv 8Gi RWO 74s==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
my-mysql-75d8875fb-r785m 0/1 Init:0/1 0 74s
1.7 升级和回滚release
release发布后可以执行helm upgrade对其进行升级,通过–values或–set应用新的配置。比如将当前的MySQL版本升级到5.7.31。
[root@k8s-master ~]# helm upgrade --set imageTag=5.7.31 my stable/mysql
WARNING: This chart is deprecated
Release "my" has been upgraded.
LAST DEPLOYED: Sun Feb 4 10:46:36 2024
NAMESPACE: default
STATUS: DEPLOYEDRESOURCES:
通过查看可以看到image已经换为了5.7.26:
[root@k8s-master ~]# kubectl get deployment my-mysql -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
my-mysql 0/1 1 0 19m my-mysql mysql:5.7.31 app=my-mysql,release=my
helm history可以查看release所有的版本
[root@k8s-master ~]# helm history my
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Sun Feb 4 10:24:03 2024 SUPERSEDED mysql-1.6.9 5.7.30 Install complete
2 Sun Feb 4 10:46:36 2024 DEPLOYED mysql-1.6.9 5.7.30 Upgrade complete
通过helm rollback可以回滚到任何版本
[root@k8s-master ~]# helm rollback my 1
Rollback was a success.
1.8自定义Chart实践
首先,通过以下命令创建一个chart命名为testchart:
helm create mychart
修改一下values.yaml
# Default values for mychart.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.replicaCount: 1image:repository: edisonsaonian/k8s-demotag: latestpullPolicy: IfNotPresentservice:type: NodePortport: 80nodePort: 31001ingress:enabled: falseresources:limits:cpu: 1memory: 228Mirequests:cpu: 100mmemory: 128Mi
这里我们选择NodePort的方式让外部可以通过31000端口访问到API,也设置了资源限制。
此外,我们再修改一下Templates目录下的deployment和service两个模板文件:
(1)deployment模板:重点关注两个探针的配置
# 探针 检测项目是否存活livenessProbe:httpGet:path: /api/valuesport: http# 探针 检测项目是否启动成功readinessProbe:httpGet:path: /api/valuesport: httpinitialDelaySeconds: 30periodSeconds: 60resources:
(2)service模板:重点关注NodePort的配置
spec:type: {{ .Values.service.type }}ports:- port: {{ .Values.service.port }}targetPort: http# 添加nodePortnodePort: {{ .Values.service.nodePort }}
调试chart
只要是程序就会有bug,chart也不例外。Helm提供了debug的工具:helm lint和helm install --dry-run --debug。
[root@k8s-master ~]# helm lint mychart
==> Linting mychart
[INFO] Chart.yaml: icon is recommended1 chart(s) linted, no failures
[root@k8s-master ~]# helm install --dry-run mychart--debug
[debug] Created tunnel using local port: '38460'[debug] SERVER: "127.0.0.1:38460"[debug] Original chart version: ""
[debug] CHART PATH: /root/mychart
helm lint会检测chart的语法,报告错误以及给出建议。
helm install --dry-run --debug会模拟安装chart,并输出每个模板生成的YAML内容。
安装chart
当我们准备就绪,就可以安装chart了。Helm支持四种安装方法:
(1)安装仓库中的chart,例如helm install stable/nginx。
(2)通过tar包安装,例如helm install ./nginx-1.2.3.tgz。
(3)通过chart本地目录安装,例如helm install ./nginx。
(4)通过url安装,例如helm install https://example.com/charts/nginx-1.2.3.tgz
这里我们使用本地目录安装:
[root@k8s-master ~]# helm install mychart
NAME: flabby-tiger
LAST DEPLOYED: Sun Feb 4 13:39:12 2024
NAMESPACE: default
STATUS: DEPLOYEDRESOURCES:
==> v1/Deployment
NAME READY UP-TO-DATE AVAILABLE AGE
flabby-tiger-mychart 0/1 1 0 0s==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
flabby-tiger-mychart-79f477ddd8-99zq7 0/1 ContainerCreating 0 0s==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
flabby-tiger-mychart NodePort 10.1.8.163 <none> 31001:30647/TCP 0s==> v1/ServiceAccount
NAME SECRETS AGE
flabby-tiger-mychart 1 0sNOTES:
1. Get the application URL by running these commands:export NODE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services flabby-tiger-mychart)export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath="{.items[0].status.addresses[0].address}")echo http://$NODE_IP:$NODE_PORT
安装后再次验证
http://192.168.200.128:32000/api/values["edc-values1","edc-values2","edc-values3","edc-values4","edc-values5","edc-values6","edc-values7","edc-values8","edc-values9","edc-values10"]