導讀
在前面的幾個章節, 我們已經知道如何部署 Deployment, StatefulSet, DaemonSet, service 等等. 從v1.4版開始, 設定的目標就是為部署軟體規範一個特定的位置. Helm其實就是K8S的包管理工具(package manager tool), 只是Helm用的是Chart而非package, 功能類似Linux 上的apt yum,Mac 上的brew 等等.
一個典型的容器化應用程序,通常會有多個清單(manifests)例如: Deployment清單, Service清單, ConfigMaps 清單等等. 又或者你會創建 secret, ingress, 及其他的物件. 每個物件都會需要一張清單.
使用Helm, 你可以
- 將所有的清單打包起來並壓縮成一個tarball. 然後將這個tarball 放上儲存庫(repository)
- 搜索儲存庫找你要的應用程序
- 然後只要一行指令, 你就可以完成部署.
Helm的服務器運行在kubernetes的叢集之中, 不過客戶端(client side)卻可以運行在任何地方, 例如: 桌機或是筆電上. 透過helm的指令可以連結多個不同的儲存庫. Helm不僅僅是安裝而已, 你也可以用Helm來升級(upgrade)或回滾(roll-back)部署.
Helm v2 與 Tiller
這個圖是Helm v2與k8s叢集的溝通方式, 這個設計需要安裝一個Tiller的pod在叢集裡面, Helm的安裝命令由Tiller接收,接著Tiller會依照需求來創建物件例如:Pod, Service, ConfigMaps等等.
咦!? 這個設計似乎有點問題, 由於Tiller具有root用戶的權限, 可能會有人在未經授權下, 訪問你的kubernetes服務器, 也因此構成巨大的資安風險.
Tiller 通常會有如上的RBAC設定. 為了要讓Helm部署變得靈活好用, Tiller有cluster-admin的權限, 這樣的架構可能暫時讓你的容器管理工作變得容易, 但是衍生出來的資安問題確實令人頭痛. 後來, Rimas(helm的作者)推出了一個tillerless的解決方案, 這個方式是把tiller 移出叢集,在客戶端運行, 這邊就不深究了, 因為後面就要講Helm v3, 這個版本是可以直接與K8s API溝通, tiller 整個被移除.
如果還是對helm-tiller有興趣的, 可以看這裡
Helm v3
- 跟v2比, 有很多的改變, 詳細的內容可以看這裡
- 再也沒有Tiller Pod
- 3-way Strategic merge patches 三方策略合併補丁
- 在安裝時需要給名稱(name), 不然就要加選項 --generated-name
- 有一些指令已經棄用 例如: helm serve
- Helm v3 也不用helm init囉~
什麼事三方策略合併補丁?
In Helm 3, we now use a three-way strategic merge patch. Helm considers the old manifest, its live state, and the new manifest when generating a patch.
如同字面所言, Helm會考慮最早的清單,正在運行的清單及最新要部署的清單. 舉例來說:
最早的清單 - memory跟cpu的需求
kind: Deployment
spec:
containers:
- resources:
requests:
memory: "64Mi"
cpu: "250m"
正在運行的清單
kind: Deployment
spec:
containers:
- resources:
requests:
memory: "128Mi"
cpu: "750m"
最新要部署的清單
kind: Deployment
spec:
containers:
- resources:
requests:
memory: "512Mi"
cpu: "250m"
最終版本清單 - 會將真實的最大所需納入考量.
這個清單取自最新版的memory 需求及運行版的cpu需求
kind: Deployment
spec:
containers:
- resources:
requests:
memory: "512Mi"
cpu: "750m"
Chart Contents
Chart是一包資源清單用來建構成K8s分佈式應用程序. Kubernetes社群有自行維護的chart儲存庫(repository), 也有廠商自行提供的儲存庫(repository), 當然, 你也可以自建自己的儲存庫.
我們接著來看看一個Chart裡面有包含哪些清單, 這裡我們看一個wordpress的chart
- Chart.yaml: [必要]包含了跟這個Chart相關的所有資訊, 還有開頭的C是大寫
- License: [非必要]許可資訊
- README.md: [非必要]跟這個chart相關的資訊, md 格式供大家可以簡易地閱讀
- values.yaml: 編寫chart的各項預設值
- charts/ 這是一個目錄, 裡面包含了所有依存的chart
- crds/ 客製化的資源定義 (custom resource definitions)
- templates/ 儲存模版的目錄, 模板裡面的變數與values.yaml設定有關.
想知道更多? 請按這裡
templates and values 模板與給值
我們來看看一個template 的 yaml檔, 若你原本就是Golang的開發者的話, 它其實用的就是Go的template 語法. 在模板裡, 用兩個大括弧 ({{ }})包起來的是要渲染的變數, 而渲染過程中會去values.yaml取得變數的數值. 如下所示, MariaDB 的 password 會去values.yaml裡面的變數(Values.externalDatabase.password)取得並存成Secret
- mariadb-password
externalDatabaseSecret.yaml
{{- if not (or .Values.mariadb.enabled .Values.externalDatabase.existingSecret) }}
apiVersion: v1
kind: Secret
metadata:
name: {{ printf "%s-externaldb" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" }}
namespace: {{ .Release.Namespace | quote }}
labels: {{- include "common.labels.standard" . | nindent 4 }}
{{- if .Values.commonLabels }}
{{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
{{- end }}
{{- if .Values.commonAnnotations }}
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
{{- end }}
type: Opaque
data:
mariadb-password: {{ .Values.externalDatabase.password | b64enc | quote }}
{{- end }}
values.yaml: 本文內容太長, 僅擷取跟Password相關的設定. 剛剛Secret 那邊要取得的mariadb-password 的值就在這裡設定.
有興趣想更深入研究這個values.yaml的同學,可以點這裡
安裝 Helm
這邊我只有提供Linux的apt安裝方式, 想要知道其他作業系統的安裝方式, 可以點這裡
Ubuntu - 安裝helm v3在我們的實驗環境
$ curl https://baltocdn.com/helm/signing.asc | sudo apt-key add -
$ sudo apt-get install apt-transport-https --yes
$ echo "deb https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
$ sudo apt-get update
$ sudo apt-get install helm
檢查一下安裝的版本, 這邊我安裝的是Helm v3.7.2
Add Helm Repos 加入儲存庫
若想要透過Helm來安裝應用程序在K8s的叢集裡, 必須要加入儲存庫. 下面兩行指令用來增加repo與刷新repo
$ helm repo add [repo名稱] [連結]
$ helm repo update
舉例來說, 要用binami的封裝的wordpress chart, 首先要加入binami的repo, 然後安裝wordpress
$ helm repo add bitnami https://charts.bitnami.com/bitnami
$ helm install my-release bitnami/wordpress
列出與helm repo 相關的使用文檔
$ helm repo -h
列出所有的repo
$ helm repo list
用關鍵字搜尋 可以用的chart
$ helm repo search [關鍵字]
例如:
$ helm repo search redis
這個是在binami這個repo上找到跟redis 相關的chart. 大家在使用repo的時候,一定要注意的:
- 是否是被驗證過的發布者
- 資安驗證等級
- 下載量
因為人人都可以發行chart, 是否有定期的維護使用的映像檔或是設定會是我們選擇chart的關鍵, 裝錯chart 很可能會讓你麻煩不斷.
如果想要客製化一些設定, 透過 --set 的方式
$ helm install my-release \
--set wordpressUsername=admin \
--set wordpressPassword=password \
--set mariadb.auth.rootPassword=secretpassword \
bitnami/wordpress
透過 values.yaml的方式, \
將要調整的設定寫在values.yaml裡面, \
然後執行下面的指令
$ helm install my-release -f \
values.yaml bitnami/wordpress
可以參考這裡
透過Helm進行第一次的部署
這裡我們透過helm的方式安裝redis
安裝參考這個repo
$ helm install redis pascaliske/redis
$ helm status redis
$ k get deploy,po
大家記得要詳細閱讀helm 安裝完成的訊息, 通常部署完成後, 如何使用的資訊都會列出如下.
這邊筆者特別把輸出列出如下, 按照給的步驟一步步指行後就可以使用剛剛部署的redis
$ export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=redis,app.kubernetes.io/instance=redis" -o jsonpath="{.items[0].metadata.name}")
$ export CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
$ echo "Visit http://127.0.0.1:6379 to use your application"
這邊筆者稍微改動一下, 讓指令在背景執行,\
這裡我們用了port-forward的方式, \
等等連接需要使用redis-cli \
且 port 已經被轉到本機的8080
$ kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT &
$ sudo apt install redis-tools
$ redis-cli -h 127.0.0.1 -p 8080
查看 redis 的資訊
> info
離開redis 介面
> exit
好拉~這就是透過helm 來安裝及測試redis連線 的流程. 其實helm有很多包好的應用, 安裝跟設定都非常的方便. 最後, 用Helm指令來移除剛剛的 redis 部署
$ helm uninstall redis
$ helm list
或者
$ helm ls
移除後將看不到你部署的chart