[管理] 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 %}