Kubernetes-helm详细说明

Helm基本介绍

  • 微服务和容器化给复杂应用部署与管理带来了极大的挑战。 Helm 是目前 Kubernetes 服务编排领域的唯一开源子项目,做为 Kubernetes 应用的一个包管理工具,可理解为 Kubernetesapt-get / yum ,由 Deis 公司发起,该公司已经被微软收购。 Helm 通过软件打包的形式,支持发布的版本管理和控制,很大程度上简化了 Kubernetes 应用部署和管理的复杂性。
  • 随着业务容器化与向微服务架构转变,通过分解巨大的单体应用为多个服务的方式,分解了单体应用的复杂性,使每个微服务都可以独立部署和扩展,实现了敏捷开发和快速迭代和部署。但任何事情都有两面性,虽然微服务给我们带来了很多便利,但由于应用被拆分成多个组件,导致服务数量大幅增加,对于 Kubernetest 编排来说,每个组件有自己的资源文件,并且可以独立的部署与伸缩,这给采用 Kubernetes 做应用编排带来了诸多挑战:
    K8s
    K8s
    
  • HelmKubernetes 资源(比如 deploymentsservicesingress )等打包到一个 chart 中,而 chart 被保存到 chart 仓库。通过 chart 仓库可用来存储和分享 chartHelm 使发布可配置,支持发布应用配置的版本管理,简化了 Kubernetes 部署应用的版本控制、打包、发布、删除、更新等操作。
  • 项目地址: https://github.com/helm/helm

Helm 术语

  • Chart : 一个 helm 程序包,是创建一个应用的信息集合,包含各种 Kubernetes 对象的配置模板、参数定义、依赖关系、文档说明等。可以将 Chart 比喻为 yum 中的软件安装包
  • Repository : Charts 仓库,用于集中存储和分发 Charts
  • config : 包含了应用发布配置信息
  • Release : 特定的 Chart 部署于目标集群上的一个实例,代表这一个正在运行的应用。当chart被安装到 Kubernetes 集群,就会生成一个 releasechart 可以多次安装到同一个集群,每次安装都是一个新的 release

Helm系统架构

helm 采用客户端/服务端架构,有如下组件组成:

  • Helm 客户端:用户命令行工具,负责本地 chart 开发、仓库管理、与 Tiller server 交互、发送预安装的 chart 、查询 release 信息和要求升级或卸载已存在的 release
  • Tiller Server :部署在 Kubernetes 集群内部的 server ,其与 Helm clientKubernetes API Server 进行交互。负责监听来自 Helm client 的请求、通过 chart 及其配置构建一次发布、安装 chartKubernetes 集群并跟踪随后的发布、通过与 Kubernetes 交互升级或卸载 chart
  • RepositoryChart 仓库, Helm 客户端通过 HTTP 协议来访问仓库中 Chart 的索引文件和压缩包

Helm 工作原理

  • Helm 包括两部分, Helm 客户端和 Tiller 服务端。
  • Helm 客户端是一个命令行工具,采用 go 语言编写,负责管理 chartsrepositoryrelease 。它通过 gPRC APITiller server 发送请求。
  • Tiller 服务端同样采用 go 语言编写,提供了 gPRC server 接受来自 Helm 客户端的请求,利用 Kubernetes client 库把相关资源的操作发送到 Kubernetes ,负责管理(安装、查询、升级或删除)和跟踪 Kubernetes 资源。为了方便管理, Tiller 服务端把 release 的相关信息保存在 KubernetesConfigMap 中。

Helm 安装

  • 准备一套 Kubernetes 集群并在每个节点都安装依赖包 socat
$ yum -y install socat
  • Helm 项目地址下载 v2.15.1 版本,将压缩包解压后的二进制文件复制到可执行文件目录 /usr/local/bin
$ tar xvf helm-v2.15.1-linux-amd64.tar.gz
$ cp /root/helm/linux-amd64/helm /usr/local/bin/helm
  • Helm TillerHelmserver 端,以 Pod 形式部署到 Kubernetes 集群中。通过命令 helm init 初始化 Helm 服务,该命令会检查 Helm 本地环境设置是否正确, helm init 会连接 kubelet 默认连接的 Kubernetes 集群,一旦连接集群成功, Tiller 服务会被安装到 Kubernetes 集群中的 kube-system 命名空间中
$ helm init --upgrade -i registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.15.1 --stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
  • 查看 Tiller 服务相关的 Pod 是否正常启动
$ kubectl get pods -n kube-system -o wide |grep tiller
  • 创建 serviceAccount 来授权 Tiller 服务可能访问 Kubernetes 集群中的资源
$ kubectl create serviceaccount --namespace kube-system tiller
$ kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
$ kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
  • 验证 Tiller 服务是否正常,如果 Helm 客户端可以正常连接 Tiller 服务则输出信息如下。
$ helm version
Client: &version.Version{SemVer:"v2.15.1", GitCommit:"cf1de4f8ba70eded310918a8af3a96bfe8e7683b", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.15.1", GitCommit:"cf1de4f8ba70eded310918a8af3a96bfe8e7683b", GitTreeState:"clean"}

Chart 私有仓库

chart 仓库用来存储和分享打包的 chart ,官方 chart 仓库由 Kubernetes Charts 维护, Helm 允许我们创建私有 chart 仓库。 chart 仓库是一个可用来存储 index.yml 与打包的 chart 文件的 HTTP server ,当要分享 chart 时,需要上传 chart 文件到 chart 仓库。任何一个能能够提供 YAMLtar 文件的 HTTP server 都可以当做 chart 仓库,比如 Google Cloud Storage (GCS) bucket、Amazon S3 bucket、Github Pages 或创建你自己的web服务器

Chart 仓库结构

  • 一个 chart 仓库由多个 chart 包与 index.yaml 文件组成, index.yaml 记录了 chart 仓库中全部 chart 的索引

创建并添加 Chart 私有仓库到本地仓库列表中

  • 创建 Chart 私有仓库存储目录并启动一个私有仓库绑定该目录
$ mkdir -p /root/helm-dir/charts/
$ helm serve --address 0.0.0.0:8879 --repo-path /root/helm-dir/charts/
  • 当私有仓库服务启动后会在 /root/helm-dir/charts 目录中自动创建一个 index.yaml 文件,内容如下
apiVersion: v1
entries: {}
generated: "2020-03-27T14:50:43.3791484+08:00"
  • 创建一个 chart 包并打包、移动压缩包到 Chart 私有仓库存储目录中
$ helm create test01
$ helm package test01
$ mv test01-0.1.0.tgz /root/helm-dir/charts/
  • 通过 helm repo index 命令重新生成 index.yaml 文件,命令会根据现有的 chart 压缩包来生成索引。新的索引文件 index.yaml 中会包含添加的 chart 压缩包信息
$ helm repo index /root/helm-dir/charts/ --url http://192.168.31.221:8879/charts
$ ls -l /root/helm-dir/charts/
total 8
-rw-r--r-- 1 root root  386 Mar 10 14:51 index.yaml
-rw-r--r-- 1 root root 3248 Mar 10 14:03 test01-0.1.0.tgz

$ cat /root/helm-dir/charts/index.yaml
apiVersion: v1
entries:
  test01:
  - apiVersion: v1
    appVersion: "1.0"
    created: "2020-03-10T14:51:27.781754825+08:00"
    description: A Helm chart for Kubernetes
    digest: cec95ca0e38174d080cc9e3d81380a0f077cd28a30b28571e76b035bc051a9b6
    name: test01
    urls:
    - http:// 192.168.31.221:8879/test01-0.1.0.tgz
    version: 0.1.0
generated: "2020-03-10T14:51:27.781091459+08:00"
  • 添加 Chart 私有仓库到本地仓库列表中,并更新本地仓库列表资源缓存
$ helm repo add localRegistry http://192.168.31.221:8879/charts
"localRegistry" has been added to your repositories

$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "localRegistry" chart repository
...Successfully got an update from the "stable" chart repository
Update Complete.
  • 查看本地仓库列表并搜索刚上传的 test01chart
$ helm repo list
NAME            URL                                                   
stable          https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
localRegistry   http://192.168.31.221:8879/charts                     
[root@node1 helm-dir]# helm search test01
NAME                    CHART VERSION   APP VERSION DESCRIPTION                
localregistry/test01    0.1.0           1.0         A Helm chart for Kubernetes

管理本地仓库列表

通过 helm 客户端可以对本地仓库列表进行管理,和 Tiller 服务没有任何关系,所有添加的本地仓库列表信息都存储在 /root/.helm/repository 目录中

  • 查看本地仓库列表
$ helm repo list 
NAME            URL                                                   
stable          https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
localRegistry   http://192.168.31.221:8879/charts
  • 添加一个 Chart 仓库名称为 binami 到本地仓库列表中并查看
$ helm repo add  binami
https://charts.bitnami.com/bitnami
"binami" has been added to your repositories

$ helm repo list 
NAME            URL                                                   
stable          https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
localRegistry   http://192.168.31.221:8879/charts                     
binami          https://charts.bitnami.com/bitnami
  • 更新本地仓库列表资源缓存并查找一个 chart
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "localRegistry" chart repository
...Successfully got an update from the "stable" chart repository
...Successfully got an update from the "binami" chart repository
Update Complete.

$ helm search mysql
NAME                            CHART VERSION   APP VERSION DESCRIPTION                                                 
binami/mysql                    6.9.2           8.0.19      Chart to create a Highly available MySQL cluster            
stable/mysql                    0.3.5                       Fast, reliable, scalable, and easy to use open-source rel...
binami/phpmyadmin               4.3.3           5.0.1       phpMyAdmin is an mysql administration frontend              
stable/percona                  0.3.0                       free, fully compatible, enhanced, open source drop-in rep...
stable/percona-xtradb-cluster   0.0.2           5.7.19      free, fully compatible, enhanced, open source drop-in rep...
binami/mariadb                  7.3.12          10.3.22     Fast, reliable, scalable, and easy to use open-source rel...
binami/mariadb-cluster          1.0.1           10.2.14     Chart to create a Highly available MariaDB cluster          
binami/mariadb-galera           0.8.2           10.4.12     MariaDB Galera is a multi-master database cluster solutio...
stable/gcloud-sqlproxy          0.2.3                       Google Cloud SQL Proxy                                      
stable/mariadb                  2.1.6           10.1.31     Fast, reliable, scalable, and easy to use open-source rel...
  • 从本地仓库列表中删除一个 Chart 仓库名称为 binami
$ helm repo remove binami
"binami" has been removed from your repositories

$ helm repo list
NAME            URL                                                   
stable          https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
localRegistry   http://192.168.31.221:8879/charts

Chart

通过命令 helm create test01 可以创建一个 test01Chart 目录,目录中包含了多个配置文件,如下所示

$ tree test01
test01
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml
│   ├── _helpers.tpl
│   ├── ingress.yaml
│   ├── NOTES.txt
│   └── service.yaml
└── values.yaml
  • 生成 Chart 目录中有 Chart.yamlvalues.yamlNOTES.txt 等文件,下面分别对 chart 中几个重要文件解释:

    • Chart.yaml :包含了 chartmetadata ,描述了 Chart 名称、描述信息和版本号
    • values.yaml :存储了模版文件的变量
    • templates :记录全部模板文件
    • charts :依赖 chart 存储路径
    • NOTES.txt :给出了部署后的信息,例如如何使用char、列出默认的设置等等
  • chart 安装有以下几种方式

    • 指定charthelm install stable/mariadb
    • 指定打包的charthelm install ./nginx-1.2.3.tgz
    • 指定打包目录helm install ./nginx
    • 指定 chartURLhelm install https://example.com/charts/nginx-1.2.3.tgz

Helm 应用部署

创建并部署 Chart

  • 通过 helm create 命令可以创建一个 Chart 包,其中包含了 Chart 包的基本文件并且可以用来作为测试用途部署到 Kubernetes 集群环境中
$ helm create nginx
Creating nginx
  • 创建完成后,可以使用命令 helm lint 检查 chart 包是否存在问题
$ helm lint nginx
==> Linting nginx
[INFO] Chart.yaml: icon is recommended

1 chart(s) linted, no failures
  • 检查过后,可以使用命令 helm install 来完成 Chart 包的部署,可以通过 -n 参数来指定部署的 release 名称,如果不指定会随机生成一个。部署过程中会打印出 Chart 包的描述信息、资源信息及提示信息
$ helm install -n nginx nginx
NAME:   nginx
LAST DEPLOYED: Fri Mar 27 16:06:20 2020
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/Pod(related)
NAME                    READY  STATUS   RESTARTS  AGE
nginx-5bb789b86d-zf7b9  0/1    Pending  0         0s

==> v1/Service

NAME   AGE
nginx  0s

==> v1beta2/Deployment
nginx  0s

NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=nginx,app.kubernetes.io/instance=nginx" -o jsonpath="{.items[0].metadata.name}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl port-forward $POD_NAME 8080:80
  • 查看部署的 release 信息及 Kubernetes 集群中创建的 PodServiceserviceAccount 信息。
$ helm list
NAME    REVISION    UPDATED                     STATUS      CHART       APP VERSION NAMESPACE
nginx   1           Tue Mar 10 16:14:59 2020    DEPLOYED    nginx-0.1.0 1.0         default  

$ kubectl get pods 
NAME                     READY     STATUS    RESTARTS   AGE
nginx-594bb9f979-5rtkz   1/1       Running   0          3m

$ kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1               443/TCP   6d
nginx        ClusterIP   10.102.126.72           80/TCP    3m

$ kubectl get sa
NAME      SECRETS   AGE
default   1         6d
nginx     1         3m

升级、回滚部署的 Release

  • 在部署 Chart 包后,如果需要对已部署 的Release 进行修改,可以通过命令 helm upgrade 来进行升级操作。修改 Chart 包内 values.yaml 文件内的镜像配置参数后进行升级操作
$ helm upgrade -f nginx/values.yaml --description "set image tag 1.8.0" nginx nginx/
Release "nginx" has been upgraded. Happy Helming!
LAST DEPLOYED: Fri Mar 27 16:14:43 2020
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/Service
NAME   AGE
nginx  8m

==> v1beta2/Deployment
nginx  8m

==> v1/Pod(related)

NAME                    READY  STATUS             RESTARTS  AGE
nginx-5bb789b86d-zf7b9  1/1    Running            0         8m
nginx-8486957c66-2xnk5  0/1    ContainerCreating  0         0s

NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=nginx,app.kubernetes.io/instance=nginx" -o jsonpath="{.items[0].metadata.name}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl port-forward $POD_NAME 8080:80
  • 升级中需要指定配置文件并可以添加升级描述信息、部署的 release 名称和 Chart 包目录,升级后查看该 Chart 包当前版本号已经滚动并且 UPDATED 时间会刷新
$ helm list 
NAME    REVISION    UPDATED                     STATUS      CHART       APP VERSION NAMESPACE
nginx   6           Tue Mar 10 16:33:52 2020    DEPLOYED    nginx-0.1.1 2.0         default
  • 查看该 Release 的历史记录,可以看到当前版本信息及版本的描述信息
$ helm history nginx
REVISION        UPDATED                         STATUS          CHART           DESCRIPTION
1               Fri Mar 27 16:06:20 2020        SUPERSEDED      nginx-0.1.0     Install complete
2               Fri Mar 27 16:14:43 2020        DEPLOYED        nginx-0.1.0     set image tag 1.8.0
  • 如果在升级后发现当前版本有问题,需要马上回滚到上一个版本,此时可以通过命令 helm rollback 来回滚到指定的版本
$  helm rollback nginx 1
Rollback was a success! Happy Helming!
  • 此时再次查看 Release 的历史记录,可以看到当前版本是回退到版本 1 的位置
$ helm history nginx
REVISION        UPDATED                         STATUS          CHART           DESCRIPTION
1               Fri Mar 27 16:06:20 2020        SUPERSEDED      nginx-0.1.0     Install complete
2               Fri Mar 27 16:14:43 2020        SUPERSEDED      nginx-0.1.0     set image tag 1.8.0
3               Fri Mar 27 16:18:11 2020        DEPLOYED        nginx-0.1.0     Rollback to 1

删除、恢复部署的 Release

  • 当不再需要部署的 Release 时,可以通过 helm delete 命令来删除部署的 Release 。当 Release 被删除后, Kubernetes 集群中部署的 Pod 也会被清空
$ helm delete nginx 
release "nginx" deleted
  • 虽然此时已经在 Kubernetes 集群中看不到部署的 Pod ,但是 Helm 中并没有真正删除该 Release 。可以通过命令 helm list -a 查看已经被删除的 Release
$ helm list -a
NAME                REVISION    UPDATED                     STATUS  CHART           APP VERSION NAMESPACE
nginx               8           Tue Mar 10 16:41:09 2020    DELETED nginx-0.1.1     2.0         default
  • 即使删除了 Release ,其发布的历史信息还是会继续被保存
$ helm history nginx
REVISION        UPDATED                         STATUS          CHART           DESCRIPTION
1               Fri Mar 27 16:06:20 2020        SUPERSEDED      nginx-0.1.0     Install complete
2               Fri Mar 27 16:14:43 2020        SUPERSEDED      nginx-0.1.0     set image tag 1.8.0
3               Fri Mar 27 16:18:11 2020        DELETED         nginx-0.1.0     Deletion complete
  • 如果此时想恢复一个被删除的 Release ,可以通过 helm rollback 命令来恢复
$ helm rollback nginx 2
Rollback was a success.
  • 此时通过命令 helm list 查看部署的 Release 时,发现被删除的Release已经恢复并且正常显示
helm list 
NAME    REVISION    UPDATED                     STATUS      CHART       APP VERSION NAMESPACE
nginx   2       Tue Mar 10 17:06:00 2020    DEPLOYED    nginx-0.1.0 1.0         default
  • 如果想彻底删除一个 release ,可以添加参数 --purge 来执行
$ helm delete nginx --purge
release "nginx" deleted

依赖关系

Helm 中,一个 chart 可能依赖于任何数量的其他 chart 。这些依赖关系可以通过 requirements.yaml 文件动态链接或引入 charts/ 目录并手动管理

requirements.yaml 来管理依赖关系

  • requirements.yaml 文件是列出 chart 的依赖关系的简单文件
dependencies:
  - name: mysql
    version: 0.3.5 
    repository: https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
  • name 字段是 chart 的名称
  • version 字段是 chart 的版本
  • repository 字段是 chart repo 的完整 URL 。请注意,还必须使用 helm repo add 添加该 repo 到本地才能使用
  • 有了依赖关系文件,你可以通过运行 helm dependency update ,它会使用你的依赖关系文件将所有指定的 chart 下载到你的 charts/ 目录中
$ helm dependency 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 "binami" chart repository
...Successfully got an update from the "stable" chart repository
Update Complete.
Saving 1 charts
Downloading mysql from repo https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
Deleting outdated charts
  • helm dependency update 检索 chart 时,它会将它们作为 chart 存档存储在 charts/ 目录中。因此,对于上面的示例,可以在 chart 目录中看到以下文件
$ ls charts/
mysql-0.3.5.tgz

通过 requirements.yaml 管理 chart 是一种轻松更新 chart 的好方法,还可以在整个团队中共享 requirements 信息。

除上述其他字段外,每个需求条目可能包含可选字段 tagscondition 。所有 charts 都会默认加载,如果存在 tagscondition 字段,将对它们进行评估并用于控制应用的 chart 的加载。

  • tagsconditions 功能介绍
  • Conditions (设置 values ) 会覆盖 tags 配置。第一个存在的 condition 路径生效,后续该 chartcondition 路径将被忽略
  • 如果 chart 的某 tag 的任一 tag 的值为 true ,那么该 tag 的值为 true ,并启用这个 chart
  • Tagsconditions 值必须在顶级父级的值中进行设置
  • tags :值中的关键字必须是顶级关键字。目前不支持全局和嵌套 tags :表格
  • Condition :字段包含一个或多个 YAML 路径(用逗号分隔)。如果此路径存在于顶级父级的值中并且解析为布尔值,则将根据该布尔值启用或禁用 chart 。只有在列表中找到的第一个有效路径才被评估,如果没有路径存在,那么该条件不起作用.
  • Tags :标签字段是与此 chart 关联的 YAML 标签列表。在顶级父级的值中,可以通过指定标签和布尔值来启用或禁用所有带有标签的 chart
# parentchart/requirements.yaml
dependencies:
      - name: subchart1
        repository: http://localhost:10191
        version: 0.1.0
        condition: subchart1.enabled, global.subchart1.enabled
        tags:
          - front-end
          - subchart1

      - name: subchart2
        repository: http://localhost:10191
        version: 0.1.0
        condition: subchart2.enabled,global.subchart2.enabled
        tags:
          - back-end
          - subchart2
# parentchart/values.yaml
subchart1:
  enabled: true
tags:
  front-end: false
  back-end: true

在上面的示例中,所有带有标签的 front-endcharts 都将被禁用,但由于 subchart1.enabled 的值在父项值中为“真”,因此条件将覆盖该 front-end标签,subchart1会启用。由于subchart2被标记back-end和标签的计算结果为true,subchart2将被启用。还要注意的是,虽然subchart2有一个在requirements.yaml中指定的条件,但父项的值中没有对应的路径和值,因此条件无效

使用命令行时带有 tagconditions--set 参数可使用来更改 tagconditions

$ helm install --set tags.front-end=true --set subchart2.enabled=false

通过 charts 目录手动管理依赖性

  • 如果需要更多的控制依赖关系,可以通过将依赖的 charts 复制到 charts 目录中来明确表达这些依赖关系 。依赖关系可以是 chart 归档( .tgz )或解压缩的 chart 目录。但它的名字不能从 _. 开始,这些文件被 chart 加载器忽略
  • 如果 WordPress chart 依赖于 Apache chartMySQL chart ,则在 WordPress chartcharts 目录中提供 Apache chartMySQL chart ,即表示相互的依赖关系。