helm是一个简化安装和管理Kubernetes应用程序的工具,可以将其视为Kubernetes的apt/yum/homebrew
。
helm是用于管理charts的工具,charts是预先配置的Kubernetes资源的软件包。
官网:https://helm.sh,最新版本:v3.3.0
helm用途:
1. 查找并使用Helm Charts将应用程序部署在Kubernetes上
2. 通过Helm Charts将应用程序共享
3. 对Kubernetes应用程序实现可重复构建
4. 简便管理Kubernetes清单文件
5. 管理Helm包的发布
helm概念:
Chart:Helm应用(package),包括对资源的定义及相关镜像的引用,还有模板文件、values文件等
Repository:Chart仓库,http/https服务器,Chart的程序包放在这里
Release:Chart的部署实例,每个Chart可以部署一个或多个Release
helm版本:
在 Helm 2 中,Tiller 是作为一个 Deployment 部署在 kube-system 命名空间中,很多情况下,我们会为 Tiller 准备一个 ServiceAccount ,这个 ServiceAccount 通常拥有集群的所有权限。
用户可以使用本地 Helm 命令,自由地连接到 Tiller 中并通过 Tiller 创建、修改、删除任意命名空间下的任意资源。
在 Helm 3 中,Tiller 被移除了。新的 Helm 客户端会像 kubectl 命令一样,读取本地的 kubeconfig 文件,使用我们在 kubeconfig 中预先定义好的权限来进行一系列操作。
chart是包含至少两项内容的helm软件包:
软件包说明(Chart.yaml)
一个或多个模板,其中包含Kubernetes清单文件
chart是描述一组相关的Kubernetes资源的文件的集合。单个chart可能用于部署简单的内容(如memcached pod)或复杂的内容(如带有http servers,数据库,缓存等的完整Web应用程序堆栈)。
chart创建为放置在特定目录树中的文件,可以将它们打包到版本存档中进行部署。
如果要下载并查看已发布chart的文件而不安装它,则可以使用 helm pull
进行操作。
chart被组织为目录内文件的集合,目录名称就是chart的名称(不包含版本信息)。因此,描述WordPress的chart将存储在wordpress/
目录中。
而在此目录中,helm将期望与以下内容匹配的结构:
wordpress/
Chart.yaml # 包含chart信息的YAML文件
LICENSE # 包含chart许可的纯文本文件(可选)
README.md # README自述文件(可选)
values.yaml # 此chart的默认配置值
values.schema.json # 用于在 values.yaml 上强加结构的JSON模式(可选)
charts/ # 包含此chart所依赖的任何charts的目录
crds/ # 自定义资源定义(CRD)
templates/ # 模板目录,与值结合时,将生成有效的Kubernetes清单文件
templates/NOTES.txt # 包含简短用法说明的纯文本文件(可选)
helm保留了charts/
、crds/
和templates/
目录的使用,以及列出的文件名。其他文件将保持原样。
Chart.yaml
文件是chart所必需的。它包含以下字段:
apiVersion: # chart API版本 (必需)
name: # chart 名称 (必需)
version: # 版本 (必需, SemVer 2标准)
kubeVersion: # 所有兼容的Kubernetes 版本 (可选, SemVer 2标准)
description: # 项目单句描述 (可选)
type: # chart 类型,application 和 library (可选)
keywords:
- # 关于项目的关键字列表 (可选)
home: # 项目主页的url (可选)
sources:
- # 项目源码的url列表 (可选)
dependencies: # chart 需求列表 (可选)
- name: # chart 名称 (nginx)
version: # chart 版本 ("1.2.3")
repository: # repo url ("https://example.com/charts") 或 别名 ("@repo-name")
condition: # 一个解析为boolean的yaml路径,用于 启用/禁用 charts (如 subchart1.enabled ) (可选)
tags: # (可选)
- # Tags 可以用来对 charts 的 启用/禁用 分组 (可选)
enabled: # 使用 bool 参数决定是否应该加载 chart (可选)
import-values: # (可选)
- # ImportValues 保存源值到要导入父键的映射。每一项可以是一个字符串或一对子/父子列表项 (可选)
alias: # 用于 chart 的别名。多次添加相同的 chart 时很有用 (可选)
maintainers: # (可选)
- name: # 维护人员名称 (每个维护人员必需)
email: # 维护人员email (每个维护人员可选)
url: # 维护人员的url (每个维护人员可选)
icon: # 作为图标使用的 SVG 或 PNG 图片 的url (可选)
appVersion: # app 版本 (可选)
deprecated: # chart 是否已弃用 (可选, boolean)
annotations:
example: # 按名称键入的注释列表 (可选)
helm中,一个chart可能会依赖任意数量的其它chart。这些依赖项可以在Chart.yaml
中通过dependencies
字段进行动态配置,也可以导入charts/
目录中并手动进行管理。
当前chart所依赖的chart在dependencies
字段中定义为列表:
dependencies:
- name: apache
version: 1.2.3
repository: https://example.com/charts
- name: mysql
version: 3.2.1
repository: https://another.example.com/charts
该repository
字段是chart repo的完整url。需要注意的是,必须使用helm repo add
本地添加该repo。可以使用存储库的名称代替url。
helm repo add example-charts https://example.com/charts
dependencies:
- name: apache
version: 1.2.3
repository: "@example-charts"
定义依赖项后,可以运行helm dependency update
,它将使用依赖项文件将所有指定的chart下载到您的charts/
目录中。
除上述字段外,每个依赖项都可以包含可选字段alias
。
为依赖的chart添加别名,将chart置于依赖关系中时将使用别名作为依赖项的名称。
dependencies:
- name: subchart
repository: http://localhost:10191
version: 0.1.0
alias: new-subchart-1
- name: subchart
repository: http://localhost:10191
version: 0.1.0
alias: new-subchart-2
- name: subchart
repository: http://localhost:10191
version: 0.1.0
在上面的示例中,将获得3个依赖项:
subchart
new-subchart-1
new-subchart-2
除上述字段外,每个依赖项还可以包含可选字段tags
和condition
。
默认情况下会加载所有chart。如果存在tags
或condition
字段,则它们将被用于控制应用它们的chart的加载。
condition
字段包含一个或多个yaml路径(以逗号分隔)。如果此路径存在于父chart的Values
中并解析为布尔值,则将基于该布尔值 启用/禁用 chart。仅列表中找到的第一个路径有效,如果不存在路径,则该条件无效。
tags
字段是与该chart关联的yaml标签列表。在父chart的Values
中,可以通过指定标签和布尔值来 启用/禁用 所有带有标签的chart。
dependencies:
- name: subchart1
repository: http://localhost:10191
version: 0.1.0
condition: subchart1.enabled, global.subchart1.enabled
tags:
- front-end
- subchart1
- name: subchart2
repository: http://localhost:10191
version: 0.1.0
condition: subchart2.enabled,global.subchart2.enabled
tags:
- back-end
- subchart2
values.yaml
subchart1:
enabled: true
tags:
front-end: false
back-end: true
上面示例中,所有带有标签front-end
都将被禁用,但是由于subchart1.enabled
路径在父chart的Values
中为true,因此条件将覆盖front-end
标签并启用subchart1
。
由于subchart2
带有标签back-end
,且back-end
为true,subchart2
将被启用。另外,尽管subchart2
指定了条件,但父chart的Values
中没有相应的路径和值,因此该条件无效。
--set
参数可以用于更改标签和条件值:
helm install --set tags.front-end=true --set subchart2.enabled=false
标签和条件解析:
- 条件(有设置时)始终会覆盖标签。存在的第一个条件路径获胜,后续条件路径将被忽略
- 如果chart的任何标签为true,则启用该chart
- 标签和条件值必须设置在父chart的 Values 中
- tags:父chart的 Values 中的键必须是顶级键;不支持全局和嵌套表
对象从模板引擎传递到模板中。
对象可以很简单,只有一个值;或者可以包含其他对象或函数。例如,Release
对象包含多个对象(如 Release.Name
)并且 Files
对象具有一些函数。
Release:此对象描述发行版本身。它里面有几个对象:
Release.Name:release 名称
Release.Namespace:release 的 namespace(如果清单未覆盖)
Release.IsUpgrade:如果当前操作是upgrade或rollback,则设置为 true
Release.IsInstall:如果当前操作是install,则设置为 true
Release.Revision:release的版本号。初始部署时为1,并且每次升级或回滚时加1
Release.Service:release 服务的名称。在Helm上,始终是Helm
Values:从 values.yaml 文件和用户提供的文件传入模板的值,默认情况下 Values 为空
Chart:Chart.yaml 文件的内容。Chart.yaml 中的任何数据都可以在此处访问
Files:提供对 chart 中所有非特殊文件的访问。不能使用它来访问模板,但是可以使用它来访问 chart 中的其他文件:
Files.Get:是用于通过名称(.Files.Get config.ini)获取文件的函数
Files.GetBytes:是将文件内容作为字节数组而不是字符串获取的函数
Files.Glob:是一个函数,该函数返回名称与给定的Shell Glob模式匹配的文件列表
Files.Lines:是逐行读取文件的函数,对于遍历文件很有用
Files.AsSecrets:是将文件主体作为Base64编码的字符串返回的函数
Files.AsConfig:是一个将文件正文作为YAML映射返回的函数
Capabilities:提供了有关Kubernetes集群支持哪些功能的信息:
Capabilities.APIVersions:是一组版本
Capabilities.APIVersions.Has $version:指示版本(例如 batch/v1)或资源(例如 apps/v1/Deployment)在集群上是否可用
Capabilities.KubeVersion 和 Capabilities.KubeVersion.Version:是Kubernetes版本
Capabilities.KubeVersion.Major:是Kubernetes的主要版本
Capabilities.KubeVersion.Minor:是Kubernetes的次要版本
Template:包含有关正在执行的当前模板的信息:
Template.Name:当前模板的命名空间文件路径(例如 mychart/templates/mytemplate.yaml)
Template.BasePath:当前 chart 的模板目录的命名空间路径(例如 mychart/templates)
上⾯的值可用于任何顶级模板,要注意内置值始终以大写字母开头。
helm模板提供的内置对象之一是Values
,该对象提供对传递到chart中的值的访问。其内容来自多种来源:
1. chart 中的 values.yaml 文件
2. 如果是子chart,则是父chart 中的 values.yaml 文件
3. helm install 或 helm upgrade 带的 -f 参数指定的yaml文件(如 helm install -f myvals.yaml ./mychart)
4. 通过 --set 参数传递的值(如 helm install --set foo=bar ./mychart)
上面按顺序排列:values.yaml
是默认值,可以被父chart的 values.yaml
覆盖,而后者可以由用户提供的yaml文件覆盖,而后者又可以由 --set
参数覆盖。
示例 values.yaml
favorite:
drink: coffee
food: pizza
根据示例 values.yaml,可以这样修改模板:
apiVersion: v1
kind: ConfigMap
metadata:
name: {
{
.Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {
{
.Values.favorite.drink }}
food: {
{
.Values.favorite.food }}
当将 .Values
对象中的字符串注入到模板时,可以通过调用模板函数 quote
来引用这些字符串:
apiVersion: v1
kind: ConfigMap
metadata:
name: {
{
.Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {
{
quote .Values.favorite.drink }}
food: {
{
quote .Values.favorite.food }}
模板函数遵循语法:functionName arg1 arg2...
,在上面代码段中,quote .Values.favorite.drink
调用 quote
函数并将其传递给单个参数。
|
:管道 |
是将一系列模板命令链接在一起的工具,以紧凑地表达一系列转换。管道 |
是按顺序完成多项工作的有效方式。
apiVersion: v1
kind: ConfigMap
metadata:
name: {
{
.Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {
{
.Values.favorite.drink | quote }}
food: {
{
.Values.favorite.food | quote }}
上面示例中,没有调用,而是反转了顺序。使用管道 |
将参数“发送”到函数:.Values.favorite.food | quote
。
反转顺序是模板中的常见做法,
.val | quote
比quote .val
更为常见。
使用管道,可以将多个功能链接在一起:
apiVersion: v1
kind: ConfigMap
metadata:
name: {
{
.Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {
{
.Values.favorite.drink | quote }}
food: {
{
.Values.favorite.food | upper | quote }}
该模板产生以下输出:
apiVersion: v1
kind: ConfigMap
metadata:
name: trendsetting-p-configmap
data:
myvalue: "Hello World"
drink: "coffee"
food: "PIZZA"
上面示例中,已经将 pizza 转换为 “PIZZA”。
default
函数:default
函数允许在模板内部指定默认值,以防省略该值。
apiVersion: v1
kind: ConfigMap
metadata:
name: {
{
.Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {
{
.Values.favorite.drink | default "tea" | quote }}
food: {
{
.Values.favorite.food | upper | quote }}
values.yaml
中可以注释drink
,得到输出:
apiVersion: v1
kind: ConfigMap
metadata:
name: fair-worm-configmap
data:
myvalue: "Hello World"
drink: "tea"
food: "PIZZA"
在实际chart中,所有默认值都应该配置在 values.yaml
中,并且不应使用 default
函数重复。
lookup
函数:lookup
函数可用于在运行中的集群中查找资源。
参数的组合:
kubectl get pod mypod -n mynamespace → lookup "v1" "Pod" "mynamespace" "mypod"
kubectl get pods -n mynamespace → lookup "v1" "Pod" "mynamespace" ""
kubectl get pods --all-namespaces → lookup "v1" "Pod" "" ""
kubectl get namespace mynamespace → lookup "v1" "Namespace" "" "mynamespace"
kubectl get namespaces → lookup "v1" "Namespace" "" ""
当 lookup
返回一个对象时,它将返回一个字典,可以进一步从字典中提取特定值。
例如,返回该 mynamespace
对象存在的注释:
(lookup "v1" "Namespace" "" "mynamespace").metadata.annotations
当 lookep
返回一个对象列表时,可以通过items字段访问对象列表:
{
{
range $index, $service := (lookup "v1" "Service" "mynamespace" "").items }}
{
{
/* do something with each service */}}
{
{
end }}
如果找不到对象,则返回一个空值。
lookup
函数使用Helm现有的Kubernetes连接配置来查询Kubernetes。如果在与调用API服务器进行交互时返回任何错误(例如缺乏访问资源的权限),则模板处理将失败。
需要注意的是,在 helm template
或 helm install|update|delete|rollback --dry-run
期间,Helm不会与Kubernetes API Server联系,因此在这种情况下 lookup
函数将返回 nil
。
indent:从左到右指定空格个数
with:可以允许将当前范围 . 设置为特定的对象。例如 .Values.service,使用 with 可以将 .Values.service 改为 .
变量:在 Helm 模板中,变量是对另一个对象的命名引用。它遵循这个形式 $name。变量被赋予一个特殊的赋值操作符::=
.Capabilities.APIVersions.Has
函数:.Capabilities.APIVersions.Has
函数返回API版本或资源在集群中是否可用。
.Capabilities.APIVersions.Has "apps/v1"
.Capabilities.APIVersions.Has "apps/v1/Deployment"
and 返回两个参数的布尔值和
or 返回两个参数的布尔值或。它返回第一个非空参数或最后一个参数
not 返回其参数的布尔取反
eq 如果Arg1 = Arg2,则返回true,否则返回false
ne 如果Arg1 != Arg2,则返回true,否则返回false
lt 如果Arg1 < Arg2,则返回true,否则返回false
le 如果Arg1 <= Arg2,则返回true,否则返回false
gt 如果Arg1 > Arg2,则返回true,否则返回false
ge 如果Arg1 >= Arg2,则返回true,否则返回false
lower 将整个字符串转换为小写
upper 将整个字符串转换为大写
repeat 重复给定字符串多次
substr 从字符串获取子字符串
nospace 从字符串中删除所有空格
indent indent 函数将给定字符串中的每一行缩进到指定的缩进宽度
nindent nindent 函数与 indent 函数相同,但是在字符串的开头添加了新行
replace 执行简单的字符串替换
reverse 用给定列表的元素,生成一个新列表,顺序与原列表相反
uniq 生成一个列表,删除所有重复项
has 测试列表是否具有特定元素,返回true,否则返回false
slice 获取列表部分元素,列表切片
until 生成一个顺序的整数列表
untilStep 和 until 一样,生成一个顺序的整数列表,但 untilStep 允许定义开始、结束和步长
seq 类似 seq 命令,生成参数之间的所有整数,默认步长为1或-1,单调递增或递减
add 相加
add1 加1
sub 相减
div 相除
mul 相乘
max 最大值
min 最小值
floor 返回 <= 输入值的最大浮点数
ceil 返回 >= 输入值的最大浮点数
round 四舍五入,返回一个浮点数
len 以整数形式返回参数的长度
base 返回路径的最后一个元素
dir 返回目录,去除路径的最后一部分
clean 清理路径,只保留路径开头和结尾
ext 返回文件扩展名
isAbs 检查文件路径是否是绝对路径
Helm包含许多模板函数,可以在模板中使用它们。常用函数:https://helm.sh/docs/chart_template_guide/function_list/
控制结构(在模板中被称为“动作”)提供了控制模板生成流程的能力。helm的模板语言提供以下控制结构:
if/else 用于创建条件块
with 指定范围
range 提供“针对每个”样式的循环
除此之外,helm还提供了一些声明和使用命名模板段的操作:
define 在模板中声明一个新的命名模板
template 导入命名模板
block 声明一种特殊的可填充模板区域
基础结构:
{
{
if PIPELINE }}
# Do something
{
{
else if OTHER PIPELINE }}
# Do something else
{
{
else }}
# Default case
{
{
end }}
如果值为以下内容,pipeline 为false:
布尔值false
数字0
空字符串
nil(empty或null)
空集合(map,slice,tuple,dict,array)
在其他条件下,pipeline 为true。
示例:
apiVersion: v1
kind: ConfigMap
metadata:
name: {
{
.Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {
{
.Values.favorite.drink | default "tea" | quote }}
food: {
{
.Values.favorite.food | upper | quote }}
{
{
if eq .Values.favorite.drink "coffee" }}mug: true{
{
end }}
输出:
apiVersion: v1
kind: ConfigMap
metadata:
name: eyewitness-elk-configmap
data:
myvalue: "Hello World"
drink: "coffee"
food: "PIZZA"
mug: true
with控制变量作用域。.
是对当前范围的引用,而 .Values
告诉模板 Values 在当前范围内查找对象。
with的语法类似于一个简单的 if 语句:
{
{
with PIPELINE }}
# restricted scope
{
{
end }}
with可以将当前范围 .
设置为特定对象:
apiVersion: v1
kind: ConfigMap
metadata:
name: {
{
.Release.Name }}-configmap
data:
myvalue: "Hello World"
{
{
- with .Values.favorite }}
drink: {
{
.drink | default "tea" | quote }}
food: {
{
.food | upper | quote }}
{
{
- end }}
但是需要注意,在受限范围内,将无法使用 .
从父chart范围访问其他对象:
{
{
- with .Values.favorite }}
drink: {
{
.drink | default "tea" | quote }}
food: {
{
.food | upper | quote }}
release: {
{
.Release.Name }}
{
{
- end }}
由于 Release.Name
不在 .
的限制范围内,因此会报错。但是可以使用 { { end }}
重置作用域:
{
{
- with .Values.favorite }}
drink: {
{
.drink | default "tea" | quote }}
food: {
{
.food | upper | quote }}
{
{
- end }}
release: {
{
.Release.Name }}
还可以用 $ 从父chart范围访问对象 Release.name
。模板执行开始时将 $ 映射到根作用域,并且在模板执行期间不会更改。以下内容也可以工作:
{
{
- with .Values.favorite }}
drink: {
{
.drink | default "tea" | quote }}
food: {
{
.food | upper | quote }}
release: {
{
$.Release.Name }}
{
{
- end }}
range
:在helm的模板语言中,迭代集合的方法是使用 range
运算符。
示例:
values.yaml
favorite:
drink: coffee
food: pizza
pizzaToppings:
- mushrooms
- cheese
- peppers
- onions
apiVersion: v1
kind: ConfigMap
metadata:
name: {
{
.Release.Name }}-configmap
data:
myvalue: "Hello World"
{
{
- with .Values.favorite }}
drink: {
{
.drink | default "tea" | quote }}
food: {
{
.food | upper | quote }}
{
{
- end }}
toppings: |-
{
{
- range .Values.pizzaToppings }}
- {
{
. | title | quote }}
{
{
- end }}
以下内容也可以工作:
apiVersion: v1
kind: ConfigMap
metadata:
name: {
{
.Release.Name }}-configmap
data:
myvalue: "Hello World"
{
{
- with .Values.favorite }}
drink: {
{
.drink | default "tea" | quote }}
food: {
{
.food | upper | quote }}
toppings: |-
{
{
- range $.Values.pizzaToppings }}
- {
{
. | title | quote }}
{
{
- end }}
{
{
- end }}
输出:
apiVersion: v1
kind: ConfigMap
metadata:
name: edgy-dragonfly-configmap
data:
myvalue: "Hello World"
drink: "coffee"
food: "PIZZA"
toppings: |-
- "Mushrooms"
- "Cheese"
- "Peppers"
- "Onions"
在helm模板中,变量是对另一个对象的命名引用。它遵循以下形式:$name
,变量使用特殊的赋值运算符::=
。
在前面的示例中,此代码会失败:
{
{
- with .Values.favorite }}
drink: {
{
.drink | default "tea" | quote }}
food: {
{
.food | upper | quote }}
release: {
{
.Release.Name }}
{
{
- end }}
Release.Name
不在该代码with块限制的范围之内。可以将上面代码重写为对变量使用Release.Name
:
apiVersion: v1
kind: ConfigMap
metadata:
name: {
{
.Release.Name }}-configmap
data:
myvalue: "Hello World"
{
{
- $relname := .Release.Name -}}
{
{
- with .Values.favorite }}
drink: {
{
.drink | default "tea" | quote }}
food: {
{
.food | upper | quote }}
release: {
{
$relname }}
{
{
- end }}
输出:
apiVersion: v1
kind: ConfigMap
metadata:
name: viable-badger-configmap
data:
myvalue: "Hello World"
drink: "coffee"
food: "PIZZA"
release: viable-badger
变量在 range
循环中特别有用。它们可以用于类似列表的对象,以同时捕获索引和值:
toppings: |-
{
{
- range $index, $topping := .Values.pizzaToppings }}
{
{
$index }}: {
{
$topping }}
{
{
- end }}
注意,range
首先跟的是变量,然后是赋值运算符,然后是列表。这会将整数索引(从零开始)分配给 $index
,并将值分配给$topping
。
输出:
toppings: |-
0: mushrooms
1: cheese
2: peppers
3: onions
对于同时具有键和值的数据结构,可以使用range两者来获取。
apiVersion: v1
kind: ConfigMap
metadata:
name: {
{
.Release.Name }}-configmap
data:
myvalue: "Hello World"
{
{
- range $key, $val := .Values.favorite }}
{
{
$key }}: {
{
$val | quote }}
{
{
- end }}
输出:
apiVersion: v1
kind: ConfigMap
metadata:
name: eager-rabbit-configmap
data:
myvalue: "Hello World"
drink: "coffee"
food: "pizza"
变量通常不是“全局”的,它们的作用域仅限于声明它们的块。$ 变量是全局变量,该变量始终指向根上下文。
命名模板也称为部分模板或子模板,是一个简单的文件中定义的、并且给定名称的模板。_helpers.tpl
文件是命名模板的默认位置。
命名模板需要注意的是,模板名称是全局的,如果声明了两个相同名称的模板,则以最后加载的那个为准。
通常的命名约定是在每个定义的模板前添加chart名称:{ { define "mychart.labels" }}
。通过使用特定的chart名称作为前缀,可以避免由于模板名称相同而引起的任何冲突。
define
:define
操作可以在模板文件内部创建命名模板,语法如下:
{
{
define "MY.NAME" }}
# body of template here
{
{
end }}
定义一个模板来封装Kubernetes标签块,示例:
{
{
- define "mychart.labels" }}
labels:
generator: helm
date: {
{
now | htmlDate }}
{
{
- end }}
将此模板嵌入到现有的ConfigMap中,然后将其包含在 template
操作中:
{
{
- define "mychart.labels" }}
labels:
generator: helm
date: {
{
now | htmlDate }}
{
{
- end }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {
{
.Release.Name }}-configmap
{
{
- template "mychart.labels" }}
data:
myvalue: "Hello World"
{
{
- range $key, $val := .Values.favorite }}
{
{
$key }}: {
{
$val | quote }}
{
{
- end }}
输出:
apiVersion: v1
kind: ConfigMap
metadata:
name: running-panda-configmap
labels:
generator: helm
date: 2016-11-02
data:
myvalue: "Hello World"
drink: "coffee"
food: "pizza"
helm chart通常将这些模板放在 _helpers.tpl
文件中,然后可以在ConfigMap中调用:
_helpers.tpl
{
{
/* Generate basic labels */}}
{
{
- define "mychart.labels" }}
labels:
generator: helm
date: {
{
now | htmlDate }}
{
{
- end }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {
{
.Release.Name }}-configmap
{
{
- template "mychart.labels" }}
data:
myvalue: "Hello World"
{
{
- range $key, $val := .Values.favorite }}
{
{
$key }}: {
{
$val | quote }}
{
{
- end }}
_helpers.tpl
{
{
/* Generate basic labels */}}
{
{
- define "mychart.labels" }}
labels:
generator: helm
date: {
{
now | htmlDate }}
chart: {
{
.Chart.Name }}
version: {
{
.Chart.Version }}
{
{
- end }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {
{
.Release.Name }}-configmap
{
{
- template "mychart.labels" . }}
helm install --dry-run --debug plinking-anaco ./mychart
输出:
apiVersion: v1
kind: ConfigMap
metadata:
name: plinking-anaco-configmap
labels:
generator: helm
date: 2016-11-02
chart: mychart
version: 0.1.0
当命名模板(使用 define
创建的模板)被渲染时,它将接收 template
调用传递的范围。
include
函数:示例:
{
{
- define "mychart.app" -}}
app_name: {
{
.Chart.Name }}
app_version: "{
{ .Chart.Version }}"
{
{
- end -}}
apiVersion: v1
kind: ConfigMap
metadata:
name: {
{
.Release.Name }}-configmap
labels:
{
{
template "mychart.app" . }}
data:
myvalue: "Hello World"
{
{
- range $key, $val := .Values.favorite }}
{
{
$key }}: {
{
$val | quote }}
{
{
- end }}
{
{
template "mychart.app" . }}
输出:
apiVersion: v1
kind: ConfigMap
metadata:
name: measly-whippet-configmap
labels:
app_name: mychart
app_version: "0.1.0+1478129847"
data:
myvalue: "Hello World"
drink: "coffee"
food: "pizza"
app_name: mychart
app_version: "0.1.0+1478129847"
可以看到,app_version 的缩进是错误的,因为 template
是操作而不是函数,所以无法将template调用的输出传递给其他函数。
helm提供了一种替代方法,include
可以将模板的内容导入到当前pipeline中,然后可以将其传递给pipeline中的其它函数。
apiVersion: v1
kind: ConfigMap
metadata:
name: {
{
.Release.Name }}-configmap
labels:
{
{
include "mychart.app" . | indent 4 }}
data:
myvalue: "Hello World"
{
{
- range $key, $val := .Values.favorite }}
{
{
$key }}: {
{
$val | quote }}
{
{
- end }}
{
{
include "mychart.app" . | indent 2 }}
apiVersion: v1
kind: ConfigMap
metadata:
name: edgy-mole-configmap
labels:
app_name: mychart
app_version: "0.1.0+1478129987"
data:
myvalue: "Hello World"
drink: "coffee"
food: "pizza"
app_name: mychart
app_version: "0.1.0+1478129987"
有时要导入文件,而不是模板,可以通过 .Files
描述的对象访问文件来实现。
helm提供了通过 .Files
对象访问文件的权限。有几点需要注意:
1. 在chart中可以添加其他文件。但由于Kubernetes对象的存储限制,chart必须小于1M
2. .Files 因为安全原因,某些文件无法通过该对象访问:
无法访问 templates/ 中的文件
无法访问使用 .helmignore 排除的文件
3. chart不保留 unix模式信息,因此文件级权限限制对 .Files 对象的文件可用性没有影响
编写一个模板,将三个文件读入ConfigMap。首先向chart添加三个文件,将三个文件放入 mychart/
目录中。
config1.toml
message = Hello from config 1
config1.toml
message = Hello from config 2
config3.toml
message = Hello from config 3
使用 range
函数来遍历它们,并将其内容注入到ConfigMap中:
apiVersion: v1
kind: ConfigMap
metadata:
name: {
{
.Release.Name }}-configmap
data:
{
{
- $files := .Files }}
{
{
- range tuple "config1.toml" "config2.toml" "config3.toml" }}
{
{
. }}: |-
{
{
$files.Get . }}
{
{
- end }}
输出:
apiVersion: v1
kind: ConfigMap
metadata:
name: quieting-giraf-configmap
data:
config1.toml: |-
message = Hello from config 1
config2.toml: |-
message = This is config 2
config3.toml: |-
message = Goodbye from config 3
在处理文件时,对文件路径本身执行一些标准操作会非常有用。相关函数有:
base 返回路径的最后一个元素
dir 返回目录,去除路径的最后一部分
clean 清理路径,只保留路径开头和结尾
ext 返回文件扩展名
isAbs 检查文件路径是否是绝对路径
随着chart的增长,可能会更需要组织文件。helm提供了 Files.Glob(pattern string)
方法,用来以glob模式灵活地提取某些文件。
例如,目录结构如下:
foo/:
foo.txt foo.yaml
bar/:
bar.go bar.conf baz.yaml
globs有多种选择:
{
{
$currentScope := .}}
{
{
range $path, $_ := .Files.Glob "**.yaml" }}
{
{
- with $currentScope}}
{
{
.Files.Get $path }}
{
{
- end }}
{
{
end }}
或
{
{
range $path, $_ := .Files.Glob "**.yaml" }}
{
{
$.Files.Get $path }}
{
{
end }}
想要将文件内容同时放入ConfigMap和Secrets中,以便在运行时安装到pod中。
结合glob模式,从上面的glob示例给出目录结构:
apiVersion: v1
kind: ConfigMap
metadata:
name: conf
data:
{
{
(.Files.Glob "foo/*").AsConfig | indent 2 }}
---
apiVersion: v1
kind: Secret
metadata:
name: very-secret
type: Opaque
data:
{
{
(.Files.Glob "bar/*").AsSecrets | indent 2 }}
可以导入文件并使用base-64模板对其进行编码,以确保成功传输:
apiVersion: v1
kind: Secret
metadata:
name: {
{
.Release.Name }}-secret
type: Opaque
data:
token: |-
{
{
.Files.Get "config1.toml" | b64enc }}
输出:
apiVersion: v1
kind: Secret
metadata:
name: lucky-turkey-secret
type: Opaque
data:
token: |-
bWVzc2FnZSA9IEhlbGxvIGZyb20gY29uZmlnIDEK
Lines
:有时,需要访问模板中文件的每一行。
为此helm提供了 Lines
方法,Lines
可以使用 range
函数循环遍历:
data:
some-file.txt: {
{
range .Files.Lines "foo/bar.txt" }}
{
{
. }}{
{
end }}
在 helm install
期间,无法将外部文件传递给chart。因此,必须使用 helm install -f
或 helm install --set
加载数据。
chart可以具有依赖项,称为子chart,子chart也有自己的values和templates。
关于子chart,有几点主要注意:
1. 子chart被看作“独立的”,它不能显式依赖其父chart,子chart无法访问其父chart的values
2. 父chart可以覆盖子chart的values
3. helm可以设置能被所有chart访问的全局values
helm create mychart
cd mychart/charts
helm create mysubchart
当子chart中values的key与父chart中values的key相同时,父chart的values会覆盖子chart的values。
全局values是可以从任何chart或子chart中以完全相同的名称访问的values。全局values需要显式声明。
Values.global
可以用来设置全局values,例如:
values.yaml
favorite:
drink: coffee
food: pizza
pizzaToppings:
- mushrooms
- cheese
- peppers
- onions
mysubchart:
dessert: ice cream
global:
salad: caesar #全局values
父chart可以与子chart共享模板。任何chart中任何已定义的模板块都可以用于其它chart。
定义一个简单的模板,例如:
{
{
- define "labels" }}from: mychart{
{
end }}
include
和 template
函数都可以引用模板,但 include
可以动态引用,而 template
仅接受字符串。
{
{
include $mytemplate }}
.helmignore
文件:.helmignore
文件用于指定不想包含在helm chart中的文件。
如果存在 .helmignore
文件,helm package
命令将忽略该文件中匹配到的所有文件。
.helmignore
文件支持unix shell全局匹配、相对路径匹配和否定(以 !
前缀)。每行仅支持一种模式。
示例:
# comment
.git
*/temp*
*/*/temp*
temp?
helm lint 验证chart是否遵循语法
helm install --dry-run --debug 渲染模板,然后返回生成的kubernetes清单文件
helm template --debug 渲染模板,然后返回生成的kubernetes清单文件
helm get manifest 查看服务器上安装了哪些模板
当yaml无法解析、但想查看生成内容时,可以先在模板中注释掉问题部分,然后重新运行 helm install --dry-run --debug
:
apiVersion: v2
# some: problem section
# {
{ .Values.foo | quote }}
上面的内容将渲染并返回完整的注释:
apiVersion: v2
# some: problem section
# "bar"