Files
davidpaulyoung/content/post/2018-04-16-using-helm-to-deploy-to-kubernetes.md
2026-05-14 14:06:21 -06:00

374 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
layout: post
title: "Helm介绍"
subtitle: "强大的Kubernetes包管理工具"
description: "Helm是Kubernetes生态系统中的一个软件包管理工具。本文将介绍为何要使用Helm进行Kubernetes软件包管理澄清Helm中使用到的相关概念并通过一个具体的示例学习如何使用Helm打包分发安装升级及回退Kubernetes应用。"
excerpt: "Helm是Kubernetes生态系统中的一个软件包管理工具。本文将介绍为何要使用Helm进行Kubernetes软件包管理澄清Helm中使用到的相关概念并通过一个具体的示例学习如何使用Helm打包分发安装升级及回退Kubernetes应用。"
date: 2018-04-16 15:00:00
author: "赵化冰"
image: "/img/2018-04-16-using-helm-to-deploy-to-kubernetes/buffalo.jpg"
publishDate: 2018-04-16 15:00:00
tags:
- Kubernetes
- Helm
categories: [ Tech ]
URL: "/2018/04/16/using-helm-to-deploy-to-kubernetes/"
---
## 前言
- - -
Helm是Kubernetes生态系统中的一个软件包管理工具。本文将介绍为何要使用Helm进行Kubernetes软件包管理澄清Helm中使用到的相关概念并通过一个具体的示例学习如何使用Helm打包分发安装升级及回退Kubernetes应用。
## Kubernetes应用部署的挑战
- - -
让我们首先来看看Kuberneteskubernetes提供了基于容器的应用集群管理为容器化应用提供了部署运行、资源调度、服务发现和动态伸缩等一系列完整功能。
kubernetes的核心设计理念是: 用户定义应用程序的规格而kubernetes则负责按照定义的规则部署并运行应用程序如果应用系统出现问题导致偏离了定义的规格kubernetes负责对其进行自动修正。例如应用规格要求部署两个实例其中一个实例异常终止了kubernetes会检查到并重新启动一个新的实例。
用户通过使用kubernetes API对象来描述应用程序规格包括PodServiceVolumeNamespaceReplicaSetDeploymentJob等等。一般这些对象需要写入一系列的yaml文件中然后通过kubernetes命令行工具kubectl进行部署。
以下面的wordpress应用程序为例涉及到多个kubernetes API对象这些kubernetes API对象分散在多个yaml文件中。
图1 Wordpress应用程序中涉及到的kubernetes API对象
![](/img/2018-04-16-using-helm-to-deploy-to-kubernetes/wordpress.png)
可以看到在进行kubernetes软件部署时我们面临下述问题
* 如何管理编辑和更新这些这些分散的kubernetes应用配置文件
* 如何把一套的相关配置文件作为一个应用进行管理?
* 如何分发和重用kubernetes的应用配置
Helm的引入很好地解决上面这些问题。
## Helm是什么
- - -
很多人都使用过Ubuntu下的ap-get或者CentOS下的yum, 这两者都是Linux系统下的包管理工具。采用apt-get/yum,应用开发者可以管理应用包之间的依赖关系,发布应用;用户则可以以简单的方式查找、安装、升级、卸载应用程序。
我们可以将Helm看作Kubernetes下的apt-get/yum。Helm是Deis (https://deis.com/) 开发的一个用于kubernetes的包管理器。
对于应用发布者而言可以通过Helm打包应用管理应用依赖关系管理应用版本并发布应用到软件仓库。
对于使用者而言使用Helm后不用需要了解Kubernetes的Yaml语法并编写应用部署文件可以通过Helm下载并在kubernetes上安装需要的应用。
除此以外Helm还提供了kubernetes上的软件部署删除升级回滚应用的强大功能。
## Helm组件及相关术语
- - -
开始接触Helm时遇到的一个常见问题就是Helm中的一些概念和术语非常让人迷惑我开始学习Helm就遇到这个问题。
因此我们先了解一下Helm的这些相关概念和术语。
* Helm
Kubernetes的应用打包工具也是命令行工具的名称。
* Tiller
Helm的服务端部署在Kubernetes集群中用于处理Helm的相关命令。
* Chart
Helm的打包格式内部包含了一组相关的kubernetes资源。
* Repoistory
Helm的软件仓库repository本质上是一个web服务器该服务器保存了chart软件包以供下载并有提供一个该repository的chart包的清单文件以供查询。在使用时Helm可以对接多个不同的Repository。
* Release
使用Helm install命令在Kubernetes集群中安装的Chart称为Release。
> 需要特别注意的是, Helm中提到的Release和我们通常概念中的版本有所不同这里的Release可以理解为Helm使用Chart包部署的一个应用实例。
>
> 其实Helm中的Release叫做Deployment更合适。估计因为Deployment这个概念已经被Kubernetes使用了因此Helm才采用了Release这个术语。
下面这张图描述了Helm的几个关键组件Helm客户端Tiller服务器RepositoryChart软件仓库Chart软件包之前的关系。
图2 Helm软件架构
![](/img/2018-04-16-using-helm-to-deploy-to-kubernetes/helm-architecture.png)
## 安装Helm
- - -
下面我们通过一个完整的示例来介绍Helm的相关概念并学习如何使用Helm打包分发安装升级及回退kubernetes应用。
可以参考Helm的帮助文档https://docs.helm.sh/using_helm/#installing-helm 安装Helm
采用二进制的方式安装Helm
1. 下载 Helm https://github.com/kubernetes/helm/releases
1. 解压 tar -zxvf helm-v2.0.0-linux-amd64.tgz
1. 拷贝到bin目录 mv linux-amd64/helm /usr/local/bin/helm
然后使用下面的命令安装服务器端组件Tiller
```bash
Helm init
```
## 构建一个Helm chart
- - -
让我们在实践中来了解Helm。这里将使用一个Go测试小程序让我们先为这个小程序创建一个Helm chart。
```
git clone https://github.com/zhaohuabing/testapi.git;
cd testapi
```
首先创建一个chart的骨架
```
helm create testapi-chart
```
该命令创建一个testapi-chart目录该目录结构如下所示我们主要关注目录中的这三个文件即可: Chart.yamlvalues.yaml 和 NOTES.txt。
```Bash
testapi-chart
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml
│   ├── _helpers.tpl
│   ├── NOTES.txt
│   └── service.yaml
└── values.yaml
```
* Chart.yaml 用于描述这个chart包括名字描述信息以及版本。
* values.yaml 用于存储templates目录中模板文件中用到的变量。 模板文件一般是Go模板。如果你需要了解更多关于Go模板的相关信息可以查看Hugo (https://gohugo.io) 的一个关于Go模板的介绍 (https://gohugo.io/templates/go-templates/)。
* NOTES.txt 用于向部署该chart的用于介绍chart部署后的一些信息。例如介绍如何使用这个chart列出缺省的设置等。
打开Chart.yaml, 填写你部署的应用的详细信息以testapi为例
```
apiVersion: v1
description: A simple api for testing and debugging
name: testapi-chart
version: 0.0.1
```
然后打开并根据需要编辑values.yaml。下面是testapi应用的values.yaml文件内容。
```
replicaCount: 2
image:
repository: daemonza/testapi
tag: latest
pullPolicy: IfNotPresent
service:
name: testapi
type: ClusterIP
externalPort: 80
internalPort: 80
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi
```
在 testapi_chart 目录下运行下面命令以对chart进行校验。
```
helm lint
==> Linting .
[INFO] Chart.yaml: icon is recommended
1 chart(s) linted, no failures
```
如果文件格式错误可以根据提示进行修改如果一切正常可以使用下面的命令对chart进行打包
```
helm package testapi-chart --debug
```
这里添加了 --debug 参数来查看打包的输出,输出应该类似于:
```
Saved /Users/daemonza/testapi/testapi-chart/testapi-chart-0.0.1.tgz to current directory
Saved /Users/daemonza/testapi/testapi-chart/testapi-chart-0.0.1.tgz to /Users/daemonza/.helm/repository/local
```
chart被打包为一个压缩包testapi-chart-0.0.1.tgz该压缩包被放到了当前目录下并同时被保存到了helm的本地缺省仓库目录中。
## Helm Repository
- - -
虽然我们已经打包了chart并发布到了helm的本地目录中但通过Helm search命令查找并不能找不到刚才生成的chart包。
```
helm search testapi
No results found
```
这是因为repository目录中的chart还没有被Helm管理。我们可以在本地启动一个Repository Server并将其加入到Helm repo列表中。
通过helm repo list命令可以看到目前helm中只配置了一个名为stable的repo该repo指向了google的一个服务器。
```Bash
helm repo list
NAME URL
stable https://kubernetes-charts.storage.googleapis.com
```
使用helm serve命令启动一个repo server该server缺省使用'$HELM_HOME/repository/local'目录作为chart存储并在8879端口上提供服务。
```Bash
helm serve&
Now serving you on 127.0.0.1:8879
```
启动本地repo server后将其加入helm的repo列表。
```Bash
helm repo add local http://127.0.0.1:8879
"local" has been added to your repositories
```
现在再查找testapi chart包就可以找到了。
```Bash
helm search testapi
NAME CHART VERSION APP VERSION DESCRIPTION
local/testapi-chart 0.0.1 A Helm chart for Kubernetes
```
## 在kubernetes中部署Chart
- - -
chart被发布到仓储后可以通过Helm instal命令部署chart部署时指定chart名及Release部署的实例
```
helm install local/testapi-chart --name testapi
```
该命令的输出应类似:
```
NAME: testapi
LAST DEPLOYED: Mon Apr 16 10:21:44 2018
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
testapi-testapi-chart ClusterIP 10.43.121.84 <none> 80/TCP 0s
==> v1beta1/Deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
testapi-testapi-chart 1 1 1 0 0s
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
testapi-testapi-chart-9897d9f8c-nn6wd 0/1 Pending 0 0s
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace default -l "app=testapi-testapi-chart" -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。
```
helm ls
```
该命令的输出应类似:
```
NAME REVISION UPDATED STATUS CHART NAMESPACE
testapi 1 Mon Apr 16 10:21:44 2018 DEPLOYED testapi-chart-0.0.1 default
```
可以看到在输出中有一个Revision更改历史字段该字段用于表示某一Release被更新的次数可以用该特性对已部署的Release进行回滚。
## 升级和回退
- - -
修改Chart.yaml将版本号从0.0.1 修改为 1.0.0, 然后使用Helm package命令打包并发布到本地仓库。
查看本地库中的Chart信息可以看到在本地仓库中testapi-chart有两个版本
```Bash
helm search testapi -l
NAME CHART VERSION APP VERSION DESCRIPTION
local/testapi-chart 0.0.1 A Helm chart for Kubernetes
local/testapi-chart 1.0.0 A Helm chart for Kubernetes
```
现在用helm upgrade将已部署的testapi升级到新版本。可以通过参数指定需要升级的版本号如果没有指定版本号则缺省使用最新版本。
```
helm upgrade testapi local/testapi-chart
```
已部署的testapi release被升级到1.0.0版本
```Bash
helm list
NAME REVISION UPDATED STATUS CHART NAMESPACE
testapi 2 Mon Apr 16 10:43:10 2018 DEPLOYED testapi-chart-1.0.0 default
```
可以通过Helm history查看一个Release的多次更改。
```Bash
helm history testapi
REVISION UPDATED STATUS CHART DESCRIPTION
1 Mon Apr 16 10:21:44 2018 SUPERSEDED testapi-chart-0.0.1 Install complete
2 Mon Apr 16 10:43:10 2018 DEPLOYED testapi-chart-1.0.0 Upgrade complete
```
如果更新后的程序由于某些原因运行有问题我们则需要回退到旧版本的应用可以采用下面的命令进行回退。其中的参数1是前面Helm history中查看到的Release的更改历史。
```Bash
helm rollback testapi 1
```
使用Helm list命令查看部署的testapi的版本已经回退到0.0.1
```Bash
helm list
NAME REVISION UPDATED STATUS CHART NAMESPACE
testapi 3 Mon Apr 16 10:48:20 2018 DEPLOYED testapi-chart-0.0.1 default
```
## 总结
- - -
Helm作为kubernetes应用的包管理以及部署工具提供了应用打包发布版本管理以及部署升级回退等功能。Helm以Chart软件包的形式简化Kubernetes的应用管理提高了对用户的友好性。
## Q&A
- - -
昨天在Docker.io技术微信群里面进行了Helm的分享下面是分享过程中得到的一些有意思的反馈进一步启发了我自己的一些思考。
**Q**: Helm结合CD有什么好的建议吗<BR>
**A**: 采用Helm可以把零散的Kubernetes应用配置文件作为一个chart管理chart源码可以和源代码一起放到git库中管理。Helm还简了在CI/CD pipeline的软件部署流程。通过把chart参数化可以在测试环境和生产环境可以采用不同的chart参数配置。
下图是采用了Helm的一个CI/CD流程
![](/img/2018-04-16-using-helm-to-deploy-to-kubernetes/ci-cd-jenkins-helm-k8s.png)
**Q**: 感谢分享,请问下多环境(test,stagingproduction)的业务配置如何管理呢通过heml打包configmap吗比如配置文件更新也要重新打chats包吗谢谢这块我比较乱<BR>
**A**Chart是支持参数替换的可以把业务配置相关的参数设置为模板变量。使用Helm install Chart的时候可以指定一个参数值文件这样就可以把业务参数从Chart中剥离了。例子 helm install --values=myvals.yaml wordpress
**Q**: helm能解决服务依赖吗<BR>
**A**可以的在chart可以通过requirements.yaml声明对其他chart的依赖关系。如下面声明表明chart依赖apache和mysql这两个第三方chart。
```yaml
dependencies:
- name: apache
version: 1.2.3
repository: http://example.com/charts
- name: mysql
version: 3.2.1
repository: http://another.example.com/charts
```
**Q**: chart的reversion 可以自定义吗比如跟git的tag<BR>
**A**: 这位朋友应该是把chart的version和Release的reversion搞混了呵呵。 Chart是没有reversion的Chart部署的一个实例Release才有ReversionReversion是Release被更新后自动生成的。
**Q**: 没有看到helm指向k8s的配置怎么确认在哪个K8s集群运行的<BR>
**A**: 使用和kubectl相同的配置在 ~/.kube/config 中。
**Q**: 这个简单例子并没有看出 Helm 相比 kubectl 有哪些优势,可以简要说一下吗?<BR>
**A** Helm将kubernetes应用作为一个软件包整体管理例如一个应用可能有前端服务器后端服务器数据库这样会涉及多个Kubernetes 部署配置文件Helm就整体管理了。另外Helm还提供了软件包版本一键安装升级回退。Kubectl和Helm就好比你手工下载安装一个应用 和 使用apt-get 安装一个应用的区别。
**Q**: 如何在helm install 时指定命名空间?<BR>
**A**: helm install local/testapi-chart --name testapi --namespace mynamespace
## 参考
- - -
* [Using Helm to deploy to Kubernetes](https://daemonza.github.io/2017/02/20/using-helm-to-deploy-to-kubernetes/)
* [Helm documentation](https://docs.helm.sh/helm/)
* [Helm - Application deployment management for Kubernetes](https://www.slideshare.net/alexLM/helm-application-deployment-management-for-kubernetes)