Published on

Kubernetes上如何使用Helm

Authors
  • avatar
    Name
    老杨的博客
    Twitter

Kubernetes 上如何使用 Helm

[TOC]

1. 环境说明

操作系统:CentOS7 kubernetes:1.11

2. helm 安装

# 下载脚本并执行安装
curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get > get_helm.sh
bash get_helm.sh
# 查看Helm客户端的版本号
helm version

注意版本号,后续容器服务的版本要和这个一致, 否则会出现问题。

Client: &version.Version{SemVer:"v2.9.1", GitCommit:"20adb27c7c5868466912eebdf6664e7390ebe710", GitTreeState:"clean"}
# 在 Kubernetes 群集上安装 Tiller(helm服务端),注意和上面版本号一致
helm init --upgrade -i registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.9.1 --stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts

说明: helm init --upgrade会在 Kubernetes 集群上安装配置 Tiller, 仓库默认使用https://kubernetes-charts.storage.googleapis.com 。由于国内无法访问相关域名,可以使用阿里云容器服务提供的镜像和站点。

查看容器运行情况

kubectl get pod --all-namespaces|grep tiller

kube-system   tiller-deploy-b67849f44-cs4qr               1/1       Running            0          46m

从 Kubernetes 1.6 开始,API Server 启用了 RBAC 授权。而 Tiller 部署没有定义授权的 ServiceAccount,这会导致访问 API Server 时被拒绝。我们可以采用如下方法,为 Tiller 部署添加授权。

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"}}}}'
# 查看已部署的应用
helm list

卸载 helm 服务端

helm reset
# helm reset --force

3. helm 使用

# 先移除原先的仓库
helm repo remove stable
# 添加新的仓库地址
helm repo add stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
# 更新仓库
helm repo update

4. 安装 Monocular

Monocular 基于 web 的用户界面,用于管理 Kubernetes 应用打包为 Helm Charts。它允许您从多个存储库搜索和发现可用 Chats,并安装在您的集群中,只需要鼠标点点就能完成。

准备条件 * Helm 和 Tiller 已安装 * Nginx Ingress controller 已安装 * Install with Helm: helm install stable/nginx-ingress * Minikube/Kubeadm: helm install stable/nginx-ingress --set controller.hostNetwork=true

安装

helm repo add monocular https://helm.github.io/monocular
helm install --name monocular monocular/monocular

默认它是配置到 ingress 中的,通过 ingress 节点 IP 就能访问。

注意 安装过程中,pvc 创建提示失败,需要手动干预提供可用 pvc。

5. 安装 Kubeapps

kubeapps 是一个基于 web 的用户界面,用于部署和管理在 kubernetes 群集中的应用程序。Kubeapps 允许你: * 浏览并部署存储库中的 chats * 检查、升级和删除集群中安装的基于helm的应用程序 * 添加自定义和私有的 chat 存储库(支持ChartMuseum and JFrog Artifactory) * 浏览并提供来自Service Catalog的外部服务和可用的服务中介 * 用服务目录绑定基于helm的应用程序连接到外部服务 * 基于 kubernetes RBAC 的安全认证和授权

安装

kubectl create namespace kubeapps
helm repo add bitnami https://charts.bitnami.com/bitnami
helm install --name kubeapps --namespace kubeapps bitnami/kubeapps

6. 2 个工具对比

  1. 在功能上,2 个基本一样;
  2. 用户体验上,当前 2 个的最新版本,Kubeapps(v1.0.0-alpha.6)要优于 Monocular(0.7.3),部署时 Kubeapps 能让用户直接修改一些默认参数;
  3. 安全上,Kubeapps 直接使用 Kubernetes 的 RBAC,和 Kubernetes 的 dashboard 的 toke 登录方式一样。Monocular 登录功能用不了;
  4. 对外提供访问上,Kubeapps 的kubectl port-forward不推荐,最好配置 ingress,而 Monocular 已自动配置 ingress;

7. chart repo

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

7.1 chart repo 结构

查看目前的 repo,helm repo list

NAME            URL
stable          https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
local           http://localhost:8879/charts
monocular       https://helm.github.io/monocular
bitnami         https://charts.bitnami.com/bitnami
incubator       http://storage.googleapis.com/kubernetes-charts-incubator

helm执行 tiller 命令后默认会配置一个名为 l 的本地 repo。

一个 chart 仓库由一个 chart 包与index.yaml文件组成,index.yaml记录了 chart 仓库中全部 chart 的索引,一个本地 chart 仓库的布局例子如下:

~/.helm/
|-- cache
| `-- archive
| |-- drupal-0.9.2.tgz
| `-- mariadb-1.0.3.tgz
|-- plugins
|-- repository
| |-- cache
| | |-- fantastic-charts-index.yaml
| | |-- local-index.yaml -> /home/ts1/.helm/repository/local/index.yaml
| | |-- mariadb-1.0.3.tgz-index.yaml
| | |-- memcached-1.2.1.tgz-index.yaml
| | |-- mychart_xia-0.1.0.tgz-index.yaml
| | |-- mysql-0.2.8.tgz-index.yaml
| | |-- stable-index.yaml
| | |-- test-0.1.0.tgz-index.yaml
| | `-- test-0.1.8.tgz-index.yaml
| |-- local
| | |-- index.yaml
| | |-- mychart-0.1.0.tgz
| | |-- mychart_xia-0.1.0.tgz
| | |-- mysql-0.2.8.tgz
| | |-- mysql-6.19.centos-29.tgz
| | |-- test-0.1.0.tgz
| | |-- test-0.1.8.tgz
| | `-- test-0.1.9.tgz
| `-- repositories.yaml
`-- starters

~/.helm/repository/local/index.yaml 文件中记录了 chart 的诸如名称、url、version 等一些 metadata 信息。

7.2 启动 repo 服务

mkdir -p /data/helm/charts
cat > /data/helm/start_local_helm.sh <<EOF
#!/usr/bin/env bash

helm_path=\$(which helm)
helm_pid=\$(pidof \$helm_path)
helm_data_path="/data/helm/charts"

if [ -z "\$helm_pid" ]; then
    cd \$helm_data_path
    nohup \$helm_path serve --address 0.0.0.0:8879 --repo-path \$helm_data_path &
else
    echo -e "helm already running."
fi

exit 0
EOF
sh /data/helm/start_local_helm.sh

helm serve --help

This command starts a local chart repository server that serves charts from a local directory.

The new server will provide HTTP access to a repository. By default, it will
scan all of the charts in '$HELM_HOME/repository/local' and serve those over
the local IPv4 TCP port (default '127.0.0.1:8879').

This command is intended to be used for educational and testing purposes only.
It is best to rely on a dedicated web server or a cloud-hosted solution like
Google Cloud Storage for production use.

See https://github.com/kubernetes/helm/blob/master/docs/chart_repository.md#hosting-chart-repositories
for more information on hosting chart repositories in a production setting.

Usage:
  helm serve [flags]

Flags:
      --address string     address to listen on (default "127.0.0.1:8879")
      --repo-path string   local directory path from which to serve charts
      --url string         external URL of chart repository

Global Flags:
      --debug                           enable verbose output
      --home string                     location of your Helm config. Overrides $HELM_HOME (default "/root/.helm")
      --host string                     address of Tiller. Overrides $HELM_HOST
      --kube-context string             name of the kubeconfig context to use
      --tiller-connection-timeout int   the duration (in seconds) Helm will wait to establish a connection to tiller (default 300)
      --tiller-namespace string         namespace of Tiller (default "kube-system")

添加本地 repo helm repo add local http://192.168.105.92:8879/charts

7.3 向 repo 中增加软件包

上面步骤中,已经创建了一个本地的 repo,接下来讲述如何在 repo 中增加一个可用来部署的软件包 chart。chart 须遵循 SemVer 2 规则填写正确的版本格式。各种 chart 包可以在github下载。

因为官方 chart 里的 image 镜像被墙的可能和自己定制参数的设置,我们将修改过的 chart 添加到本机 chart 中。

cd /data/helm
helm fetch incubator/zookeeper --untar
helm package zookeeper
mv zookeeper-1.1.1.tgz charts/

helm package的作用是在当前目录下将软件打包为 tgz,假如这个软件包中有 requirement.yaml,则打包时还需要加上--dependency-update,用来update dependencies from "requirements.yaml" to dir "charts/" before packaging

更新 index.yaml 文件

cd /data/helm
helm repo index charts --url http://192.168.105.92:8879/charts
helm repo remove local
helm repo add local http://192.168.105.92:8879/charts

查看 chart 是否上传仓库成功: helm search zookeeper|grep local

local/zookeeper         1.1.1           3.4.10          Centralized service for maintaining configurati...

8. 应用部署和版本管理

获取 chart 获取版本为 0.3.5 的 mysql 并解压缩包:

$ helm fetch stable/mysql --version 0.3.5 --untar
$ ls mysql/
Chart.yaml  README.md  templates  values.yaml
$ helm lint mysql
==> Linting mysql
Lint OK

1 chart(s) linted, no failures

利用 helm lint 命令检查下载的 chart 是否存在问题:

$ helm lint mysql
==> Linting mysql
Lint OK
1 chart(s) linted, no failures

创建自定义 chart helm create mychart

查看 mychart 结构:

mychart/
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml
│   ├── _helpers.tpl
│   ├── ingress.yaml
│   ├── NOTES.txt
│   └── service.yaml
└── values.yaml

2 directories, 7 files

生成 chart 目录里有Chart.yaml, values.yaml and NOTES.txt等文件,下面分别对 chart 中几个重要文件解释: Chart.yaml 包含了 chart 的 metadata,描述了 Chart 名称、描述信息与版本。 values.yaml:存储了模板文件变量。 templates/:记录了全部模板文件。 charts/:依赖 chart 存储路径。

其中mychart/templates/的文件及其作用如下: NOTES.txt:给出了部署 chart 后的帮助文档,例如如何使用 chart、列出默认的设置等。 deployment.yaml:创建 Kubernetes deployment 的 yaml 文件。 service.yaml:创建 deployment 的 service endpoint yams 文件。 _helpers.tpl: 模板使用帮助文件。

chart 安装有以下几种方式: 指定 chart: helm install stable/mariadb 指定打包的 chart: helm install ./nginx-1.2.3.tgz 指定打包目录: helm install ./nginx 指定 chart 包 URL: helm install https://example.com/charts/nginx-1.2.3.tgz

覆盖 chart 中的默认值,通过指定配置文件方式: helm install -f myvalues.yaml ./redis

或者通过–set key=value 形式: helm install --set name=prod ./redis

安装 release 名称为 mysql 例子如下,请注意 NOTES 中对 Mysql 的使用说明:

vim mysql/values.yaml

找到 storageClass,并修改其值,这里我们使用可用的动态卷ceph-rbd

  storageClass: "ceph-rbd"`

安装 release

[root@lab1 helm]# helm install -n mysql -f mysql/values.yaml --set resources.requests.memory=512Mi mysql
NAME:   mysql
LAST DEPLOYED: Mon Aug 27 11:23:27 2018
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/Secret
NAME         TYPE    DATA  AGE
mysql-mysql  Opaque  2     0s

==> v1/PersistentVolumeClaim
NAME         STATUS   VOLUME    CAPACITY  ACCESS MODES  STORAGECLASS  AGE
mysql-mysql  Pending  ceph-rbd  0s

==> v1/Service
NAME         TYPE       CLUSTER-IP     EXTERNAL-IP  PORT(S)   AGE
mysql-mysql  ClusterIP  10.101.206.24  <none>       3306/TCP  0s

==> v1beta1/Deployment
NAME         DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
mysql-mysql  1        1        1           0          0s

==> v1/Pod(related)
NAME                          READY  STATUS   RESTARTS  AGE
mysql-mysql-7f56cd565b-sfmgj  0/1    Pending  0         0s


NOTES:
MySQL can be accessed via port 3306 on the following DNS name from within your cluster:
mysql-mysql.default.svc.cluster.local

To get your root password run:

    MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace default mysql-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 mysql-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 commands to route the connection:
    export POD_NAME=$(kubectl get pods --namespace default -l "app=mysql-mysql" -o jsonpath="{.items[0].metadata.name}")
    kubectl port-forward $POD_NAME 3306:3306

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

查看 release 状态helm status mysql

NAME:   mysql
LAST DEPLOYED: Mon Aug 27 11:23:27 2018
NAMESPACE: default
STATUS: DEPLOYED

或通过 helm list -a 查看全部的 release,tag “-a”是查看全部的 release,包括已部署、部署失败、正在删除、已删除 release 等。

更新 release

helm upgrade mysql -f mysql/values.yaml --set resources.requests.memory=1024Mi mysql

查看指定 release 的历史部署版本信息:

[root@lab1 helm]# helm hist mysql
REVISION        UPDATED                         STATUS          CHART           DESCRIPTION
1               Mon Aug 27 11:23:27 2018        SUPERSEDED      mysql-0.3.5     Install complete
2               Mon Aug 27 11:26:09 2018        DEPLOYED        mysql-0.3.5     Upgrade complete

查看指定 release 的历史版本部署时部分配置信息,以 resources.requests.memory 为例,符合查看部署符合预期:即第一次部署 resources.requests.memory 设置为 512Mi,第二次的升级 resources.requests.memory 设置为 1024Mi:

helm get --revision 1 mysql

版本回滚

回滚到第一次的版本:

[root@lab1 helm]# helm rollback --debug mysql 1
[debug] Created tunnel using local port: '44164'

[debug] SERVER: "127.0.0.1:44164"

Rollback was a success! Happy Helming!

查看 mysql release 的版本信息,当前已经回滚到 REVISION 为 1 的版本:

[root@lab1 helm]# helm hist mysql
REVISION        UPDATED                         STATUS          CHART           DESCRIPTION
1               Mon Aug 27 11:23:27 2018        SUPERSEDED      mysql-0.3.5     Install complete
2               Mon Aug 27 11:26:09 2018        SUPERSEDED      mysql-0.3.5     Upgrade complete
3               Mon Aug 27 11:29:24 2018        SUPERSEDED      mysql-0.3.5     Rollback to 1

删除 release

[root@lab1 helm]# helm delete mysql
release "mysql" deleted

确认 release 是否删除:

[root@lab1 helm]# helm ls -a mysql
NAME    REVISION        UPDATED                         STATUS  CHART           NAMESPACE
mysql   4               Mon Aug 27 11:29:45 2018        DELETED mysql-0.3.5     default

即使删除的 release ,其发布的历史信息还是继续被保存。

[root@lab1 helm]# helm hist mysql
REVISION        UPDATED                         STATUS          CHART           DESCRIPTION
1               Mon Aug 27 11:23:27 2018        SUPERSEDED      mysql-0.3.5     Install complete
2               Mon Aug 27 11:26:09 2018        SUPERSEDED      mysql-0.3.5     Upgrade complete
3               Mon Aug 27 11:29:24 2018        SUPERSEDED      mysql-0.3.5     Rollback to 1
4               Mon Aug 27 11:29:45 2018        DELETED         mysql-0.3.5     Deletion complete

可以恢复一个已经删除的 release:

[root@lab1 helm]# helm rollback --debug mysql 2
[debug] Created tunnel using local port: '33811'

[debug] SERVER: "127.0.0.1:33811"

Error: "mysql" has no deployed releases

如果希望彻底删除一个 release,可以用如下命令:

[root@lab1 helm]# helm delete --purge mysql
release "mysql" deleted

再次查看刚被删除的 mysql release,提示已经无法找到,符合预期:

[root@lab1 helm]# helm hist mysql
Error: release: "mysql" not found

Helm 对 release 的版本管理
在上面例子中,已经展示了 Helm 对 release 的非常强大的版本管理功能,比如通过helm list -a查看有哪些 release,通过helm hist查看某一个具体的 release 发布过的历史版本,以及通过helm get --revision,查看某个 release 的一次历史版本对应的具体应用配置信息等。即使已经被删除的 release 仍然有记录,并且通过 Helm 能够快速回滚到已删除 release 的某个发布过的历史版本。Helm 的这些版本管理功能,Kubernetes 原生并不支持。

参考资料:
[1] https://helm.sh/
[2] https://whmzsu.github.io/helm-doc-zh-cn/
[3] 简化 Kubernetes 应用部署工具-Helm 简介
[4] 简化 Kubernetes 应用部署工具-Helm 安装
[5] 简化 Kubernetes 应用部署工具-Helm 之应用部署
[6] 简化 Kubernetes 应用部署工具-Helm 之 Release 配置
[7] https://github.com/helm/monocular
[8] https://github.com/kubeapps/kubeapps