Helm
Helm 是 Kubernetes 的软件包管理工具。本文需要读者对 Docker、Kubernetes 等相关知识有一定的了解。 本文将介绍 Helm 中的相关概念和基本工作原理,并通过一些简单的示例来演示如何使用Helm来安装、升级、回滚一个 Kubernetes 应用。
1. helm的理解
1.1 Helm 是什么?
Helm 是 Kubernetes 的包管理器。包管理器类似于我们在 Ubuntu 中使用的apt、Centos中使用的 yum 或者Python中的 pip 一样,能快速查找、下载和安装软件包。Helm 由客户端组件 helm 和服务端组件 Tiller 组成,能够将一组K8S资源打包统一管理,是查找、共享和使用为Kubernetes构建的软件的最佳方式。
Helm类似于yum安装指令,统一对安装服务进行管理,使得用户不需要关系服务之间的依赖关系。
1.2 Helm 解决了什么痛点?
在 Kubernetes中部署一个可以使用的应用,需要涉及到很多的 Kubernetes 资源的共同协作。比如你安装一个 WordPress 博客,用到了一些 Kubernetes (下面全部简称k8s)的一些资源对象,包括 Deployment 用于部署应用、Service 提供服务发现、Secret 配置 WordPress 的用户名和密码,可能还需要 pv 和 pvc 来提供持久化服务。并且 WordPress 数据是存储在mariadb里面的,所以需要 mariadb 启动就绪后才能启动 WordPress。这些 k8s 资源过于分散,不方便进行管理,直接通过 kubectl 来管理一个应用,你会发现这十分蛋疼。
所以总结以上,我们在 k8s 中部署一个应用,通常面临以下几个问题:
- 如何统一管理、配置和更新这些分散的 k8s 的应用资源文件
- 如何分发和复用一套应用模板
如何将应用的一系列资源当做一个软件包管理
K8s有非常多资源对象,部署一个服务时候,往往需要操作多个服务资源对象,且资源对象相互依赖,非常不好管理。Helm帮助管理资源对象。
1.3 Helm 相关组件及概念
Helm 包含两个组件,分别是 helm 客户端
和 Tiller 服务器
:
- helm 是一个命令行工具,用于本地开发及管理chart,chart仓库管理等
- Tiller 是 Helm 的服务端。Tiller 负责接收 Helm 的请求,与 k8s 的 apiserver 交互,根据chart 来生成一个 release 并管理 release
- chart
Helm的打包格式叫做chart
,所谓chart就是一系列文件, 它描述了一组相关的 k8s 集群资源 - release 使用 helm install 命令在 Kubernetes 集群中部署的 Chart 称为 Release
- Repoistory Helm chart 的仓库,Helm 客户端通过 HTTP 协议来访问存储库中 chart 的索引文件和压缩包
1.4 Helm 原理
下面两张图描述了 Helm 的几个关键组件 Helm(客户端)、Tiller(服务器)、Repository(Chart 软件仓库)、Chart(软件包)之间的关系以及它们之间如何通信,如下图(helm通信组件)
1.5 helm架构
创建release
- helm 客户端从指定的目录或本地tar文件或远程repo仓库解析出chart的结构信息
- helm 客户端指定的 chart 结构和 values 信息通过 gRPC 传递给 Tiller
- Tiller 服务端根据 chart 和 values 生成一个 release
- Tiller 将install release请求直接传递给 kube-apiserver
删除release
- helm 客户端从指定的目录或本地tar文件或远程repo仓库解析出chart的结构信息
- helm 客户端指定的 chart 结构和 values 信息通过 gRPC 传递给 Tiller
- Tiller 服务端根据 chart 和 values 生成一个 release
- Tiller 将delete release请求直接传递给 kube-apiserver
更新release
- helm 客户端将需要更新的 chart 的 release 名称 chart 结构和 value 信息传给 Tiller
- Tiller 将收到的信息生成新的 release,并同时更新这个 release 的 history
- Tiller 将新的 release 传递给 kube-apiserver 进行更新
1.6 chart 的基本结构
k8s编程非常麻烦,资源对象非常多,因此helm就是一种k8s项目开发的方式,且k8s项目开发有固定项目结构。
Helm的打包格式叫做chart,所谓chart就是一系列文件, 它描述了一组相关的 k8s 集群资源。Chart中的文件安装特定的目录结构组织, 最简单的chart 目录如下所示:
- charts 目录存放依赖的chart
- Chart.yaml 包含Chart的基本信息,包括chart版本,名称等
- templates 目录下存放应用一系列 k8s 资源的 yaml 模板
- _helpers.tpl 此文件中定义一些可重用的模板片断,此文件中的定义在任何资源定义模板中可用
- NOTES.txt 介绍chart 部署后的帮助信息,如何使用chart等
- values.yaml 包含了必要的值定义(默认值), 用于存储 templates 目录中模板文件中用到变量的值
2. helm安装
Helm 提供了几种安装方式,本文提供两种安装方式,想要查看更多安装方式,请阅读 Helm 的官方文档:
下载地址:https://github.com/helm/helm/releases
# ======= 第一种安装方式: 手动方式安装 ========
# 下载 Helm 二进制文件
wget https://storage.googleapis.com/kubernetes-helm/helm-v2.9.1-linuxamd64.tar.gz
# 解压缩
tar -zxvf helm-v2.9.1-linux-amd64.tar.gz
# 复制 helm 二进制 到bin目录下,但是要确保/usr/local/bin/在环境变量里配置过
cp linux-amd64/helm /usr/local/bin/
# ======= 第二种安装方式: 使用官方二进制脚本进行安装 ========
curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get > get_helm.sh
chmod 700 get_helm.sh
./get_helm.sh
# 你还可以通过 Helm 的 github 项目下找到你想要的 Helm 版本的二进制,然后通过手动安装方式一样安装即可
看到Client端好了,Server端还没好
3. tiller安装
helm 由客户端helm和服务端tiller组成,而helm3.0之后它去掉了tiller,而直接与k8s通讯,可以说在部署上更简单了,而今天我们主要还是部署2.x版本的helm.
安装好 helm 客户端后,就可以通过以下命令将 Tiller 安装在 kubernetes 集群中:
首先tiller作为pod运行,需要一个集群角色的用户:
apiVersion: v1
kind: ServiceAccount
metadata:
name: tiller
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: tiller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: tiller
namespace: kube-system
初始化tiller,自动安装:
# 构建rbac
kubectl create -f rbac-config.yaml
# 初始化tiller
helm init --service-account tiller --skip-refresh
# 查看tiller的pod信息
kubectl get pods -n kube-system | grep tiller
看到运行了一个tiller的pod,但是处于镜像下载失败状态
查看详情:
看到下载地址是国外的,可以从阿里云下载对应的版本
# Pulling image "gcr.io/kubernetes-helm/tiller:v2.15.2 发现下载镜像tiller:v2.15失败
# 镜像从阿里云平台下载,然后命名为使用的默认的镜像:gcr.io/kuberneteshelm/tiller:v2.15.2
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.15.2
# 打包镜像
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.15.2 gcr.io/kubernetes-helm/tiller:v2.15.2
# 然后把镜像上传到其他2个node节点即可,tiller安装将会优先使用本地镜像
将从阿里云下载的换个名字打包,并上传到其他所有node节点
等待一会儿后发现启动成功
到现在为止,client和server端都安装成功。
# 查询helm是否安装成功 helm version # 其他的安装方式: 可以指定阿里云镜像 helm init --upgrade -i registry.cnhangzhou.aliyuncs.com/google_containers/tiller:v2.15.2 --stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
4. Helm工程开发
4.1 创建Chart.yaml
指定工程名称 和 版本。
# 创建文件夹
mkdir hello-helm
cd hello-helm
# 创建自描述文件 Chart.yaml , 这个文件必须有 name 和 version 定义
cat << 'EOF' > ./Chart.yaml
name: hello-world
version: 1.0.0
EOF
4.2 创建templates
创建各种K8S资源文件。
# 创建模板文件, 用于生成 Kubernetes 资源清单(manifests)
mkdir ./templates
创建templates目录(固定写法,必须叫这个)
cat << 'EOF' > ./templates/deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: hello-world
spec:
replicas: 1
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: hello-world
image: hub.kaikeba.com/java12/myapp:v1
ports:
- containerPort: 80
protocol: TCP
EOF
创建deployment.yaml
cat << EOF > ./templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: hello-world
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
app: hello-world
EOF
创建service.yaml
4.3 安装
# 使用命令 helm install RELATIVE_PATH_TO_CHART 创建一次Release
# 安装完毕即可在外网进行访问
helm install .
安装:
测试访问:
外网也是可以的
4.4 helm常用指令
# 列出已经部署的 Release
helm ls
# 查询一个特定的 Release 的状态
helm status RELEASE_NAME
# 移除所有与这个 Release 相关的 Kubernetes 资源
helm delete RELEASE_NAME
# helm rollback RELEASE_NAME REVISION_NUMBER
helm rollback RELEASE_NAME 1
# 使用 helm delete --purge RELEASE_NAME 移除所有与指定 Release 相关的 Kubernetes 资源和所有这个 Release 的记录
helm delete --purge RELEASE_NAME
helm ls --deleted
helm delete 的删除指令删除的不干净,一般用
helm delete --purge
helm ls –deleted 如果没有记录,说明已经删除掉了
删除:
4.5 创建values.yaml
类似于configmap。
# 配置体现在配置文件 values.yaml
cat << 'EOF' > ./values.yaml
image:
repository: hub.kaikeba.com/java12/myapp
tag: 'v1'
EOF
目前values.yaml放的是仓库地址和版本信息
在模板中引入上面的配置,在模板文件中可以通过 .VAlues对象
访问到:
# 这个文件中定义的值,在模板文件中可以通过 .VAlues对象访问到
cat << 'EOF' > ./templates/deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: hello-world
spec:
replicas: 1
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: hello-world
image: {
{
.Values.image.repository }}:{
{
.Values.image.tag }}
ports:
- containerPort: 8080
rotocol: TCP
EOF
4.6 动态更新配置文件
现在如果我们想要发布新版本,直接修改values.yaml
# 修改配置文件更新
helm upgrade RELEASE_NAME .
改成v2,然后执行更新命令
等一会儿
变v2了
在 values.yaml 中的值可以被部署 release 时用到的参数 --values YAML_FILE_PATH 或 – set key1=value1, key2=value2 覆盖掉:
# 在 values.yaml 中的值可以被部署 release 时用到的参数 --values YAML_FILE_PATH 或 -- set key1=value1, key2=value2 覆盖掉
helm install --set image.tag='v3' .
helm upgrade RELEASE_NAME --set image.tag='v3' .
# 升级版本
helm upgrade -f values.yaml test .
还可以通过更简洁的方式:
5. Debug
使用模板动态生成K8s资源清单,非常需要能提前预览生成的结果。
使用–dry-run --debug 选项来打印出生成的清单文件内容,而不执行部署
helm install . --dry-run --debug --set image.tag=latest