当前位置: 代码迷 >> 综合 >> heml3 charts 语法函数相关
  详细解决方案

heml3 charts 语法函数相关

热度:50   发布时间:2024-02-21 18:53:05.0

Chart 文件结构

一个 Chart 包由以下几个配置文件组成:
wordpress/Chart.yaml          # Yaml文件,用于描述 Chart 的基本信息,包括名称版本等LICENSE             # [可选] 文本格式的协议README.md           # [可选] 应用介绍、使用说明requirements.yaml   # [可选] 用于存放当前 Chart 依赖的其它 Chart 的说明文件values.yaml         # Chart 的默认值配置文件charts/             # [可选] 该目录中放置当前 Chart 依赖的其它 Charttemplates/          # [可选] 部署文件模版目录,模版填入 values.yaml 中相应值,生成最终的 
kubernetes 配置文件├── NOTES.txt        [可选] 使用指南├── _helpers.tpl     下划线开头的文件,可以被其他模板引用├── deployment.yaml  创建k8s资源deployment的yaml文件├── ingress.yaml     创建k8s资源ingress的yaml文件└── service.yaml     创建k8s资源service的yaml文件├── .....Chart.yaml 文件apiVersion: [必须] Chart API 版本,可用值 v1
name: [必须] Chart 名称
version: [必须] 版本,遵循 [SemVer 2 标准](https://semver.org/)
kubeVersion: [可选] 兼容的 Kubernetes 版本,遵循 [SemVer 2 标准](https://semver.org/)
description: [可选] 一句话的应用描述
keywords:- [可选] 应用关键字列表
home: [可选] 应用主页 URL
sources:- [可选] 当前应用下载地址列表
maintainers: [可选]- name: [必须] name email: [可选] emailurl: [可选] url
engine: [可选] 模板引擎,默认值是 gotpl
icon: [可选] SVG 或者 PNG 格式的图片地址
appVersion: [可选] 应用版本
deprecated: [可选] boolean 类型,是否不建议使用
tillerVersion: [可选] Chart 需要的 Tiller 版本,遵循 [SemVer 2 标准](https://semver.org/),需要 ">2.0.0"Requirements.yaml 文件和 Charts 目录Chart支持两种方式表示依赖关系,可以写入 requirements.yaml 文件动态链接[推荐],也可以将依赖的 Chart 放入 charts 目录手动管理。requirements.yaml 文件样例:dependencies:- name: apacheversion: 1.2.3repository: http://example.com/charts- name: mysqlversion: 3.2.1repository: http://another.example.com/chartsname:Chart 名称version:Chart 版本repository: Chart 仓库 URL 地址有了 requirements.yaml 文件,可以运行 helm dependency update,依赖的 Chart 会被自动的下载到 charts 目录下。
Values.yaml 文件和 Templates 目录values.yaml 文件中记录了模板中引用的默认值。 templates 目录中存放了 Kubernetes 部署文件的模版,遵循 Go template 语法templates 中模板文件样例:apiVersion: v1
kind: ReplicationController
metadata:name: deis-databasenamespace: deislabels:app.kubernetes.io/managed-by: deis
spec:replicas: 1selector:app.kubernetes.io/name: deis-databasetemplate:metadata:labels:app.kubernetes.io/name: deis-databasespec:serviceAccount: deis-databasecontainers:- name: deis-databaseimage: {
   {.Values.imageRegistry}}/postgres:{
   {.Values.dockerTag}}imagePullPolicy: {
   {.Values.pullPolicy}}ports:- containerPort: 5432env:- name: DATABASE_STORAGEvalue: {
   {default "minio" .Values.storage}}上述样例是一个 Kubernetes 中 replication controller 的模板文件定义,其中引用了以下几个值(一般定义在 values.yaml 中)imageRegistry:Docker 映像仓库dockerTag: Docker 映像标签pullPolicy: 下载映像策略storage: 存储后端,默认值是 "minio"values.yaml 文件样例:imageRegistry: "quay.io/deis"
dockerTag: "latest"
pullPolicy: "Always"
storage: "s3"

 开始

1 简单示例

1.1 生成案例结构 mycahrt

$ helm create mychart
Creating mychart

1.2 helm 客户端会自动的为我们创建些文件:

mychart
├── Chart.yaml
├── charts
├── templates
│   ├── NOTES.txt
│   ├── _helpers.tpl
│   ├── deployment.yaml
│   ├── ingress.yaml
│   └── service.yaml
└── values.yaml

2 第一个模板

2.1 删除所有文件,我们自己手动,有助于深入理解

 rm -rf mychart/templates/*.*

删除掉 Helm 生成的模板文件,我们自己来实现一个模板。

我们的第一个模板是创建一个 ConfigMap。创建一个 mychart/templates/configmap.yaml文件,并写入如下内容:

apiVersion: v1
kind: ConfigMap
metadata:name: mychart-configmap
data:myvalue: "Hello World"

注意:Template 目录下的文件没有严格的命名规范。但我们推荐用 .yaml 的后缀表示 YAML 文件,用 .tpl 表示帮助文件。

现在我们来部署它:

$ helm install wubo ./mychart
NAME: full-coral
LAST DEPLOYED: Tue Nov  09 17:36:01 2020
NAMESPACE: default
STATUS: DEPLOYEDRESOURCES:
==> v1/ConfigMap
NAME                DATA      AGE
mychart-configmap   1         1m

我们可以来查看下部署信息

$ helm get manifest wubo
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:name: mychart-configmap
data:myvalue: "Hello World"

helm get manifest 这条命令可以通过 release 名来打印其相关信息。release的名字此时就是wubo

现在,删除掉刚刚发布的 release:helm delete wubo

3 赋值示例

3.1内置对象

  • Release:用来描述 release 本身
    • Release.Name
    • Release.Time
    • Release.Namespace
    • Release.Service:值总是 Tiller 注:在 Helm 2 中,Tiller 是作为一个 Deployment 部署在 kube-system 命名空间中,很多情况下,我们会为 Tiller 准备一个 ServiceAccount ,这个 ServiceAccount 通常拥有集群的所有权限。 用户可以使用本地 Helm 命令,自由地连接到 Tiller 中并通过 Tiller 创建、修改、删除任意命名空间下的任意资源。 在 Helm 3 中,Tiller 被移除了。新的 Helm 客户端会像 kubectl 命令一样,读取本地的 kubeconfig 文件,使用我们在 kubeconfig 中预先定义好的权限来进行一系列操作。
    • Release.Revision:release 版本号。从 1 开始,每次执行 helm upgrade ,数加 1
    • Release.IsUpgrade:本次操作是否为升级
    • Release.IsInstall:本次操作是否为安装
  • Values:
  • Chart:Chart.yaml里的内容
  • Files:
    • File.Get 通过名字获取文件(.Files.Get config.ini
    • File.getBytes 以字节流的方式获取,在获取类型图片时比较有用
  • Capabilities:
  • Template:

3.2 Values Files

前面讲了内置对像 Values,它的值有四个来源:

  • values.yaml 文件
  • 如果这是个子 chart,其父 chart 的 Values.yaml 文件
  • 在 helm install 或 helm upgrade 时,通过 -f 指定的文件
  • 通过 --set 指定的参数( 例:helm install --set foo=bar ./mychart )

优先级从上到下依次增加,即 --set 最高。

现在让我们来编辑 mychart/values.yaml,删除默认值,只写一个参数:

cat values.yamlfavoriteDrink:coffee

在模板中使用刚刚写的参数:

apiVersion: v1
kind: ConfigMap
metadata:name: {
   { .Release.Name }}-configmap
data:myvalue: "Hello World"drink: {
   { .Values.favoriteDrink}}

注意最后一行,我们通过访问 Values 属性的方式 { { .Values.favoriteDrink}} 来获取 favoriteDrink 值。

来看下渲染的结果:

$ helm install wubo --dry-run --debug ./mychart
SERVER: "localhost:44134"
CHART PATH: /Users/mattbutcher/Code/Go/src/k8s.io/helm/_scratch/mychart
NAME: wubo
TARGET NAMESPACE:   default
CHART:  mychart 0.1.0
MANIFEST:
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:name: geared-marsupi-configmap
data:myvalue: "Hello World"drink: coffee

还可以通过 --set 覆盖掉这个值:

helm install wubo --dry-run --debug --set favoriteDrink=slurm ./mychart
SERVER: "localhost:44134"
CHART PATH: /Users/mattbutcher/Code/Go/src/k8s.io/helm/_scratch/mychart
NAME:   wubo
TARGET NAMESPACE:   default
CHART:  mychart 0.1.0
MANIFEST:
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:name: solid-vulture-configmap
data:myvalue: "Hello World"drink: slurm

由于 --set 的优先级高于 values.yaml,所有我们的模板最终输出为 drink: slurm

Values 文件还可以包含结构内容。

favorite:drink: coffeefood: pizza

现在我们需要修改下模板:

apiVersion: v1
kind: ConfigMap
metadata:name: {
   { .Release.Name }}-configmap
data:myvalue: "Hello World"drink: {
   { .Values.favorite.drink }}food: {
   { .Values.favorite.food }}

 看下效果2中方式

1 此种方式可以拿到Release相关的内置属性值

root@localhost:~/go/test1/mychart # helm install wubo  -f values.yaml --dry-run --debug .          
install.go:172: [debug] Original chart version: ""
install.go:189: [debug] CHART PATH: /root/go/test1/mychartNAME: wubo
LAST DEPLOYED: Wed Sep 23 17:07:52 2020
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
USER-SUPPLIED VALUES:
favorite:drink: coffeefood: pizzaCOMPUTED VALUES:
favorite:drink: coffeefood: pizzaHOOKS:
MANIFEST:
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:name: wubo-configmap
data:myvalue: "Hello World"drink: coffeefood: pizza

2 此种方式只是根据values和temp模板生成最终可供k8s的kubectl create -f 执行的一个yaml文件

root@localhost:~/go/test1/mychart # helm template . -s templates/configmap.yaml -f values.yaml 
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:name: RELEASE-NAME-configmap
data:myvalue: "Hello World"drink: coffeefood: pizza

3.3. 删除默认Key

如果你想从默认值中删除一个key,你可以通过传 null 值,这样 Helm 在合并时就会删除这个 key。

举个例子, 名为 Drupal 的 chart 中配置的有存活检测。下面是它的默认设置:

livenessProbe:httpGet:path: /user/loginport: httpinitialDelaySeconds: 120
如果你要使用 exec 替换 httpGet,可以通过 --set livenessProbe.exec.command=[cat,docroot/CHANGELOG.txt],Helm 会合并默认值和传进去的值,结果如下:
livenessProbe:httpGet:path: /user/loginport: httpexec:command:- cat- docroot/CHANGELOG.txtinitialDelaySeconds: 120

这时,k8s 就会出错,因为你定义了两个 liveness handler。要解决这个问题,你可以通过给 livenessProbe.httpGet传个 null 值来删除它:

helm install stable/drupal --set image=my-registry/drupal:0.1.0 --set livenessProbe.exec.command=[cat,docroot/CHANGELOG.txt] --set livenessProbe.httpGet=null

4 模板函数和Pipelines(管道)

让我们从一个练习开始:当我们往 .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 函数并传递了一个参数。

4.1. Pipelines(管道)

通过管道可以在一行里干多件事,我们使用 pipeline 重写上面的例子:

apiVersion: v1
kind: ConfigMap
metadata:name: {
   { .Release.Name }}-configmap
data:myvalue: "Hello World"drink: {
   { .Values.favorite.drink | quote }}food: {
   { .Values.favorite.food | quote }}

通过 pipeline(管道),我们可以链式的调用多个函数:

apiVersion: v1
kind: ConfigMap
metadata:name: {
   { .Release.Name }}-configmap
data:myvalue: "Hello World"drink: {
   { .Values.favorite.drink | quote }}food: {
   { .Values.favorite.food | upper | quote }}

4.2 使用 Default 函数

这个函数允许你指定一个默认值:

drink: {
   { .Values.favorite.drink | default "tea" | quote }}

4.3. OPERATORS ARE FUNCTIONS

操作符是按照函数的方式实现的,返回一个布尔值。使用 eq, ne, lt, gt, and, or, not时,要将它们放到句子的最前面,后面跟上对应的参数。多个操作符一起使用时,可以用小括号包起来。

{
   {/* include the body of this if statement when the variable .Values.fooString exists and is set to "foo" */}}
{
   { if and .Values.fooString (eq .Values.fooString "foo") }}{
   { ... }}
{
   { end }}意思就是Values.fooString不能为空且Values.fooString的值等于foo{
   {/* do not include the body of this if statement because unset variables evaluate to false and .Values.setVariable was negated with the not function. */}}
{
   { if or .Values.anUnsetVariable (not .Values.aSetVariable) }}{
   { ... }}
{
   { end }}

4.4控制流

Helm 的模板语言提供下面几种控制结构:

  • if / else
  • with
  • range 提供类型 for each 的循环

另外,还提供了几种方式来声明和使用命名模板:

  • define
  • template
  • block

这节只讨论 ifwith, 和 range。其它的会在之后的 “Named Templates” 那节介绍。

4.4.1 . IF / ELSE

基本结构如下

{
   { if PIPELINE }}# Do something
{
   { else if OTHER PIPELINE }}# Do something else
{
   { else }}# Default case
{
   { end }}

注意这里我们用 pipelines 面不是 values,是为了表明这个控制结构是可以运行完全的 pipeline 的,而不仅仅只能放个值。

下面情况其值会被认为是 false:

  1. bool 型的 false
  2. 数字 0
  3. 空字符串
  4. nil
  5. 空集合(map, slice, tuple, dict, array)

让我们来修改下 ConfigMap。当 drink 是 coffee时,增加一个设置:

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 and .Values.favorite.drink (eq .Values.favorite.drink "coffee") }}mug: true{
   { end }}注意mug: true前后不能有空格

注意, .Values.favorite.drink 最好是判断下是否为空,否则当它和 coffee作比较时会报错。最后的输出就变成: 

root@localhost:~/go/test1/mychart # helm template . -s templates/configmap.yaml -f values.yaml
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:name: RELEASE-NAME-configmap
data:myvalue: "Hello World"drink: "coffee"food: "PIZZA"mug: tru

root@localhost:~/go/test1/mychart # helm install wubo  -f values.yaml --dry-run --debug .                                                                                                                                         1 ?
install.go:172: [debug] Original chart version: ""
install.go:189: [debug] CHART PATH: /root/go/test1/mychartNAME: wubo
LAST DEPLOYED: Wed Sep 23 17:18:12 2020
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
USER-SUPPLIED VALUES:
favorite:drink: coffeefood: pizzaCOMPUTED VALUES:
favorite:drink: coffeefood: pizzaHOOKS:
MANIFEST:
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:name: wubo-configmap
data:myvalue: "Hello World"drink: "coffee"food: "PIZZA"mug: true

4.4.2. 空白管理

空白的使用在模板中是受限制的。下面把之前的代码格式修改下,使它更易阅读:

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}}

它看起来不错,但当真正运行时,会报错:

$ helm install --dry-run --debug ./mychart
SERVER: "localhost:44134"
CHART PATH: /Users/mattbutcher/Code/Go/src/k8s.io/helm/_scratch/mychart
Error: YAML parse error on mychart/templates/configmap.yaml: error converting YAML to JSON: yaml: line 9: did not find expected key

这就是因为空格导致的:

这是翻译之后的最终数据 发现最后一样有问题 多2个空格
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:name: eyewitness-elk-configmap
data:myvalue: "Hello World"drink: "coffee"food: "PIZZA"mug: true

mug的嵌套位置不正确。让我们简单的修改下:

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}}

再次运行,发现生成的 YAML 格式正确了,但是有点丑: 

root@localhost:~/go/test1/mychart # helm install wubo  -f values.yaml --dry-run --debug .                                                                                                                                        20 ?
install.go:172: [debug] Original chart version: ""
install.go:189: [debug] CHART PATH: /root/go/test1/mychartNAME: wubo
LAST DEPLOYED: Wed Sep 23 17:20:22 2020
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
USER-SUPPLIED VALUES:
favorite:drink: coffeefood: pizzaCOMPUTED VALUES:
favorite:drink: coffeefood: pizzaHOOKS:
MANIFEST:
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:name: wubo-configmap
data:myvalue: "Hello World"drink: "coffee"food: "PIZZA"mug: trueroot@localhost:~/go/test1/mychart # helm template . -s templates/configmap.yaml -f values.yaml
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:name: RELEASE-NAME-configmap
data:myvalue: "Hello World"drink: "coffee"food: "PIZZA"mug: true

注意,YAML 中有行是空的。

{ {  - 表示去掉左边或前的空格 }}

{ {   表示去掉右边或后的空格  -}}

{ {  - 表示去掉左边或前和右边或后的空格  -}}

好好理解一下 案例如下

root@localhost:~/go/test1/mychart # cat templates/configmap.yaml 
apiVersion: v1
kind: ConfigMap
metadata:name: {
   { .Release.Name }}-configmapnamespace: {
   { .Release.Namespace }}time: {
   { .Release.Time }}
data:myvalue: "Hello World"{
   { with .Values.favorite }}{
   { if and $.Values.favorite.drink (eq $.Values.favorite.drink "coffee") }}mug: true{
   { end }}name: wubo{
   { end }}age: 12{
   { if and .Values.favorite.drink (eq .Values.favorite.drink "coffee") }}mug: true{
   { end }}drink: {
   { .Values.favorite.drink | default "tea" | quote }}food: {
   { .Values.favorite.food | upper | quote }}

执行效果 

root@localhost:~/go/test1/mychart # helm template . -s templates/configmap.yaml -f values.yaml                                                                                                                                   20 ?
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:name: RELEASE-NAME-configmapnamespace: defaulttime: 
data:myvalue: "Hello World"mug: truename: wuboage: 12mug: truedrink: "coffee"food: "PIZZA"

改成

apiVersion: v1
kind: ConfigMap
metadata:name: {
   { .Release.Name }}-configmapnamespace: {
   { .Release.Namespace }}time: {
   { .Release.Time }}
data:myvalue: "Hello World"{
   {- with .Values.favorite }}{
   {- if and $.Values.favorite.drink (eq $.Values.favorite.drink "coffee") }}mug: true{
   {- end }}name: wubo{
   {- end }}age: 12{
   {- if and .Values.favorite.drink (eq .Values.favorite.drink "coffee") }}mug: true{
   {- end }}drink: {
   { .Values.favorite.drink | default "tea" | quote }}food: {
   { .Values.favorite.food | upper | quote }

效果 

root@localhost:~/go/test1/mychart # helm template . -s templates/configmap.yaml -f values.yaml                                                                                                                                   20 ?
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:name: RELEASE-NAME-configmapnamespace: defaulttime: 
data:myvalue: "Hello World"mug: truename: wuboage: 12mug: truedrink: "coffee"food: "PIZZA"

分析内容如下: 

myvalue: "Hello World"
  { {- with .Values.favorite }}
  { {- if and $.Values.favorite.drink (eq $.Values.favorite.drink "coffee") }}
  mug: true
  { {- end }}
  name: wubo
  { {- end }}
  age: 12
  { {- if and .Values.favorite.drink (eq .Values.favorite.drink "coffee") }}
  mug: true
  { {- end }}
  drink: { { .Values.favorite.drink | default "tea" | quote }}
  food: { { .Values.favorite.food | upper | quote }}
 

解释:

myvalue: "Hello World"和 mug: true之间会有2个空行,因为有两个流程操作{ { with }} 和 { { if }}

mug: true和 name: wubo之间有一个空行,因为有一个操作{ { end }}

name: wubo和  age: 12之间也有一个操作同上

age: 12和mug: true之间也有一个同上

mug: true和drink: { { .Values.favorite.drink | default "tea" | quote }}之间也有一个

drink: { { .Values.favorite.drink | default "tea" | quote }}和 food: { { .Values.favorite.food | upper | quote }}之间没有

然后就是怎么去除空行

  myvalue: "Hello World"
  { {- with .Values.favorite }}  "-" 写在前代表的是删除上面或左边的所有空行,但是右边或后面还有一个空行没有处理呢
  { {- if and $.Values.favorite.drink (eq $.Values.favorite.drink "coffee") }} 同理如上
  mug: true

上面这个还可以这样写

  myvalue: "Hello World"
  { {- with .Values.favorite -}}  "-" 写在前和后代表的是删除上面或左边和后面或右边的空行,就是把前后所有的空行都删除了,注意是所有的空行,不是一个空行
  { { if and $.Values.favorite.drink (eq $.Values.favorite.drink "coffee") }} 此时{ {- if }} 也是可以的,因为他的前面或左边确实有空行。{ {- with -}} 共同删除空行没毛病。但是{ { if -}} 后面加个”-" 就会报错了,因为后面就是 mug: true没有空行了。
  mug: true

4.5. 修改作用域

通过 . 可以引用当前的作用域。 .Values 告诉模板在当前作用域上查找 Values

可以通过 with 来调整作用域

{
   { with PIPELINE }}# restricted scope
{
   { end }}
with 允许你把当前作用域(.)指到一个特定的对象上。举个例子,将 . 指到 .Values.favorites上:
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 }}

警告,在这个特定的作用域中,你不能够访问其父领域的对象。下面的例子,访问会出错:

{
   {- with .Values.favorite }}drink: {
   { .drink | default "tea" | quote }}food: {
   { .food | upper | quote }}wubo: {
   { .Values.favorit.food  }} 此处获取不到release: {
   { .Release.Name }} 也获取不到
{
   {- end }}

此时有两中解决办法,定义变量和全局获取

1种解决办法.由于下方的with语句引入相对命令空间,无法通过.Release引入,提前定义relname变量
2种解决办法.者可以使用$符号,引入全局命名空间
{
   {- $relname := .Values.favorit.food }}
{
   {- with .Values.favorite }}drink: {
   { .drink | default "tea" | quote }}food: {
   { .food | upper | quote }}wubo: {
   { $relname }} # 或者可以使用$符号,引入全局命名空间wubo: {
   {$.Values.favorit.food}}release: {
   { $.Release.Name }}
{
   {- end }}

4.6. range 操作

Helm 可以通过 range 操作符来迭代集合。

在 values.yaml 中增加列表: