[主題][helm template] 用 `--api-versions` 驗證條件渲染 === ###### tags: `K8s / Helm` ###### tags: `Kubernetes`, `k8s`, `Helm Chart`, `HelmChart`, `.Capabilities.APIVersions.Has`, `--api-versions` <br> [TOC] <br> > by gpt-5 (2025/10/13) :::info #### :books: 摘要 - 為什麼 `helm template` 無法渲染出某些東西? - 為什麼 `helm template` 需要 `--api-versions` 才能渲染出條件資源? - 在本機/叢集各自怎麼測? ::: <br> ## 目標 * 了解 `.Capabilities.APIVersions.Has` 的行為 * 本機用 `helm template` 模擬 API 存在與否 * 在真實叢集用 `helm install/upgrade` 自動偵測 API <br> --- ## 1) 建立最小 Chart > **檔案清單**: > ``` > ├── Chart.yaml > ├── templates > │ ├── configmap.yaml > │ └── hello-cr.yaml <- 如何做,才能渲染出該條件資源? > └── values.yaml > ``` ```bash= mkdir hello-apiversions && cd hello-apiversions # Chart.yaml cat > Chart.yaml <<'YAML' apiVersion: v2 name: hello-apiversions description: Hello world for .Capabilities and --api-versions type: application version: 0.1.0 appVersion: "0.1.0" YAML # ------------------------------------- # values.yaml cat > values.yaml <<'YAML' feature: enableHelloCR: true YAML mkdir -p templates # ------------------------------------- # 一個一定會渲染的 ConfigMap cat > templates/configmap.yaml <<'YAML' apiVersion: v1 kind: ConfigMap metadata: name: hello-config data: message: "This always renders." YAML # ------------------------------------- # 一個「只有當 API 存在」才渲染的資源(假裝有個 CRD:example.com/v1, Kind=Hello) cat > templates/hello-cr.yaml <<'YAML' {{- if and (.Capabilities.APIVersions.Has "example.com/v1") .Values.feature.enableHelloCR }} apiVersion: example.com/v1 kind: Hello metadata: name: hello-conditional spec: message: "Rendered because example.com/v1 is available." {{- end }} YAML ``` <br> --- ## 2) 本機渲染:觀察差異 ### 2.1 不加 `--api-versions` ```bash helm template hello . ``` 你會只看到 `ConfigMap`,**看不到** `Hello`(因為本機離線渲染,`.Capabilities.APIVersions` 內沒有 `example.com/v1`)。 ### 2.2 加上 `--api-versions` ```bash helm template hello . \ --api-versions example.com/v1 ``` 這次會多出: ```yaml apiVersion: example.com/v1 kind: Hello metadata: name: hello-conditional ... ``` 因為你**手動告訴** Helm:「把 `example.com/v1` 視為存在」。 > 小結:`helm template` 離線、**不會探測叢集**,除非你用 `--api-versions` 模擬。 <br> --- ## 3) 在真實叢集的行為 ### 3.1 若叢集**真的**有對應 CRD * 用 `helm install/upgrade`(連線叢集),Helm 會自動將叢集支援的 API 放進 `.Capabilities.APIVersions`。 * 條件 `Has "example.com/v1"` 成立 → `Hello` 會被渲染與建立。 * 驗證: ```bash # 示意(若你確實安裝了對應 CRD) helm install hello . -n demo --create-namespace kubectl -n demo get configmap hello-config kubectl -n demo get hello hello-conditional # 假設有 Hello 這種 CR ``` ### 3.2 若叢集**沒有**該 CRD * `Hello` 不會被渲染(避免部署失敗) * `ConfigMap` 仍會照常建立 * 驗證: ```bash helm install hello . -n demo --create-namespace kubectl -n demo get configmap hello-config # 有 kubectl -n demo get hello hello-conditional # 會找不到(因為沒被渲染/建立) ``` <br> --- ## 4) 只看特定模板(加碼技巧) 想「只輸出某檔案」檢查? ```bash helm template hello . \ --show-only templates/hello-cr.yaml # 搭配: helm template hello . \ --api-versions example.com/v1 \ --show-only templates/hello-cr.yaml ``` <br> --- ## 5) 套到常見情境(ServiceMonitor 範例) 很多 chart 會這樣寫: ```yaml {{- if and (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1") .Values.exporter.serviceMonitor.enabled }} apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: { name: my-exporter } spec: { /* ... */ } {{- end }} ``` * `helm template` 本機:**要**加 `--api-versions monitoring.coreos.com/v1` 才看得到 * 叢集有 Prometheus Operator 時:`helm install/upgrade` 會自動偵測到,條件成立 → 會建立 如果你只想在本機預覽並且**只看** ServiceMonitor: ```bash helm template my . \ --api-versions monitoring.coreos.com/v1 \ --set exporter.serviceMonitor.enabled=true \ --show-only templates/servicemonitor.yaml ``` <br> --- ## 6) 常見 QA ### Q1:為什麼 `kubectl get` 看得到,但 `helm template` 看不到?** A:`kubectl get` 查的是**叢集已存在**的資源;`helm template` 是**離線渲染**,不會連線叢集去偵測 API,因此條件不成立就不渲染。加 `--api-versions` 才能在本機模擬「API 存在」。 ### Q2:我可以在 `helm install` 也用 `--api-versions` 嗎?** A:不行,`helm install` 不支援 `--api-versions`,會有底下錯誤訊息: ``` Error: unknown flag: --api-versions ``` ### Q3:我只想要渲染/檢視特定檔案 A:用 `--show-only templates/xxx.yaml`。 <br> --- ## 7) 清理 ```bash helm uninstall hello -n demo || true kubectl delete ns demo || true ``` <br> --- <br> ## 總結 ### `helm template` vs `helm install/upgrade` - ### 1. `helm template` 的行為 - **本地渲染**,不連接 Kubernetes cluster - **無法自動偵測** cluster 的 API versions(`.Capabilities.APIVersions`) - 條件 `{{- if .Capabilities.APIVersions.Has "monitoring.coreos.com/v1" }}` 會失敗 - 因此 **ServiceMonitor 不會被渲染** - ### 2. `helm install/upgrade` 的行為 - **連接到 Kubernetes cluster** - **自動偵測** cluster 支援的 API versions - 如果 cluster 安裝了 Prometheus Operator,會偵測到 `monitoring.coreos.com/v1` - 條件通過,**ServiceMonitor 會被創建** <br> --- ### 不同操作下的比較 | 指令 | ServiceMonitor 輸出 | 原因 | |------|-------------------|------| | `helm template` | ❌ 沒有 | 無法偵測 API versions | | `helm template --api-versions monitoring.coreos.com/v1` | ✅ 有 | 手動指定 API version | | `helm install` (實際部署) | ✅ 有 | 自動偵測 cluster 的 API versions | | `kubectl get servicemonitor` | ✅ 有 | 已經在 cluster 中部署 | <br> --- ### 梗概(背後原理) * `.Capabilities.APIVersions`:Helm 在**連線叢集**時填入可用 API;在**離線**(`helm template`)時是空的,除非你用 `--api-versions` 補上。 * Chart 透過條件判斷,自動在「有/無對應 CRD」的環境**安全降級**,提升可攜性。 <br> {%hackmd vaaMgNRPS4KGJDSFG0ZE0w %}
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up