42. Helm安装使用

Helm这个东西其实早有耳闻,但是一直没有用在生产环境,而且现在对这货的评价也是褒贬不一。正好最近需要再次部署一套测试环境,对于单体服务,部署一套测试环境我相信还是非常快的,但是对于微服务架构的应用,要部署一套新的环境,就有点折磨人了,微服务越多、你就会越绝望的。虽然我们线上和测试环境已经都迁移到了kubernetes环境,但是每个微服务也得维护一套yaml文件,而且每个环境下的配置文件也不太一样,部署一套新的环境成本是真的很高。如果我们能使用类似于yum的工具来安装我们的应用的话是不是就很爽歪歪了啊?Helm就相当于kubernetes环境下的yum包管理工具。

用途

做为 Kubernetes 的一个包管理工具,Helm具有如下功能:

  • 创建新的 chart
  • chart 打包成 tgz 格式
  • 上传 chart 到 chart 仓库或从仓库中下载 chart
  • Kubernetes集群中安装或卸载 chart
  • 管理用Helm安装的 chart 的发布周期

重要概念

Helm 有三个重要概念:

  • chart:包含了创建Kubernetes的一个应用实例的必要信息
  • config:包含了应用发布配置信息
  • release:是一个 chart 及其配置的一个运行实例

Helm组件

Helm 有以下两个组成部分: Helm Structrue

Helm Client 是用户命令行工具,其主要负责如下:

  • 本地 chart 开发
  • 仓库管理
  • 与 Tiller sever 交互
  • 发送预安装的 chart
  • 查询 release 信息
  • 要求升级或卸载已存在的 release

Tiller Server是一个部署在Kubernetes集群内部的 server,其与 Helm client、Kubernetes API server 进行交互。Tiller server 主要负责如下:

  • 监听来自 Helm client 的请求
  • 通过 chart 及其配置构建一次发布
  • 安装 chart 到Kubernetes集群,并跟踪随后的发布
  • 通过与Kubernetes交互升级或卸载 chart
  • 简单的说,client 管理 charts,而 server 管理发布 release

安装

我们可以在Helm Realese页面下载二进制文件,这里下载的v2.10.0版本,解压后将可执行文件helm拷贝到/usr/local/bin目录下即可,这样Helm客户端就在这台机器上安装完成了。

现在我们可以使用Helm命令查看版本了,会提示无法连接到服务端Tiller

  1. $ helm version
  2. Client: &version.Version{SemVer:"v2.10.0", GitCommit:"9ad53aac42165a5fadc6c87be0dea6b115f93090", GitTreeState:"clean"}
  3. Error: could not find tiller

要安装 Helm 的服务端程序,我们需要使用到kubectl工具,所以先确保kubectl工具能够正常的访问 kubernetes 集群的apiserver哦。

然后我们在命令行中执行初始化操作:

  1. $ helm init

由于 Helm 默认会去gcr.io拉取镜像,所以如果你当前执行的机器没有配置科学上网的话可以实现下面的命令代替:

  1. $ helm init --upgrade --tiller-image cnych/tiller:v2.10.0
  2. $HELM_HOME has been configured at /root/.helm.
  3. Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.
  4. Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
  5. To prevent this, run `helm init` with the --tiller-tls-verify flag.
  6. For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation
  7. Happy Helming!

如果一直卡住或者报 google api 之类的错误,可以使用下面的命令进行初始化:

  1. $ helm init --upgrade --tiller-image cnych/tiller:v2.10.0 --stable-repo-url https://cnych.github.io/kube-charts-mirror/

这个命令会把默认的 google 的仓库地址替换成我同步的一个镜像地址。

如果在安装过程中遇到了一些其他问题,比如初始化的时候出现了如下错误:

  1. E0125 14:03:19.093131 56246 portforward.go:331] an error occurred forwarding 55943 -> 44134: error forwarding port 44134 to pod d01941068c9dfea1c9e46127578994d1cf8bc34c971ff109dc6faa4c05043a6e, uid : unable to do port forwarding: socat not found.
  2. 2018/01/25 14:03:19 (0xc420476210) (0xc4203ae1e0) Stream removed, broadcasting: 3
  3. 2018/01/25 14:03:19 (0xc4203ae1e0) (3) Writing data frame
  4. 2018/01/25 14:03:19 (0xc420476210) (0xc4200c3900) Create stream
  5. 2018/01/25 14:03:19 (0xc420476210) (0xc4200c3900) Stream added, broadcasting: 5
  6. Error: cannot connect to Tiller

解决方案:在节点上安装socat可以解决

  1. $ sudo yum install -y socat

Helm 服务端正常安装完成后,Tiller默认被部署在kubernetes集群的kube-system命名空间下:

  1. $ kubectl get pod -n kube-system -l app=helm
  2. NAME READY STATUS RESTARTS AGE
  3. tiller-deploy-86b844d8c6-44fpq 1/1 Running 0 7m

此时,我们查看 Helm 版本就都正常了:

  1. $ helm version
  2. Client: &version.Version{SemVer:"v2.10.0", GitCommit:"9ad53aac42165a5fadc6c87be0dea6b115f93090", GitTreeState:"clean"}
  3. Server: &version.Version{SemVer:"v2.10.0", GitCommit:"9ad53aac42165a5fadc6c87be0dea6b115f93090", GitTreeState:"clean"}

另外一个值得注意的问题是RBAC,我们的 kubernetes 集群是1.10.0版本的,默认开启了RBAC访问控制,所以我们需要为Tiller创建一个ServiceAccount,让他拥有执行的权限,详细内容可以查看 Helm 文档中的Role-based Access Control。 创建rbac.yaml文件:

  1. apiVersion: v1
  2. kind: ServiceAccount
  3. metadata:
  4. name: tiller
  5. namespace: kube-system
  6. ---
  7. apiVersion: rbac.authorization.k8s.io/v1beta1
  8. kind: ClusterRoleBinding
  9. metadata:
  10. name: tiller
  11. roleRef:
  12. apiGroup: rbac.authorization.k8s.io
  13. kind: ClusterRole
  14. name: cluster-admin
  15. subjects:
  16. - kind: ServiceAccount
  17. name: tiller
  18. namespace: kube-system

然后使用kubectl创建:

  1. $ kubectl create -f rbac-config.yaml
  2. serviceaccount "tiller" created
  3. clusterrolebinding.rbac.authorization.k8s.io "tiller" created

创建了tiller的 ServceAccount 后还没完,因为我们的 Tiller 之前已经就部署成功了,而且是没有指定 ServiceAccount 的,所以我们需要给 Tiller 打上一个 ServiceAccount 的补丁:

  1. $ kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'

上面这一步非常重要,不然后面在使用 Helm 的过程中可能出现Error: no available release name found的错误信息。

至此, Helm客户端和服务端都配置完成了,接下来我们看看如何使用吧。

使用

我们现在了尝试创建一个 Chart:

  1. $ helm create hello-helm
  2. Creating hello-helm
  3. $ tree hello-helm
  4. hello-helm
  5. ├── charts
  6. ├── Chart.yaml
  7. ├── templates
  8. ├── deployment.yaml
  9. ├── _helpers.tpl
  10. ├── ingress.yaml
  11. ├── NOTES.txt
  12. └── service.yaml
  13. └── values.yaml
  14. 2 directories, 7 files

我们通过查看templates目录下面的deployment.yaml文件可以看出默认创建的 Chart 是一个 nginx 服务,具体的每个文件是干什么用的,我们可以前往 Helm 官方文档进行查看,后面会和大家详细讲解的。比如这里我们来安装 1.7.9 这个版本的 nginx,则我们更改 value.yaml 文件下面的 image tag 即可,将默认的 stable 更改为 1.7.9,为了测试方便,我们把 Service 的类型也改成 NodePort

  1. ...
  2. image:
  3. repository: nginx
  4. tag: 1.7.9
  5. pullPolicy: IfNotPresent
  6. nameOverride: ""
  7. fullnameOverride: ""
  8. service:
  9. type: NodePort
  10. port: 80
  11. ...

现在我们来尝试安装下这个 Chart :

  1. $ helm install ./hello-helm
  2. NAME: iced-ferret
  3. LAST DEPLOYED: Thu Aug 30 23:39:45 2018
  4. NAMESPACE: default
  5. STATUS: DEPLOYED
  6. RESOURCES:
  7. ==> v1/Service
  8. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  9. iced-ferret-hello-helm ClusterIP 10.100.118.77 <none> 80/TCP 0s
  10. ==> v1beta2/Deployment
  11. NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
  12. iced-ferret-hello-helm 1 0 0 0 0s
  13. ==> v1/Pod(related)
  14. NAME READY STATUS RESTARTS AGE
  15. iced-ferret-hello-helm-58cb69d5bb-s9f2m 0/1 Pending 0 0s
  16. NOTES:
  17. 1. Get the application URL by running these commands:
  18. export POD_NAME=$(kubectl get pods --namespace default -l "app=hello-helm,release=iced-ferret" -o jsonpath="{.items[0].metadata.name}")
  19. echo "Visit http://127.0.0.1:8080 to use your application"
  20. kubectl port-forward $POD_NAME 8080:80
  21. $ kubectl get pods -l app=hello-helm
  22. NAME READY STATUS RESTARTS AGE
  23. iced-ferret-hello-helm-58cb69d5bb-s9f2m 1/1 Running 0 2m
  24. $ kubectl get svc -l app=hello-helm
  25. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  26. iced-ferret-hello-helm NodePort 10.104.127.141 <none> 80:31236/TCP 3m

等到 Pod 创建完成后,我们可以根据创建的 Service 的 NodePort 来访问该服务了,然后在浏览器中打开http://k8s.haimaxy.com:31236就可以正常的访问我们刚刚部署的 nginx 应用了。 nginx

查看release

  1. $ helm list
  2. NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
  3. winning-zebra 1 Thu Aug 30 23:50:29 2018 DEPLOYED hello-helm-0.1.0 1.0 default

打包chart

  1. $ helm package hello-helm
  2. Successfully packaged chart and saved it to: /root/course/kubeadm/helm/hello-helm-0.1.0.tgz

然后我们就可以将打包的tgz文件分发到任意的服务器上,通过helm fetch就可以获取到该 Chart 了。

删除release

  1. $ helm delete winning-zebra
  2. release "winning-zebra" deleted

然后我们看到kubernetes集群上的该 nginx 服务也已经被删除了。

  1. $ kubectl get pods -l app=hello-helm
  2. No resources found.

还有更多关于Helm的使用命令,我们可以前往官方文档查看。下节课我们再来和大家详细讲解。


点击查看本文视频

扫描下面的二维码(或微信搜索k8s技术圈)关注我们的微信公众帐号,在微信公众帐号中回复 加群 即可加入到我们的 kubernetes 讨论群里面共同学习。

k8s技术圈二维码