在我们学习 kubernetes 的过程中,用的最多的是 kubectl 命令行工具,使用 kubectl 工具需要我们编写好各种部署文件,这在生产中是非常不方便的,因此 Helm 这个 kubernetes 包管理工具就应运而生了。

Helm 包管理工具不仅可以为我们安装网上已经成熟的部署库文件,而且可以生产本地部署模板,我们只需要简单改一改,就可以完成一个应用的部署,不需要我们记住那么多的命令和配置。下面我们就看一下 Helm 的使用。

Helm 基础介绍

Helm V2/V3 的对比

组件架构对比:

1. :由2个二进制组成:(客户端cli)、(服务端)

2. :只有1个二进制组成:、移除了tiller

工作原理对比:

1. :helm->tiller->k8s。首先由helm和tiller交互,然后由tiller负责和k8s交互来完成操作。

2. :helm->k8s。由helm命令去调用获取k8s权限,然后直接与交互操作。

Helm 安装的 Chart 的记录到k8s的里面,secret名字叫,另外还有一个,名字叫。命令读取secret才知道安装了哪些包。

Helm 主要模块

1. :包含应用程序所需要的所有 k8s 资源定义。

2. :存放chart的仓库,类似于docker的镜像仓库。

3. :chart的实例化,将chart安装到k8s上,就叫做生成一个release。

Helm 的安装和基本操作

安装 Helm

因为 helm3 只有一个二进制文件,因此安装非常简单

命令自动补全,在 /etc/profile 里增加如下内容:

添加仓库

helm 和 docker 一样有默认的官方仓库,也可以添加第三方仓库和本地仓库

查看添加了哪些仓库

更新仓库缓存(helm repo add的时候会获取一次chart列表并缓存,接下来的helm search都是读取本地缓存列表,因此我们需要经常更新缓存)

移除仓库

安装应用

以安装 nginx 为例

我们安装bitnami仓库的nginx,并指定release名字为myweb

如果要指定命名空间,则加上-n参数

查看安装了哪些库

自定义参数

helm支持两种自定义参数的方式

1. values.yaml文件

2. 命令行参数--set

如果两种同时使用的话,--set的优先级要高于values.yaml,我们可以通过以下命令来查看一个chart支持哪些配置参数

使用values.yaml自定义参数来安装

使用--set自定义参数来安装

查看我们在某个chart中自定义了哪些参数

升级应用

假设要扩容cpu、memory,则修改values.yaml内容,改为

升级命令

应用回滚

回滚前先查看历史版本

获得号后就可以进行回滚操作

卸载应用

卸载并保留历史记录,加上(不影响卸载应用,但会保留记录)

查看卸载过哪些应用(只有保留记录的才能看到)

Chart 目录结构

如果我们不能联网,那么也可以通过helm创建一个本地chart

foo目录结构如下:

templates目录里下划线开头的不会被渲染,tests用于安装完成后,执行检测

测试用例

helm也支持测试用例,例如对于web应用,可以测试http接口是否为200。

那么如何让helm认为是测试使用:helm会读取templates下所有yaml,当带有如下注解时,helm则认为这是测试专用,而不是普通对象。注意,helm不会去认名字为的目录,只会认注解,因此如果tests下放置没有注解的k8s对象时会被当作普通对象对待

helm install安装后不会自动进行测试,需要手工执行helm test命令,此时会创建k8s对象(如pod)进行测试,若pod执行完毕(状态为Completed,即容器里的程序退出码为0则表示成功)

如果Phase显示Successed表示成功,检测失败则为Failed

Chart 的依赖和父子关系

简介

什么是chart依赖:如果将chart比作rpm包,则chart依赖也相当于rpm包的依赖,当yum install时候会自动安装依赖包。对于helm来说,chart依赖就是在里设置依赖哪些仓库的哪些chart,在helm intall时候就会自动把依赖的chart下载到charts目录。也可以手工把依赖包下载下来放到charts目录里。

什么是父子chart:下载、手工放到charts目录里的chart就是子chart,根目录的chart就是父chart。无论是否在Values.yaml里设置了。

简单来讲:

子Chart

只要是已经放到会helm install会自动下载到charts目录里的chart,都是子chart

chart依赖

Chart.yaml里配置了dependencies就是chart依赖

处理chart依赖的2种方式

嵌入式

手工创建,可以通过helm package打成tgz包

依赖导入式

通过仓库获取,helm dependency update会自动从指定仓库下载指定版本的chart

Chart依赖

我们来测试一下Chart的依赖,首先准备测试环境

编辑Chart.yaml,增加如下内容

file://是使用本地目录,但是只能用于外部目录,不能用于当前目录下的自定义子目录,比如

处理依赖

查看charts目录,应当有2个tgz

另外,除了update,还有build命令

build和update的区别是

update:重新读取Chart.yaml来获取依赖包

build:要先执行过update才能执行build,否则会提示Chart.lock和Chart.yaml不同步,请先update

父子Chart

怎么确定Chart的父子关系,我们看以下的例子:

在Chart包foo的子目录charts下创建新的Chart包bar,foo就是父,bar就是子

如果我们把子Chart放到外部目录,然后通过file://../bar或者其他方式引用,那么就成了依赖,而不是父子

子Chart如果没写到Chart.yaml里面,在查看依赖时候会提示,但不影响使用

Helm模板详解

模板基本使用

使用模板的含义就是要创建一个通用的Chart。如果不用模版,就需要为每个应用创建独立的deployment、service等资源对象,那么此时用helm的意义就不大,可以看下面的例子:

测试

Helm模版,支持很多特性,使用起来非常灵活,本质是基于内置的模块。如果想在Chart安装前查看模版渲染后的内容,有2种办法

1. 第一种是很纯粹的看模板渲染效果

2. 第二种还有附带install的其他信息

上面自定义参数提到的2种方法,也可以用在helm template

上面命令的前提是当前目录下有一个foo目录,如果想看仓库里的,带上仓库名即可

helm template查看的是尚未安装成release的yaml,而不是已经安装成为release的yaml。如果安装后查看yaml的命令是

模板标签

模版标签:,例如

测试

加上 # 的原因是此时的a.yaml不是合法的k8s资源对象格式

可以看出.Release.Name渲染成了release名,如果想要查看所有的变量/常量

模板注释

模板中的注释有2种

yaml的注释

模板的注释

yaml注释

模板注释

内置对象

常用的模版内置对象可查看官方文档:https://helm.sh/zh/docs/chart_template_guide/builtin_objects/

:该对象描述了版本发布本身。包含了以下对象:

:release名称

:版本中包含的命名空间(如果manifest没有覆盖的话)

:如果当前操作是升级或回滚的话,需要将该值设置为

:如果当前操作是安装的话,需要将该值设置为

:此次修订的版本号。安装时是1,每次升级或回滚都会自增

:该service用来渲染当前模板。Helm里一般是

:Values是从文件和用户提供的文件传进模板的。默认为空

:文件内容。里的任意数据在这里都可以可访问的。比如 会打印出

Chart 指南 中列出了可用字段

:在chart中提供访问所有的非特殊文件。当你不能使用它访问模板时,你可以访问其他文件。请查看这个 文件访问部分了解更多信息

通过文件名获取文件的方法。()

用字节数组代替字符串获取文件内容的方法。对图片之类的文件很有用

用给定的shell glob模式匹配文件名返回文件列表的方法

逐行读取文件内容的方法。迭代文件中每一行时很有用

使用Base 64编码字符串返回文件体的方法

使用YAML格式返回文件体的方法

:提供关于Kubernetes集群支持功能的信息

是一个版本集合

说明集群中的版本 (e.g., ) 或是资源 (e.g., ) 是否可用

和 是Kubernetes的版本号

Kubernetes的主版本

Kubernetes的次版本

:包含了已经被执行的当前模板信息

: 当前模板的命名空间文件路径 (e.g. )

: 当前chart模板目录的路径 (e.g. )

模板函数

使用函数有2种写法:函数名前置和管道,效果是相同的,管道主要用于组合多个函数使用

helm内置很多模版函数,这里无法一一列举,因此选取几个常用来说明

quote:双引号

default:默认值

indent:缩进

nindent:新换行,再缩进,并且只能处理字符串,而且不能用

title:首字母大写

upper:全部大写

b64enc:base64编码

b64dec:base64解码

更多内置函数,详见:https://helm.sh/docs/chart_template_guide/function_list

条件判断if

if/else

if如何判断条件是否为假

布尔值false

数字0

空字符串""

不存在的变量/常量,如(假设xxx不存在)

空集合(map, slice, tuple, dict, array),如values.yaml里有

除此之外条件都为真

示例如下:

字符串/数字大小 比较

eq:字符串相同/数字相同

ne:字符串不同/数字不同

lt:字符串(根据编码)前者小于后者/数字前者小于后者

le:字符串(根据编码)前者小于等于后者/数字前者小于等于后者

gt:字符串(根据编码)前者大于后者/数字前者大于后者

ge:字符串(根据编码)前者大于等于后者/数字前者大于等于后者

数字比较,要用格式,即带小数点的

示例如下:

空白符

遍历with/range

with:用于map结构

假设values.yaml里有这么一段

用省去了

可以用函数进一步简写

range

和with很像,更适合数组而不是map(即hash),因为range会自动将map结构中的value获取出来(忽略key)

渲染为如下,可以看到少了key

因此range更适合数组,假设values.yaml有一段

示例如下:

with里不能用变量

假设values.yaml

模板

会报错,因为用了with后,.Release.Name变成是从with .Values.aa里找,当然找不到。有2个解决办法:

变量赋值

用$符号:

range获取键值

命名模板

使用函数定义命名模板,使用函数引用命名模板

可以写在templates的yaml里也可以写在(templates目录里)作为全局使用

直接写在templates的yaml里

写在里

上述2种方法输出结果都是

template函数不支持管道

会报错,解决办法:改用函数

变量/常量/作用域

变量

常量

yaml语法自带的节点定位()

常量:values.yaml里定义的replicaCount: 1

共享常量

子chart和父chart之间的常量不能共享,如果需要共享,就需要共享常量,这定义在父chart中

父chart的values.yaml里加入

注意必须是子chart名,即charts目录里存在该名字

接下来,子chart的模板里就可以引用

当helm发现节点名是子chart名时,它会自动拷贝这个常量到子chart的values.yaml中

全局常量

共享常量只能把常量共享给一个子chart,如果需要多个子chart之间共享,需要全局常量。在父chart的values.yaml里用标识

父chart的values.yaml里加入

父和子chart的模板里都可以引用

搭建私有仓库

安装push插件

ChartMuseum

官方提供的私有仓库,功能较少,适合学习测试使用,类似docker的registry

上传chart方法1:chartmuseum专属方法,不通用

上传chart方法2:使用push插件(要先添加仓库)

查询有哪些chart

下载chart

Harbor

harbor内置集成了chartmuseum

在harbor上配置

创建用户,假设为user1

创建私有项目,假设为helm

将user1添加到helm项目里

添加仓库

输入密码后,成功的话会提示

上传chart并查看

下载chart

生产环境最佳实践

建议1:参数名要统一,尤其在一个团队里。例如表示deployment副本数,不要有的用replicas,有的用replicaCount

建议2:给参数加注释。因为chart写好后很少需要改动,时间长了容易忘。

建议3:针对不同环境(开发/测试/生产),创建不同的values.yaml,如values-dev.yaml、values-production.yaml

其中第4点例子如下,假设values.yaml里有如下内容

要求image参数必须存在,要求image必须存在repository和pullPolicy

repository类型为字符串,值的格式为小写字母、数字、横线、下划线

pullPolicy类型为字符串,值只能有3种:Always、Never、IfNotPresent

在同级目录下创建,内容如下

执行helm install、helm upgrade、helm lint、helm template测试,若不满足如上3点要求,则应当报错。

建议5:在chart目录下放置README.md,将chart的设计思想、注意事项写清楚,推荐格式如下

建议6:templates里的NOTES.txt是部署完成后看到的内容,针对不同条件设置输出

建议7:helm默认读取/root/.kube/config,但这样权限过大,很不安全,而且helm通常是由开发或CD系统来使用,因此需要提前在K8S的RBAC里创建分配好权限,只允许在指定的namespace里进行部署

建议8:不要把各种微服务集中于一个chart,可以采用父子chart方式,让每个chart更轻量

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐