← 返回上一頁
Kubernetes

Helm Chart 模板語法完整攻略:從結構到進階技巧一次搞懂

本頁目錄
Helm CNCF 官方圖示
Helm Kubernetes 套件管理工具 Logo
Helm - Kubernetes 的套件管理工具

身為一個常常在 Kubernetes 叢集上部署各種服務的工程師,Helm 絕對是我工具箱裡不可或缺的利器。之前我們聊過 Helm Chart 的基本概念,今天就來把 Helm Chart 的目錄結構和模板語法徹底拆解一遍,讓你日後自己寫 Chart 時能夠得心應手。


Helm Chart 目錄結構

要建立一個全新的 Chart,只需要一行指令:

helm create mychart

產生出來的目錄結構如下:

路徑用途說明
mychart/Chart.yamlChart 的元資料檔案(名稱、版本等)
mychart/values.yaml預設的組態設定值
mychart/charts/存放相依的子 Chart
mychart/templates/Kubernetes 資源的模板檔案
templates/deployment.yamlDeployment 資源模板
templates/_helpers.tpl可重複使用的模板片段
templates/hpa.yamlHPA 水平自動擴展模板
templates/ingress.yamlIngress 入口規則模板
templates/service.yamlService 服務模板
templates/serviceaccount.yamlServiceAccount 模板
templates/NOTES.txt安裝後的使用說明
templates/tests/測試用的模板

Chart.yaml 長什麼樣?

這是 Chart 的身分證,記載了所有基本資訊:

apiVersion: v2                     # Chart API 版本(必填)
name: mychart                      # Chart 名稱(必填)
version: 0.1.0                     # Chart 版本號(必填)
description: 我的第一個 Chart       # 描述(選填)
appVersion: "1.0"                  # 應用程式版本(選填)

values.yaml 預設組態

這份檔案定義了模板中會用到的變數預設值,在模板裡面用 {{ .Values.replicaCount }} 這樣的語法來引用:

replicaCount: 1
image:
  repository: nginx
  tag: "1.19"
  pullPolicy: IfNotPresent
service:
  type: ClusterIP
  port: 80

templates/ 與 charts/ 目錄

templates/ 裡面放的是 Kubernetes 資源的模板文件,Helm 引擎會把 values 注入模板後,產生實際可以部署的 YAML 清單。

charts/ 則是用來放相依的子 Chart,可以透過 helm dependency 指令來管理這些依賴關係。


模板語法核心觀念

模板指令與跳脫

  • {{ }} 雙大括號裡面的就是模板指令
  • 如果內容本身包含大括號,需要用反引號跳脫處理

註解寫法

位置註解方式
values.yaml使用 #
templates/ 目錄下的模板使用 {{/* 註解內容 */}}

內建物件一覽

Helm 提供了好幾個內建物件,讓你在模板裡可以靈活取用各種資訊。

Release 物件

描述當次部署實例的資訊:

物件說明
Release.NameRelease 名稱
Release.TimeRelease 時間
Release.Namespace所在的命名空間
Release.ServiceRelease 服務名稱
Release.Revision修訂版本號(從 1 開始遞增)
Release.IsUpgrade是否為升級或回滾操作
Release.IsInstall是否為首次安裝

Chart 物件與 Values 物件

Chart 物件對應 Chart.yaml 裡的內容,例如 {{ .Chart.Name }}{{ .Chart.Version }}

Values 物件的資料來源有四個,優先順序由低到高:

優先順序來源
1子 Chart 的 values.yaml
2父 Chart 的 values.yaml
3-f--values 指定的 YAML 檔
4--set 指定的鍵值對參數

Files 物件

用來存取 Chart 中非特殊用途的檔案:

函數用途
Files.Get透過檔名取得檔案
Files.Lines逐行讀取檔案
Files.AsSecrets以 BASE64 編碼回傳
Files.Glob以 pattern 比對取得檔案列表
Files.AsConfig以 YAML 格式回傳

Capabilities 物件

取得 Kubernetes 叢集相關資訊:

{{ .Capabilities.KubeVersion }}                    # K8s 版本
{{ .Capabilities.APIVersions.Has "batch/v1" }}     # 是否支援某 API 版本
Kubernetes 圖示
Kubernetes - 容器編排平台

模板函數大全

Helm 內建了豐富的模板函數,以下整理成表格方便查閱:

函數功能說明
quote自動加上雙引號 ""
squote自動加上單引號 ''
title首字母大寫
upper全部轉大寫
lower全部轉小寫
empty判斷值是否為空
repeat N將值重複 N 次
indent N縮排 N 個空格
nindent N換行 + 縮排 N 個空格
default "xxx"設定預設值
split "/"以指定字元分割
toYaml將 List 轉成 YAML 格式
b64enc / b64decBASE64 編碼 / 解碼
print組合字串
printf格式化字串
trim移除首尾空白
trimAll移除指定字元
contains判斷是否包含子字串
cat用空格合併多個字串
tpl將 Values 中的模板指令進行渲染

管道(Pipeline)

跟 Linux 的管道 | 概念一樣,可以串接函數處理值:

k8s: {{ .Values.course.k8s | quote }}

這行的意思是:從 Values 讀取 course.k8s 的值,再透過 quote 函數加上雙引號。


流程控制語法

if / else 條件判斷

{{- if eq .Values.xxx "參數" }}
xxxx
{{- else if xxxx }}
yyyy
{{- else }}
zzzz
{{- end }}

支援的比較運算子:eq(等於)、ne(不等於)、lt(小於)、gt(大於)、andornot

with 限定作用域

{{- with .Values.course }}
k8s: {{ .k8s | upper | quote }}
python: {{ .python | repeat 3 | quote }}
release: {{ .Release.Name }}
{{- end }}

with 區塊內,. 的作用域會限縮到指定的物件上。

range 迴圈

方式一:遍歷 Map

# values.yaml
env:
  enable: true
  items:
    name1: value1
    name2: value2

# templates/deployment.yaml
containers:
- name: xxx
  {{- if .Values.env.enable }}
  env:
  {{- range $name, $value := .Values.env.items }}
  - name: {{ $name }}
    value: {{ $value | quote }}
  {{- end }}
  {{- end }}

方式二:遍歷 List

# values.yaml
env:
- name: xxx1
  value: xxx1
- name: xxx2
  value: xxx2

# templates/deployment.yaml
containers:
- name: xxx
  env:
  {{- range .Values.env }}
  - name: {{ .name }}
    value: {{ .value | quote }}
  {{- end }}

模板變數

:=(海象運算子)來宣告變數:

{{- $releaseName := .Release.Name }}

實際範例:

# 用 split 分割路徑,取第二個元素
{{- $service := (.Template.Name | split "/")._2 }}

# 用 index 從 map 中取值
{{- $config := index .Values.config $service }}

命名模板(Named Templates)

這是 Helm 裡面實現程式碼重用的關鍵機制。

重點觀念

  • 模板名稱是全域
  • 通常定義在 _helpers.tpl 檔案中
  • templates/ 下以 _ 開頭的檔案和 NOTES.txt 不會被當作資源清單
  • _ 開頭的檔案可以被其他模板引用

define 定義模板

{{/* 產生基本的 labels 標籤 */}}
{{- define "mychart.labels" }}
  labels:
    generator: helm
    date: {{ now | htmlDate }}
{{- end }}

template vs include

特性templateinclude
類型動作(action)函數(function)
管道支援不支援支援
縮排控制無法控制可搭配 indent 函數
# template 用法
{{- template "mychart.labels" }}

# include 用法(推薦,可控制縮排)
{{- include "mychart.labels" . | indent 2 }}

實務上我幾乎都用 include,因為能搭配 indentnindent 來精確控制 YAML 的縮排,避免格式錯亂的問題。


YAML 錨點(Anchor)

這其實是 YAML 本身的功能,但在 Helm 模板中也很實用:

# 定義錨點
anchors:
  pod_template: &pod_template
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        app: demo

# 引用錨點
apiVersion: v1
kind: Pod
metadata:
  name: demo_pod
  <<: *pod_template

& 定義錨點,用 * 引用錨點,搭配 <<: 可以合併鍵值。這在有大量重複設定時特別好用。


結語

Helm Chart 的模板語法乍看之下有點複雜,但只要理解了內建物件、模板函數、流程控制和命名模板這幾個核心概念,基本上就能應付大多數的場景了。

我自己的經驗是:先從修改既有的 Chart 開始練習,等熟悉語法後再嘗試從零開始建立自己的 Chart,這樣學習曲線會平緩很多。如果在 debug 的時候遇到問題,記得善用 helm template 指令來預覽渲染結果,這招真的超級實用!

分享這篇
X LinkedIn Facebook Hacker News Reddit

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料