在 Kubernetes 環境中佈署應用程式時,Helm Chart 提供了便捷的封裝和佈署方式。然而,隨著應用程式規模的增長,Chart 內的 YAML 檔案可能會變得冗長且難以維護。本文將介紹如何利用 Helm 的命名範本功能來提高程式碼重用性,簡化 Chart 的管理,並探討如何定義和使用自定義資源定義 (CRD)。透過命名範本,我們可以將常用的程式碼片段封裝起來,例如標籤、註解或其他重複的 Kubernetes 資源設定。這不僅減少了程式碼的冗餘,也提高了一致性,方便日後的維護和更新。此外,當需要修改這些分享的程式碼片段時,只需要修改命名範本即可,而不需要修改每個使用到它的 YAML 檔案。除了命名範本,我們還將探討如何使用 Helm 來管理自定義資源。CRD 允許我們擴充套件 Kubernetes API,定義新的資源型別。Helm Chart 可以包含 CRD 的定義,並在佈署過程中自動安裝它們。這使得管理和佈署自定義資源變得更加方便。最後,我們將深入解析 Chart.yaml 檔案,這是 Helm Chart 的核心檔案,包含了 Chart 的後設資料,例如名稱、版本、依賴關係等。理解 Chart.yaml 的結構和重要欄位,對於正確地構建和管理 Helm Chart 至關重要。
透過命名範本來實作程式碼重用
在建立 Kubernetes 資源的過程中,Go 範本不僅可以生成 Kubernetes 資源,還可以用來建立可重複使用的函式,這些函式可以應用於包含重複性範本的 YAML 資源。這可以透過建立命名範本來實作,這部分內容將在下一節中詳細說明。
使用命名範本來啟用程式碼重用
在建立範本檔案時,Kubernetes 資源中可能會出現重複的 YAML 塊。例如,資源的標籤可以如下指定:
labels:
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
為了保持一致性,這些標籤可以新增到 Helm 圖表中的每個資源。如果圖表包含多種不同的 Kubernetes 資源,則在每個檔案中包含所需標籤可能會變得繁瑣,特別是如果需要修改標籤或未來需要在每個資源上新增新標籤。
Helm 提供了一個稱為命名範本的建構,它允許圖表開發人員建立可重複使用的範本來減少樣板程式碼。命名範本定義在 templates/ 目錄下,並以底線開頭、.tpl 結尾的檔案表示。許多圖表都會有一個名為 _helpers.tpl 的檔案,其中包含命名範本,儘管該檔案不必命名為 helpers。
要在 tpl 檔案中建立一個命名範本,開發人員可以利用 define 操作。以下示例展示瞭如何建立一個可以用來封裝資源標籤的命名範本:
{{- define 'mychart.labels' }}
labels:
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
define 操作接受一個範本名稱作為引數。在前面的示例中,範本名稱被稱為 mychart.labels。命名範本的常見約定是 $CHART_NAME.$TEMPLATE_NAME,其中 $CHART_NAME 是 Helm 圖表的名稱,而 $TEMPLATE_NAME 是一個簡短、描述性的名稱,用於描述該範本的目的。
mychart.labels 名稱暗示該範本是 mychart Helm 圖表的一部分,並且將生成應用該範本的資源標籤。
在 Kubernetes YAML 範本中使用命名範本
要在 Kubernetes YAML 範本中使用命名範本,可以使用 include 函式,其用法如下:
include [TEMPLATE_NAME] [SCOPE]
TEMPLATE_NAME 引數是要處理的命名範本名稱。SCOPE 引數是要處理的值和內建物件的範圍。大多數情況下,此引數是一個點 (.) 用於表示當前頂級範圍,但如果參照當前範圍之外的值,則應使用美元符號 ($) 。
以下示例演示瞭如何使用 include 函式處理命名範本:
metadata:
name: {{ .Release.Name }}
{{- include 'mychart.labels' . | indent 2 }}
此示例首先將資源的名稱設定為釋出版本名稱。然後它使用 include 函式處理標籤並對每行進行兩個空格縮排,如管道所宣告。處理完成後,釋出中的一個名為 template-demonstration 的資源可能如下所示:
metadata:
name: template-demonstration
labels:
app.kubernetes.io/instance: template-demonstration
app.kubernetes.io/managed-by: Helm
Helm 還提供了一個 template 操作,也可以展開命名範本。此操作與 include 的使用方式相同,但有一個主要限制——它不能在管道中用於提供額外格式化和處理。此操作僅用於內聯顯示資料。由於此限制,圖表開發人員應優先使用 include 函式而非 template 操作,因為 include 與 template 功能相同且具有管道處理的額外好處。
內容解密:
上述程式碼範例展示瞭如何利用 Go 範本語法定義及呼叫命名範本。首先「define」關鍵字定義了一個名為「mychart.labels」的命名範本(此段落作用就是告訴其他程式碼這裡有我們想要重複使用的一段程式碼),接著在需要呼叫重複程式碼時利用「include」關鍵字進行呼叫(此段落作用就是告訴其他程式碼我們想要重複使用哪一段程式碼),其中 .Release.Name 和 .Release.Service 是 Helm 範本中的內建變數,分別代表當前 Helm Chart 的釋出名稱和服務名稱。
接著來解釋「indent」功能:「indent」是 Go 範本中的一個內建函式(「builtin function」),它會對輸入進行縮排(indentation)。在上面範例中,「indent」函式接收兩個引數:第一個是要縮排的內容,「- include ‘mychart.labels’ .」回傳的是所呼叫之 mychart.labels 的執行結果;第二個引數是縮排的空白字元長度(以空格計算),在此範例中是「2」,表示每行輸出都會縮排兩個空白字元。
最後針對「scope」這部分進行說明:在 Go 模版語法裡面,「.」和「$」都是「scope」,會影響 Go 模版去取值或變數時會從哪邊開始取值。上述範例所提到的是最常見情況:「.」代表的是當前範圍(current scope),而「$」則代表的是全域範圍(global scope),所以大部份時候都會選擇當前範圍。「scope」概念類別似一般網頁瀏覽器目前瀏覽的頁面與主機機器上所有網頁頁面之間關係。「current scope」就跟瀏覽器現在所看到網頁相當;而「global scope」就是所有網頁頁面。
倉函式庫圖表
Helm 圖表有一個在 Chart.yaml 檔案中定義的型別欄位(type field),設定為 application 或 library 。應用程式圖表(application charts) 用於將完整應用程式佈署到 Kubernetes 。這是最常見型別的圖表且為預設設定 ,然而 ,圖表也可被定義為函式庫圖表(library chart) 。這型別圖表並不直接佈署應用程式 ,而是提供可被多種不同圖表所使用之命名模版 。以之前提到之 label 作為例子 ,開發者可維護多種不同之圖表其資源具有相同之 labels ,而不是將相同之命名模版定義於每張圖表之 _helpers.tpl 檔案中 ,開發者可以宣告一張 library chart 提供產生資源 labels 之命名模版作為依賴專案 。
庫存自訂資源
雖然 Helm 最常見之功能是在建立傳統 Kubernetes 資源上 ,但它也能建立自訂資源(CRs) ,這部分會在下一節進行說明 。 CRs 用於建立並非原生 Kubernetes API 的資源 ,玄貓你可能想利用此功能增強 Kubernetes 提供之功能 。 與原生 Kubernetes 資源類別似 ,CRs 也可透過 Helm 模版進行建立 ,但必須先有 Custom Resource Definition ( CRD )來定義 CR ,否則安裝將會失敗 。
Helm Chart 中可包含 crds/ 資料夾 ,其中包含必要之 CRD ,才能在安裝模版之前呈現 。以下展示了一個 crds/ 資料夾之範例:
crds/
my-custom-resource-crd.yaml
檔案 my-custom-resource-crd.yaml 的內容可能如下所示:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: my-custom-resources.learnhelm.io
spec:
group: learnhelm.io
names:
kind: MyCustomResource
listKind: MyCustomResourceList
內容解密:
以上介紹了 Custom Resource Definition ( CRD )及其基本概念。「CRD 是什麼?」就是指自訂我們想要 Kubernetes 認得我們新增進去之物件資料、設定、服務等 。例如上面範例中的「MyCustomResource」,Kubernetes 原本就沒有支援此種物件;但是我們希望能支援該物件時我們就需要透過 CRD 告知 Kubernetes 。
CRD 的結構分成三大部份:1. apiVersion, kind, metadata(代表你自己決定給定 API Version, Kind, Name);2. spec.group, names.kind, names.listKind(代表你自己決定給定 group 和 kind 的名稱以及 list kind 的名稱)。
玄貓再強調一次:CRD 本身只是 Kubernetes 認得新增進去我們自己的物件而已!它不是我們自己想要新增進去那個物件本身!所以真正新增進去 Kuberentes 的那個物件是另外一件事!所以如果只有一般人說他有新增 CRD 在 Kubernetes 上 ,那隻能算他告知 Kubernetes 他新增進去他自己想要新增進去物件而已!不代表他真的有新增進去那個物件!
從以上這段話玄貓希望大家能瞭解到:CRD 跟真正新增進去 Kuberentes 的物件之間有什麼關係?答案就是:沒有直接關係!
一般人常常搞混了 CRD 跟真正新增進去 Kuberentes 的物件之間有什麼關係?因為他們知道 CRD 有包含「kind」,所以他們就認為 CRD 跟真正新增進去 Kuberentes 的物件必然是相同!但是兩者只有間接關係而已!
從以上介紹大家就知道了:CRD 裡面真的只是告知 Kuberentes 「你認得我的 API Version, Group, Kind, Name!」而已!
Helm Chart 解析與架構設計
Helm 是 Kubernetes 的套件管理工具,允許我們方便地安裝、升級和管理 Kubernetes 應用程式。在本文中,我們將探討 Helm Chart 的核心概念,特別是 Chart.yaml 檔案的結構及其重要性。
Helm Chart 的基礎架構
在開始之前,我們需要了解 Helm Chart 的基本架構。一個典型的 Helm Chart 包含以下幾個主要目錄和檔案:
Chart.yaml:這是 Helm Chart 的定義檔案,包含了關於 Chart 的後設資料。values.yaml:這是 Chart 的預設組態檔案,可以被覆寫以定製安裝。templates/:這個目錄包含了 Kubernetes 資源範本,Helm 會根據這些範本生成實際的 Kubernetes 佈署資源。crds/:這個目錄包含了自定義資源定義 (CRD),當 Chart 需要定義新的 Kubernetes 資源時會用到。
自定義資源定義 (CRD)
在一些情況下,我們可能需要定義自定義資源。例如,如果我們有一個自定義的資源型別 MyCustomResource,我們可以在 crds/ 目錄中定義它。以下是一個簡單的例子:
# crds/mycustomresource.yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: mycustomresources.example.com
spec:
group: example.com
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
foo:
type: string
scope: Namespaced
names:
plural: mycustomresources
singular: mycustomresource
kind: MyCustomResource
接著,在 templates/ 目錄中,我們可以建立一個例項:
# templates/my-custom-resource.yaml
apiVersion: example.com/v1
kind: MyCustomResource
metadata:
name: example-mcr
spec:
foo: bar
這樣的結構確保了 MyCustomResource CRD 在 templates/ 目錄中的 CR 被佈署之前已經安裝。
注意事項
建立 CRD 需要高許可權,因此通常需要由叢集管理員來完成。如果你不是叢集管理員,可以請管理員提前建立 CRD,這樣就不需要在你的 Chart 中包含 crds/ 目錄。
Chart.yaml 檔案解析
Chart.yaml 是 Helm Chart 的核心檔案,它包含了關於 Chart 的後設資料。以下是一些必須瞭解的重要欄位:
必要欄位
apiVersion:這個欄位可以設定為v1或v2。如果設定為v1,則表示使用舊版本的 Chart 架構;如果設定為v2,則表示使用最新版本。Helm 3 與v1相容,但新的 Chart 應該使用v2。name:這個欄位定義了 Helm Chart 的名稱。這個名稱應該與包含 Helm Chart 檔案的頂層目錄名稱相同。version:這個欄位定義了 Helm Chart 的版本號碼。版本號碼應該遵循 Semantic Versioning (SemVer) 規格。
示例
# Chart.yaml
apiVersion: v2
name: wordpress
version: 8.1.0
必要欄位解說
- apiVersion:指定 API 的版本。由於我們是使用最新版本的 Helm(Helm v3),所以我們應該使用
v2 - name:即為此次 chart 名稱;此處採用的是 Wordpress ,因此名稱便以 wordpress 命名。
- version:Wordpress chart 的版本號碼即為8.1.0
次級標題:依賴性管理
小段落標題:依賴性結構
在某些情況下,我們的 Helm Chart 需要依賴其他 Helm Chart。例如,WordPress chart 需要 MariaDB 作為後端資料函式庫支援。
依賴性通常在 Chart.yaml 中的 dependencies 欄位中宣告:
# Chart.yaml 中的 dependencies 標示範例:
dependencies:
- name: mariadb
version: "~7.x.x"
repository: "https://charts.bitnami.com/bitnami"
小段落標題:依賴性解說
- name:即為此次 chart 名稱;此處採用的是 MariaDB ,因此名稱便以 mariadb 命名。
- version:在此處採用的是7.x.x版本;一旦使用 ~7.x.x時則表示只會更新最新 x.y.z內部數字版本號碼。
- repository:即為 mariadb chart 已經釋出至 https://charts.bitnami.com/bitnami 網址網站之上。
推薦閱讀
在瞭解了基本概念後,建議進一步閱讀《Helm 本地化佈署》及《Kubernetes 自動化佈署》等書籍或文章,以取得更多實務經驗和深度知識。
