本文的目标不限于對Helm官方文檔的翻譯或解釋,更在于幫助開發者能夠快速編寫出一個标準且合理的helm chart。
Helm簡介
一句話描述:Helm是Kubernetes的包管理工具
Helm vs Operator
Helm 和 Operator都可以實作在k8s上安裝應用。但二者有着不同的适用場景。
Helm适用于:
- 開發者群體
- 門檻低:熟悉k8s即可
- 重點在于實作應用的“安裝-更新-删除”
Operator适用于:
- 運維或SRE團隊
- 門檻高:對k8s精通,并能結合k8s編寫自運維腳本,實作複雜且定制化的配置
- 重點在于實作應用的自運維、高可靠。
Helm2 or Helm3
Helm2和Helm3,從開發者的視角有如下差别:
- 增加了JSON格式的校驗,可以輸出更容易讓人了解的錯誤報告
- Release name從可選變成必選
- Release name作用域從全局被限制到了namespace級别
- Namespaces不再自動建立。如果chart中的namespace不存在,需要手動建立namespace
- 将requirements.yaml,requirements.lock的内容合并到Chart.yaml,Chart.lock
- Chart.yaml的apiVersion從v1到v2
其實對開發者來說,helm2 與helm3差異不大,就是helm3對于helm編寫體驗更加友好。
Heml的安裝
Helm的github位址:
https://github.com/helm/helm可以選擇安裝最新的Helm3,也可以使用Helm2,通過tag找到2.x的最新版本:2.17. 在release中有編譯好的mac二進制程式可以下載下傳直接使用。
Helm 開發技巧
命名模闆(named templates)
命名模闆(named templates)也可以成為子模闆,但他是有個名稱的,可以結合include使用。
我們可以友善把一個模闆檔案中,公共或通用的部分,提取出來,放到一個新的檔案中,并給其命名,這樣就可以帶其他地方使用
通過
define
定義模闆
{{ define "MY.NAME" }}
# body of template here
{{ end }}
include
記住标準用法
{{ include "named template" . }}
解釋: . 表示的是scope。 這裡也可以改成 .Values
空格
注意:換行也算空格
{{- 表示左邊的空格和換行會移除
-}} 表示右邊的空格和換行會移除
執行個體:
food: {{ .Values.favorite.food | upper | quote }}
{{ if eq .Values.favorite.drink "coffee" -}}
mug: "true"
{{ end }}
會渲染出
food: "PIZZA"
mug: "true"
food: {{ .Values.favorite.food | upper | quote }}
{{- if eq .Values.favorite.drink "coffee" -}}
mug: "true"
{{- end -}}
food: "PIZZA"mug: "true"
正确的寫法是
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 }}
Helm 本地測試技巧
格式化校驗
helm lint Path [flag]
- Path: a path of chart
本地渲染
helm template path [flag]
helm template指令來自于開源的
https://github.com/technosophos/helm-templateHelm chart最佳實踐
基本規約
Chart命名
必須是小寫字母,分割符用
-
版本規範
版本号遵循SemVer2的規範
Yaml縮進
使用兩個空格縮進,不能用tab
Values 自定義變量
values.yaml編寫的最佳實踐
命名規範
首字母小寫的駝峰式命名
反例:
Chicken: true # initial caps may conflict with built-ins
chicken-noodle-soup: true # do not use hyphens in the name
所有Helm内置的變量都是大寫開頭(如.Chart.Name, .Capabilities.KubeVersion),這樣可以和使用者自定義的變量區分開
變量平鋪 Or 層疊
Yaml格式靈活,裡面的變量既可以平鋪也可以層疊編寫
層疊:
server:
name: nginx
port: 80
平鋪:
serverName: nginx
serverPort: 80
通常:平鋪更好,因為簡單
當相關的一些變量是可選的,為了安全起見,使用層疊方式,并在每個層級中都對變量進行校驗。
{{ if .Values.server }}
{{ default "none" .Values.server.name }}
{{ end }}
類型清醒
Yaml的類型轉化的規則有時是反直覺的。比如
foo: false
和
foo: "false"
不一樣。 大數
foo:1234567
在某些場景下會變成科學計數法表達。
最簡單,清醒的做法:所有變量都用 ""引号 表達成字元串。
在需要使用數字時,用
{{ int $value }}
進行變量轉換
使用字典而不是數組
由于values.yaml的變量是可以支援被指令行的參數
--set
或
--set-string
改寫,而參數的寫法有限。
是以values.yaml變量的寫法盡可能使用map,而不是數組
servers:
- name: foo
port: 80
- name: bar
port: 81
如何用
--set
改寫端口, Helm2.4之前不支援, 2.5之後可以用
--set servers[0].port=80
。 但表意不明确,萬一values裡的順序改變了,就糟糕了。
正例:
servers:
foo:
port: 80
bar:
port: 81
改foo的端口
--set servers.foo.port=80
注釋
每個變量都應該注釋。
注釋必須以變量名開頭
正例
# serverHost is the host name for the webserver
serverHost: example
# serverPort is the HTTP listener port for the webserver
serverPort: 9191
變量名開頭的注釋有利于在grep時,可以快速抓取變量及其文檔說明
Templates 模闆
templates
的結構化規範:
- 所有的yaml模闆必須有
字尾, 非格式化内容的模闆使用.yaml
字尾.tpl
- 模闆檔案的命名使用小寫,
虛線表示法。如(my-example-configmap.yaml)-
- 每種資源的定義必須單獨的模闆檔案
- 模闆檔案名必須反應出其表示的資源。如:
,foo-pod.yaml
bar-svc.yaml
命名模闆
{{ define }}
建立出命名模闆是全局可見的,為了避免名稱沖突,命名中應該帶上命名空間。
{{- define "nginx.fullname" }}
{{/* ... */}}
{{ end -}}
反例
{{- define "fullname" -}}
{{/* ... */}}
{{ end -}}
推薦使用
helm create
建立新的chart,它會自動循序最佳實踐
模闆指令
{{ }}
表示模闆指令。在
{{
後和
}}
前需要用一個空格隔開
{{ .foo }}
{{ print "foo" }}
{{- print "bar" -}}
{{.foo}}
{{print "foo"}}
{{-print "bar"-}}
Yaml注釋: 常用注釋,而且在
helm install --debug
調試時可見
# This is a comment
type: sprocket
模闆注釋:多行注釋,常用于對子產品、方法的說明
{{- /*
This is a comment.
*/}}
type: frobnitz
Lable和Anonotation
二者都是中繼資料,有着各自的适用場景。
Label
- 被k8s用來辨別資源
- 被運維用來查詢
上述兩個目的外的場景,都應該使用Annonation
标準标簽
Name | Status | Description | |
---|---|---|---|
app.kubernetes.io/name | 推薦 | {{ .Chart.Name }} | |
helm.sh/chart | {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} | |
app.kubernetes.io/managed-by | {{ .Release.Service }}, 可用來找Helm托管的應用 | ||
app.kubernetes.io/instance | {{ .Release.Name }} | ||
app.kubernetes.io/version | 可選 | {{ .Chart.AppVersion }} | |
app.kubernetes.io/component | 标記應用在系統的角色。如app.kubernetes.io/component: frontend | ||
app.kubernetes.io/part-of | 标記所屬的整體 |
Pod 容器
Image
鏡像需要用固定的标簽或鏡像的sha值,不能用
latest
head
canary
這些“引用”性質标簽
ImagePullPolicy
deployment.yaml
imagePullPolicy: {{ .Values.image.pullPolicy }}
values.yaml
image:
pullPolicy: IfNotPresent
PodTemplates
必須定義一個selector
selector:
matchLabels:
app.kubernetes.io/name: MyName
template:
metadata:
labels:
app.kubernetes.io/name: MyName
一個标準的Helm Chart
待補充