Helm一文全解

Helm簡(jiǎn)介

Helm 是 Kubernetes 的開(kāi)源包管理器唇敞。它提供了一種查找墩弯、共享和使用為 Kubernetes 構(gòu)建的軟件的簡(jiǎn)便方法兰英。該項(xiàng)目使用一種稱(chēng)為圖表的打包格式,它是描述一組相關(guān) Kubernetes 資源的文件集合蜗搔。

Helm 于 2015 年在 Deis 創(chuàng)建劲藐,后來(lái)被微軟收購(gòu)。現(xiàn)在稱(chēng)為 Helm Classic 的是在當(dāng)年 11 月的首屆 KubeCon 上推出的樟凄。2016 年 1 月聘芜,Helm Classic 與谷歌的 Kubernetes 部署管理器合并到現(xiàn)在是 Helm 主要項(xiàng)目的存儲(chǔ)庫(kù)中。2018 年 6 月 加入 CNCF 缝龄。2018年年底推出了Helm Hub用于存儲(chǔ)chart汰现。2019年11月發(fā)布V3版本。

官網(wǎng):https://helm.sh/zh/docs/

三大概念

  • Chart:代表著 Helm 包叔壤。它包含在 Kubernetes 集群內(nèi)部運(yùn)行應(yīng)用程序瞎饲,工具或服務(wù)所需的所有資源定義。你可以把它看作是 Homebrew formula百新,Apt dpkg企软,或 Yum RPM 在Kubernetes 中的等價(jià)物庐扫。

  • Repository:倉(cāng)庫(kù)饭望,是用來(lái)存放和共享 charts 的地方。

  • Release:類(lèi)似于版本號(hào)形庭,Release 是運(yùn)行在 Kubernetes 集群中的 chart 的實(shí)例铅辞。一個(gè) chart 通常可以在同一個(gè)集群中安裝多次萨醒。每一次安裝都會(huì)創(chuàng)建一個(gè)新的 release斟珊。

特色

  • 輕松創(chuàng)建和托管自己的應(yīng)用(以應(yīng)用為一個(gè)維度,而不是k8s的一個(gè)deploy富纸、cm等)

  • 將軟件包安裝到任何 K8S 集群中

  • 查詢(xún)集群以查看已安裝和正在運(yùn)行的程序包

  • 更新囤踩、刪除旨椒、回滾或查看已安裝軟件包的歷史記錄

目標(biāo)

  • 從頭開(kāi)始創(chuàng)建新的chart

  • 將chart打包成歸檔(tgz)文件

  • 與存儲(chǔ)chart的倉(cāng)庫(kù)進(jìn)行交互

  • 在現(xiàn)有的Kubernetes集群中安裝和卸載chart

  • 管理與Helm一起安裝的chart的發(fā)布周期

版本形式和版本偏差

Helm 的版本用 x.y.z 的形式描述,x 是主版本堵漱,y 是次版本综慎,z 是補(bǔ)丁版本。

Helm的版本與k8s存在版本的兼容性問(wèn)題:Helm 沒(méi)有向上兼容機(jī)制勤庐,故推薦安裝下表進(jìn)行版本選擇示惊。

https://helm.sh/docs/topics/version_skew/

Helm Version Supported Kubernetes Versions
3.11.x 1.26.x - 1.23.x
3.10.x 1.25.x - 1.22.x
3.9.x 1.24.x - 1.21.x
3.8.x 1.23.x - 1.20.x
3.7.x 1.22.x - 1.19.x
3.6.x 1.21.x - 1.18.x
3.5.x 1.20.x - 1.17.x
3.4.x 1.19.x - 1.16.x
3.3.x 1.18.x - 1.15.x
3.2.x 1.18.x - 1.15.x
3.1.x 1.17.x - 1.14.x
3.0.x 1.16.x - 1.13.x
2.16.x 1.16.x - 1.15.x
2.15.x 1.15.x - 1.14.x
2.14.x 1.14.x - 1.13.x
2.13.x 1.13.x - 1.12.x

V2和V3版本變化

2019年11月,helm團(tuán)隊(duì)發(fā)布了第一個(gè)helm v3穩(wěn)定版愉镰,其與helm v2主要的變化如下:

1米罚、架構(gòu)變化:最顯著的變化,就是刪除了Tiller而采用kubeconfig來(lái)授權(quán)和調(diào)用k8s api.

2丈探、Release變化:Release名稱(chēng)可以在不通NameSpace中重用

3录择、chart存儲(chǔ)變化:支持將chart推送到OCI注冊(cè)中心(類(lèi)似于Docker Registry)

4、支持JSONschema的Chart Values

5类嗤、其他

helm delete  更名  helm uninstall
helm inspect 更名  helm show
helm fetch   更名  helm pull
helm reset (已刪除)
helm serve (已刪除)
  • 移除了用于本地臨時(shí)搭建Chart Repository的命令helm serve

  • 不再需要requirements.txt糊肠,將其合并到Chart.yaml

社區(qū)chart倉(cāng)庫(kù)

https://artifacthub.io/packages/search?kind=0

安裝Helm

helm v3(推薦)

下載想要的版本:[https://github.com/helm/helm/tags)


# 安裝二進(jìn)制命令
wget https://get.helm.sh/helm-v2.17.0-linux-amd64.tar.gz
tar -zxvf helm-v2.17.0-linux-amd64.tar.gz
cp helm-v2.17.0-linux-amd64/helm /usr/local/sbin/

# 安裝Tiller:https://github.com/orgs/helm/packages/container/package/tiller
cat <<EOF | kubectl apply -f -
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: tiller
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: tiller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
  - kind: ServiceAccount
    name: tiller
    namespace: kube-system
EOF

# init安裝tiller
helm init --service-account tiller --skip-refresh
kubectl get pod -n kube-system -l app=helm

helm v2(不推薦)

下載想要的版本:https://github.com/helm/helm/releases/tag/v2.17.0

# 安裝二進(jìn)制命令
wget https://get.helm.sh/helm-v2.17.0-linux-amd64.tar.gz
tar -zxvf helm-v2.17.0-linux-amd64.tar.gz
cp helm-v2.17.0-linux-amd64/helm /usr/local/sbin/

# 安裝Tiller:https://github.com/orgs/helm/packages/container/package/tiller
cat <<EOF | kubectl apply -f -
---
apiVersion: v1
kind: ServiceAccount
metadata:
 name: tiller
 namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
 name: tiller
roleRef:
 apiGroup: rbac.authorization.k8s.io
 kind: ClusterRole
 name: cluster-admin
subjects:
 - kind: ServiceAccount
 name: tiller
 namespace: kube-system
EOF

# init安裝tiller
helm init --service-account tiller --skip-refresh
kubectl get pod -n kube-system -l app=helm

Helm常用命令

命令自動(dòng)補(bǔ)全

yum install -y bash-completion
source <(helm completion bash)
helm completion bash > /etc/bash_completion.d/helm
# 查看helm相關(guān)環(huán)境變量
helm env

# 添加公用或私有倉(cāng)庫(kù)
helm repo add stable http://mirror.azure.cn/kubernetes/charts
helm repo add  elastic    https://helm.elastic.co
helm repo add  gitlab     https://charts.gitlab.io
helm repo add  bitnami    https://charts.bitnami.com/bitnami
helm repo add  incubator  https://kubernetes-charts-incubator.storage.googleapis.com
helm repo add  stable     https://kubernetes-charts.storage.googleapis.com
helm repo add  harbor     https://helm.goharbor.io

# 在 Repo 中查詢(xún)可安裝的 chart 包(支持模糊匹配)
$ helm search repo harbor
NAME          CHART VERSION  APP VERSION  DESCRIPTION 
harbor/harbor  1.11.1        2.7.1       An open source trusted cloud native reg...
$ helm search repo harbor --version 1.5
NAME          CHART VERSION  APP VERSION  DESCRIPTION 
harbor/harbor  1.5.6         2.1.6       An open source trusted cloud native reg...


# 下載一個(gè)chart到本地(--untar 表示解壓,不加下載后為.tgz)
helm pull harbor/harbor --untar

# 檢查一個(gè)chart是否合法
helm lint mychart


# 安裝名為nginx的chart包在bitnmai倉(cāng)庫(kù)遗锣,并制定命令空間
helm install [NAME] [CHART] [-n namespace]
helm install nginx bitnami/nginx -n mycloud
helm install nginx bitnami/nginx  --debug --dry-run   # 用于調(diào)試货裹,并不真正執(zhí)行

# 查看全部應(yīng)用(包含安裝和卸載的)
helm list -n mydlqcloud --all

# 查看應(yīng)用狀態(tài)
helm status nginx -n mycloud

# 卸載應(yīng)用,并保留安裝記錄
helm uninstall nginx -n mycloud --keep-history

# 卸載應(yīng)用精偿,不保留安裝記錄
helm delete nginx -n mycloud

# 渲染模板(查看通過(guò)指定的參數(shù)渲染的 Kubernetes 部署資源模板)
helm template bitnami/nginx

# 查看chart 可配置參數(shù)
helm show values bitnami/nginx

# 查看已安裝chart配置的參數(shù)
helm get values nginx

# 應(yīng)用升級(jí)
helm upgrade -f values.yaml nginx bitnami/nginx -n mycloud

# 應(yīng)用回滾
helm history nginx
helm rollback nginx 1

Chart打包上傳到chartmusem倉(cāng)庫(kù)(以Harbor為例)

需要helm 插件:https://github.com/chartmuseum/helm-push

注意:上傳比較規(guī)劃的公網(wǎng)公開(kāi)chat還應(yīng)該做簽名弧圆,并生成一個(gè)*.prov

  • helm package --sign --key 'helm signing key' --keyring path/to/keyring.secret mychart
# 打包上傳Chart
# * 打包c(diǎn)hart(版本默認(rèn)由<chart_name>/Chart.yaml 中的version決定)
helm package <chart_name>

# * 生成索引
helm repo index .

# * 方式一:下載push插件
$ helm plugin install https://github.com/chartmuseum/helm-push
Downloading and installing helm-push v0.10.3 ...
https://github.com/chartmuseum/helm-push/releases/download/v0.10.3/helm-push_0.10.3_linux_amd64.tar.gz

# * 方式二:helm plugin install 失敗,可以wget下載然后解壓打插件目錄
wget https://github.com/chartmuseum/helm-push/releases/download/v0.10.3/helm-push_0.10.3_linux_amd64.tar.gz

$ helm env | grep PLUGIN
HELM_PLUGINS="/root/.local/share/helm/plugins"

$ mkdir /root/.local/share/helm/plugins/cm-push

tar xf helm-push_0.10.3_linux_amd64.tar.gz -C /root/.local/share/helm/plugins/cm-push

# 查看helm插件
helm plugin list

# 添加要上傳的倉(cāng)庫(kù)
helm repo add  --username admin --password Harbor12345 --ca-file /harbor/tls/ca.crt localchart https://harbor.wzp.com/chartrepo/library

# 上傳Chart到倉(cāng)庫(kù)
helm cm-push --ca-file /harbor/tls/ca.crt mycahrt-0.1.0.tgz localchart

Chart詳解

helm默認(rèn)本地存儲(chǔ)的配置文件

helm env可以查看

System Cache Path Configuration Path Data Path
Linux $HOME/.cache/helm $HOME/.config/helm $HOME/.local/share/helm
macOS $HOME/Library/Caches/helm $HOME/Library/Preferences/helm $HOME/Library/helm
Windows %TEMP%\helm %APPDATA%\helm %APPDATA%\helm

什么是Chart笔咽?

Helm 使用一種稱(chēng)為Chart的打包格式搔预。Chart是描述一組相關(guān) Kubernetes 資源的文件集合。單個(gè)Chart可以用于部署簡(jiǎn)單的東西叶组,如 memcached pod拯田,或復(fù)雜的東西,如帶有 HTTP 服務(wù)器甩十、數(shù)據(jù)庫(kù)船庇、緩存等的完整 Web 應(yīng)用程序堆棧。部署時(shí)通過(guò)helm客戶(hù)端提交給k8s apiserver去完成

Chart的文件結(jié)構(gòu)

mychart/

├── Chart.yaml                  # 包含了chart信息的YAML文件
├── LICENSE                      # 可選: 包含chart許可證的純文本文件
├── README.md                       # 可選: 可讀的README文件
├── values.yaml                  # chart 默認(rèn)的配置值
├── values.schema.json           # 可選: 一個(gè)使用JSON結(jié)構(gòu)的values.yaml文件
├── templates                  # 資源模版侣监,配置 values 進(jìn)行渲染鸭轮,生成有效的 K8s manifest
│   ├── deployment.yaml
│   ├── _helpers.tpl          # 定義可以復(fù)用的子模板文件
│   ├── hpa.yaml
│   ├── ingress.yaml
│   ├── NOTES.txt              # 可選: 包含簡(jiǎn)要使用說(shuō)明的純文本文件
│   ├── serviceaccount.yaml
│   ├── service.yaml
│   └── tests                  # 用于測(cè)試的文件
│       └── test-connection.yaml  # 具體做測(cè)試的容器或是k8s能識(shí)別的資源類(lèi)型
├── crds/                        # 自定義資源的定義
├── Chart.lock                  # 保存先前版本的依賴(lài)
├── charts/                         # 包含chart依賴(lài)的其他chart
├── .helmignore                  # 指定忽略 Helm 包中哪些文件和目錄
└── xxxx                      # 其他自定義內(nèi)容,可以是conf/xxx.conf 一些配置文件
文件/目錄 定義 是否必須
Chart.yaml 該文件中包含了Chart的元數(shù)據(jù)
templates/ 存放chart的資源模板文件橄霉,這些文件是 YAML 格式 是(除非依賴(lài)項(xiàng)在 Chart.yaml 文件中聲明)
templates/NOTES.txt chart的說(shuō)明文件窃爷。安裝、升級(jí)或執(zhí)行 notes 命令會(huì)輸出此文件內(nèi)容
values.yaml chart的默認(rèn)存放變量的文件 否,但作為最佳實(shí)踐按厘,最好包含此文件
.helmignore 指定忽略 Helm 包中哪些文件和目錄
charts/ 存放chart依賴(lài)的其他chart 無(wú)需明確提供医吊,Helm 的依賴(lài)管理系統(tǒng)會(huì)自動(dòng)創(chuàng)建此目錄
Chart.lock 保存先前版本的依賴(lài) 無(wú)需明確提供,Helm 的依賴(lài)管理系統(tǒng)會(huì)自動(dòng)創(chuàng)建此文件
crds/ 存儲(chǔ)自定義(CRD)資源的目錄逮京。YAML 格式遮咖。這些資源會(huì)在 templates/ 中的資源之前安裝。
README.md chart安裝和使用說(shuō)明的自述文件 否造虏,但作為最佳實(shí)踐伴网,最好包含此文件
LICENSE license 文件
values.schema.json JSON 格式的chart values文件

Chart文件詳解

https://helm.sh/zh/docs/topics/charts/

Chart.yaml文件

  • 注意:從v3.3.2之后該文件不允許缓屠,設(shè)置如下字段以外的任何字段唉韭,推薦的方法是在 annotations 中添加自定義元數(shù)據(jù)柔逼。
apiVersion: # 必需: chart API 版本, v2 版本為 helm3 語(yǔ)法,v1 版本仍然保留使用
name: # 必需: chart名稱(chēng)

# 遵循規(guī)范 https://semver.org/spec/v2.0.0.html
# 打包Chart時(shí)享钞,以此版本作為后綴和包版本
version:        # 必需: 版本標(biāo)識(shí) 示例:1.0.0 < 1.0.0-alpha < 1.0.0-beta < 2.0.0 < 2.1.0

# 一旦設(shè)置揍诽,會(huì)檢測(cè)k8s版本,不匹配會(huì)顯式報(bào)錯(cuò)
kubeVersion: # 可選: 兼容的k8s版本標(biāo)識(shí) # 示例:>= 1.13.0 < 1.14.0 || >= 1.14.1 < 1.15.0
description: # 可選: 項(xiàng)目的描述


# 有兩種類(lèi)型: application(默認(rèn))和 library(不可用于安裝helm install)
# - library類(lèi)型:定義了可以由其他chart中Helm 模板共享的chart原語(yǔ)或定義栗竖。這允許用戶(hù)通過(guò)chart分享可復(fù)用得代碼片段來(lái)避免重復(fù)并保持chart 干燥暑脆。
type: # 可選:chart類(lèi)型

keywords: # 可選: 項(xiàng)目的關(guān)鍵字標(biāo)識(shí)
 - xxx
 - xxx
home: # 可選:項(xiàng)目home頁(yè)面的URL
sources: # 可選:項(xiàng)目源碼的URL列表
 - https://xxxx
 - https://xxxx

dependencies: # 可選:chart 依賴(lài)條件列表
 - name: # chart名稱(chēng) (nginx)
 version: # chart版本 ("1.2.3")
 repository: # 可選:倉(cāng)庫(kù)URL ("https://example.com/charts") 或別名 ("@repo-name")
 condition:  # 可選:解析為布爾值的yaml路徑,用于啟用/禁用chart (e.g. subchart1.enabled )
 tags: # 可選
 - 關(guān)聯(lián)values.yaml文件狐肢,可以用于指定啟用或禁用所有的帶tag的chart添吗。
 import-values: # (可選)
 - ImportValue 保存源值到導(dǎo)入父鍵的映射。每項(xiàng)可以是字符串或者一對(duì)子/父列表項(xiàng)
 alias: (可選) chart中使用的別名份名。當(dāng)你要多次添加相同的chart時(shí)會(huì)很有用
maintainers: # 可選
 - name: 維護(hù)者名字 (每個(gè)維護(hù)者都需要)
 email: 維護(hù)者郵箱 (每個(gè)維護(hù)者可選)
 url: 維護(hù)者URL (每個(gè)維護(hù)者可選)
icon: # 可選:用做icon的SVG或PNG圖片URL
appVersion: # 可選:包含的應(yīng)用版本碟联。不需要是語(yǔ)義化,建議使用引號(hào)

# 表示是否被棄用僵腺,latest版本被標(biāo)記為已棄用鲤孵,則所有的chart都會(huì)被認(rèn)為是已棄用的
deprecated: # 可選:是否被啟用,布爾值

# 自定義元數(shù)據(jù)
annotations:
 example: 按名稱(chēng)輸入的批注列表 (可選).

LICENSE文件

許可證(LICENSE)是一個(gè)包含了chart license的純文本文件辰如。

README.md文件

Markdown格式的說(shuō)明文件普监,一般應(yīng)包含:

  • chart提供的應(yīng)用或服務(wù)的描述

  • 運(yùn)行chart的先決條件或要求

  • values.yaml的可選項(xiàng)和默認(rèn)值的描述

  • 與chart的安裝或配置相關(guān)的其他任何信息

crds/目錄

用于存放crd資源的目錄,其下存放具體的CRD

  • Helm確定crds/目錄中的CRD已經(jīng)存在琉兜,Helm不會(huì)安裝或升級(jí)凯正。

  • 在升級(jí)或回滾時(shí)不會(huì)更新CRD。Helm只會(huì)在安裝時(shí)創(chuàng)建CRD呕童。

  • CRD從不會(huì)被刪除漆际。自動(dòng)刪除CRD會(huì)刪除集群中所有命名空間中的所有CRD內(nèi)容淆珊。因此Helm不會(huì)刪除CRD夺饲。

# crds/crontab.yaml
# 需要注意的是:該文件中不能存在模板語(yǔ)言,不可引用變量
kind: CustomResourceDefinition
metadata:
 name: crontabs.stable.example.com
spec:
 group: stable.example.com
 versions:
 - name: v1
 served: true
 storage: true
 scope: Namespaced
 names:
 plural: crontabs
 singular: crontab
 kind: CronTab

values.yaml文件

  • 存放變量的位置,YAML格式往声,支持層次

  • 變量名稱(chēng)以小寫(xiě)字母開(kāi)頭擂找,單詞按駝峰區(qū)分:

chicken: true
chickenNoodleSoup: true

.helmignore文件

用來(lái)指定你不想包含在你的helm chart中的文件。

helm package 命令會(huì)在打包應(yīng)用時(shí)忽略所有在.helmignore文件中匹配的文件浩销。

# comment

# Match any file or path named .helmignore
.helmignore

# Match any file or path named .git
.git

# Match any text file
*.txt

# Match only directories named mydir
mydir/

# Match only text files in the top-level directory
/*.txt

# Match only the file foo.txt in the top-level directory
/foo.txt

# Match any file named ab.txt, ac.txt, or ad.txt
a[b-d].txt

# Match any file under subdir matching temp*
*/temp*

*/*/temp*
temp?
  • 不支持'!'作為特殊的引導(dǎo)序列

  • 默認(rèn)不會(huì)排除自身贯涎,需要顯式添加 .helmignore

  • 末尾空格總會(huì)被忽略(不支持轉(zhuǎn)義序列)

  • 不支持'**'語(yǔ)法。

NOTES.txt文件

helm installhelm upgrade命令的最后慢洋,Helm會(huì)打印出對(duì)用戶(hù)有用的信息塘雳。

要在chart添加安裝說(shuō)明,只需創(chuàng)建templates/NOTES.txt文件即可普筹。該文件是純文本败明,但會(huì)像模板一樣處理, 所有正常的模板函數(shù)和對(duì)象都是可用的太防。

示例

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

Chart模板詳解

Helm Chart 模板是按照 Go模板語(yǔ)言書(shū)寫(xiě)妻顶, 增加了50個(gè)左右的附加模板函數(shù) 來(lái)自 Sprig庫(kù) 和一些其他 指定的函數(shù)

所有模板文件存儲(chǔ)在chart的 templates/ 文件夾蜒车。 當(dāng)Helm渲染chart時(shí)讳嘱,它會(huì)通過(guò)模板引擎遍歷目錄中的每個(gè)文件。

模板的Value來(lái)源:

  • Chart開(kāi)發(fā)者可以在chart中提供一個(gè)命名為 values.yaml (默認(rèn))的文件酿愧。

  • Chart用戶(hù)可以在執(zhí)行helm install -f values.yamlhelm install --set key=value來(lái)提供一個(gè)包含了value的YAML文件或變量

    • 提供的文件中的value會(huì)覆蓋chart包中的values.yaml中的value
  • 如果是子chart沥潭,就是父chart中的values.yaml文件

yaml 文件寫(xiě)法 set 的寫(xiě)法
name: value --set name=value
a: b c: d --set a=b,c=d
outer: inner: value --set outer.inner=value
name: - a - b -c --set name={a, b, c}
servers: - port: 80 --set servers[0].port=80
servers: - port: 80 host: example --set servers[0].port=80,servers[0].host=example
name: "value1,value2" --set name=value1,value2
nodeSelector: kubernetes.io/role: master --set nodeSelector."kubernetes.io/role"=master

模板中各資源的先后加載順序

# 從上到下依次執(zhí)行
Namespace
NetworkPolicy
ResourceQuota
LimitRange
PodSecurityPolicy
PodDisruptionBudget
ServiceAccount
Secret
SecretList
ConfigMap
StorageClass
PersistentVolume
PersistentVolumeClaim
CustomResourceDefinition
ClusterRole
ClusterRoleList
ClusterRoleBinding
ClusterRoleBindingList
Role
RoleList
RoleBinding
RoleBindingList
Service
DaemonSet
Pod
ReplicationController
ReplicaSet
Deployment
HorizontalPodAutoscaler
StatefulSet
Job
CronJob
Ingress
APIService

模板使用方式

在模板的使用過(guò)程中不論是變量還是函數(shù)都通過(guò){{ }}中引用

Values 通過(guò)模板中{{ .Values }}對(duì)象可訪問(wèn)的values.yaml文件,也可以通過(guò) {{ .Chart }} 對(duì)象可訪問(wèn)的 Chart.yaml 嬉挡,以此類(lèi)推叛氨。

內(nèi)置Values

此外helm內(nèi)置了一些values

  • .Release

    • 該對(duì)象描述了版本發(fā)布本身。

    • 使用方法如棘伴,{{ .Release.Name }} (獲取 release 的名稱(chēng))

.Release.Name        # 版本名稱(chēng)(非chart的)
.Release.Namespace   # 發(fā)布的chart版本的命名空間
.Release.Service     # 組織版本的服務(wù),通常都是Helm
.Release.IsUpgrade    # 如果當(dāng)前操作是升級(jí)或回滾寞埠,設(shè)置為true
.Release.IsInstall    # 如果當(dāng)前操作是安裝,設(shè)置為true
  • .Values

    • 訪問(wèn) values.yaml 的內(nèi)容焊夸。

    • 使用方法如仁连,{{ .Values.image.repository }} (獲取 values.yaml 中 image - repository 的值)

  • .Chart

    • 訪問(wèn) Chart.yaml 的內(nèi)容。

    • 使用方法如阱穗, {{ .Chart.Version }}

    • 注意:Chart.yaml中的字段在調(diào)用時(shí)首字母大寫(xiě)

    • 語(yǔ)法風(fēng)格遵循 go 模版規(guī)則饭冬,類(lèi)似 jinja2。是一種層級(jí)檢索的方式揪阶,. 表示層級(jí)昌抠,最頂層的 .

  • .Files

    • 訪問(wèn) chart 中存在的文件的內(nèi)容 (.helmignore 除外)鲁僚。

    • 使用方法如炊苫,{{ index .Files "file.name" }} (獲取該文件中 name的值)裁厅,它等效于 {{ .Files.Get name }} 方法。

    • {{ .Files.GetBytes }} 方法等效于訪問(wèn)文件中的 []byte 對(duì)象

    • {{ (.Files.Glob "conf/*.conf").AsConfig }} 以configmap的形式獲取文件名和內(nèi)容

    • {{ (.Files.Glob "conf/*.conf").AsSecrets }}以secret的形式獲取文件名和內(nèi)容

  • .Capabilities

    • 訪問(wèn) K8s 的 Capabilities 對(duì)象侨艾。

    • 使用方法如执虹,{{ .Capabilities.KubeVersion }} (獲取 K8s 版本)、{{ .Capabilities.APIVersions.Has "batch/v1" }}(獲取支持的 K8s API 版本)

.Capabilities.APIVersions          # 返回所有api列表
.Capabilities.APIVersions.Has $version  # 判斷是否支持對(duì)應(yīng)的api唠梨,布爾值
.Capabilities.KubeVersion          # k8s 版本
.Capabilities.KubeVersion.Version  # k8s 版本
.Capabilities.KubeVersion.Major      # k8s 主版本號(hào)
.Capabilities.KubeVersion.Minor      # k8s 次版本號(hào)
  • .Template

    • 當(dāng)前被執(zhí)行的當(dāng)前模板信息

    • .Template.Name: 當(dāng)前模板的命名空間文件路徑 (e.g. mychart/templates/mytemplate.yaml)

    • .Template.BasePath: 當(dāng)前chart模板目錄的路徑 (e.g. mychart/templates)

使用示例

$ helm create mychart
rm -rf mychart/templates/*

cat << EOF > mychart/values.yaml
who: wzp
 user: test
EOF

cat << EOF > mychart/templates/configmap.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
 name: {{ .Release.Name }}-cm
data:
 rel_name: {{ .Release.Name }}
 rel_namespace: {{ .Release.Namespace }}
 rel_service: {{ .Release.Service }}
 rel_isupgrade: {{ .Release.IsUpgrade }}
 rel_install: {{ .Release.IsInstall }}
 value_who: {{ .Values.who }}
 value_user: {{ .Values.who.user  }}
 chart_name: {{ .Chart.Name }}
 chart_Version: {{ .Chart.Version }}
 k8s_metadata: |
 {{ .Capabilities.APIVersions.Has "batch/v1" }}
 {{ .Capabilities.KubeVersion }}
 {{ .Capabilities.KubeVersion.Version }}
 {{ .Capabilities.KubeVersion.Major }}
 {{ .Capabilities.KubeVersion.Minor }}
EOF

$ tree mychart
mychart
├── charts
├── Chart.yaml
├── templates
│   └── configmap.yaml
└── values.yaml


# 測(cè)試執(zhí)行
helm install mycm mychart/ --debug --dry-run
NAME: mycm
LAST DEPLOYED: Tue Mar 21 07:26:47 2023
NAMESPACE: default
...
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: mycm-cm
data:
 rel_name: mycm
 rel_namespace: default
 rel_service: Helm
 rel_isupgrade: false
 rel_install: true
 value_who: map[user:test]
 value_user: test
 chart_name: mychart
 chart_Version: 0.1.0
 k8s_metadata: |
 true
 v1.23.13
 v1.23.13
 1
 23

內(nèi)置函數(shù)

函數(shù)的使用格式

  • 語(yǔ)法:func_name arg1 arg2 ...

  • 倒置命令:arg1 | func_name arg2 ... 推薦用法

在倒置命令中的| 也被稱(chēng)之為管道符袋励,類(lèi)似于unix的管道概念通過(guò)管道符|將一系列的模板語(yǔ)言緊湊地將多個(gè)流式處理結(jié)果合并的工具。

不過(guò)值得注意是管道僅能將第一個(gè)參數(shù)傳遞給函數(shù)使用当叭,在大多數(shù)僅有一個(gè)參數(shù)的函數(shù)使用時(shí)很直觀

常用函數(shù)

quote <str> 或 squote <str>      # 將指定字符串添加上雙引號(hào)或單引號(hào)

upper <str> 或 lower <str>      # 將指定字符串變成全部大寫(xiě)或小寫(xiě)

indent                              # 用于指定字符串縮進(jìn)指定長(zhǎng)度茬故,以上一行為標(biāo)準(zhǔn)開(kāi)始縮進(jìn)

nindent                              # 用于指定字符串縮進(jìn)指定長(zhǎng)度,以行首為標(biāo)準(zhǔn)開(kāi)始縮進(jìn)蚁鳖,且會(huì)在上方添加一個(gè)新行

toYAML                              # 引用一整塊YAMl內(nèi)容,像健康檢查均牢,資源配額resources,或者端口才睹,這都是一塊一塊的內(nèi)容徘跪,通過(guò)toYaml引用很方便,(默認(rèn)定格將后部分內(nèi)容引入琅攘,所以需要連用縮進(jìn))

uuid                                 # 生成隨機(jī)uuid

repeat <str> <n>                  # 將指定字符串重復(fù)n次

trim <str>                          # 去除字符串兩邊的空格

trimAll  <> <str>                  # 用于移除兩邊字符串中指定字符

trimPerfix <> <str>                  # 用于移除字符串指定的前綴

trimSuffix <> <str>                  # 用于移除字符串指定后綴

default <str> <default_value>      # 指定一個(gè)默認(rèn)值垮庐,當(dāng)引用值不存在時(shí),使用默認(rèn)值

unixEpoch                          # 返回時(shí)間戳坞琴,now | unixEpoch

sha256sum <str>                      # 用于計(jì)算字符串的SHA256值進(jìn)行加密

htpasswd <user> <pass>              # 根據(jù)傳入的username和paasword生成一個(gè)密碼的bcrypt哈希值哨查,可以用于HTTP Server的基礎(chǔ)認(rèn)證

encryptAES <鹽> <要加密的內(nèi)容>      # 加密函數(shù),使用一個(gè)AES-256 CBC加密文本并返回一個(gè)base64編碼字符串

decryptAES <鹽> <加密后的內(nèi)容>      # 解密函數(shù)剧辐,接收一個(gè)AES-256 CBC編碼的字符串返回解密文本

b64enc                              # 將字符串以base64進(jìn)行編碼

printf "%s is %s" "wzp" "boby"      # 格式化輸出 

lookup "apiVersion" "kind" "namespace" "name"  # 用于獲取k8s的一些信息寒亥,類(lèi)似于kubectl
# k8s 命令                         lookup函數(shù)
kubectl get pod mypod -n myns      lookup "v1" "Pod" "myns" "mypod"
kubectl get pod -n myns              lookup "v1" "Pod" "myns" ""
kubectl get pod -A                  lookup "v1" "Pod" "" ""
kubectl get ns myns                  lookup "v1" "Namespace" "myns" ""
kubectl get ns                       lookup "v1" "Namespace" "" ""

結(jié)尾附大部分函數(shù)說(shuō)明

使用示例

helm create mychart
rm -rf mychart/templates/*

cat << EOF > mychart/values.yaml
who:
 user: test
trim: "  space   "
str: "hello world hello"
hello:
 nindent1: test
 nindent2: test2
EOF

cat << EOF > mychart/templates/configmap.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
 name: {{ .Release.Name }}-cm
data:
 quote: {{ .Release.Name | quote }}                      # .Release.Name 加雙引號(hào)
 squote: {{ .Release.Name | squote }}                    # .Release.Name 加單引號(hào)
 indent: {{ .Release.Name | indent 2 | quote }}          # 以當(dāng)前行的位置,縮進(jìn)
 nindent: {{ .Release.Name | nindent 2 | quote }}        # 增加一個(gè)換行荧关,然后也行首為標(biāo)準(zhǔn)縮進(jìn)
 {{- with .Values.hello }}
 {{- toYaml . | nindent 2 }}
 {{- end }}
 upper: {{ .Release.Name | upper | quote }}              # .Release.Name 全大寫(xiě)
 lower: {{ .Release.Name | lower | quote }}              # .Release.Name 全小寫(xiě)
 repeat3: {{ .Release.Name | repeat 3 | quote }}         # 重復(fù).Release.Name 三次溉奕,并加上雙引號(hào)(quote)
 default: {{ .Release.Haha | default "默認(rèn)值" | quote }} # Haha并不存在,給一個(gè)默認(rèn)值忍啤,并加上雙引號(hào)(quote) 
 all_ns: {{ "v1" | lookup "Namespace" "" "" | quote }}   # 相當(dāng)于kubectl get ns, 加了--dry-run時(shí)不會(huì)獲取值
 unixepoch: {{ now | unixEpoch }}                        # 返回時(shí)間戳
 trim: {{ .Values.trim | trim | quote }}                         # 去掉.Values.trim字段兩邊的空格
 trimall: {{ trimAll "wo" "wohello worldwo" }}           # 去掉wohello worldwo 兩邊的 wo
 trimprefix: {{ trimPrefix "wo" "wohello worldwo" }}     # 去掉wohello worldwo 前邊的 wo
 trimsuffix: {{ trimSuffix "wo" "wohello worldwo" }}     # 去掉wohello worldwo 后邊的 wo
 sha256sum: {{ sha256sum "hello world" }}                # sha256加密 hello world
 htpasswd: {{ htpasswd "user1" "password" }}             # httppass加密user1和password
 b64enc: {{ b64enc "hello world" }}                      # base64編碼 hello world
 encryptaes: {{ encryptAES "testkey" "testvalues" }}     # 以testky為加密秘鑰加勤,加密testvalues
 decryptaes: {{ decryptAES "testkey" "1BEUTeflfCLvsg5ivwh3OJ50zDfsHYqM1lYPndFNDck=" }} # 以testkey為秘鑰,解密加密內(nèi)容
 uuid: {{ uuidv4 }}
EOF

$ tree mychart
mychart
├── charts
├── Chart.yaml
├── templates
│   └── configmap.yaml
└── values.yaml

# 測(cè)試執(zhí)行
helm install mycm mychart/ --debug --dry-run
install.go:172: [debug] Original chart version: ""
install.go:189: [debug] CHART PATH: /root/wzp/mychart
NAME: mycm
...
HOOKS:
MANIFEST:
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: mycm-cm
data:
 quote: "mycm"                      # .Release.Name 加雙引號(hào)
 squote: 'mycm'                    # .Release.Name 加單引號(hào)
 indent: "  mycm"          # 以當(dāng)前行的位置同波,縮進(jìn)
 nindent: "\n  mycm"        # 增加一個(gè)換行鳄梅,然后也行首為標(biāo)準(zhǔn)縮進(jìn)
 nindent1: test
 nindent2: test2
 upper: "MYCM"              # .Release.Name 全大寫(xiě)
 lower: "mycm"              # .Release.Name 全小寫(xiě)
 repeat3: "mycmmycmmycm"         # 重復(fù).Release.Name 三次,并加上雙引號(hào)(quote)
 default: "默認(rèn)值" # Haha并不存在未檩,給一個(gè)默認(rèn)值戴尸,并加上雙引號(hào)(quote) 
 all_ns: "map[]"   # 相當(dāng)于kubectl get ns, 加了--dry-run時(shí)不會(huì)獲取值
 unixepoch: 1679646539                        # 返回時(shí)間戳
 trim: "space"                         # 去掉.Values.trim字段兩邊的空格
 trimall: hello world           # 去掉wohello worldwo 兩邊的 wo
 trimprefix: hello worldwo     # 去掉wohello worldwo 前邊的 wo
 trimsuffix: wohello world     # 去掉wohello worldwo 后邊的 wo
 sha256sum: b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9                # sha256加密 hello world
 htpasswd: user1:$2a$10$HLqEoWCIK0E6NCved.r7me8CiIM0USPMiet9AbE1u6mEuOBRYJ75K             # httppass加密user1和password
 b64enc: aGVsbG8gd29ybGQ=                      # base64編碼 hello world
 encryptaes: dEziheGC1mXzWq+VEHhqN/ebvsl0Km1MJb3Jgs/T5hg=     # 以testky為加密秘鑰,加密testvalues
 decryptaes: testvalues # 以testkey為秘鑰冤狡,解密加密內(nèi)容
 uuid: 24e17b0e-bfaf-4e52-9a4a-ec3394e691cd

流程控制語(yǔ)句

控制結(jié)構(gòu)(在模板語(yǔ)言中稱(chēng)為"actions")提供控制模板迭代流的能力孙蒙。Helm的模板語(yǔ)言提供了以下控制結(jié)構(gòu):

  • if/else项棠, 用來(lái)創(chuàng)建條件語(yǔ)句

  • with, 用來(lái)指定范圍

  • range马篮, 提供"for each"類(lèi)型的循環(huán)

if/else

條件控制語(yǔ)句

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

如下值為被解析為false:

  • 布爾false

  • 數(shù)字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 }}

# 我們看一下結(jié)果,多了一個(gè)空行怜奖,為什么浑测?
helm install mycm mychart/ --debug --dry-run
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: telling-chimp-configmap
data:
 myvalue: "Hello World"
 drink: "coffee"
 food: "PIZZA"

 mug: "true"

空行是怎么來(lái)的?

當(dāng)模板引擎運(yùn)行時(shí)歪玲,它 移除了 {{}} 里面的內(nèi)容迁央,但是留下的空白完全保持原樣。

YAML認(rèn)為空白是有意義的滥崩,因此管理空白變得很重要岖圈。helm模板中也給我們提供了處理該問(wèn)題的方法

首先,模板聲明的大括號(hào)語(yǔ)法可以通過(guò)特殊的字符修改钙皮,并通知模板引擎取消空白蜂科。{{-(包括添加的橫杠和空格)表示向左刪除空白, 而-}}表示右邊的空格應(yīng)該被去掉短条。 一定注意空格就是換行

要確保-和其他命令之間有一個(gè)空格导匣。 {{- 3 }} 表示“刪除左邊空格并打印3”,而{{-3 }}表示“打印-3”茸时。

使用這個(gè)語(yǔ)法贡定,我們就可修改我們的模板,去掉新加的空白行:

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


# 注意不要{{-   -}}  前后都加-可都,都加上會(huì)變成把兩邊的新行都刪除了
 food: {{ .Values.favorite.food | upper | quote }}
 {{- if eq .Values.favorite.drink "coffee" -}}
 mug: "true"
 {{- end -}}
# 這樣會(huì)變成food: "PIZZA"mug:"true"缓待,因?yàn)檫@把兩邊的新行都刪除了。

比較復(fù)雜的用法

 annotations:
{{- if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "auto") }}
 checksum/tls: {{ include (print $.Template.BasePath "/internal/auto-tls.yaml") . | sha256sum }}
{{- else if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "manual") }}
 checksum/tls: {{ include (print $.Template.BasePath "/core/core-tls.yaml") . | sha256sum }}
{{- end }}

 spec:
{{- if .Values.core.serviceAccountName }}
 serviceAccountName: {{ .Values.core.serviceAccountName }}

with

這個(gè)用來(lái)控制變量范圍渠牲⌒矗回想一下,.是對(duì) 當(dāng)前作用域 的引用签杈。因此 .Values就是告訴模板在當(dāng)前作用域查找Values對(duì)象国葬。而with就是用來(lái)改變.的查找作用域

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

作用域可以被改變。with允許你為特定對(duì)象設(shè)定當(dāng)前作用域(.)芹壕。比如汇四,我們已經(jīng)在使用.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 }}

注意踢涌,在限定的作用域內(nèi)通孽,無(wú)法使用.訪問(wèn)父作用域的對(duì)象。

例如:

 {{- with .Values.favorite }}
 drink: {{ .drink | default "tea" | quote }}
 food: {{ .food | upper | quote }}
 release: {{ .Release.Name }}              # 會(huì)報(bào)錯(cuò)睁壁,找不到
 {{- end }}

 {{- with .Values.favorite }}
 drink: {{ .drink | default "tea" | quote }}
 food: {{ .food | upper | quote }}
 {{- end }}
 release: {{ .Release.Name }}              # 拿到 {{ end }} 之外可以正常執(zhí)行

range

類(lèi)似for循環(huán)的機(jī)制背苦。Helm的模板語(yǔ)言中互捌,在一個(gè)集合中迭代的方式是使用range操作符。

range可被用于列表和元組行剂、用于迭代有鍵值對(duì)的集合(像mapdict

range 如果給定兩個(gè)變量接收 列表或元組秕噪,那么第一個(gè)變量為索引(0開(kāi)始),第二個(gè)為值厚宰。

range 如果給定兩個(gè)變量接收 map或字典腌巾,那么第一個(gè)變量為key,第二個(gè)為值铲觉。

# values.yaml
favorite:
 drink: coffee
 food: pizza
pizzaToppings: # 列表(模板中稱(chēng)為切片)
 - mushrooms
 - cheese
 - peppers
 - onions

# templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: {{ .Release.Name }}-configmap
data:
 {{- with .Values.favorite }}
 drink: {{ .drink | default "tea" | quote }}
 food: {{ .food | upper | quote }}
 {{- end }}
 toppings: |-
 {{- range .Values.pizzaToppings }}
 - {{ . | title | quote }}
 {{- end }}

# range方法“涵蓋”(迭代)pizzaToppings列表澈蝙。
# 就像with設(shè)置了.的作用域,range操作符也做了同樣的事撵幽。
# 每一次循環(huán)灯荧,.都會(huì)設(shè)置為當(dāng)前的作用域。 也就是說(shuō)盐杂,第一次.設(shè)置成了mushrooms逗载,第二次迭代設(shè)置成了cheese,等等链烈。



helm install mycm mychart/ --debug --dry-run
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: edgy-dragonfly-configmap
data:
 myvalue: "Hello World"
 drink: "coffee"
 food: "PIZZA"
 toppings: |-
 - "Mushrooms"
 - "Cheese"
 - "Peppers"
 - "Onions"

變量

在helm3 中撕贞,變量一般我們不會(huì)直接使用,通常搭配 withrange 一起使用测垛。

變量的定義格式:$name := value , :=為賦值運(yùn)算符捏膨。

作用域

變量一般不是"全局的"。作用域是其聲明所在的塊食侮。

with可以改變他的作用域号涯,下面我們看個(gè)例子

data:
 {{- with .Values.favorite }}
 drink: {{ .drink | default "tea" | quote }}
 food: {{ .food | upper | quote }}
 release: {{ .Release.Name }}
 {{- end }}
  • 在這個(gè)例子中,執(zhí)行會(huì)失敗锯七,因?yàn)閣ith將其作用域改到了.Values.favorite

  • 那么在去調(diào)用.Release.Name就變成了.Values.favorite.Release.Name從而未發(fā)現(xiàn)而失敗

考慮到作用域的問(wèn)題链快,我們可以若下操作:重定義一個(gè)變量用來(lái)存放.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 }}

在模板的頂層賦值了$relname。變量的作用域會(huì)是整個(gè)模板眉尸。

變量在range循環(huán)中特別有用域蜗。可以用于類(lèi)似列表的對(duì)象噪猾,以獲取索引和值:

pople:
 - name
 - sex
 - num


data:
 pople: |-
 {{- range $index, $value := .Values.pople }}
 # 整型索引(從0開(kāi)始)賦值給$index并將值賦值給$value
 {{ $index }}: {{ $value }}
 {{- end }}

# 此時(shí)我們可以獲取到類(lèi)似于帶索引的列表
data:
 pople: |-
 0: name
 1: sex
 2: num

對(duì)于數(shù)據(jù)結(jié)構(gòu)有key和value霉祸,可以使用range獲取key和value。

# values.yaml
favorite:
 myvalue: "Hello World"
 drink: "coffee"
 food: "pizza"


apiVersion: v1
kind: ConfigMap
metadata:
 name: {{ .Release.Name }}-configmap
data:
 myvalue: "Hello World"
 {{- range $key, $val := .Values.favorite }}
 {{ $key }}: {{ $val | quote }}
 {{- end }}

# 此時(shí)我們可以連帶著獲取key和value
data:
 myvalue: "Hello World"
 drink: "coffee"
 food: "pizza"

上with的例子中說(shuō)在模板的頂層賦值了$relname袱蜡。變量的作用域會(huì)是整個(gè)模板丝蹭。

而本次例子$key$value作用域會(huì)在{{ range... }}{{ end }}塊內(nèi)。

這里有一個(gè)特殊的變量 $ 這個(gè)變量一直是指向根的上下文坪蚁。當(dāng)在一個(gè)范圍內(nèi)循環(huán)同時(shí)要用一些根的一些變量很有用

apiVersion: v1
kind: ConfigMap
metadata:
 name: {{ .Release.Name }}-configmap
data:
 {{- with .Values.favorite }}
 drink: {{ .drink | default "tea" | quote }}
 food: {{ .food | upper | quote }}
 release: {{ $.Release.Name }}
 chart: {{ $.Chart.Name }}
 {{- end }}

命名模板和引用

命名模板 (有時(shí)稱(chēng)作一個(gè) 部分 或一個(gè) 子模板)僅僅是在文件內(nèi)部定義的模板奔穿,并使用了一個(gè)名字镜沽。有兩種創(chuàng)建方式和幾種不同的使用方法。

  • 局部命名(每個(gè)模板文件中)

  • __helpers.tpl (類(lèi)似于全局贱田,__helpers.tpl是默認(rèn)名稱(chēng))

  • templates/目錄中缅茉,任何以下劃線(_)開(kāi)始的文件(慣例使用__helpers.tpl)

不管何種方式定義的子模板,模板名稱(chēng)都是全局的男摧,名稱(chēng)相同時(shí)最后一個(gè)加載的覆蓋之前的

命名模板通常用于多行需要被重復(fù)使用或被變量化的內(nèi)容蔬墩。

聲明和管理模板的方法:

  • define

    • 聲明命名模塊塊
  • template

    • 引用子模板,接受1或2個(gè)參數(shù)(命名模板名稱(chēng)和變量的獲取范圍)

    • 無(wú)法被 其他函數(shù)修飾彩倚,(常見(jiàn)于縮進(jìn)修飾)

  • block

  • include(推薦)

    • 引用子模板筹我,接受2個(gè)參數(shù)(命名模板名稱(chēng)和變量的獲取范圍)

    • 可以被 其他函數(shù)修飾 (常見(jiàn)于縮進(jìn)修飾)

定義和引用

define來(lái)聲明模板

{{/* Generate basic labels */}}  # 按照慣例我們應(yīng)該使用注釋說(shuō)明作用
{{- define "MY.NAME" -}}
 # body of template here
{{- end -}}

templateinclude(推薦)來(lái)引用

{{ template "MY.NAME" }}

{{ include "MY.NAME" }}

template示例

# 在主模板中
# templates/configmap.yaml 
{{- define "mychart.labels" }}
 labels:
 generator: helm
 date: {{ now | htmlDate }}
{{- end }}
apiVersion: v1
kind: ConfigMap
metadata:
 name: {{ .Release.Name }}-cm
 {{ template "mychart.labels" }}
data:
 myvalue: "Hello World"

注意:當(dāng)一個(gè)(使用define創(chuàng)建的)命名模板被渲染時(shí)扶平,會(huì)接收被templateinclude調(diào)用傳入的內(nèi)容帆离。 若引用了對(duì)象,默認(rèn)情況是無(wú)法用.訪問(wèn)任何內(nèi)容结澄。所以引用對(duì)象時(shí)必須傳遞一個(gè)范圍給模板

template注意示例

# templates/configmap.yaml 
{{- define "mychart.labels" }}
 labels:
 generator: helm
 date: {{ now | htmlDate }}
 chart: {{ .Chart.Name }}
{{- end }}
apiVersion: v1
kind: ConfigMap
metadata:
 name: {{ .Release.Name }}-cm
 {{ template "mychart.labels" . }}    # 將'.'根位置傳遞進(jìn)去哥谷,這時(shí)渲染時(shí)就可以調(diào)用.Chart.Name了,否則報(bào)錯(cuò)
data:
 myvalue: "Hello World"

為什么有了template后還要增加一個(gè)include方法麻献?我們看個(gè)案例

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

apiVersion: v1
kind: ConfigMap
metadata:
 name: {{ .Release.Name }}-configmap
 labels:
 {{ template "mychart.labels" . }}
data:
 myvalue: "Hello World"
{{ template "mychart.labels" . }}

當(dāng)我們嘗試渲染上述模板時(shí)直接報(bào)錯(cuò)了

$ helm install mycm mychart/  --dry-run 
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]

# 我們加個(gè) --disable-openapi-validation 看看我們渲染了什么
$ helm install mycm mychart/  --dry-run --disable-openapi-validation 
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: mycm-configmap
 labels:
 app_name: mychart
app_version: "0.1.0"          # 錯(cuò)亂的位置
data:
 myvalue: "Hello World"
app_name: mychart              # 錯(cuò)亂的位置
app_version: "0.1.0"          # 錯(cuò)亂的位置

很顯然這參數(shù)的擺放位置并不是我們想要的们妥,這是因?yàn)楸惶鎿Q的模板中文本是左對(duì)齊的。由于template是一個(gè)行為勉吻,不是方法监婶,無(wú)法將 template調(diào)用的輸出傳給其他方法,數(shù)據(jù)只是簡(jiǎn)單地按行插入齿桃。

這時(shí)引入了include , 它是一個(gè)方法可以被函數(shù)修飾惑惶,所以在helm中使用include被認(rèn)為是更好的方式,可以更好地處理YAML文檔的輸出格式

這時(shí)調(diào)整我們的模板短纵,通過(guò)indent 函數(shù)修飾為正確的樣子

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

apiVersion: v1
kind: ConfigMap
metadata:
 name: {{ .Release.Name }}-configmap
 labels:
{{ include  "mychart.labels" . | indent 4 }}
data:
 myvalue: "Hello World"
{{ include  "mychart.labels" . | indent 2 }}


$ helm install mycm mychart/  --dry-run 
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: mycm-configmap
 labels:
 app_name: mychart
 app_version: "0.1.0"
data:
 myvalue: "Hello World"
 app_name: mychart
 app_version: "0.1.0"

在模板中獲取文件內(nèi)容

有時(shí)想導(dǎo)入的不是模板的文件带污,而是無(wú)需模板渲染的文件內(nèi)容時(shí)使用此方式。

Helm 提供了通過(guò).Files對(duì)象訪問(wèn)文件的方法香到。不過(guò)鱼冀,在我們使用模板示例之前,有些事情需要注意:

  • 可以添加額外的文件到chart中悠就。但是要小心千绪,由于Kubernetes對(duì)象的限制,Chart必須小于1M梗脾。

  • 通常處于安全考慮翘紊,一些文件無(wú)法通過(guò).Files對(duì)象訪問(wèn):

    • 無(wú)法訪問(wèn)templates/中的文件

    • 無(wú)法訪問(wèn)使用.helmignore排除的文件

    • 之Chart無(wú)法使用父Chart的文件

.Files使用方法

  • .Files.Get:獲取文件內(nèi)容

  • .Files.Glob:獲取文件名和內(nèi)容(支持正則指定多個(gè)文件)

    • .Files.Glob.AsConfig:獲取后文件內(nèi)容以configmap的形式展示
    • .Files.Glob.AsSecret:獲取后文件內(nèi)容以secret的形式展示
  • .Files.Lines:獲取文件的每一行

路徑方法

  • base

    • 返回路徑的最后一個(gè)元素(即文件名稱(chēng))
  • dir

    • 返回路徑中的目錄
  • ext

    • 返回文件擴(kuò)展名(即最后一個(gè).和其后面的內(nèi)容)
  • isAbs

    • 布爾值,是否為絕對(duì)路徑
  • clean

    • 清除路徑中間部分的..和前一個(gè)路徑藐唠,如/foo/bar/../hello.txt帆疟,清除后為/foo/hello.txt

使用示例

讀取三個(gè)文件使用.Files.Get方法獲取內(nèi)容

# mychart/hello.txt
hello world 

# mychart/nginx.conf
nginx conf ....

# mychart/conf.toml
message = hello from conf.toml

# mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: {{ .Release.Name }}-configmap
data:
 {{- range tuple "hello.txt" "nginx.conf" "conf.toml" }}
 {{ . }}: |-
 {{ .Files.Get . }}
 {{- end }}
 token: |-
 {{ .Files.Get "conf.toml" | b64enc }}

# 調(diào)試渲染模板
$ helm template --debug mychart
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: RELEASE-NAME-configmap
data:
 hello.txt: |-
 hello world

 nginx.conf: |-
 nginx conf ....

 conf.toml: |-
 message = hello from conf.toml
 token: |-
 bWVzc2FnZSA9IGhlbGxvIGZyb20gY29uZi50b21sCg==

使用.Files.Glob獲取多個(gè)Files對(duì)象

這意味著.Files.Glob返回的對(duì)象還可以繼續(xù)調(diào)用Files對(duì)象的方法

示例1

# mychart/hello.txt
hello world 

# mychart/nginx.conf
nginx conf ....

# mychart/mysql.conf
mysql conf

# mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: {{ .Release.Name }}-configmap
data:
{{- range $path, $_ := .Files.Glob "**.conf" }}
 path: {{ $path }}
 {{ $path }}: {{ $.Files.Get $path }}
{{- end }}


# 調(diào)試渲染模板
helm template --debug mychart
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: RELEASE-NAME-configmap
data:
 path: mysql.conf
 mysql.conf: mysql conf

 path: nginx.conf
 nginx.conf: nginx conf ....

示例2

# mychart/hello.txt
hello world 

# mychart/nginx.conf
nginx conf ....

# mychart/mysql.conf
mysql conf

# mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: {{ .Release.Name }}-configmap
data:
{{ (.Files.Glob "**.conf").AsConfig | indent 2 }}
{{ (.Files.Glob "**.conf").AsSecrets | indent 2 }}


# 調(diào)試渲染模板
$ helm template --debug mychart
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: RELEASE-NAME-configmap
data:
 mysql.conf: |
 mysql conf
 nginx.conf: |
 nginx conf ....
 mysql.conf: bXlzcWwgY29uZgo=
 nginx.conf: bmdpbnggY29uZiAuLi4uCg==

使用.Files.Lines配合range遍歷文件每一行

# mychart/lines.txt
the line1
the line2
the line3
the line4

# mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: {{ .Release.Name }}-configmap
data:
{{- range $index, $line := .Files.Lines "lines.txt" }}
 {{- if $line }}
 {{ $index }}: {{ $line | quote }}
 {{- end }}
{{- end }}
 lines.txt: {{ range .Files.Lines "lines.txt" }}
 {{ . }}{{ end }}


# 調(diào)試渲染模板
$ helm template --debug mychart
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: RELEASE-NAME-configmap
data:
 0: "the line1"
 1: "the line2"
 2: "the line3"
 3: "the line4"
 lines.txt: 
 the line1
 the line2
 the line3
 the line4

路徑示例

apiVersion: v1
kind: ConfigMap
metadata:
 name: {{ .Release.Name }}-configmap
data:
 base: {{ "/root/wzp.txt" | base }}
 dir: {{ "/root/wzp.txt" | dir }}
 dir: {{ "mychart/template/wzp.txt" | dir }}
 clean: {{ "/root/wzp.txt" | clean }}
 clean: {{ "/opt/test/../mq/wzp.txt" | clean }}
 clean: {{ "opt/test/../mq/wzp.txt" | clean }}
 ext: {{ "/root/wzp.txt" | ext }}
 isAbs: {{ "/root/wzp.txt" | isAbs }}


# 調(diào)試渲染模板
$ helm template --debug mychart
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: RELEASE-NAME-configmap
data:
 base: wzp.txt
 dir: /root
 dir: mychart/template
 clean: /root/wzp.txt
 clean: /opt/mq/wzp.txt
 clean: opt/mq/wzp.txt
 ext: .txt
 isAbs: true

模板調(diào)試技巧

  • helm lint 用于驗(yàn)證chart是否遵循最佳實(shí)踐的首選工具鹉究。

  • helm template --debug 在本地測(cè)試渲染chart模板。

  • helm install --dry-run --debug:服務(wù)器渲染模板踪宠,并返回生成的清單文件自赔。

  • helm get manifest: 查看安裝在服務(wù)器上的模板。

另外一個(gè)可能在我們渲染模板由于格式錯(cuò)誤等問(wèn)題柳琢,無(wú)法返回我們yaml清單绍妨,這時(shí)可以通過(guò)--dry-run --disable-openapi-validation來(lái)顯示最終的效果方便我們排查錯(cuò)誤

helm install  xxx -f mychart/ --dry-run --disable-openapi-validation

Chart開(kāi)發(fā)小技巧

1. 模板渲染required

在正常情況下,模板渲染所需的特定值柬脸。如果這個(gè)值是空的他去,模板渲染會(huì)出錯(cuò)并打印用戶(hù)提交的錯(cuò)誤信息。

這時(shí)如果可以提前預(yù)見(jiàn)有些情況某些值就是可能由于使用上的不小心會(huì)存在空值倒堕,可以通過(guò)required來(lái)聲明灾测,且在為空時(shí)打印自定義提示

例如

# 正常情況下,當(dāng).Values.who不存在時(shí)垦巴,渲染模板會(huì)直接報(bào)錯(cuò)
value: {{ .Values.who }}

# 當(dāng).Values.who不存在時(shí)會(huì)打印錯(cuò)誤信息
value: {{ required "A valid .Values.who entry required!" .Values.who }}

2. 字符串引號(hào)括起來(lái)媳搪,但整型不用

由于chart不會(huì)提前聲明變量類(lèi)型,類(lèi)似于python自動(dòng)識(shí)別骤宣,所以如果確認(rèn)是字符串應(yīng)當(dāng)使用引號(hào)括起來(lái)保證秦爆,在得到數(shù)字時(shí)也是字符串類(lèi)型而不是整形

# 使用字符串?dāng)?shù)據(jù)時(shí),將字符串括起來(lái)而不是露在外面
name: {{ .Values.MyName | quote }}

# 使用整型時(shí) 不要把值括起來(lái)憔披。在很多場(chǎng)景中那樣會(huì)導(dǎo)致Kubernetes內(nèi)解析失敗等限。
port: {{ .Values.Port }}

# 當(dāng)然使用整形時(shí),不要括起來(lái)不適用于環(huán)境變量為整形時(shí)芬膝,即使表現(xiàn)為整型
env:
 - name: HOST
 value: "http://host"
 - name: PORT
 value: "1234"

3. image_pull_secret

在拉取私有倉(cāng)庫(kù)的鏡像時(shí)望门,通過(guò)要掛載一個(gè)secret用于存放鏡像倉(cāng)庫(kù)地址、用戶(hù)名和密碼蔗候,但創(chuàng)建時(shí)需要用base64跑一會(huì)影響速度怒允,所以我們可以通過(guò)模板用于承載秘鑰

# values.yaml
registry: quay.io
username: someone
password: someone
email: wzp@163.com
# 聲明命名模板
{{- define "imagePullSecret" }}
{{- with .Values.imageCredentials }}
{{- printf "{\"auths\":{\"%s\":{\"username\":\"%s\",\"password\":\"%s\",\"email\":\"%s\",\"auth\":\"%s\"}}}" .registry .username .password .email (printf "%s:%s" .username .password | b64enc) | b64enc }}
{{- end }}
{{- end }}

# templates/registry-secret.yaml
apiVersion: v1
kind: Secret
metadata:
 name: myregistrykey
type: kubernetes.io/dockerconfigjson
data:
 .dockerconfigjson: {{ template "imagePullSecret" . }}
  1. 滾動(dòng)部署

由于配置configmapsecret作為配置文件注入容器以及其他外部依賴(lài)更新導(dǎo)致經(jīng)常需要滾動(dòng)部署pod。

但可能存在helm upgrade更新chart時(shí)锈遥,由于delpyment本身沒(méi)有更改并使用原有配置保持運(yùn)行纫事,導(dǎo)致部署不一致。

此時(shí)可以通過(guò)sha256sum方法保證在另一個(gè)文件發(fā)生更改時(shí)deployment也跟著變更

kind: Deployment
spec:
 template:
 metadata:
 annotations:
 checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
[...]


# 另外一種純隨機(jī)的方式
kind: Deployment
spec:
 template:
 metadata:
 annotations:
 rollme: {{ randAlphaNum 5 | quote }}
[...]
  1. 避免全部卸載

有時(shí)在執(zhí)行helm uninstall時(shí)有些資源不應(yīng)該被卸載所灸。Chart的開(kāi)發(fā)者可以在資源中添加額外的說(shuō)明避免被卸載丽惶。

kind: Secret
metadata:
 annotations:
 "helm.sh/resource-policy": keep
[...]

"helm.sh/resource-policy": keep 允許指示Helm操作(比如helm uninstallhelm upgradehelm rollback)要?jiǎng)h除時(shí)跳過(guò)刪除這個(gè)資源爬立,然而钾唬,這個(gè)資源會(huì)變成孤立的。Helm不再以任何方式管理它。

如果在已經(jīng)卸載的但保留資源的版本上使用helm install --replace會(huì)出問(wèn)題抡秆。

Chart 鉤子

Helm 提供了一個(gè) hook 機(jī)制允許chart開(kāi)發(fā)者在發(fā)布生命周期的某些點(diǎn)進(jìn)行干預(yù)奕巍。比如你可以使用hook用于:

  • 安裝時(shí)在加載其他chart之前加載配置映射或密鑰

  • 安裝新chart之前執(zhí)行備份數(shù)據(jù)庫(kù)的任務(wù),然后在升級(jí)之后執(zhí)行第二個(gè)任務(wù)用于存儲(chǔ)數(shù)據(jù)儒士。

  • 在刪除發(fā)布之前執(zhí)行一個(gè)任務(wù)以便在刪除服務(wù)之前退出滾動(dòng)的止。

鉤子的工作方式與常規(guī)模板類(lèi)似,但因?yàn)镠elm對(duì)其不同的使用方式着撩,會(huì)有一些特殊的注釋诅福。

參考:https://helm.sh/docs/topics/charts_hooks/

大部分函數(shù)

邏輯比較函數(shù)

大部分都返回一個(gè)布爾值

函數(shù)名 說(shuō)明
eq 用于判斷兩個(gè)參數(shù)是否相等
ne 用于判斷兩個(gè)參數(shù)是否不相等
lt 用于判斷第一個(gè)參數(shù)是否小于第二個(gè)參數(shù)
le 用于判斷第一個(gè)參數(shù)是否小于等于第二個(gè)參數(shù)
gt 用于判斷第一個(gè)參數(shù)是否大于第二個(gè)參數(shù)
ge 用于判斷第一個(gè)參數(shù)是否大于等于第二個(gè)參數(shù)
and 返回兩個(gè)參數(shù)的邏輯與結(jié)果(布爾值)
or 返回兩個(gè)參數(shù)的邏輯或結(jié)果(布爾值)
not 用于對(duì)參數(shù)的布爾值取反
default 用于設(shè)置默認(rèn)值,參數(shù)為空時(shí)使用默認(rèn)值
empty 用于判斷給定的參數(shù)是否為空
coalesce 用于掃描一個(gè)給定的列表拖叙,并返回第一個(gè)非空數(shù)值
ternary 接收兩個(gè)參數(shù)和一個(gè)test氓润,如果test為true返回第一個(gè)參數(shù),為false返回第二個(gè)參數(shù)

字符串函數(shù)

函數(shù)名 說(shuō)明
print 將所有參數(shù)格式化輸出
println 將所有參數(shù)格式化輸出薯鳍,并且每個(gè)字符串后增加一個(gè)空格咖气,結(jié)尾增加一個(gè)換行符
printf 將所有參數(shù)格式化輸出,并且支持占位符 {{ printf "the float is %.2f" 3.1415 }}
trim 去除字符串兩邊的空格
trimAll 用于移除字符串中指定字符
trimPrefix 用于移除字符串指定的前綴
trimSuffix 用于移除字符串指定的后綴
lower 字符串字母全部大寫(xiě)
upper 字符串字母全部小寫(xiě)
title 字符串首字母轉(zhuǎn)換成大寫(xiě)
untitle 字符串首字母轉(zhuǎn)換成小寫(xiě)
snakecase 用于將駝峰寫(xiě)法轉(zhuǎn)換成下劃線命名法
camelcase 用于將下?lián)Q線名稱(chēng)法轉(zhuǎn)成駝峰命名
kebabcase 用于將駝峰寫(xiě)法轉(zhuǎn)換成縱橫杠寫(xiě)法
swapcase 用于切換字符串大小寫(xiě) a)大寫(xiě)字母變小寫(xiě) b)首字母變小寫(xiě) c)空格后或開(kāi)頭的小寫(xiě)字母轉(zhuǎn)換成大寫(xiě) d)其他小寫(xiě)字母換成大寫(xiě)
substr 用于切割字符串(指定切割起辐啄、始位置)采章,并返回切割后的字符串
trunc 用于截?cái)嘧址耸龋谜麛?shù)或負(fù)整數(shù)壶辜,表示從左向右或從右向左截取字符的個(gè)數(shù)
abbrev 切割字符串,保留指定長(zhǎng)度担租,結(jié)尾用...砸民,省略號(hào)占三個(gè)長(zhǎng)度
randAlpha 使用a-zA-Z,生成隨機(jī)字符串
randAlphaNum 使用0-9a-zA-Z奋救,生成隨機(jī)字符串
randNumeric 使用0-9岭参,生成隨機(jī)字符串
randAscii 使用所有ASCII字符,生成隨機(jī)字符串
contains 用于測(cè)試一個(gè)字符串是否包含在另一個(gè)中
hasPrefix 用于測(cè)試一個(gè)字符串是否是指定的前綴
hasSuffix 用于測(cè)試一個(gè)字符串是否是指定的后綴
repeat 用于將指定字符串重復(fù)n次
nospace 去掉字符串的所有空格
initials 截取指定字符串的每個(gè)單詞的首字母尝艘,并拼接成新的字符串
wrapWith 用于在文檔字符串中指定的列添加內(nèi)容
quote 給字符串增加雙引號(hào)
squote 給字符串增加單引號(hào)
cat 合并多個(gè)字符串演侯,并用空格分隔
replace 執(zhí)行字符串替換,三個(gè)參數(shù):待替換的字符背亥,替換后的字符串秒际,源字符串
shuffle 用于對(duì)字符串重新排序,
indent 用于指定字符串縮進(jìn)指定長(zhǎng)度狡汉,以上一行為標(biāo)準(zhǔn)開(kāi)始縮進(jìn)
nindent 用于指定字符串縮進(jìn)指定長(zhǎng)度娄徊,以行首為標(biāo)準(zhǔn)開(kāi)始縮進(jìn),且會(huì)在上方添加一個(gè)新行
plural 判斷字符串長(zhǎng)度盾戴,根據(jù)值不同寄锐,返回不同的字符串 {{ len "a" plural "one" "many" }} a) 長(zhǎng)度為1,返回第一個(gè)字符串 b)長(zhǎng)度不為1,返回第二個(gè)字符串

類(lèi)型轉(zhuǎn)換和正則函數(shù)

函數(shù)名 說(shuō)明
kindOf 判斷字符串類(lèi)型
atoi 將字符串轉(zhuǎn)換為整型
float64 轉(zhuǎn)換為float64類(lèi)型
int 轉(zhuǎn)換為整型
int64 轉(zhuǎn)換為int64類(lèi)型
toString 轉(zhuǎn)換成字符串
toDecimal 將 unix 八進(jìn)制轉(zhuǎn)成 int64
toStrings 將列表橄仆、切片剩膘、數(shù)組轉(zhuǎn)換成字符串列表
toJson 將列表、切片盆顾、數(shù)組援雇、字典或?qū)ο筠D(zhuǎn)換成Json
toPrettyJson 將列表、切片椎扬、數(shù)組惫搏、字典或?qū)ο筠D(zhuǎn)換成格式化Json
toRawJson 將列表、切片蚕涤、數(shù)組筐赔、字典或?qū)ο筠D(zhuǎn)換成格式化Json(不轉(zhuǎn)義HTML字符)
regexFind 根據(jù)正則匹配查找匹配的內(nèi)容,并返回第一個(gè)匹配的結(jié)果
regexFindAll 用于獲取字符串中匹配正則表達(dá)式的所有子字符串揖铜,并在該函數(shù)的最后指定一個(gè)整數(shù)來(lái)表示返回多少個(gè)正則匹配的字符串
regexMatch 用指定正則茴丰,匹配字符串,匹配正常返回true 匹配郵箱:{{ regexMatch "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,}$" "test@xxx.com" }}
regexReplaceAll 用指定的字符串替換正則匹配到的字符
regexReplaceAllLiteral 將通過(guò)正則匹配的內(nèi)容天吓,替換成其他內(nèi)容
regexSplit 指定一個(gè)分隔符贿肩,將正則匹配到的內(nèi)容替換為分隔符,切割字符串龄寞,并返回指定的分片汰规,-1表示所有
各個(gè)regex開(kāi)頭的都有must版 例如:mustRegexMatch、mustRegexFindAll 區(qū)別在于有表達(dá)式錯(cuò)誤時(shí)物邑,不帶must的直接報(bào)錯(cuò)溜哮,must版會(huì)想模板引擎返回錯(cuò)誤

加密函數(shù)和編解碼函數(shù)

函數(shù)名 說(shuō)明
sha1sum 用于計(jì)算字符串的SHA1值進(jìn)行加密
sha256sum 用于計(jì)算字符串的SHA256值進(jìn)行加密
adler32sum 用于計(jì)算字符串的Adler-32校驗(yàn)和進(jìn)行加密
htpasswd 根據(jù)傳入的username和paasword生成一個(gè)密碼的bcrypt哈希值,可以用于HTTP Server的基礎(chǔ)認(rèn)證
encryptAES 加密函數(shù)色解,使用一個(gè)AES-256 CBC加密文本并返回一個(gè)base64編碼字符串
decryptAES 解密函數(shù)茂嗓,接收一個(gè)AES-256 CBC編碼的字符串返回解密文本
b64enc 將字符串以base64進(jìn)行編碼
b32enc 將字符串以base32進(jìn)行編碼

日期函數(shù)

now 返回當(dāng)前日期和時(shí)間
date 將日期信息格式化,必須使用'2006-01-02'或'2006/01/02'來(lái)表明科阎,否則出錯(cuò) {{ now date "02/01/2006" }}
dateInZone 與date基本一致述吸,增加了指定時(shí)區(qū) {{ dateInZone "2006-01-02" (now) "UTC" }}
duration 將給定的秒數(shù)轉(zhuǎn)換為好閱讀類(lèi)型,如95 -> 1m35s
durationRound 用于取整保留最大的時(shí)間單位锣笨,2h10m5s -> 2h
unixEpoch 返回時(shí)間戳蝌矛,now unixEpoch
dateModify 將給定時(shí)間加減后返回新的時(shí)間 now dateModify "-2h"
toDate 將給定字符串轉(zhuǎn)換成時(shí)間格式,toDate "2006-01-02" "2023-01-01"

字典函數(shù)

dict 創(chuàng)建一個(gè)字典,key必須是字符串 {{- $myDict := "k1" "v1" "k2" "v2" }}
get 通過(guò)key獲取字典的值
set 向已有字典新加鍵值對(duì),也可以修改原來(lái)的
unset 刪除字典中指定的key
keys 獲取一個(gè)或多個(gè)字典中的所有key荒吏,并返回一個(gè)列表
haskey 判斷字典中是否存在指定key
pluck 根據(jù)一個(gè)key在多個(gè)字典中獲取所有匹配的value号枕,返回value組成的列表
merge 合并一個(gè)或多個(gè)字典,key相同時(shí)以第一個(gè)為準(zhǔn)
mergeOverwrite 合并一個(gè)或多個(gè)字典,key相同時(shí)以最后一個(gè)為準(zhǔn)
values 用于獲取一個(gè)字典的所有值返回一個(gè)列表
pick 根據(jù)字典指定的key獲取value囚戚,返回一個(gè)新字典
omit 與pick相反磁携,忽略指定key氮唯,獲取未指定的key和value鉴吹,返回新字典
deepCopy 深度拷貝一個(gè)字典

列表函數(shù)

list 生成一個(gè)列表 {{ $myList := list 1 2 3 "onw" "two" }}
first 獲取列表的第一個(gè)值
rest 獲取除第一個(gè)值以外的所有值
last 獲取列表的最后一個(gè)值
initial 獲取列表中除最后一個(gè)以外的所有值
append 在已有列表中追加一項(xiàng)(最后)
prepend 在列表的最前面加入一個(gè)新值
concat 將任意數(shù)量的列表合并一個(gè)新的列表
reverse 返回一個(gè)反轉(zhuǎn)后的列表
uniq 去除列表的重復(fù)項(xiàng)
without 用于過(guò)濾掉某個(gè)值(即不要某個(gè)值)
has 判斷一個(gè)值是否包含在列表中
compact 刪除一個(gè)列表中的空值
slice 用于對(duì)列表切片, slice [n] [m]
until 用于構(gòu)建一個(gè)指定整數(shù)范圍內(nèi)的列表
untilStep 與Until類(lèi)似,可以指定步長(zhǎng)惩琉,untilStep [n] [m] [步長(zhǎng)]
seq 生成指定范圍內(nèi)的整數(shù)列表
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末豆励,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子瞒渠,更是在濱河造成了極大的恐慌良蒸,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伍玖,死亡現(xiàn)場(chǎng)離奇詭異嫩痰,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)窍箍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)串纺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人椰棘,你說(shuō)我怎么就攤上這事纺棺。” “怎么了邪狞?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵祷蝌,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我外恕,道長(zhǎng)杆逗,這世上最難降的妖魔是什么乡翅? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任鳞疲,我火速辦了婚禮,結(jié)果婚禮上蠕蚜,老公的妹妹穿的比我還像新娘尚洽。我一直安慰自己,他們只是感情好靶累,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布腺毫。 她就那樣靜靜地躺著,像睡著了一般挣柬。 火紅的嫁衣襯著肌膚如雪潮酒。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,549評(píng)論 1 312
  • 那天邪蛔,我揣著相機(jī)與錄音急黎,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛勃教,可吹牛的內(nèi)容都是我干的淤击。 我是一名探鬼主播,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼故源,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼污抬!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起绳军,我...
    開(kāi)封第一講書(shū)人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤印机,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后门驾,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體耳贬,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年猎唁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了咒劲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡诫隅,死狀恐怖腐魂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情逐纬,我是刑警寧澤蛔屹,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站豁生,受9級(jí)特大地震影響兔毒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜甸箱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一育叁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧芍殖,春花似錦豪嗽、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至窃躲,卻和暖如春计贰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蒂窒。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工躁倒, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留赎婚,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓樱溉,卻偏偏與公主長(zhǎng)得像挣输,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子福贞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容