Helm是一款非常流行的k8s包管理工具。以前就一直想用它,但看到它产生的文件比k8s要复杂许多,就一直犹豫,不知道它的好处能不能抵消掉它的复杂度。但如果不用,而是用Kubectl来进行调式真的很麻烦。正好最近Helm3正式版出来了,比原来的Helm2简单了不少,就决定还是试用一下。结果证明确实很复杂,它的好处和坏处大致相当。有了它确实能大大简化对k8s的调式,但也需要花费比较多的时间来学习,而且产生的配置文件要复杂许多。但是事实是现在没有什么很方便的帮助调式k8s的工具,在没有更好的方案之前,我还是建议用它,只是前期需要花些功夫学习和掌握它。
Helm3和Helm2的语法差不太多,只是使用起来更方便,不用安装Tiller。一个比较明显的变化是不再需要“requirements.yaml”, 依赖关系是直接在“chart.yaml”中定义。有关Helm3和Helm2的区别,详情请参见CHANGES SINCE HELM 2。
网上有不少讲述Helm的文章,但大部分都是主要讲解安装和举一个简单的例子。但Helm使用起来还是比较复杂的,一定要有一个复杂的例子才能把它的功能讲清楚,里面有不少设计方面的问题需要思考。我刚开始接触的时候就觉得头绪繁多,不知从哪下手。本文就通过一个相对复杂的例子来讲解用Helm3来设计配置文件的思路,使上手更容易。
这里不讲Helm3的安装,它比较很容易。也不讲解Helm的基本语法,你可以自己去看其他文档。即使你不懂Helm,应该也能猜出七八成,剩下的就要读文档了(Charts)。Helm的语法还是比较复杂的,要想搞懂可能要花一两天时间。
本文假设你对helm有一个大概的了解,想要构建一个复杂的微服务,但有不知如何下手;或者你想了解一下构建Helm的最佳实践,那就请你继续读下去。
Helm文件结构
chart里一个很重要的概念就是模板(template),它就是Go语言模板,它是里面加入了编程逻辑的k8s文件。这些模板文件在使用时都要先进行模板解析,把其中的程序逻辑转化成对应的编码,最终生成k8s配置文件。

以上就是Helm自动生成的chart目录结构,在Helm里每个项目叫一个chart,它由下面几个组成部分:
- “Chart.yaml”:存有这个chart的基本信息,
- "values.yaml":定义模板中要用到的常量。
- “template”目录:里面存有全部的模板文件,其中最重要的是“deployment.yaml”和“service.yaml”,分别是部署和服务文件. "helpers.tpl"用来定义变量,"ingress.yaml"和"serviceaccount.yaml"分别是对外接口和服务账户,这里暂时没用,“NOTES.txt”是注释文件。
- “charts”目录: 存有这个chart依赖的所有子chart。
Helm的基本元素
Helm有四个基本元素,值,常量,变量和共享常量(这个后面会讲)
值(literal)
Helm在k8s的基础之上增加了模板功能,使k8s的配置文件更加灵活。里面的主要概念就是模板(Template),也就是在k8s的配置文件里增加了常量和变量以及编程逻辑。如果你不用这些新增功能,那么就是普通的YAML文件(k8s配置文件),里面用到的基本元素就是值。
常量
节点定位(Node Anchor):
如果你想复用重复的值,能把它定义成常量吗?YAML有一个功能叫节点定位(Node Anchor),类似于定义一个常量,然后引用。但它有一些限制,定义的必须是一个节点,因此不如真正的常量灵活。
例如如下文件中,用“&”定义了一个常量“&k8sdemoDatabaseService”,然后用“*k8sdemoDatabaseService”引用它。
global:
k8sdemoDatabaseService: &k8sdemoDatabaseService k8sdemo-database-service
mysqlHost: *k8sdemoDatabaseService
这时,“k8sdemoDatabaseService:”是YAML文件节点的键名,“&k8sdemoDatabaseService”是节点定位的名字,相当于常量名,“k8sdemo-database-service”是YAML节点的键值。在上述代码中,k8sdemoDatabaseService和mysqlHost的值都是“k8sdemo-database-service”。
有关节点定位(Node Anchor)的详细内容,请参见 YAML。
常量:
由于节点定位的局限性,Helm引入了真正的常量,也就是在"values.yaml"里定义的内容,它可以定义是任何东西,不只限于节点。
在"values.yaml"里定义常量:
replicaCount: 1
在部署模板里引用:
replicas: {
{
.Values.replicaCount }}
那么什么时候用常量,什么时候用值(Literal)呢?如果一个值在模板中出现多次,就要定义常量,避免重复。例如“accessModes”,既要在存储卷里出现,又要在存储卷申请里出现。另外如果值有可能变化(不论是随部署环境变化,还是随时间变化),那么就定义成常量,这样在修改时就只用改"values.yaml",而不必修改模板文件。例如“replicas”的值(也就是集群的个数)是可能变化的,就要定义成常量。在模板里可以引用常量的,但在"values.yaml"里不行,因为它只是普通YAML文件,没有模板解析功能,因此不支持常量,这里就只能用节点定位(来代替常量)。
有关Helm常量的详细内容,请参见 Use placeholders in yaml和Use YAML with variables。
变量
节点定位的功能是有限的,例如你想利用已有的节点定位,对它进行转换,定义一个新的节点定位,这在"values.yaml"里就不行了。
例如你已有节点定位“name”,你想在这个基础上定义一个新的节点定位“serviceName”,这个"values.yaml"就不支持了,你必须要用模板。
如下所示,这在"values.yaml"里是不支持的。
name: &name k8sdemo-backend
serviceName:*name-service
这就引出了变量的概念,但它只能在模板里才行。 换句话说,模板既支持常量,也支持变量。但如果把变量的定义逻辑放在Helm每个模板里,就显得很乱。因此一般的做法是把这些逻辑放在一个单独的模板文件里,这个就是前面讲到的"_helpers.tpl"文件。当你需要对常量进行转换,生成新的常量,你就在定义变量,这部分代码就放在"_helpers.tpl"里。
下面就是"_helpers.tpl"中定义"k8sdemo.name"的代码。
{
{
- define "k8sdemo.name" -}}
{
{
- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{
{
- end -}}
在以上这些元素中,常量(也就是在"values.yaml"中定义的)是最灵活的,能用它时尽量用它。而且因为它是定义在普通YAML文件中(“values.ya

本文深入探讨了使用Helm3构建多层微服务的实践,包括Helm的文件结构、基本元素如值、常量、变量和共享常量,以及调试流程。通过一个复杂的微服务示例,解释了如何设计和管理配置文件,阐述了Helm3相对于Helm2的改进,强调了在没有便捷的k8s调试工具时,Helm3的价值。同时,文章提供了调试各个服务的步骤,以及处理依赖关系和共享常量的方法,帮助读者更好地理解和应用Helm3。
最低0.47元/天 解锁文章
1119

被折叠的 条评论
为什么被折叠?



