Helm
常用命令
|  |  | 
    --set 定制安装
当你安装 Helm charts 时,你可以通过两种方式传递配置数据,让安装更符合你的需求:
- 使用 --values参数(或者-f简写):通过指定一个 YAML 文件来覆盖默认的 values,这个文件中可以指定多个值,最终会使用文件中最后出现的值。
- 使用 --set参数:直接在命令行上指定要覆盖的配置。
如果你同时使用这两个参数,那么 --values(或 -f)的值会被合并到具有更高优先级的 --set 中。使用 --set 指定的值会被持久化在 ConfigMap 中,你可以通过运行 helm get values <release-name> 命令来查看已经设置的值。你也可以通过运行 helm upgrade 并指定 --reset 参数来清除已设置的值。
--set 选项可以接受零个或多个名/值对。最简单的用法是 --set name=value,这相当于在 YAML 文件中写入:
|  |  | 
你也可以用逗号分隔多个值,比如 --set a=b,c=d,相当于在 YAML 文件中写入:
|  |  | 
--set 还支持更复杂的表达式,比如 --set outer.inner=value,对应的 YAML 结构为:
|  |  | 
对于列表数组,可以使用大括号来包裹,比如 --set name={a, b, c},对应的 YAML 结构为:
|  |  | 
从 Helm 2.5.0 开始,你还可以使用数组索引语法来访问列表中的某个项,比如 --set servers[0].port=80,对应的 YAML 结构为:
|  |  | 
你也可以一次设置多个值,比如 --set servers[0].port=80,servers[0].host=example,对应的 YAML 结构为:
|  |  | 
有时候你可能需要在 --set 选项中使用特殊字符,这时可以使用反斜杠来转义字符,比如 --set name=value1\,value2,对应的 YAML 结构为:
|  |  | 
同样地,你也可以转义点号(.)。这在 chart 模板中使用 toYaml 函数来解析 annotations、labels 以及 node selectors 等时非常有用。比如 --set nodeSelector."kubernetes\.io/role"=master,对应的 YAML 结构为:
|  |  | 
Chart 文件目录结构
|  |  | 
Values
内置的 Values
Helm 有一些预定义的对象和值,这些可以在模板中使用。以下是一些主要的预定义值:
- 
.Release: 在 Helm 运行时自动提供的。这些值包括 Helm release 的详细信息,如名称、命名空间、是否为升级操作等。在你的示例中,{{ .Release.Name }}将被替换为当前 Helm release 的名称。例如,如果你使用helm install my-release my-chart命令安装 chart,那么{{ .Release.Name }}将被替换为my-release。这个对象描述了 release 本身。它有几个预定义的值,包括:- .Release.Name: release 的名称。
- .Release.Namespace: release 被安装的命名空间。
- .Release.IsUpgrade: 这是一个布尔值,表示当前操作是否是一个升级操作。
- .Release.IsInstall: 这是一个布尔值,表示当前操作是否是一个安装操作。
- .Release.Revision: 当前 release 的修订版本号。
 
- 
.Values: 这个对象包含了values.yaml文件中定义的值。
- 
.Chart: 来自于 Helm chart 的Chart.yaml文件。这个文件包含了 chart 的元数据,例如 chart 的名称、版本、描述等。它有几个预定义的值,包括:- .Chart.Name: chart 的名称。
- .Chart.Version: chart 的版本。
- .Chart.AppVersion: chart 的 app 版本。
 
- 
.Files: 来自 Helm chart 的文件系统。这个对象提供了一种方法,可以让你在模板中访问 chart 文件夹中的非模板文件。例如,如果你的 chart 文件夹中有一个名为config.ini的文件,你可以在模板中使用{{ .Files.Get "config.ini" }}来获取该文件的内容。
- 
.Capabilities: 来自 Helm 运行时环境,它提供了关于 Kubernetes 集群的信息。这些信息包括 Kubernetes 的版本、API 版本、Helm 版本等。例如,.Capabilities.KubeVersion提供了 Kubernetes 的版本信息,.Capabilities.APIVersions.Has "batch/v1"可以用来检查 Kubernetes 集群是否支持batch/v1API 版本。
- 
.Template: 来自 Helm 的运行时环境。这个对象包含了关于当前正在执行的模板的信息。例如,.Template.Name提供了当前模板的名称(包括路径),.Template.BasePath提供了当前 chart 的模板目录的路径。
全局的 Values
- 全局值是可以从任何图表或子图表通过完全相同的名称访问的值。全局值需要明确声明,不能将现有的非全局值当作全局值使用。
- Values 数据类型有一个名为 Values.global 的保留部分,可以在其中设置全局值。例如,在 mychart/values.yaml文件中设置一个全局值。
- 由于全局值的工作方式,mychart/templates/configmap.yaml和mysubchart/templates/configmap.yaml都应该能够以{{ .Values.global.salad }}的形式访问该值。
- 如果我们进行干运行安装,我们将在两个输出中看到相同的值。
- 全局值对于传递这样的信息很有用,尽管需要一些规划来确保正确的模板被配置为使用全局值。
- 父图表和子图表可以共享模板。任何图表中定义的块都可以供其他图表使用。
- 我们可以定义一个简单的模板,如 {{- define "labels" }}from: mychart{{ end }}。请记住,模板上的标签是全局共享的。因此,标签图表可以从任何其他图表中包含。
- 虽然图表开发者可以在 include和template之间选择,但使用include的一个优点是include可以动态引用模板:{{ include $mytemplate }}。上述将解引用$mytemplate。相比之下,template函数只接受字符串字面量。
- 避免使用块。Go 模板语言提供了一个 block关键字,允许开发者提供一个默认实现,后续可以覆盖。在 Helm 图表中,块不是最好的覆盖工具,因为如果提供了同一块的多个实现,选择哪一个是不可预测的。建议使用include。
Custom Resource Definitions
以下是关于 Helm 中自定义资源定义(CRDs)的一些关键点:
- 
CRD 有两个部分:CRD 的声明( kind: CustomResourceDefinition的 YAML 文件)和使用 CRD 的资源(例如,如果 CRD 定义了foo.example.com/v1,那么任何apiVersion: example.com/v1和kind: Foo的资源都是使用该 CRD 的资源)。
- 
在使用 CRD 的资源之前,必须先安装 CRD 的声明。这是因为 Kubernetes 需要一些时间来注册 CRD。 
- 
Helm 3 提供了一个名为 crds的特殊目录,你可以在这个目录中放置你的 CRDs。这些 CRDs 不会被模板化,但在运行 helm 安装 chart 时会默认安装。如果 CRD 已经存在,它将被跳过并给出警告。如果你希望跳过 CRD 的安装步骤,你可以传递--skip-crds标志。
- 
目前,Helm 不支持升级或删除 CRDs。这是经过社区讨论后的明确决定,因为这可能导致数据意外丢失。此外,目前社区对于如何处理 CRDs 及其生命周期还没有达成共识。随着这个问题的发展,Helm 将添加对这些用例的支持。 
- 
Helm 的 --dry-run标志目前不支持 CRDs。这是因为 “Dry Run” 的目的是验证 chart 的输出是否可以在发送到服务器后正常工作。但是,CRDs 实际上是修改了服务器的行为。Helm 无法在 dry run 中安装 CRD,因此 discovery 客户端将不知道该自定义资源(CR),并且验证将失败。
- 
另一种处理 CRD 的方法是将 CRD 定义放在一个 chart 中,然后将使用该 CRD 的任何资源放在另一个 chart 中。在这种方法中,每个 chart 必须单独安装。然而,这种工作流可能对具有集群管理员访问权限的集群运维人员更有用。 
Chart 示例
|  |  | 
函数库
Helm 模板支持以下函数库:
- 
Sprig: Sprig 是一个 Go 语言的函数库,提供了一系列用于处理字符串、日期、字典、加密等常见任务的函数。例如,你可以使用 trim函数来删除字符串的前导和尾随空格,或者使用upper函数将字符串转换为大写。
- 
Helm 内置函数: Helm 还提供了一些内置函数,例如 include用于包含并解析其他模板,required用于声明某个值是必需的,如果该值为空或不存在,Helm 将停止并返回错误。
- 
Pipelines and flow control: Helm 模板支持 Go 语言的管道和流控制结构,例如 if、else、with、range等。
- 
Values functions: Helm 还提供了一些函数用于处理 values 文件中的值,例如 .Values用于访问 values 文件中的值,.Files用于访问 chart 中的文件,.Capabilities用于访问 Kubernetes 集群的功能。
- 
Chart functions: Helm 还提供了一些函数用于处理 chart,例如 .Chart用于访问 chart 的元数据,.Release用于访问 release 的信息,.Template用于访问当前模板的信息。
Named Templates
- Named Templates,也被称为 partials 或 subtemplates,是在文件中定义并赋予名称的模板。
- 在命名模板时,模板名称是全局的。如果声明了两个同名的模板,最后加载的那个将被使用。
- 为了避免命名冲突,一种常见的命名约定是在每个定义的模板前加上图表的名称,例如:{{ define "mychart.labels" }}。
- 文件名以下划线(_)开头的文件被认为不包含清单。这些文件不会被渲染为 Kubernetes 对象定义,但可以在其他图表模板中使用。
- define动作允许我们在模板文件中创建一个命名模板。例如,我们可以定义一个模板来封装 Kubernetes 的标签块。
- template动作允许我们在现有的 ConfigMap 中嵌入这个模板,然后使用- template动作来包含它。
- include函数允许我们将模板的内容导入到当前的管道中,其中它可以被传递给管道中的其他函数。
- 在定义的模板中,我们可以包含图表名称和图表版本。如果我们在渲染时遇到错误,我们可以通过传递作用域给模板来解决这个问题。
- 在 Helm 模板中,使用 include而不是template是更好的选择,因为这样可以更好地处理输出格式化。
访问模板中的文件
在 Helm 中,你可以通过 .Files 对象访问文件。这使得你可以在模板中导入非模板文件,并在不通过模板渲染器处理内容的情况下注入其内容。以下是一些关键点:
- 你可以向 Helm 图表添加额外的文件,这些文件将被打包。但是要注意,由于 Kubernetes 对象的存储限制,图表的大小必须小于 1M。
- 出于安全原因,有些文件不能通过 .Files对象访问,例如templates/目录中的文件,被.helmignore排除的文件,以及 Helm 应用子图表之外的文件。
- Helm 不保留 UNIX 模式信息,因此文件级权限对 .Files对象可用文件的影响无效。
- 你可以使用 .Files对象的方法,如Get,Glob,Lines等,来读取文件内容或获取文件列表。
- 你可以使用 AsConfig和AsSecrets方法将文件内容放入 ConfigMaps 和 Secrets 中。
- 你可以使用 b64enc函数将文件内容进行 base-64 编码,以确保成功传输。
- 在 Helm 安装期间,无法传递图表外部的文件。所以如果你要求用户提供数据,必须使用 helm install -f或helm install --set来加载。
子 Charts
Subcharts and Global Values 是 Helm 中的两个重要概念。
- 
Subcharts:Subcharts 是 Helm chart 的依赖项,它们也有自己的值和模板。Subcharts 被视为 “stand-alone”,这意味着它们不能显式地依赖于其父 chart。因此,Subchart 不能访问其父 chart 的值。但是,父 chart 可以覆盖 Subcharts 的值。 
- 
Global Values:Helm 有一个全局值的概念,所有的 chart 都可以访问这些值。全局值需要显式声明,不能将现有的非全局值当作全局值使用。全局值可以在 Values.global中设置。
创建 Subchart 的步骤如下:
- 在 mychart/charts目录下创建一个新的 chart(例如,mysubchart)。
- 删除所有基础模板,以便从头开始。
- 在 mysubchart中创建一个简单的模板和值文件。
父 chart 可以覆盖 Subchart 的值。例如,我们可以在 mychart/values.yaml 中修改 mysubchart 的 dessert 值。
全局值可以被任何 chart 或 subchart 访问。例如,我们可以在 mychart/values.yaml 文件中设置一个全局值 salad,然后在 mychart/templates/configmap.yaml 和 mysubchart/templates/configmap.yaml 中都可以访问这个值。
父 chart 和 subchart 可以共享模板。任何在任何 chart 中定义的块都可以被其他 chart 使用。例如,我们可以定义一个简单的模板 labels,然后在任何其他 chart 中都可以包含这个模板。
注意,Go 模板语言提供了一个 block 关键字,允许开发者提供一个默认实现,然后在后面覆盖它。但在 Helm charts 中,block 不是覆盖的最佳工具,因为如果提供了多个相同的 block 实现,选择哪个是不可预测的。建议使用 include。
Chart Hooks
Helm 提供了一个钩子机制,允许图表开发者在发布生命周期的某些点进行干预。例如,你可以使用钩子来:
- 在安装任何其他图表之前,加载 ConfigMap 或 Secret。
- 在安装新图表之前,执行一个 Job 来备份数据库,然后在升级后执行第二个 Job 来恢复数据。
- 在删除发布之前运行一个 Job,以便在删除服务之前优雅地将其从轮换中移除。
钩子就像常规模板一样工作,但是它们有特殊的注解,使 Helm 以不同的方式使用它们。在这一部分,我们将介绍钩子的基本使用模式。
钩子和发布生命周期 钩子允许你,图表开发者,在发布生命周期的关键点进行操作。例如,考虑 helm install 的生命周期。默认情况下,生命周期如下:
- 用户运行 helm install foo
- 调用 Helm 库安装 API
- 在一些验证之后,库渲染 foo 模板
- 库将生成的资源加载到 Kubernetes
- 库将发布对象(和其他数据)返回给客户端
- 客户端退出
Helm 为安装生命周期定义了两个钩子:pre-install 和 post-install。如果 foo 图表的开发者实现了这两个钩子,生命周期就会像这样改变:
- 用户运行 helm install foo
- 调用 Helm 库安装 API
- 在 crds/ 目录中安装 CRDs
- 在一些验证之后,库渲染 foo 模板
- 库准备执行 pre-install 钩子(将钩子资源加载到 Kubernetes)
- 库按权重(默认为 0)、资源类型和名称的升序对钩子进行排序。
- 然后,库首先加载权重最低的钩子(从负到正)
- 库等待直到钩子处于 “就绪” 状态(除了 CRDs)
- 库将生成的资源加载到 Kubernetes。注意,如果设置了 –wait 标志,库将等待所有资源处于就绪状态,并且在它们就绪之前不会运行 post-install 钩子。
- 库执行 post-install 钩子(加载钩子资源)
- 库等待直到钩子处于 “就绪” 状态
- 库将发布对象(和其他数据)返回给客户端
- 客户端退出
编写钩子 钩子只是带有特殊注解的 Kubernetes 清单文件。因为它们是模板文件,所以你可以使用所有的正常模板功能,包括读取 .Values、.Release 和 .Template。
例如,这个模板,存储在 templates/post-install-job.yaml 中,声明了一个在 post-install 运行的 job:
|  |  | 
使这个模板成为钩子的是注解:
|  |  | 
一个资源可以实现多个钩子:
|  |  | 
同样,对于可以实现给定钩子的不同资源没有限制。例如,可以声明一个 secret 和一个 config map 作为 pre-install 钩子。
当子图表声明钩子时,这些也会被评估。顶级图表无法禁用子图表声明的钩子。
可以为钩子定义一个权重,这将有助于构建一个确定的执行顺序。权重是使用以下注解定义的:
|  |  | 
钩子删除策略 可以定义决定何时删除相应钩子资源的策略。钩子删除策略是使用以下注解定义的:
|  |  | 
你可以选择一个或多个定义的注解值:
注解值 描述 before-hook-creation 在启动新钩子之前删除之前的资源(默认) hook-succeeded 在钩子成功执行后删除资源 hook-failed 如果钩子在执行过程中失败,则删除资源 如果没有指定钩子删除策略注解,则默认应用 before-hook-creation 行为。
    NOTES.txt 文件
NOTES.txt 文件会在用户安装或升级 Helm chart 时显示。在这个文件中,我们使用了一些内置的 Helm 模板变量,如 .Chart.Name 和 .Release.Name,分别表示 chart 的名称和 release 的名称。用户可以通过运行 helm status 和 helm get all 命令来获取更多关于 release 的信息。
|  |  | 
    .helmignore 文件
.helmignore 文件用于指定你不希望包含在 Helm chart 中的文件。如果这个文件存在,helm package命令在打包应用程序时,将忽略所有与.helmignore文件中指定的模式匹配的文件。这可以帮助避免将不必要的或敏感的文件或目录添加到你的 Helm chart 中。.helmignore文件支持 Unix shell glob 匹配、相对路径匹配和否定(以 ! 为前缀)。每行只考虑一个模式。
|  |  |