[管理] Helm Chart === ###### tags: `K8s / Helm` ###### tags: `Kubernetes`, `k8s`, `Helm Chart`, `HelmChart`, `tgz` <br> [TOC] <br> ## 術語:Helm vs Chart ### 📚 Helm 與 Chart 的關係 | 名稱 | 簡單定義 | 什麼時候用這個詞? | |:----|:----|:----| | **Helm** | 是工具。幫你管理 Kubernetes 的套件管理器(像 apt、yum 一樣的東西) | 當你在談「操作工具」、「執行指令」的時候,用 Helm | | **Chart** | 是套件。描述一個應用程式要怎麼在 Kubernetes 上部署(包含 template、設定值等) | 當你在談「描述檔案」、「定義一個應用」的時候,用 Chart | - ### 🔵 直接舉例讓你秒懂 | 行為 | 用語應該用 Helm 還是 Chart? | 正確說法 | |:----|:----|:----| | 我執行 `helm install` 指令 | Helm(因為你在用工具) | I use **Helm** to install a release. | | 我在編輯 `Chart.yaml` 或 templates | Chart(因為你在定義描述) | I'm editing a **Helm chart**. | | 我要安裝一套應用到 K8s 上 | 兩個詞都可以,看角度 | "Install a **Helm chart**" (focus on what),"Use **Helm** to install" (focus on action) | | 我把 `src/` 打包成 `.tgz` | Chart(因為你是打包描述檔) | I'm packaging a **Helm chart**. | | 我要移除部署好的應用 | Helm(因為你是執行 Helm 工具去刪) | I use **Helm** to uninstall a release. | - ### 總結一句話 用 Helm 這個工具,去管理 Charts 這些套件描述。 - ### 🔥 一句話公式給你記 - Helm 是工具,Chart 是產品。 - Helm 管理 Chart。 <br> ### 🚫 最常見的 Helm vs Chart 錯誤用法對照表 | 誤用句子 | 問題 | 正確說法 | 說明 | |:----|:----|:----|:----| | Install Helm to Kubernetes | ❌ 不對,Helm 是工具,不是要安裝到 K8s 上 | Install a **Helm chart** to Kubernetes | 安裝的是 Chart,不是 Helm 工具本身 | | Package Helm | ❌ 錯,Helm 不需要被打包 | Package a **Helm chart** | 打包的是 Chart 目錄(src/)成 `.tgz` | | Edit Helm | ❌ 錯,Helm 不是一個檔案 | Edit a **Helm chart** | 改的是 Chart 的內容 (Chart.yaml、templates) | | Deploy Helm | ❌ 不夠精確 | Deploy a **Helm chart** using Helm | 用 Helm 工具部署 Chart | | Uninstall Helm | ❌ 很容易誤會成卸載 Helm 工具 | Uninstall a **Helm release** | 移除一個部署過的 Helm 釋出 | | Create a Helm | ❌ 不完整 | Create a **Helm chart** | 建一個新的 Chart 專案(用 `helm create`) | | Upgrade Helm | ❌ 容易誤解成升級 Helm 工具 | Upgrade a **Helm release** | 升級一個已部署的 Chart | | Helm charts is deployed | ❌ grammar 錯,單複數搞錯 | Helm charts are deployed | 多個 Charts,要用 are | - ### 📌 補充:超常聽到的自然英文句型 | 場景 | 最自然的英文用法 | |:----|:----| | 打包 Chart | "Package the Helm chart." | | 安裝 Chart | "Install the Helm chart." | | 部署應用 | "Deploy the Helm chart using Helm." | | 升級部署 | "Upgrade the Helm release." | | 卸載部署 | "Uninstall the Helm release." | | 修正 Chart | "Edit the Helm chart." | - ### ✨ 簡易記憶法 > 📦 **Chart 是商品**(要打包、安裝、部署) > 🛠️ **Helm 是工具**(拿來打包、安裝、部署 Chart) → 說**商品**的行為用 Chart, 說**行動與指令**用 Helm! <br> --- ## Helm 參數 > [[HackMD]](https://hackmd.io/ASOVgefqR_a4Twcw0uvH0g) <br> --- ## 指令 - 使用現有的 HelmChart > 操作範例 ### 登入 registry 若 registry 是私有的,先登入: ``` helm registry login ghcr.io ``` <br> ### 下載 Helm Chart 的 tgz 檔 ``` SLURM_VERSION=0.3.1 helm pull oci://ghcr.io/slinkyproject/charts/slurm \ --version "${SLURM_VERSION}" \ --destination ./dist ``` - 會得到:`./dist/slurm-${SLURM_VERSION}.tgz` - `dist` 目錄若不存在,會有錯誤 - 因此,必須先建立 `dist` 目錄 <br> ### 查看 Helm Chart 的 `values.yaml` 檔 ``` SLURM_VERSION=0.3.1 helm show values oci://ghcr.io/slinkyproject/charts/slurm \ --version "${SLURM_VERSION}" ``` <br> ### 下載 Helm Chart 的 `values.yaml` 檔 ``` SLURM_VERSION=0.3.1 helm show values oci://ghcr.io/slinkyproject/charts/slurm \ --version "${SLURM_VERSION}" > values.yaml ``` <br> ### 查詢/取得當前版本 - ### 從 Chart.yaml 查看 ``` $ helm show chart oci://ghcr.io/slinkyproject/charts/slurm | grep '^version:' version: 0.4.1 ``` ``` $ helm show chart slurm-*.tgz | grep '^version:' version: 0.4.1 ``` <br> ### 查詢可用版本/查詢最新版本 - ### 用 ORAS > - [oras 指令安裝](https://oras.land/docs/installation/) > - url 不加 `oci://` ```bash $ oras repo tags ghcr.io/slinkyproject/charts/slurm 0.1.0 0.2.0 0.2.1 0.3.0 0.3.1 0.4.0 0.4.1 # 列出最新的版本 $ oras repo tags ghcr.io/slinkyproject/charts/slurm | sort -V | tail -1 0.4.1 ``` - ### 純 curl(直接打 GHCR v2 API) ``` $ TOKEN=$(curl -s 'https://ghcr.io/token?service=ghcr.io&scope=repository:slinkyproject/charts/slurm:pull' \ | jq -r '.token') $ curl -s -H "Authorization: Bearer $TOKEN" \ https://ghcr.io/v2/slinkyproject/charts/slurm/tags/list | jq { "name": "slinkyproject/charts/slurm", "tags": [ "0.1.0", "0.2.0", "0.2.1", "0.3.0", "0.3.1", "0.4.0", "0.4.1" ] } ``` - 沒帶 token 會遇到 `{"errors":[{"code":"UNAUTHORIZED","message":"authentication required"}]}` <br> ### 測試模板渲染 ```bash $ helm template oci://ghcr.io/slinkyproject/charts/slurm \ --version "${SLURM_VERSION}" > all-files.yaml ``` - 可串接 `grep` 過濾 keywords ,加上前後文參數 `-B 10` & `-A 10` (前10行 & 後10行) <br> --- ## 指令 - 自製 HelmChart > 操作範例 ### 建立 Chart 結構 ```bash $ helm create mychart ``` ```bash $ tree mychart mychart ├── charts ├── Chart.yaml ├── templates │ ├── deployment.yaml │ ├── _helpers.tpl │ ├── hpa.yaml │ ├── ingress.yaml │ ├── NOTES.txt │ ├── serviceaccount.yaml │ ├── service.yaml │ └── tests │ └── test-connection.yaml └── values.yaml ``` <br> ### 測試模板渲染 ```bash $ helm template mychart ``` <br> ### 打包成 Chart 檔案,再佈署 ```bash $ helm package mychart $ helm install <release-name> ./mychart-0.1.0.tgz ``` - 若發布名稱為 myrelease,則命令如下: ``` helm install myrelease ./mychart-0.1.0.tgz ``` - 客製化安裝 ``` $ helm install myrelease ./mychart-0.1.0.tgz --set replicaCount=2 $ helm install myrelease ./mychart-0.1.0.tgz -f custom-values.yaml ``` <br> ### 直接佈署 ``` $ helm install <release-name> ./mychart ``` <br> ### 驗證部署狀態 ``` $ helm list $ kubectl get all ``` <br> --- ## 管理當前的 Helm release > 以 cert-manager 為例 ### 找出 release 與版本 - **範例1** ```bash helm -n cert-manager list # 通常 release 名稱就是 cert-manager ``` - **範例2**:不知道 namespace 的情況下 ```bash helm list -A # --all-namespaces helm list -A | grep cert ``` <br> ### 看目前生效的 values(含預設合併) > doc: [Helm Get Values](https://helm.sh/docs/helm/helm_get_values/) - **範例1**:找出 `crds.enabled` 的值是 `true` 還是 `false` ```bash # 顯示所有(使用者 + chart 預設)合併後的值 helm -n cert-manager get values cert-manager -a # -a --all, dump all (computed) values ``` 在輸出中尋找: ```yaml crds: enabled: true # 或 false ``` - **補充**: - 舊版 chart 可能用的是 `installCRDs` 這個 key。若找不到 `crds.enabled`,再找: ```bash helm -n cert-manager get values cert-manager -a | grep -i installCRDs ``` - cert-manager 自 v1.15 起改用 `crds.enabled`,早期文件使用 `installCRDs`。([cert-manager](https://cert-manager.io/v1.15-docs/installation/helm/) - ### 對照該版本 chart 的預設值(可選) ```bash # 先從第 1 步看到的 Chart 版本帶入 <VERSION> helm show values oci://quay.io/jetstack/charts/cert-manager \ --version v1.17.1 | sed -n '/^crds:/,/^[^ ]/p' ``` - 這可以確認該版本 chart 的 `crds.enabled` 預設值,對比你 release 目前的生效值。 - ### 判讀與後續 - 看到 `crds.enabled: true`:代表此 release 由 Helm 安裝/升級 CRDs。後續 `helm upgrade` 會連同 CRDs 一起處理。([cert-manager](https://cert-manager.io/docs/installation/upgrade/)) - 看到 `crds.enabled: false` 或該 key 不存在:通常表示 CRDs 不是由此 Helm release 管理(可能是手動 `kubectl apply` 過或是舊版 `installCRDs` 流程)。 - 只想確認 CRDs 是否存在(不能據此判斷是否由 Helm 管理): ``` $ kubectl get crd | grep cert-manager.io certificaterequests.cert-manager.io 2025-04-07T08:34:31Z certificates.cert-manager.io 2025-04-07T08:34:31Z challenges.acme.cert-manager.io 2025-04-07T08:34:31Z clusterissuers.cert-manager.io 2025-04-07T08:34:31Z issuers.cert-manager.io 2025-04-07T08:34:31Z orders.acme.cert-manager.io 2025-04-07T08:34:31Z ``` - ### 想改成由 Helm 管理 CRDs? 若目前不是 Helm 管理、你想改由 Helm 管理,官方建議的安全流程是先**手動升級 CRDs**,再升級 chart;或在之後的安裝/升級中帶上 `--set crds.enabled=true` 讓 Helm 接手管理。細節見官方升級文件。([cert-manager](https://cert-manager.io/docs/installation/upgrade/)) <br> ### 如何變更當前生效的 values? - ### 範例1:將 `crds.enabled` 的值設定為 `true` - #### 最快做法(保留原本 values,只覆蓋 crds.enabled) ```bash # 建議先確認目前使用的 chart 版本 helm -n cert-manager list # 將 crds.enabled 改成 true helm upgrade cert-manager oci://quay.io/jetstack/charts/cert-manager \ --namespace cert-manager \ --version <目標版本> \ --reuse-values \ --set crds.enabled=true \ --wait ``` > `--reuse-values` 會沿用現有 release 的值,再把你用 `--set` 指定的差異覆蓋上去。([helm.sh](https://helm.sh/docs/helm/helm_upgrade/)) - #### 更穩健做法(升級同時採用新 chart 的必要預設) 如果你也要一起升級 chart 版本,或想讓新版本 chart 的**新預設值**生效,官方文件示例會用: ```bash helm upgrade cert-manager jetstack/cert-manager \ --namespace cert-manager \ --version <目標版本> \ --reset-then-reuse-values \ --set crds.enabled=true \ --wait ``` > **cert-manager 官方說明**: > 當以 Helm 管理 CRDs(`crds.enabled=true`)時,往後升級會自動升級 CRDs;範例使用 `--reset-then-reuse-values`。([cert-manager](https://cert-manager.io/docs/installation/upgrade/)) --- - #### 升級後如何確認 ```bash # 1) 看生效的 values helm -n cert-manager get values cert-manager -a | sed -n '/^crds:/,/^[^ ]/p' # 2) 確認 CRDs 存在(僅確認是否在叢集內) kubectl get crd | grep cert-manager.io # 3) 元件狀態 kubectl -n cert-manager get deploy,pod ``` > 之後你只要持續用 `--set crds.enabled=true`(或 values 檔設為 true),Helm 就會在升級 chart 時一併處理 CRDs。([cert-manager](https://cert-manager.io/docs/installation/upgrade/)) --- - #### 舊版相容性備註 * **若你的舊 chart 還在用 `installCRDs`**:那就是早期鍵名,等效做法是改用 `--set installCRDs=true`,或先升級到使用 `crds.enabled` 的版本(v1.15 起官方文件改用此鍵)。([cert-manager](https://cert-manager.io/v1.6-docs/installation/helm/)) * **CRDs 原本不是由 Helm 安裝**:先把 `crds.enabled=true` 打開也沒問題;往後升級時 Helm 會處理 CRD 的更新。若你仍打算手動管理 CRDs,官方建議是每次先套用新版 CRDs,再升級 chart。([cert-manager](https://cert-manager.io/docs/installation/upgrade/)) <br> --- <br> ## 規則 ### 全域變數 在 Helm 的 Go template 中,所有全域變數都是以大寫開頭: - `.Values` 是使用者提供的變數(來自 `values.yaml`) - `.Release` 是 release 資訊 - `.Chart` 是 chart metadata - `.Files` 是 chart 中的檔案物件 範例: - ✅ `.Values.platform` 是正確的(`platform` 是 `values.yaml` 裡的小寫 key) - ❌ `.values` → 根本不存在(Go Template 會噴錯:nil pointer evaluating) <br> ### 大小寫敏感 template 中需用**完全相同大小寫**的 `.Values.key` 來存取。 - ### ✅ 正確示範(values.yaml) - `values.yaml` ```yaml platform: AWS ``` - `templates/test.yaml` ```yaml msg: {{ .Values.platform }} # ✅ OK msg: {{ .Values.Platform }} # ❌ 錯誤:找不到 key,會是 nil ``` <br> --- --- <br> ## 模板語法(Go template 語法) ### `{{- ... }}` vs `{{- ... -}}` vs `{{ ... -}}` - ### 簡單解釋 | 語法形式 | 說明 | | ------------- | ----------------------- | | `{{ ... }}` | 正常模板語法,**不清除前後空白** | | `{{- ... }}` | 清除模板 **左邊的空白與換行符號** | | `{{ ... -}}` | 清除模板 **右邊的空白與換行符號** | | `{{- ... -}}` | 同時清除模板 **左右兩側的空白與換行符號** | - ### 舉例說明 - ### ✅ 範例一:不使用 `-` ```gotmpl foo {{ printf "bar" }} baz ``` ➡️ 渲染結果: ``` foo bar baz ``` - ### ✅ 範例二:使用 `{{- ...}}`(清除左邊空白) ```gotmpl foo {{- printf "bar" }} baz ``` ➡️ `foo` 後面多餘空白會被清除: ``` foo bar baz ``` - ### ✅ 範例三:使用 `{{ ... -}}`(清除右邊空白) ```gotmpl foo {{ printf "bar" -}} baz ``` ➡️ `bar` 後面那行空白不會多印: ``` foo bar baz ``` - ### ✅ 範例四:使用 `{{- ... -}}`(清左右空白) ```gotmpl foo {{- printf "bar" -}} baz ``` ➡️ `bar` 前後都不會有多餘空白: ``` foo bar baz ``` - ### 💡 實務建議 | 使用情境 | 建議語法 | | --------------- | ---------------- | | 避免空行或多餘縮排 | 使用 `{{-` 或 `-}}` | | 產生 YAML、不想出現空白行 | 使用 `{{- ... -}}` | | 保留格式、讓內容可讀性好 | 適當保留 `{{ ... }}` | <br> --- <br> ### index - ### 語法 - `{{ index <map> <key> }}` - ### 範例 - `values.yaml` ```yaml= platform: "5glab" # "5glab" | "241" nodeNameMap: "5glab": "esc8000-e11p-02" "241": "mymini" ``` - `templates/service.yaml` ```yaml= ... spec: template: spec: nodeName: {{ index .Values.nodeNameMap .Values.platform }} # nodeName: "esc8000-e11p-02" ``` <br> ## Troubleshooting `$ helm install sync-pilot-client sync-pilot-client-1.0.0.tgz` `Error: rendered manifests contain a resource that already exists. Unable to continue with install: ServiceAccount "sync-pilot-sa" in namespace "default" exists and cannot be imported into the current release: invalid ownership metadata; label validation error: missing key "app.kubernetes.io/managed-by": must be set to "Helm"; annotation validation error: missing key "meta.helm.sh/release-name": must be set to "sync-pilot-client"; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "default"` <br> ## helm lint > 檢查 Chart 合法性 ``` $ helm lint helm/src/ ==> Linting helm/src/ [ERROR] Chart.yaml: apiVersion is required. The value must be either "v1" or "v2" [INFO] Chart.yaml: icon is recommended Error: 1 chart(s) linted, 1 chart(s) failed ``` <br> <hr> <br> ## 應用 ### 每次都能 render 出有變更的 yaml 內容 ``` metadata: annotations: helm.sh/restart-timestamp: "{{ now | unixEpoch }}" ``` - ### 什麼環境下能執行 unixEpoch? - ### o4-mini-high (2025/05/06) ### 使用 `unixEpoch` 的環境 `unixEpoch` 不是一個系統指令,而是來自 Go 模板函式庫 **Sprig**(Masterminds/sprig)中的一個日期函式。它的功能是將一個 `time.Time` 物件(例如 `now`)轉換成自 Unix 紀元(1970-01-01 00:00:00 UTC)以來的秒數。 要執行 `now | unixEpoch`,必須滿足以下條件: 1. **Go 模板環境** 使用 Go 的 `text/template` 或 `html/template`,並在程式中註冊 Sprig 的函式地圖(FuncMap): ```go import ( "text/template" sprig "github.com/Masterminds/sprig/v3" ) tmpl := template.New("example").Funcs(sprig.FuncMap()) tmpl, _ = tmpl.Parse(`{{ now | unixEpoch }}`) tmpl.Execute(os.Stdout, nil) ``` 2. **Helm Chart 模板** Helm v3 預先整合了 Sprig 函式庫,所以在撰寫 Helm 模板時,直接就能使用: ```yaml apiVersion: v1 kind: ConfigMap metadata: name: timestamp data: now: "{{ now | unixEpoch }}" ``` 3. **其他採用 Sprig 的系統** 除了 Helm,還有一些 CI/CD 或基礎架構工具(例如 Concourse CI 的 pipeline、或自己用 Go 編寫的靜態站點產生器)如果有引入 Sprig,同樣可以直接在模板裡調用 `unixEpoch`。 --- **總結**: - `unixEpoch` 來自 Sprig 函式庫。 - 必須在 **Go 模板** 環境中註冊 Sprig(或使用預載 Sprig 的工具如 Helm)才能呼叫。 - 在 Helm Chart 裡寫 `{{ now | unixEpoch }}` 就能直接用,無需額外設定。 <br> <hr> <br> ## 討論 ### HelmChart 與 Kubernetes YAML 部署比較 - ### Question 關於 k8s 與 HelmChart 的關係 有人說 yaml 檔會再把包成 HelmChart ,再進行佈署 這樣的好處為何?為何不直接 apply yaml 檔就好? - ### gpt-o3-mini-high (2025/03/28) HelmChart 是 Kubernetes 的套件管理工具,它可以把一組 YAML 資源打包成一個可重複使用、可配置的應用程式包。直接用 `kubectl apply -f` 當然能部署資源,但使用 HelmChart 有以下幾個主要好處: ### 1. 模板化與參數化 Helm 讓你能利用模板(Template)技術,把重複的 YAML 抽象化,只需要提供不同的變數(例如副本數、端口、資源限制等)即可針對不同環境做客製化設定,減少重複配置的工作量。 ### 2. 版本管理與回滾 每次 Helm 部署都會生成一個 release,可以記錄部署的狀態與版本,方便未來升級或回滾。如果發現新版本有問題,可以迅速回復到上一個穩定版本。 ### 3. 依賴管理 複雜應用往往需要多個組件相互協作。Helm 允許你在 Chart 中定義依賴,並自動處理依賴的安裝與版本匹配,使整個部署流程更順暢。 ### 4. 統一管理與共享 Helm Chart 可以儲存在 Chart Repository 中,方便團隊間共享和維護,讓應用部署變得標準化和可重複。 ### 5. 升級和維護的便利性 當應用需要調整配置或增加新功能時,更新 Chart 並執行 `helm upgrade` 可以自動套用變更,相較直接修改 YAML,維護起來更有條理且風險較低。 **總結:** 雖然直接 apply YAML 檔案適用於簡單或一次性的部署,但在面對複雜、需要頻繁調整或跨環境部署的情況下,使用 HelmChart 可以提升可維護性、靈活性與版本控制,進而降低操作出錯的風險。 <br> ### helm upgrade 指令怎麼用? - ### gpt-o3-mini-high (2025/03/28) > Helm Upgrade 指令的使用方式 `helm upgrade` 指令主要用來升級已部署的 Helm Release,當你需要更新應用的設定或更換 Chart 版本時,就可以使用這個命令。以下是一些常見用法與範例: ### 1. 基本語法 ```bash helm upgrade <release name> <chart path or chart name> ``` 這裡 `<release name>` 為你部署時定義的名稱,而 `<chart path or chart name>` 則指向 Chart 的目錄或 Chart Repository 裡的名稱。 ### 2. 使用 --install 選項 若指定的 release 尚未存在,你可以加上 `--install` 參數,這樣就會先安裝再升級: ```bash helm upgrade --install my-release ./mychart ``` ### 3. 覆蓋預設值 - 使用 `-f` 或 `--values` 選項讀取自定義的 values 檔案: ```bash helm upgrade my-release ./mychart -f custom-values.yaml ``` - 使用 `--set` 選項直接在命令行中指定值: ```bash helm upgrade my-release ./mychart --set replicaCount=3 ``` ### 4. 指定 Chart 版本 如果 Chart 有多個版本,可以用 `--version` 選項指定升級到的特定版本: ```bash helm upgrade my-release ./mychart --version 1.2.3 ``` ### 5. 檢查升級結果與回滾 - 升級後,可以用 `helm status <release name>` 來查看目前狀態。 - 若發現問題,可以透過 `helm history <release name>` 查看歷史版本,並用 `helm rollback <release name> <revision>` 回滾到先前穩定的版本。 這些功能讓 `helm upgrade` 成為管理 Kubernetes 應用程式時非常強大的工具,使得應用更新與版本控制更為簡便與安全。 <br> ### 如何將 YAML 文件打包成 Helm Chart - ### Question 關於 K8s, 假設我有 yaml 檔如下,我要如何打包成 helmchart? ```yaml ... --- ... --- ... ``` - ### gpt-o3-mini-high (2025/03/28) 你可以將這個 YAML 文件轉換成 Helm Chart,主要步驟如下: 1. **建立 Chart 結構** 使用 Helm 指令建立一個新的 Chart(例如:mychart): ```bash helm create mychart ``` 這會自動生成一個目錄結構,包括: - **Chart.yaml**:Chart 的描述文件。 - **values.yaml**:預設變數值,可以用來參數化配置。 - **templates/**:存放所有 Kubernetes 資源模板的目錄。 2. **整合 YAML 文件** - 將你提供的 YAML 文件內容複製到 **`templates/`** 目錄中,可以依功能拆分成多個檔案,例如: - `statefulset.yaml`:放置 StatefulSet 定義。 - `service.yaml`:放置 Service 定義。 - `ingress.yaml`:放置 Ingress 定義。 - `rbac.yaml`:放置 ClusterRole 與 ClusterRoleBinding 定義。 - 如果需要,刪除或修改 Helm 預設生成的模板。 3. **模板化配置** 將 YAML 中一些固定值轉換成可參數化的變數,這樣使用者可以在部署時自訂配置。例如: - 將副本數替換成 `{{ .Values.replicaCount }}`,並在 `values.yaml` 中定義預設值: ```yaml replicaCount: 1 ``` - 將 image 名稱和 tag 參數化: ```yaml image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" ``` 並在 `values.yaml` 中增加: ```yaml image: repository: ociscloud/sync-pilot tag: v0.1 ``` - 其他參數(例如 nodeName、port、env 等)也可以用同樣的方式替換成變數。 4. **更新 Chart.yaml** 編輯 Chart.yaml,填寫 Chart 名稱、版本、描述等元數據,這有助於其他使用者理解這個 Chart 的用途。 5. **測試模板渲染** 使用以下命令來檢查模板渲染後的 Kubernetes 資源是否正確: ```bash helm template mychart ``` 6. **打包或部署 Helm Chart** 如果要打包成 Chart 檔案,可使用: ```bash helm package mychart ``` 或者直接部署: ```bash helm install <release-name> ./mychart ``` 這樣,你就能將原本的 YAML 文件轉換成一個可重複部署、靈活配置的 Helm Chart。 <br> ### 如何將 YAML 檔打包成 Helm Chart - ### gpt-4o (2025/04/24) ### 🧭 一、目錄結構 Helm chart 有固定的結構,假設你的 chart 名為 `myapp`,目錄應如下: ``` myapp/ ├── Chart.yaml # Chart 的 metadata ├── values.yaml # 使用者可自訂的變數 ├── templates/ # 內含 k8s YAML 檔案(支援 Helm template 語法) │ ├── deployment.yaml │ ├── service.yaml │ └── ... ``` --- ### 🧱 二、建立 Chart 你可以使用 `helm create` 自動產生一個 chart 的骨架: ``` helm create myapp ``` 這會建立上述結構。你可以將你原本的 YAML 檔案放到 `templates/` 裡(注意:這些檔案可以是純 YAML,也可以加上 Helm 模板語法)。 --- ### ✍️ 三、編輯 Chart.yaml ``` apiVersion: v2 name: myapp description: A sample Helm chart for Kubernetes version: 0.1.0 appVersion: "1.0" ``` --- ### 🛠 四、填寫 values.yaml(可選) 這個檔案用來設置變數,例如: ```yaml replicaCount: 2 image: repository: nginx tag: "1.21" pullPolicy: IfNotPresent ``` 你可以在 `templates/` 中使用這些變數,例如: ```yaml # templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: {{ .Chart.Name }} spec: replicas: {{ .Values.replicaCount }} ... ``` --- ### 📦 五、打包成 `.tgz` 完成後,使用以下指令打包: ```bash helm package myapp ``` 會產生 `myapp-0.1.0.tgz`,這就是可供部署的 Helm Chart。 --- ### 🚀 六、部署到 K8s(驗證 chart) 從打包好的檔案安裝: ```bash helm install myapp ./myapp-0.1.0.tgz ``` 或直接從資料夾安裝: ```bash helm install myapp ./myapp ``` <br> ### 如果是打包成 Chart 檔案,我要如何執行安裝? - ### gpt-o3-mini-high (2025/03/28) > Helm Chart 安裝指南 以下說明如何將打包好的 Helm Chart 檔案安裝到 Kubernetes 叢集中。 ### 前置條件 - 確保已安裝 [Helm](https://helm.sh/) 並能連線到 Kubernetes 叢集。 ### 安裝步驟 1. **打包 Chart 檔案** 假設你的 Chart 檔案名稱為 `mychart-0.1.0.tgz`。 2. **執行安裝命令** 使用下列指令來部署 Chart,其中 `<release-name>` 為你指定的發布名稱: ```bash helm install <release-name> ./mychart-0.1.0.tgz ``` 例如,若發布名稱為 `myrelease`,則命令如下: ```bash helm install myrelease ./mychart-0.1.0.tgz ``` 3. **自訂值(可選)** 如果需要調整預設配置,可以透過 `--set` 參數或提供自訂的 values 檔案來指定變數: - 使用 `--set` 指定參數: ```bash helm install myrelease ./mychart-0.1.0.tgz --set replicaCount=2 ``` - 或是使用自訂的 values 檔案: ```bash helm install myrelease ./mychart-0.1.0.tgz -f custom-values.yaml ``` 4. **驗證部署狀態** 部署完成後,請使用以下命令確認部署狀態: - 查看 Helm 發布列表: ```bash helm list ``` - 使用 kubectl 檢查資源狀態: ```bash kubectl get all ``` ### 結語 按照上述步驟,你就能成功將打包好的 Helm Chart 安裝到 Kubernetes 叢集中。根據實際需求調整參數,即可進行自訂化部署。 <br> ### 在 k8s Pod 中執行 Helm Chart 安裝可行性說明 - ### Question 有一個 SyncResource App,位於 k8s pod (有相關存取 k8s 資源的權限) 如果在 pod 中想要執行 helm chart 安裝,是否可行? - ### gpt-o3-mini-high (2025/03/28) > 在 k8s Pod 中執行 Helm Chart 安裝可行性說明 只要滿足幾個前提條件,在 pod 中執行 Helm chart 安裝是可行的。 ### 前提條件 - **Helm 工具安裝:** Pod 中必須包含 Helm 客戶端(例如,作為容器內的一個工具或透過自定義的鏡像內置)。 - **Kubeconfig 或 in-cluster 配置:** Pod 必須能夠正確訪問 Kubernetes API,這可以通過掛載 kubeconfig 文件或使用 in-cluster 配置(利用服務帳戶令牌)來實現。 - **足夠的 RBAC 權限:** Pod 需要所屬的服務帳戶有足夠的權限去建立、更新或刪除 Helm chart 中定義的各種 Kubernetes 資源。 ### 結論 如果 SyncResource app 已具備上述條件,那麼在其所在的 k8s pod 中直接執行 Helm chart 安裝是完全可行的。 例如,可參考以下的安裝範例(請注意,實際環境中可能需要調整參數): ```bash helm install my-release my-chart --namespace my-namespace ``` 請根據您的實際情況進行調整。 <br> ### Helm 是直接存取 kubectl 指令?還是透過 RESTful API 形式溝通? - ### gpt-o3-mini-high (2025/03/28) Helm 並不是直接調用 `kubectl` 指令,而是透過 Kubernetes 提供的客戶端庫(例如 client-go)來直接與 Kubernetes API Server 進行 RESTful 通訊。也就是說,當你使用 Helm 來安裝或管理 chart 時,它會建立 HTTP/HTTPS 請求與 Kubernetes API 互動,而不是透過執行 `kubectl` 指令。 <br> ### Helm Chart 客製化:根據平台(`platform-A`, `platform-B`)條件啟用 Ingress - ### gpt-4o (2025/03/28) 當你需要根據平台環境(例如 "platform-A" 不需 Ingress、"platform-B" 需 Ingress)控制 Helm chart 中是否產生 Ingress 資源時,可依以下方式設計: --- #### 1. `values.yaml`:定義平台與 Ingress 開關 ```yaml platform: platform-A # 或 platform-B ingress: enabled: false className: kong host: sync-pilot-61-222-206-87.sslip.io tlsSecret: sync-pilot-61-222-206-87.sslip.io servicePort: 6688 ``` --- #### 2. `templates/ingress.yaml`:透過條件語法控制是否產生 Ingress ```yaml {{- if and .Values.ingress.enabled (eq .Values.platform "platform-B") }} apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: sync-pilot annotations: cert-manager.io/cluster-issuer: letsencrypt-prod spec: ingressClassName: {{ .Values.ingress.className }} rules: - host: {{ .Values.ingress.host }} http: paths: - path: / pathType: ImplementationSpecific backend: service: name: sync-pilot-service port: number: {{ .Values.ingress.servicePort }} tls: - hosts: - {{ .Values.ingress.host }} secretName: {{ .Values.ingress.tlsSecret }} {{- end }} ``` --- #### 3. 安裝 Helm 時指定平台與參數 在部署到不同平台時,可依照情境調整: - 部署到 **platform-B**(需要 Ingress): ```bash helm install sync-pilot ./myapp -f values.yaml --set platform=platform-B --set ingress.enabled=true ``` - 部署到 **platform-A**(不需要 Ingress): ```bash helm install sync-pilot ./myapp -f values.yaml --set platform=platform-A --set ingress.enabled=false ``` --- #### ✅ 優點 - 保留同一份 Helm chart - 可針對不同平台靈活開關 Ingress - 使用 `--set` 或 `-f` 客製化配置 --- 如需進一步支援,如使用多份 `values-*.yaml` 或變數預設化處理,可再擴充模板設計。 <br> ### Helm 客製參數設定 - ### Question ``` # [INSTALL] echo ">>> Install ${SLURM_NAME}:" helm upgrade -i ${SLURM_NAME} oci://ghcr.io/slinkyproject/charts/slurm \ --values=${SLURM_VALUE} \ --version=0.3.1 \ --namespace=${SLURM_NAME} \ --create-namespace kubectl apply -f pvc.yaml -n ${SLURM_NAME} echo "<<< Done" ``` helm 是否能只攜帶額外參數?就是,我不要直接改官方 --values,我要在另外客製參數值 - ### gpt-5 (2025/09/03) 可以!Helm 支援把「官方預設 values」當作底稿,再用你自己的客製值**分層覆蓋**,不需要去改官方檔。 下面是幾種做法(依常見度排序): ### 1) 只帶一個 override 檔(推薦) `values.yaml` 會用 chart 內建的預設,`override.yaml` 只放你要改的鍵即可。 ```bash cat > override.yaml <<'YAML' image: tag: "0.3.1-custom" controller: resources: requests: cpu: "500m" memory: "1Gi" YAML helm upgrade -i "${SLURM_NAME}" oci://ghcr.io/slinkyproject/charts/slurm \ --version 0.3.1 \ -n "${SLURM_NAME}" --create-namespace \ -f override.yaml ``` ### 2) 多檔分層覆蓋(由左到右,後者覆蓋前者) ```bash helm upgrade -i "${SLURM_NAME}" oci://ghcr.io/slinkyproject/charts/slurm \ --version 0.3.1 \ -n "${SLURM_NAME}" --create-namespace \ -f base.yaml \ -f env/prod.yaml \ -f local.override.yaml ``` **優先序**:chart 內建預設 < `base.yaml` < `prod.yaml` < `local.override.yaml` < `--set` ### 3) 用 `--set`/`--set-string`/`--set-file` 臨時覆蓋 適合只改一兩個鍵(注意 shell quoting)。 ```bash helm upgrade -i "${SLURM_NAME}" oci://ghcr.io/slinkyproject/charts/slurm \ --version 0.3.1 \ -n "${SLURM_NAME}" --create-namespace \ --set controller.replicas=2 \ --set-string controller.env[0].name=MODE \ --set-string controller.env[0].value=prod # 若要把檔案內容注入: # --set-file controller.extraConfig=./myconfig.conf ``` ### 4) 針對已部署過的 release:在「保留既有值」上加新覆蓋 ```bash helm upgrade "${SLURM_NAME}" oci://ghcr.io/slinkyproject/charts/slurm \ --version 0.3.1 \ -n "${SLURM_NAME}" \ --reuse-values \ -f extra.patch.yaml ``` --- ## 實用小撇步 * 先看官方預設值(不用下載 chart): ```bash helm show values oci://ghcr.io/slinkyproject/charts/slurm --version 0.3.1 > base.values.yaml ``` * 驗證合併後的最終 manifest: ```bash helm template test oci://ghcr.io/slinkyproject/charts/slurm \ --version 0.3.1 -f override.yaml | less ``` * **陣列不會「合併」只會被整個覆蓋**(Helm 的行為);需要微調陣列時,通常用 `--set-string key[0].name=...` 這種方式比較可控。 --- ### 套用到你的片段 你可以把 `${SLURM_VALUE}` 換成 `-f override.yaml`(或一串 `-f`),其餘指令不變: ```bash helm upgrade -i ${SLURM_NAME} oci://ghcr.io/slinkyproject/charts/slurm \ --version=0.3.1 \ --namespace=${SLURM_NAME} \ --create-namespace \ -f override.yaml kubectl apply -f pvc.yaml -n ${SLURM_NAME} ``` 如需,我可以幫你把常改的 Slurm 參數整理成一個精簡的 `override.yaml` 範本。 <br> {%hackmd vaaMgNRPS4KGJDSFG0ZE0w %}