Helm是k8s的包管理工具,類似Linux系統常用的 apt、yum等包管理工具。
使用helm可以簡化k8s應用部署
- Chart:一個 Helm 包,其中包含了運行一個應用所需要的鏡像、依賴和資源定義等,還可能包含 Kubernetes 集群中的服務定義,類似 Homebrew 中的 formula、APT 的 dpkg 或者 Yum 的 rpm 文件。
- Release:在 Kubernetes 集群上運行的 Chart 的一個實例。在同一個集群上,一個 Chart 可以安裝很多次。每次安裝都會創建一個新的 release。例如一個 MySQL Chart,如果想在服務器上運行兩個數據庫,就可以把這個 Chart 安裝兩次。每次安裝都會生成自己的 Release,會有自己的 Release 名稱。
- Repository:用於發布和存儲 Chart 的存儲庫。
Chart Install 過程:
- Helm從指定的目錄或者tgz文件中解析出Chart結構信息
- Helm將指定的Chart結構和Values信息通過gRPC傳遞給Tiller
- Tiller根據Chart和Values生成一個Release
- Tiller將Release發送給Kubernetes運行。
Chart Update過程:
- Helm從指定的目錄或者tgz文件中解析出Chart結構信息
- Helm將要更新的Release的名稱和Chart結構,Values信息傳遞給Tiller
- Tiller生成Release並更新指定名稱的Release的History
- Tiller將Release發送給Kubernetes運行
helm主要包括helm客戶端和Tiller服務端兩部分,Tiller部署在k8s集群中。
如果使用阿里雲容器服務kubernetes版,默認已經安裝了helm的服務端(Tiller),只要安裝helm客戶端即可。
下載地址:https://github.com/helm/helm/releases
下載后解壓到自己喜歡的目錄,然后配置下對應的PATH環境變量。
創建chart包
helm create myapp
myapp - chart 包目錄名 ├── charts - 依賴的子包目錄,里面可以包含多個依賴的chart包 ├── Chart.yaml - chart定義,可以定義chart的名字,版本號信息。 ├── templates - k8s配置模版目錄, 我們編寫的k8s配置都在這個目錄, 除了NOTES.txt和下划線開頭命名的文件,其他文件可以隨意命名。 │ ├── deployment.yaml │ ├── _helpers.tpl - 下划線開頭的文件,helm視為公共庫定義文件,主要用於定義通用的子模版、函數等,helm不會將這些公共庫文件的渲染結果提交給k8s處理。 │ ├── ingress.yaml │ ├── NOTES.txt - chart包的幫助信息文件,執行helm install命令安裝成功后會輸出這個文件的內容。 │ └── service.yaml └── values.yaml - chart包的參數配置文件,模版可以引用這里參數。
我們要在k8s中部署一個網站應用,需要編寫deployment、service、ingress三個配置文件,剛才通過helm create命令已經創建好了。
把deployment、service、ingress三個配置文件的內容清空,重新編寫k8s部署文件。
deployment.yaml 配置文件定義如下:
apiVersion: apps/v1beta2 kind: Deployment metadata: name: myapp #deployment應用名 labels: app: myapp #deployment應用標簽定義 spec: replicas: 1 #pod副本數 selector: matchLabels: app: myapp #pod選擇器標簽 template: metadata: labels: app: myapp #pod標簽定義 spec: containers: - name: myapp #容器名 image: xxxxxx:1.7.9 #鏡像地址 ports: - name: http containerPort: 80 protocol: TCP
service.yaml定義如下:
apiVersion: v1 kind: Service metadata: name: myapp-svc #服務名 spec: selector: #pod選擇器定義 app: myapp ports: - protocol: TCP port: 80 targetPort: 80
ingress.yaml定義如下:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: myapp-ingress #ingress應用名 spec: rules: - host: www.xxxxx.com #域名 http: paths: - path: / backend: serviceName: myapp-svc #服務名 servicePort: 80
{{ }} 兩個花括號包裹的內容為模版表達式 如
apiVersion: apps/v1beta2 kind: Deployment metadata: name: {{ .Release.Name }} #deployment應用名 labels: app: {{ .Release.Name }} #deployment應用標簽定義 spec: replicas: {{ .Values.replicas}} #pod副本數 selector: matchLabels: app: {{ .Release.Name }} #pod選擇器標簽 template: metadata: labels: app: {{ .Release.Name }} #pod標簽定義 spec: containers: - name: {{ .Release.Name }} #容器名 image: {{ .Values.image }}:{{ .Values.imageTag }} #鏡像地址 ports: - name: http containerPort: 80 protocol: TCP apiVersion: v1 kind: Service metadata: name: {{ .Release.Name }}-svc #服務名 spec: selector: #pod選擇器定義 app: {{ .Release.Name }} ports: - protocol: TCP port: 80 targetPort: 80 apiVersion: extensions/v1beta1 kind: Ingress metadata: name: {{ .Release.Name }}-ingress #ingress應用名 spec: rules: - host: {{ .Values.host }} #域名 http: paths: - path: / backend: serviceName: {{ .Release.Name }}-svc #服務名 servicePort: 80
values.yaml chart包參數定義:
#域名 host: www.XXX.com #鏡像參數 image: XXXXXXXXXXXXXXXXXX imageTag: 1.7.9 #pod 副本數 replicas:1
安裝應用:
#命令格式: helm install chart包目錄
helm install ./myapp
#命令格式: helm install --set key=value chart包目錄 #–set 參數可以指定多個參數,他的值會覆蓋values.yaml定義的值,對象類型數據可以用 . (點)分割屬性名,例子: --set apiAppResources.requests.cpu=1 $ helm install \ --set replicas=2 \ --set host=www.xxxx.com \ ./myapp
更新應用:
#命令格式: helm upgrade release名字 chart包目錄
helm upgrade myapp ./myapp
$ helm upgrade \ --set replicas=2 \ --set host=www.xxxx.com \ myapp ./myapp
6.模版語法
6.1.表達式
模版表達式: {{ 模版表達式 }}
模版表達式: {{- 模版表達式 -}} , 表示去掉表達式輸出結果前面和后面的空格,去掉前面空格可以這么寫{{- 模版表達式 }}, 去掉后面空格 {{ 模版表達式 -}}
6.2.變量
默認情況點( . ), 代表全局作用域,用於引用全局對象。
例子:
#這里引用了全局作用域下的Values對象中的key屬性。
{{ .Values.key }}
helm全局作用域中有兩個重要的全局對象:Values和Release
Values代表的就是values.yaml定義的參數,通過.Values可以引用任意參數。
例子:
{{ .Values.replicaCount }}
#引用嵌套對象例子,跟引用json嵌套對象類似
{{ .Values.image.repository }}
Release代表一次應用發布,下面是Release對象包含的屬性字段:
- Release.Name - release的名字,一般通過Chart.yaml定義,或者通過helm命令在安裝應用的時候指定。
- Release.Time - release安裝時間
- Release.Namespace - k8s名字空間
- Release.Revision - release版本號,是一個遞增值,每次更新都會加一
- Release.IsUpgrade - true代表,當前release是一次更新.
- Release.IsInstall - true代表,當前release是一次安裝
例子:
{{ .Release.Name }}
除了系統自帶的變量,我們自己也可以自定義模版變量。
#變量名以$開始命名, 賦值運算符是 := (冒號+等號)
{{- $relname := .Release.Name -}}
引用自定義變量:
#不需要 . 引用
{{ $relname }}
6.3.函數&管道運算符
調用函數的語法:{{ functionName arg1 arg2... }}
例子:
#調用quote函數,將結果用“”引號包括起來。
{{ quote .Values.favorite.food }}
管道(pipelines)運算符 |
類似linux shell命令,通過管道 | 將多個命令串起來,處理模版輸出的內容。
例子:
#將.Values.favorite.food傳遞給quote函數處理,然后在輸出結果。
{{ .Values.favorite.food | quote }}
#先將.Values.favorite.food的值傳遞給upper函數將字符轉換成大寫,然后專遞給quote加上引號包括起來。
{{ .Values.favorite.food | upper | quote }}
#如果.Values.favorite.food為空,則使用default定義的默認值
{{ .Values.favorite.food | default "默認值" }}
#將.Values.favorite.food輸出5次
{{ .Values.favorite.food | repeat 5 }}
#對輸出結果縮進2個空格
{{ .Values.favorite.food | nindent 2 }}
常用的關系運算符>、 >=、 <、!=、與或非在helm模版中都以函數的形式實現。
關系運算函數定義:
eq 相當於 =
ne 相當於 !=
lt 相當於 <=
gt 相當於 >=
and 相當於 &&
or 相當於 ||
not 相當於 !
例子:
#相當於 if (
.Values.fooString && (.Values.fooString == "foo")
)
{{ if and .Values.fooString (eq .Values.fooString "foo") }} {{ ... }} {{ end }}
6.4.流程控制語句
6.4.1. IF/ELSE
語法:
{{ if 條件表達式 }}
# Do something
{{ else if 條件表達式 }}
# Do something else
{{ else }}
# Default case
{{ end }}
例子:
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}}
6.4.2. with
with主要就是用來修改 . 作用域的,默認 . 代表全局作用域,with語句可以修改.的含義.
語法:
{{ with 引用的對象 }}
這里可以使用 . (點), 直接引用with指定的對象
{{ end }}
例子:
#.Values.favorite是一個object類型
{{- with .Values.favorite }}
drink: {{ .drink | default "tea" | quote }} #相當於.Values.favorite.drink
food: {{ .food | upper | quote }}
{{- end }}
ps: 不能在with作用域內使用 . 引用全局對象, 如果非要在with里面引用全局對象,可以先在with外面將全局對象復制給一個變量,然后在with內部使用這個變量引用全局對象。
例子:
{{- $release:= .Release.Name -}} #先將值保存起來
{{- with .Values.favorite }}
drink: {{ .drink | default "tea" | quote }} #相當於.Values.favorite.drink
food: {{ .food | upper | quote }}
release: {{ $release }} #間接引用全局對象的值
{{- end }}
6.4.3. range
range主要用於循環遍歷數組類型。
語法1:
#遍歷map類型,用於遍歷鍵值對象
#變量key代表對象的屬性名,key代表對象的屬性名,val代表屬性值
{{- range key,key,val := 鍵值對象 }}
{{ $key }}: {{ $val | quote }}
{{- end}}
語法2:
{{- range 數組 }}
{{ . | title | quote }} # . (點),引用數組元素值。
{{- end }}
例子:
#values.yaml定義 #map類型 favorite: drink: coffee food: pizza #數組類型 pizzaToppings: - mushrooms - cheese - peppers - onions map類型遍歷例子: {{- range $key, $val := .Values.favorite }} {{ $key }}: {{ $val | quote }} {{- end}} 數組類型遍歷例子: {{- range .Values.pizzaToppings}} {{ . | quote }} {{- end}}
6.5.子模版定義
我們可以在_(下划線)開頭的文件中定義子模版,方便后續復用。
helm create默認為我們創建了_helpers.tpl 公共庫定義文件,可以直接在里面定義子模版,也可以新建一個,只要以下划線開頭命名即可。
子模版語法:
定義模版
{{ define "模版名字" }} 模版內容 {{ end }}
引用模版:
{{ include "模版名字" 作用域}}
例子:
#模版定義 {{- define "mychart.app" -}} app_name: {{ .Chart.Name }} app_version: "{{ .Chart.Version }}+{{ .Release.Time.Seconds }}" {{- end -}} apiVersion: v1 kind: ConfigMap metadata: name: {{ .Release.Name }}-configmap labels: {{ include "mychart.app" . | nindent 4 }} #引用mychart.app模版內容,並對輸出結果縮進4個空格 data: myvalue: "Hello World"
6.6.調試
編寫好chart包的模版之后,我們可以給helm命令加上--debug --dry-run 兩個參數,讓helm輸出模版結果,但是不把模版輸出結果交給k8s處理。
例子:
#helm install命令類似,加上--debug --dry-run兩個參數即可
$ helm upgrade --debug --dry-run -i \
--set replicas=2 \
--set host=www.xxxx.com \
myapp ./myapp