Helm 從入門到專家

作者:liugp

出處:https://u.kubeinfo.cn/28oCWV

一、概述

我們可以將 Helm 看作 Kubernetes 下的 apt-get/yum。Helm 是 kubernetes 的包管理器,helm 倉庫裏面只有配置清單文件, 而沒有鏡像, 鏡像還是由鏡像倉庫來提供, 比如 hub.docker.com、私有倉庫。

官方文檔:

https://v3.helm.sh/zh/docs/

二、Helm 架構

三、Helm 安裝

下載地址:

https://github.com/helm/helm/releases

# 下載包
$  wget https://get.helm.sh/helm-v3.9.4-linux-amd64.tar.gz
# 解壓壓縮包
$ tar -xf helm-v3.9.4-linux-amd64.tar.gz
# 製作軟連接
$ ln -s /opt/helm/linux-amd64/helm /usr/local/bin/helm
# 驗證
$ helm version
$ helm help

四、Helm 組件及相關術語

五、Helm Chart 詳解

1)Chart 目錄結構

# 通過helm create命令創建一個新的chart包
helm create nginx
tree nginx

nginx/
├── charts  #依賴其他包的charts文件
├── Chart.yaml # 該chart的描述文件,包括ico地址,版本信息等
├── templates  # #存放k8s模板文件目錄
│   ├── deployment.yaml # 創建k8s資源的yaml 模板
│   ├── _helpers.tpl # 下劃線開頭的文件,可以被其他模板引用
│   ├── hpa.yaml # 彈性擴縮容,配置服務資源CPU 內存
│   ├── ingress.yaml # ingress 配合service域名訪問的配置
│   ├── NOTES.txt # 說明文件,helm install之後展示給用戶看的內容
│   ├── serviceaccount.yaml # 服務賬號配置
│   ├── service.yaml # kubernetes Serivce yaml 模板
│   └── tests # 測試模塊
│       └── test-connection.yaml
└── values.yaml # 給模板文件使用的變量

可能有寫包還會有以下幾個目錄:

wordpress/
...
  LICENSE             # 可選: 包含chart許可證的純文本文件
  README.md           # 可選: 可讀的README文件
  values.schema.json  # 可選: 一個使用JSON結構的values.yaml文件
  charts/             # 包含chart依賴的其他chart
  crds/               # 自定義資源的定義
...

2)Chart.yaml 文件

apiVersion: chart API 版本 (必需)
name: chart名稱 (必需)
version: chart 版本,語義化2 版本(必需)
kubeVersion: 兼容Kubernetes版本的語義化版本(可選)
description: 一句話對這個項目的描述(可選)
type: chart類型 (可選)
keywords:
  - 關於項目的一組關鍵字(可選)
home: 項目home頁面的URL (可選)
sources:
  - 項目源碼的URL列表(可選)
dependencies: # chart 必要條件列表 (可選)
  - name: chart名稱 (nginx)
    version: chart版本 ("1.2.3")
    repository: (可選)倉庫URL ("https://example.com/charts") 或別名 ("@repo-name")
    condition: (可選) 解析爲布爾值的yaml路徑,用於啓用/禁用chart (e.g. subchart1.enabled )
    tags: # (可選)
      - 用於一次啓用/禁用 一組chart的tag
    import-values: # (可選)
      - ImportValue 保存源值到導入父鍵的映射。每項可以是字符串或者一對子/父列表項
    alias: (可選) chart中使用的別名。當你要多次添加相同的chart時會很有用
maintainers: # (可選)
  - name: 維護者名字 (每個維護者都需要)
    email: 維護者郵箱 (每個維護者可選)
    url: 維護者URL (每個維護者可選)
icon: 用做icon的SVG或PNG圖片URL (可選)
appVersion: 包含的應用版本(可選)。不需要是語義化,建議使用引號
deprecated: 不被推薦的chart (可選,布爾值)
annotations:
  example: 按名稱輸入的批註列表 (可選).

比如 nginx chart 的版本字段 version: 1.2.3 按照名稱被設置爲:

nginx-1.2.3.tgz

【溫馨提示】appVersion字段與version字段並不相關。這是指定應用版本的一種方式。比如,這個 drupal chart 可能有一個 appVersion: "8.2.1",表示包含在 chart(默認)的 Drupal 的版本是 8.2.1。

3)Chart 依賴管理(dependencies)

當前 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

示例演示:

helm repo add bitnami https://charts.bitnami.com/bitnami
helm pull bitnami/wordpress
tar -xf wordpress
cat wordpress/Chart.yaml


一旦你定義好了依賴,運行 helm dependency update 就會使用你的依賴文件下載所有你指定的 chart 到你的 charts / 目錄。

helm dependency update ./wordpress

當 helm dependency update 拉取 chart 時,會在 charts / 目錄中形成一個 chart 包。因此對於上面的示例,會在 chart 目錄中期望看到以下文件:

wordpress/charts/
├── common
├── common-2.0.1.tgz
├── mariadb
├── mariadb-11.2.2.tgz
├── memcached
└── memcached-6.2.3.tgz

依賴中的 tag 和條件字段

除了上面的其他字段外,每個需求項可以包含可選字段 tagscondition所有的 chart 會默認加載。如果存在 tags 或者 condition 字段,它們將被評估並用於控制它們應用的 chart 的加載。

# parentchart/Chart.yaml

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
# parentchart/values.yaml

subchart1:
  enabled: true
tags:
  front-end: false
  back-end: true

--set 參數可以用來設置標籤和條件值。

helm install --set tags.front-end=true --set subchart2.enabled=false

標籤和條件的解析:

4)通過依賴導入子 Value

使用導出格式:
如果子 chart 的 values.yaml 文件中在根節點包含了 exports 字段,它的內容可以通過指定的可以被直接導入到父 chart 的 value 中, 如下所示:

# parent's Chart.yaml file

dependencies:
  - name: subchart
    repository: http://localhost:10191
    version: 0.1.0
    import-values:
      - data
# child's values.yaml file

exports:
  data:
    myint: 99

只要我們再導入列表中指定了鍵 data,Helm 就會在子 chart 的 exports 字段查找 data 鍵並導入它的內容。

最終的父級 value 會包含我們的導出字段:

# parent's values

myint: 99

【注意】父級鍵 data 沒有包含在父級最終的 value 中,如果想指定這個父級鍵,要使用'子-父' 格式

下面示例中的import-values 指示 Helm 去拿到能再 child: 路徑中找到的任何值,並拷貝到 parent: 的指定路徑。

# parent's Chart.yaml file

dependencies:
  - name: subchart1
    repository: http://localhost:10191
    version: 0.1.0
    ...
    import-values:
      - child: default.data
        parent: myimports

上面的例子中,在 subchart1 裏面找到的 default.data 的值會被導入到父 chart 的 myimports 鍵中,細節如下:

# parent's values.yaml file

myimports:
  myint: 0
  mybool: false
  mystring: "helm rocks!"
# subchart1's values.yaml file

default:
  data:
    myint: 999
    mybool: true

父 chart 的結果值將會是這樣:

# parent's final values

myimports:
  myint: 999
  mybool: true
  mystring: "helm rocks!"

六、Templates and Values

1)Templates and Values 簡介

模板的 Value 通過兩種方式提供:

模板示例

apiVersion: v1
kind: ReplicationController
metadata:
  name: deis-database
  namespace: deis
  labels:
    app.kubernetes.io/managed-by: deis
spec:
  replicas: 1
  selector:
    app.kubernetes.io/name: deis-database
  template:
    metadata:
      labels:
        app.kubernetes.io/name: deis-database
    spec:
      serviceAccount: deis-database
      containers:
        - name: deis-database
          image: {{ .Values.imageRegistry }}/postgres:{{ .Values.dockerTag }}
          imagePullPolicy: {{ .Values.pullPolicy }}
          ports:
            - containerPort: 5432
          env:
            - name: DATABASE_STORAGE
              value: {{ default "minio" .Values.storage }}

上面的例子,鬆散地基於

https://github.com/deis/charts

是一個 Kubernetes 副本控制器的模板。可以使用下面四種模板值(一般被定義在 values.yaml 文件):

2)預定義的 Values

Values 通過模板中. Values 對象可訪問的 values.yaml 文件(或者通過 --set 參數) 提供, 但可以模板中訪問其他預定義的數據片段。

以下值是預定義的,對每個模板都有效,並且可以被覆蓋。和所有值一樣,名稱 區分大小寫。

考慮到前面部分的模板,values.yaml文件提供的必要值如下:

imageRegistry: "quay.io/deis"
dockerTag: "latest"
pullPolicy: "Always"
storage: "s3"

values 文件被定義爲 YAML 格式。chart 會包含一個默認的 values.yaml 文件。Helm 安裝命令允許用戶使用附加的 YAML values 覆蓋這個 values:

helm install --generate-name --values=myvals.yaml wordpress

3)範圍,依賴和值

Values 文件可以聲明頂級 chart 的值,以及charts/目錄中包含的其他任意 chart。或者換個說法,values 文件可以爲 chart 及其任何依賴項提供值。比如,上面示範的 WordPress chart 同時有 mysql 和 apache 作爲依賴。values 文件可以爲以下所有這些組件提供依賴:

title: "My WordPress Site" # Sent to the WordPress template

mysql:
  max_connections: 100 # Sent to MySQL
  password: "secret"

apache:
  port: 8080 # Passed to Apache

高階的 chart 可以訪問下面定義的所有變量。因此 WordPress chart 可以用. Values.mysql.password 訪問 MySQL 密碼。但是低階的 chart 不能訪問父級 chart,所以 MySQL 無法訪問 title 屬性。同樣也無法訪問 apache.port。

4)全局 Values

從 2.0.0-Alpha.2 開始,Helm 支持特殊的 "global" 值。設想一下前面的示例中的修改版本:

title: "My WordPress Site" # Sent to the WordPress template

global:
  app: MyWordPress

mysql:
  max_connections: 100 # Sent to MySQL
  password: "secret"

apache:
  port: 8080 # Passed to Apache

面添加了 global 部分和一個值 app: MyWordPress。這個值以.Values.global.app所有 chart 中有效

比如,mysql 模板可以以{{.Values.global.app}}訪問 app,同樣 apache chart 也可以訪問。實際上,上面的 values 文件會重新生成爲這樣:

title: "My WordPress Site" # Sent to the WordPress template

global:
  app: MyWordPress

mysql:
  global:
    app: MyWordPress
  max_connections: 100 # Sent to MySQL
  password: "secret"

apache:
  global:
    app: MyWordPress
  port: 8080 # Passed to Apache

七、Helm 資源安裝順序

八、Helm 安裝 Chart 包的三種方式

Helm 自帶一個強大的搜索命令,可以用來從兩種來源中進行搜索:

# 添加bitnami倉庫源
helm repo add bitnami https://charts.bitnami.com/bitnami
# 從bitnami源查找所有chart包,不指定具體源的話,會查找本地添加的所有源地址的所有chart包
helm search repo bitnami

1)values 傳參

安裝過程中有兩種方式傳遞配置數據:

如果同時使用兩種方式,則 --set 中的值會被合併到 --values 中,但是 --set 中的值優先級更高。在 --set 中覆蓋的內容會被被保存在 ConfigMap 中。可以通過 helm get values <release-name>查看指定 release 中 --set 設置的值。也可以通過運行 helm upgrade 並指定 --reset-values 字段來清除 --set 中設置的值。示例如下:

echo '{mariadb.auth.database: user0db, mariadb.auth.username: user0}' > values.yaml
helm install -f values.yaml bitnami/wordpress --generate-name

2)【第一種方式】直接在線 安裝不需要先下載包到本地

helm install mysql bitnami/mysql
helm list

3)【第二種方式】離線安裝 直接通過安裝包安裝

# 先刪除
helm uninstall mysql
# 拉包到本地
helm pull bitnami/mysql
# 不解壓直接安裝
helm install mysql ./mysql-9.3.1.tgz
helm list

4)【第三種方式】離線安裝 解壓包再安裝

# 拉包到本地
helm pull bitnami/mysql
# 解壓安裝
tar -xf mysql-9.3.1.tgz

# 開始安裝
helm install mysql ./mysql \
--namespace=mysql \
--create-namespace \
--set image.registry=myharbor.com \
--set image.repository=bigdata/mysql \
--set image.tag=8.0.30 \
--set primary.service.type=NodePort \
--set service.nodePorts.mysql=30306

# 查看在運行的Release
helm list

# 卸載
helm uninstall mysql -n mysql

九、Helm 基礎語法

1)變量

模板(templates/)中的變量都放在{{}}中,比如:{{ .Values.images }} 表示 Values 對象下的 images 字段。Values 來源於values.yaml文件或者-f指定的 yaml 文件,或者--set設置的變量。

【溫馨提示】使用-刪除空格和換行符,要想刪除那行其他的空格和換行符可以用{{-或者-}},** 一個是刪除左邊的空格換行符**,**一個是刪除右邊的空格換行符**。

2)內置對象

3)常用的內置函數

1、quote and squote

該函數將值轉換成字符串雙引號 (quote) 或者 ** 單引號 (squote)** 括起來。示例如下:

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

倒置命令是模板中的常見做法。可以經常看到 .val | quote 而不是 quote .val。實際上兩種操作都是可以的。

2、default

這個函數允許你在模板中指定一個默認值,以防這個值被忽略。

# 如果.Values.favorite.drink是非空值,則使用它,否則會返回tea。
drink: {{ .Values.favorite.drink | default "tea" | quote }}

# 還可以這樣寫,如果.Bar是非空值,則使用它,否則會返回foo。
default "foo" .Bar

"空" 定義取決於以下類型:

整型: 0
字符串: ""
列表: []
字典: {}
布爾: false
以及所有的nil (或 null)

3、print

返回各部分組合的字符串,非字符串類型會被轉換成字符串。

print "Matt has " .Dogs " dogs"

【溫馨提示】當相鄰兩個參數不是字符串時會在它們之間添加一個空格。

4、println

和 print 效果一樣,但會在末尾新添加一行。

5、printf

返回參數按順序傳遞的格式化字符串。

printf "%s has %d dogs." .Name .NumberDogs
{{printf "%d" (.Values.externalCache.port | int ) -}}
{{printf "%s" .Values.existingSecret -}}

{{printf "%v" .context.Values.redis.enabled -}}

# %s 字符串佔位符,未解析的二進制字符串或切片
# %d 數字佔位符,十進制
# %v 默認格式的值,當打印字典時,加號參數(%+v)可以添加字段名稱

更多佔位符的使用,可以參考官方文檔:

https://helm.sh/zh/docs/chart_template_guide/function_list/

6、trim

trim 行數移除字符串兩邊的空格:

trim "   hello    "

7、trimAll

從字符串中移除給定的字符:

trimAll "$" "$5.00"

上述結果爲:5.00 (作爲一個字符串)。

8、lower

將整個字符串轉換成小寫:

lower "HELLO"

上述結果爲:hello

9、upper

將整個字符串轉換成大寫:

upper "hello"

上述結果爲:HELLO

10、title

首字母轉換成大寫:

title "hello world"

上述結果爲:Hello World

11、substr

獲取字符串的子串,有三個參數:

substr 0 5 "hello world"

上述結果爲:hello

12、abbrev

用省略號截斷字符串 (...)

abbrev 5 "hello world"
# 第一個參數:最大長度
# 第二個參數:字符串

上述結果爲:he..., 因爲將省略號算進了長度中。

13、contains

測試字符串是否包含在另一個字符串中:

contains "cat" "catch"

14、cat

cat 函數將多個字符串合併成一個,用空格分隔:

cat "hello" "beautiful" "world"

上述結果爲:hello beautiful world

15、indent

indent 以指定長度縮進給定字符串所在行,在對齊多行字符串時很有用:

indent 4 $lots_of_text

上述結果會將每行縮進 4 個空格。

16、nindent

nindent 函數和 indent 函數一樣,但可以在字符串開頭添加新行。

nindent 4 $lots_of_text

上述結果會在字符串所在行縮進 4 個字符,並且在開頭新添加一行。

17、replace

執行簡單的字符串替換。

# 下面兩行等價
replace " " "-" "I Am Henry VIII"
"I Am Henry VIII" | replace " " "-"

# 參數1:待替換字符串
# 參數2:要替換字符串
# 參數3:源字符串

上述結果爲:I-Am-Henry-VIII

18、date

date 函數格式化日期,日期格式化爲 YEAR-MONTH-DAY:

now | date "2006-01-02"

想了解更多內置函數,可以參考官方文檔:

https://helm.sh/zh/docs/chart_template_guide/function_list/

4)類型轉換函數

Helm 提供了以下類型轉換函數:

5)正則表達式(Regular Expressions)

Helm 包含以下正則表達式函數

6)編碼和解碼函數

Helm 有以下編碼和解碼函數:

7)Dictionaries and Dict Functions

Helm 提供了一個 key/value 存儲類型稱爲 dict("dictionary" 的簡稱,Python 中也有)。dict 是無序類型。字典的 key 必須是字符串但值可以是任意類型,甚至是另一個 dict 或 list

1、創建字典(dict)

下面是創建三個鍵值對的字典:

$myDict := dict "name1" "value1" "name2" "value2" "name3" "value 3"

2、獲取值(get)

給定一個映射和一個鍵,從映射中獲取值。

get $myDict "name1"

上述結果爲:"value1"

注意如果沒有找到,會簡單返回 ""。不會生成 error。

3、添加鍵值對(set)

使用 set 給字典添加一個鍵值對。

$_ := set $myDict "name4" "value4"

注意 set 返回字典 (Go 模板函數的一個要求),因此你可能需要像上面那樣使用使用$_賦值來獲取值。

4、刪除(unset)

給定一個映射和 key,從映射中刪除這個 key。

$_ := unset $myDict "name4"

和 set 一樣,需要返回字典。

5、判斷 key(hasKey)

hasKey 函數會在給定字典中包含了給定 key 時返回 true。

hasKey $myDict "name1"

如果 key 沒找到,會返回 false。

6、pluck

pluck 函數給定一個鍵和多個映射,並獲得所有匹配項的列表:

pluck "name1" $myDict $myOtherDict

上述會返回的 list 包含了每個找到的值 ([value1 otherValue1])。

7、合併 dict(merge, mustMerge)

將兩個或多個字典合併爲一個, 目標字典優先:

$newdict := merge $dest $source1 $source2

8、獲取所有 keys

keys 函數會返回一個或多個 dict 類型中所有的 key 的 list。由於字典是 無序的,key 不會有可預料的順序。可以使用 sortAlpha 存儲。

keys $myDict | sortAlpha

當提供了多個詞典時,key 會被串聯起來。使用uniq函數和sortAlpha獲取一個唯一有序的鍵列表。

keys $myDict $myOtherDict | uniq | sortAlpha

9、獲取所有 values

values 函數類似於 keys,返回一個新的 list 包含源字典中所有的 value(只支持一個字典)。

$vals := values $myDict

上述結果爲:list["value1", "value2", "value 3"]。

注意 values 不能保證結果的順序;如果你需要順序, 請使用sortAlpha

8)Lists and List Functions

Helm 提供了一個簡單的 list 類型,包含任意順序的列表。類似於數組或切片,但列表是被設計用於不可變數據類型。

1、創建列表

$myList := list 1 2 3 4 5

上述會生成一個列表 [1 2 3 4 5]。

2、獲取列表第一項(first, mustFirst)

獲取列表中的第一項,使用 first。

first $myList
# 返回 1

first 有問題時會出錯,mustFirst 有問題時會向模板引擎返回錯誤。

3、獲取列表的尾部內容(rest, mustRest)

獲取列表的尾部內容 (除了第一項外的所有內容),使用 rest。

rest $myList
# 返回 [2 3 4 5]

rest 有問題時會出錯,mustRest 有問題時會向模板引擎返回錯誤。

4、獲取列表的最後一項(last, mustLast)

使用 last 獲取列表的最後一項:

last $myList
# 返回 5。這大致類似於反轉列表然後調用first。

5、獲取列表所有內容(initial, mustInitial)

通過返回所有元素 但 除了最後一個元素。

 initial $myList
 # 返回 [1 2 3 4]。

initial 有問題時會出錯,但是 mustInitial 有問題時會向模板引擎返回錯誤。

6、末尾添加元素(append, mustAppend)

在已有列表中追加一項,創建一個新的列表。

$new = append $myList 6

上述語句會設置 爲。myList 會保持不變。

append 有問題時會出錯,但 mustAppend 有問題時會向模板引擎返回錯誤。

7、前面添加元素(prepend, mustPrepend)

將元素添加到列表的前面,生成一個新的列表。

prepend $myList 0

上述語句會生成 [0 1 2 3 4 5]。$myList 會保持不變。

prepend 有問題時會出錯,但 mustPrepend 有問題時會向模板引擎返回錯誤。

8、多列表連接(concat)

將任意數量的列表串聯成一個。

concat $myList ( list 6 7 ) ( list 8 )

上述語句會生成 [1 2 3 4 5 6 7 8]。$myList 會保持不變。

9、反轉(reverse, mustReverse)

反轉給定的列表生成一個新列表。

reverse $myList

上述語句會生成一個列表:[5 4 3 2 1]。

reverse 有問題時會出錯,但 mustReverse 有問題時會向模板引擎返回錯誤。

10、去重(uniq, mustUniq)

生成一個移除重複項的列表。

list 1 1 1 2 | uniq

上述語句會生成 [1 2]

uniq 有問題時會出錯,但 mustUniq 有問題時會向模板引擎返回錯誤。

11、過濾(without, mustWithout)

without 函數從列表中過濾內容。

without $myList 3
# 上述語句會生成 [1 2 4 5]

一個過濾器可以過濾多個元素:

without $myList 1 3 5
# 這樣會得到: [2 4]

without 有問題時會出錯,但 mustWithout 有問題時會向模板引擎返回錯誤。

12、判斷元素是否存在(has, mustHas)

驗證列表是否有特定元素。

has 4 $myList

上述語句會返回 true, 但 has "hello" $myList 就會返回 false。

has 有問題時會出錯,但 mustHas 有問題時會向模板引擎返回錯誤。

13、刪除空項(compact, mustCompact)

接收一個列表並刪除空值項。

$list := list 1 "a" "foo" ""
$copy := compact $list

compact 會返回一個移除了空值 (比如, "") 的新列表。

compact 有問題時會出錯,但 mustCompact 有問題時會向模板引擎返回錯誤。

14、index

使用 index list [n] 獲取列表的第 n 個元素。使用 index list [n] [m] ... 獲取多位列表元素。

15、獲取部分元素(slice, mustSlice)

從列表中獲取部分元素,使用 slice list [n] [m]。等同於 list[n:m].

slice 有問題時會出錯,但 mustSlice 有問題時會向模板引擎返回錯誤。

16、構建一個整數列表(until)

until 函數構建一個整數範圍。

until 5

上述語句會生成一個列表:[0, 1, 2, 3, 4]。

對循環語句很有用:range e := until 5。

17、seq

seq 5       => 1 2 3 4 5
seq -3      => 1 0 -1 -2 -3
seq 0 2     => 0 1 2
seq 2 -2    => 2 1 0 -1 -2
seq 0 2 10  => 0 2 4 6 8 10
seq 0 -2 -5 => 0 -2 -4

9)數學函數(Math Functions)

1、求和(add)

使用 add 求和。接受兩個或多個輸入。

add 1 2 3

2、自加 1(add1)

自增加 1,使用 add1。

3、相減(sub)

相減使用 sub。

4、除(div)

整除使用 div。

5、取模(mod)

取模使用 mod。

6、相乘(mul)

相乘使用 mul。接受兩個或多個輸入。

mul 1 2 3

7、獲取最大值(max)

返回一組整數中最大的整數。

max 1 2 3
# 返回 3

8、獲取最小值(min)

返回一組數中最小的數。

min 1 2 3
# 會返回 1。

9、獲取長度(len)

以整數返回參數的長度。

len .Arg

10)Network Functions

Helm 提供了幾個網絡函數:

10)條件語句

運算符:

eq: 等於(equal to)
ne: 不等於(not equal to)
lt: 小於(less than)
le: 小於等於(less than or equal to)
gt: 大於(greater than)
ge: 大於等於(greater than or equal to)

if/else 用法:

{{if 命令}}{{else if 命令}}{{else}}{{end}}

如果是以下值時,管道會被設置爲 false:

布爾false
數字0
空字符串
nil (空或null)
空集合(map, slice, tuple, dict, array)

【示例】

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

11)變更作用域 with

下一個控制結構是with操作。這個用來控制變量範圍。回想一下,.是對 當前作用域 的引用。因此 .Values就是告訴模板在當前作用域查找 Values 對象。

with 的語法與 if 語句類似:

{{ with PIPELINE }}
  # restricted scope
{{ end }}

作用域可以被改變。with 允許你爲特定對象設定當前作用域 (.)。比如,我們已經在使用. Values.favorite。修改配置映射中的. 的作用域指向. Values.favorite:

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 }}
release: {{ .Release.Name }}
{{- end }}

這樣會報錯因爲Release.Name不在.限定的作用域內。但是如果對調最後兩行就是正常的, 因爲在 {{end}} 之後作用域被重置了。

{{- with .Values.favorite }}
drink: {{ .drink | default "tea" | quote }}
food: {{ .food | upper | quote }}
{{- end }}
release: {{ .Release.Name }}

或者,我們可以使用$從父作用域中訪問 Release.Name 對象。當模板開始執行後$會被映射到根作用域,且執行過程中不會更改。下面這種方式也可以正常工作:

{{- with .Values.favorite }}
drink: {{ .drink | default "tea" | quote }}
food: {{ .food | upper | quote }}
release: {{ $.Release.Name }}
{{- end }}

也可以在外邊定義變量,遵循$name變量的格式且指定了一個特殊的賦值運算符::=。我們可以使用針對 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 }}

注意在 with 塊開始之前,賦值$relname := .Release.Name。現在在 with 塊中,$relname 變量仍會執行版本名稱。

12)rang 循環語句

很多編程語言支持使用 for 循環,foreach 循環,或者類似的方法機制。在 Helm 的模板語言中,在一個集合中迭代的方式是使用range操作符。

定義 values

favorite:
  drink: coffee
  food: pizza
pizzaToppings:
  - mushrooms
  - cheese
  - peppers
  - onions

現在我們有了一個 pizzaToppings 列表(模板中稱爲切片)。修改模板把這個列表打印到配置映射中:

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

有時能在模板中快速創建列表然後迭代很有用,Helm 模板的 tuple 可以很容易實現該功能。在計算機科學中, 元組表示一個有固定大小的類似列表的集合,但可以是任意數據類型。這大致表達了tuple的用法。

  sizes: |-
    {{- range tuple "small" "medium" "large" }}
    - {{ . }}
    {{- end }}

上述模板會生成以下內容:

  sizes: |-
    - small
    - medium
    - large

13)命名模板

此時需要越過模板,開始創建其他內容了。該部分我們會看到如何在一個文件中定義 命名模板,並在其他地方使用。命名模板 (有時稱作一個 部分 或一個 子模板) 僅僅是在文件內部定義的模板,並使用了一個名字。有兩種創建方式和幾種不同的使用方法。

在編寫模板細節之前,文件的命名慣例需要注意:

這些文件用來存儲局部和輔助對象,實際上當我們第一次創建 mychart 時,會看到一個名爲_helpers.tpl的文件,這個文件是模板局部的默認位置

1、用 define 和 template 聲明和使用模板

define 操作允許我們在模板文件中創建一個命名模板,語法如下:

{{- define "MY.NAME" }}
  # body of template here
{{- end }}

比如我們可以定義一個模板封裝 Kubernetes 的標籤:

{{- define "mychart.labels" }}
  labels:
    generator: helm
    date: {{ now | htmlDate }}
{{- end }}

現在我們將模板嵌入到了已有的配置映射中,然後使用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 }}

當模板引擎讀取該文件時,它會存儲 mychart.labels 的引用直到 template "mychart.labels" 被調用。然後會按行渲染模板,因此結果類似這樣:

# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: running-panda-configmap
  labels:
    generator: helm
    date: 2022-09-04
data:
  myvalue: "Hello World"
  drink: "coffee"
  food: "pizza"

注意:define 不會有輸出,除非像本示例一樣用模板調用它。

按照慣例,Helm chart 將這些模板放置在局部文件中,一般是_helpers.tpl。把這個方法移到那裏:

{{/* Generate basic labels */}}
{{- define "mychart.labels" }}
  labels:
    generator: helm
    date: {{ now | htmlDate }}
{{- end }}

2、設置模板範圍

在上面定義的模板中,我們沒有使用任何對象,僅僅使用了方法。修改定義好的模板讓其包含 chart 名稱和版本號:

{{/* Generate basic labels */}}
{{- define "mychart.labels" }}
  labels:
    generator: helm
    date: {{ now | htmlDate }}
    chart: {{ .Chart.Name }}
    version: {{ .Chart.Version }}
{{- end }}

3、include 方法

假設定義了一個簡單模板如下:

{{- define "mychart.app" -}}
app_name: {{ .Chart.Name }}
app_version: "{{ .Chart.Version }}"
{{- end -}}

現在假設我想把這個插入到模板的 labels: 部分和 data: 部分:

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

如果渲染這個,會得到以下錯誤:

$ helm install --dry-run measly-whippet ./mychart
Error: unable to build kubernetes objects from release manifest: error validating "": error validating data: [ValidationError(ConfigMap): unknown field "app_name" in io.k8s.api.core.v1.ConfigMap, ValidationError(ConfigMap): unknown field "app_version" in io.k8s.api.core.v1.ConfigMap]

要查看渲染了什麼,可以用--disable-openapi-validation參數重新執行:helm install --dry-run --disable-openapi-validation measly-whippet ./mychart。輸入不是我們想要的:

# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: measly-whippet-configmap
  labels:
    app_name: mychart
app_version: "0.1.0"
data:
  myvalue: "Hello World"
  drink: "coffee"
  food: "pizza"
app_name: mychart
app_version: "0.1.0"

注意兩處的 app_version 縮進都不對,爲啥?因爲被替換的模板中文本是左對齊的。由於template是一個行爲,不是方法無法將 template調用的輸出傳給其他方法,數據只是簡單地按行插入

爲了處理這個問題,Helm 提供了一個include,可以將模板內容導入當前管道,然後傳遞給管道中的其他方法。下面這個示例,使用indent正確地縮進了 mychart.app 模板:

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

現在生成的 YAML 每一部分都可以正確縮進了:

# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: edgy-mole-configmap
  labels:
    app_name: mychart
    app_version: "0.1.0"
data:
  myvalue: "Hello World"
  drink: "coffee"
  food: "pizza"
  app_name: mychart
  app_version: "0.1.0"

include 相較於使用 template,在 helm 中使用 include 被認爲是更好的方式 只是爲了更好地處理 YAML 文檔的輸出格式。

14)NOTES.txt 文件

該部分會介紹爲 chart 用戶提供說明的 Helm 工具。在 helm install 或 helm upgrade 命令的最後,Helm 會打印出對用戶有用的信息。使用模板可以高度自定義這部分信息。

要在 chart 添加安裝說明,只需創建templates/NOTES.txt文件即可。該文件是純文本,但會像模板一樣處理, 所有正常的模板函數和對象都是可用的。讓我們創建一個簡單的 NOTES.txt 文件:

Thank you for installing {{ .Chart.Name }}.

Your release is named {{ .Release.Name }}.

To learn more about the release, try:

  $ helm status {{ .Release.Name }}
  $ helm get all {{ .Release.Name }}

現在如果我們執行 helm install rude-cardinal ./mychart 會在底部看到:

RESOURCES:
==> v1/Secret
NAME                   TYPE      DATA      AGE
rude-cardinal-secret   Opaque    1         0s

==> v1/ConfigMap
NAME                      DATA      AGE
rude-cardinal-configmap   3         0s


NOTES:
Thank you for installing mychart.

Your release is named rude-cardinal.

To learn more about the release, try:

  $ helm status rude-cardinal
  $ helm get all rude-cardinal

使用 NOTES.txt 這種方式是給用戶提供關於如何使用新安裝的 chart 細節信息的好方法。儘管並不是必需的,強烈建議創建一個NOTES.txt文件

15)模板調試

調試模板可能很棘手,因爲渲染後的模板發送給了 Kubernetes API server,可能會以格式化以外的原因拒絕 YAML 文件。以下命令有助於調試:

當你的 YAML 文件解析失敗,但你想知道生成了什麼,檢索 YAML 一個簡單的方式是註釋掉模板中有問題的部分, 然後重新運行 helm install --dry-run --debug

apiVersion: v2
# some: problem section
# {{ .Values.foo | quote }}

以上內容會被渲染同時返回完整的註釋:

apiVersion: v2
# some: problem section
#  "bar"

其實這裏主要是正對官方文檔進行整理,列出了常見的使用語法,想了解更多,可以參考官方文檔,官方文檔講解的很細緻,有疑問的小夥伴歡迎給我留言哦

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/aWXqRYlj4TEyGOG-X18lOg