helm
What is Helm
一般來說,要 deploy 一個服務,即使是簡單的 app
也要建立一整套完整的 k8s 元件
ex: Secret, Deployment, Service, PersistentVolumeClaim… 等等,需要 apply 一堆 yaml 檔案
Helm 被稱為 k8s 的 package manager
想像一個遊戲由千百個檔案組成
我們不需要自己處理那摩多檔案,透過安裝程式的方式
做到一次安裝一個完整的遊戲,對應的檔案也都被安裝到正確的位置
而 Helm 就像這樣,一次處理一堆 YAML 檔案和 K8s 物件,來設定 application
Helm 讓我們操作 k8s 的元件就像操作 app 一樣,而不是一堆檔案物件
# 透過 helm 安裝 wordpress
helm install wordpress
# 修改完 yaml 檔案套用
helm upgrade wordpress
# 可倒退版本
helm rollback wordpress
# 移除 wordpress
helm uninstall wordpress
# debug 資訊
helm --debug
Helm2 vs Helm3
Helm3 多了
- RBAC (Role Based Access Control)
- CRD (Custom Resource Definition)
- 提供 snapshot (revision)
Helm3 移除了 Helm2 用的 Tiller
Helm Components
Charts
- 一包 files
- 包含 Helm 需要的所有 instruction 在 k8s cluster 上建立物件
- 套用 Chart 到 cluster 上的時候,會建立 release (每個 release 都代表一次 chart 的安裝)
- 像 docker 有 docker hub 一樣,helm 也有對應的 online chart repository
- ArtifaceHUB
- 為了追蹤 helm 對 k8s cluster 做了什麼變更,Helm 會儲存這些資訊 (as metadata)
- Helm 把這資訊以 k8s secret 的方式存在 k8s cluster
- yaml file 裡面可以像填空一樣放 template
- 用來填空的資訊放在 values.yaml
- 我們可以下載到各式各樣的 Helm charts,之後的工作就是透過 values.yaml 填空把 configuration 設定好
# 安裝 chart
helm install [release name] [chart-name]
Helm charts
一般的 helm chart 都還會包含的 files
- values.yaml: 用來放要嵌入 template 的資訊
- chart.yaml: 標明這份 chart 本身的資訊
- 包含 apiVersion, appVersion, name…等等
chart.yaml
- apiVersion: 套用的 api 版本 (Helm3 用 v2)
- appVersion: 是指這個 app 要用哪個版本 deploy (ex: wordpress)
- version: 這份 chart 的版本
- name: chart 的名稱
- type:
- application (default): 指是建立作為 deploying application
- library: 指提供 utilities 來幫助 building charts
- dependencies: 有相依的套件,同樣以 helm 的方式載入
- keywords: 有點像 tag 的概念,可以被搜尋
- maintainers: 維護者資訊
- home: homepage url
- icon: icon url
Working with Helm: basics
# help
helm --help
# repo help (支援 sub command 的 help)
helm repo --help
# 在 Artifact Hub 上搜尋 wordpress
helm search hub wordpress
# 在 local repo 搜尋已加入的 wordpress
helm searach repo wordpress
helm repo
指令是對應 chart repository 的操作
- 包含 add, remove, list…
helm repo list
列出加入的 repohelm repo update
更新加入的 repo 資訊
範例: 安裝 wordpress wordpress in Artiface HUB
# 查看 wordpress 的 readme
# 把 wordpress chart 路徑加入,這樣之後要抓的話就知道路徑
helm repo add bitnami https://chars/bitnami.com/bitnami
# 安裝 release 名為 my-release 的版本
helm install my-release bitnami/wordpress
# 查看 release
helm list
# 移除 release
helm uninstall my-release
repo 不代表 application
application 是在該 repo 下面的應用
Customizing chart parameters
安裝 chart 的時候如果沒指定參數的話是套用全部的 default value
# 指定參數
# 會 overwrite values.yaml
helm install --set wordpressBlogName="Helm Tutorials" my-release binami/wordpress
--set wordpressEmail="yakushou730@gmail.com"
# 或是準備好自定義的 custom-values.yaml
helm install --values custom-values.yaml my-release bitnami/wordpress
# 兩段式 release
# 1. 先拉 charts 然後更改內容
# 2. 改完後 release
helm pull bitnami/wordpress
# or
helm pull --untar bitnami/wordpress
# 拉下來後更改 values.yaml,之後release
helm install my-release ./wordpress
# 安裝 bitami repo 下的 apache application,release 名為 amaze-surf
helm install amaze-surf bitnami/apache
Lifecycle management with Helm
# 指定安裝版本
helm install nginx-release bitnami/nginx --version 7.1.0
# 更新 release 版本
helm upgrade nginx-release bitnami/nginx
helm upgrade dazzling-web bitnami/nginx --version 9
# 查看 release 紀錄
helm history nginx-release
# 退回指定的 release 版本 (by 指定 revision)
helm rollback nginx-release 1
Writing a Helm chart
把寫 helm chart 想像成是寫安裝精靈
也可以做到 在更新某個版本之前 先備份 database (hook)
# 建立一個新的 charts 框架
helm create nginx-chart
# 如果 templates 裡面的內容用不到的話就拿掉,放上要用的 k8s yaml 檔案
# 為了讓 chart 可以複用,metadata 的地方名稱可以使用嵌入的
# helm install [ReleaseName] ./chartRepo
name: {{ .Release.Name }}-nginx
# 可組合
name: {{ .Values.image.repository }}:{{ .Values.image.tag }}
如果需要用到 Chart.yaml 作為嵌入變數的話,可以使用
- Chart.Name
- Chart.ApiVersion
- Chart.Version
- … 等等等
或是用到 k8s cluster 本身的資源
- Capabilities.KubeVersion
- Capabilities.ApiVersions
- … 等等等
或是用到 Values.yaml 作為嵌入變數
- Values.[自定義欄位 必須是小寫開頭]
變數名稱的重點
Release / Chart / Capabilities 後面接大寫開頭的欄位 (因為是 builtin 欄位)
Values 的自定義欄位必須是小寫開頭
完整的 helm chart = template + release details + char details + values.yaml
Making sure chart is working as intended
安裝 chart 之前的 3 種驗証方式
- lint: 驗證 yaml 格式正確
- template: 驗證 template 格式正確
- dry run: 驗證 charts 對 k8s 是正確的
# helm lint
helm lint ./nginx-chart
# helm template 可以看組出來的 chart 長怎樣
helm template ./nginx-chart
# 可以補上 release name,如果 template 有用到的話才有資訊
helm template hello-world-1 ./nginx-chart
# 可以補上 debug flag,印出的錯誤訊息比較完整
helm template ./nginx-chart --debug
# --dry-run 可以檢查如果真的要安裝到 k8s 的結果
helm install hello-world-1 ./nginx-chart --dry-run
Functions
functions 可以操作資料且不影響 values.yaml 內的資料
# 假設 .Values.image.repository 是 nginx
# upper 是把字串改成大寫
{{ upper .Values.image.repository }} # image: NGINX
# quota 是在字串外多加上雙引號
{{ quote .Values.image.repository }} # image: "nginx"
# replace 可以用來取代字元
{{ replace "x" "y" .Values.image.repository }} # image: nginy
# default 會以第一個參數為預設值,如果第二個參數不存在的話
{{ default "nginx" .Values.image.repository }}
functions 的種類繁多,如 string, regex, file path, k8s, …
Pipelines
用 |
來做到管線式的參數轉換
{{ upper .Values.image.repository }} # image: NGINX
# 同
{{ .Values.image.repository | upper }} # image: NGINX
# 也可以一直串下去
{{ .Values.image.repository | upper | quote }} # image: "NGINX"
# 套用 default: 如果 .Values.image.tag 不存在的話,套用 default .Chart.AppVersion
{{ .Values.image.tag | default .Chart.AppVersion }}"
Conditions
根據條件決定要不要在 yaml 檔刪除或新增對應的 key-value pair
# 下面 - 的意思是轉換的時候不要空下這兩行
# eq 根據後面的兩個參數決定是 true 或 false
metadata:
{{- if .Values.orgLabel }}
labels:
org: {{ .Values.orgLabel }}
{{- else if eq .Values.orgLabel "hr" }}
labels:
org: human resources
{{- else }}
{{- end }}
Function | Purpose |
---|---|
eq | equal |
ne | not equal |
lt | less than |
le | less than or equal to |
gt | greater than |
ge | greater than or equal to |
not | negative |
empty | value is empty |
With Blocks
重複的 namespace 可以用 with 包成 block
$
代表 root namespace
data:
{{- with .Values.app }}
{{- with .ui }}
background: {{ .bg }}
foreground: {{ .fg }}
{{- end }}
{{- with .db }}
database: {{ .name }}
connection: {{ .conn }}
{{- end }}
release: {{ $.Release.Name }}
{{- end }}
Ranges
可以用來設定 array 資料
# values.yaml
regions:
- ohio
- newyork
- otario
- london
- sigapore
# configmap.yaml
data:
regions:
{{- range .Values.regions }}
- {{ . | guote }} # 支援 pipeline
{{- end }}
Named Templates
重複使用相同的 key-value pair
可以提出為 _helpers.tpl
其中 _
的開頭代表告訴 helm 忽略這個檔案,不要當成 manifest 來用
# _helpers.tpl
{{- define "labels" }}
app.kubernetes.io/name: {{ .Release.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
# 在要嵌入的地方放
# 後面的小點點很重要,代表 labels 內要參考的 scope 是 current scope
{{- template "labels" . }}
要注意 _helpers.tpl 內的縮排
要和目標放入的地方縮排一致
但可能要放入的地方縮排不一致
所以要另外透過 (pipeline) indent [num] 處理
# 原本的呼叫方式
{{- template "labels" . }}
# 多 縮排 2 格
{{- include "labels" . | indent 2 }}
# 多 縮排 4 格
{{- include "labels" . | indent 4 }}
template 是 action
include 是 function,才可以接 pipeline
Chart Hooks
可以設定在套用新的 helm 設定前,觸發 hook
典型的 workflow
$ helm upgrade
-> verify
-> render
-> upgrade
加入 pre-upgrade 和 post-upgrade 後
$ helm upgrade
-> verify
-> render
-> pre-upgrade
-> upgrade
-> post-upgrade
其他的如
$ helm install
-> verify
-> render
-> pre-install
-> upgrade
-> post-install
$ helm delete
-> verify
-> render
-> pre-delete
-> upgrade
-> post-delete
$ helm rollback
-> verify
-> render
-> pre-rollback
-> upgrade
-> post-rollback
重點是可以起一個 pod 或 job 來處理 script 之類在 hook 要做的程序
其中透過 annotations
標記來讓 helm 忽略這份 manifest 檔案 (不要當成一般的 k8s manifest)
# templates/backup-job.yaml
kind: Job
metadata:
annotations:
"helm.sh/hook": pre-upgrade
"helm.sh/hook-weight": "5" # 設定 pre-upgrade job 的優先權,要是字串格式
"helm.sh/hook-delete-policy": hook-succeeded # 如果成功執行的話就砍掉這個 job
hood-delete-policy 有三種
- hook-succeeded: 如果執行成功的話就刪除
- hook-failed: 如果執行失敗的話就刪除
- before-hook-creation: default,在新的 hook 開始的時候,刪掉舊的 resource
Packaging and Signing Charts
打包上傳 helm charts
# 以上傳 nginx-chart 為例
helm package ./nginx-chart
整包 nginx-chart 會被打包成 nginx-chart-0.1.0.tgz (透過 Chart.yaml 內的版本)
tgz 是指 tar archive compressed with gzip
上傳時要簽名,讓其他使用者知道這包 helm 是合法的
# 產生簽名
gpg --quick-generate-key "Yakushou"
# 如果是 production 要用的 key,盡量使用完整資訊
gpg --full-generate-key "YakuShou"
# 產生舊版格式的金鑰檔案
gpg --export-secret-keys >~./.gnupg/secring.gpg
# 打包 helm 並附上簽名
helm package --sign --key "Yakushou" --keyring ~/.gnupg/secring.gpg ./nginx-chart
# 列出 gpg key list
gpg --list-keys
Uploading Charts
上傳 helm charts 需要的要件
- 打包好的 package (如: nginx-chart-0.1.0.tgz)
- index.yaml
- provenance (如: nginx-chart-0.1.0.tgz.prov)