K8s 筆記:如何選擇 values.yaml 與 ConfigMap?
values.yaml 是 Helm 在部署前使用的輸入參數;ConfigMap 是 Kubernetes 原生資源,部署後會存在叢集中,供 Pod 讀取非機密設定。
configmap.yaml 只是常見的檔名。它可以是一份標準 Kubernetes YAML;如果放在 Helm Chart 的 templates/ 目錄中,也可以使用 values 動態產生 ConfigMap。
兩者分工不同,並且經常搭配使用:
例如,可以先在 values.yaml 中定義應用程式的 log level:
接著在 templates/configmap.yaml 中指定這個值要成為 ConfigMap 的 LOG_LEVEL:
Helm 渲染後,才會產生真正交給 Kubernetes 的 ConfigMap:
這裡的 app.logLevel 是 values.yaml 中的 Helm 參數名稱;LOG_LEVEL 則是 ConfigMap 提供給程式使用的設定名稱。兩者的名稱不必相同,由 templates/configmap.yaml 負責建立它們之間的對應關係
主要差異
| 比較項目 | values.yaml | ConfigMap |
|---|---|---|
| 所屬系統 | Helm | Kubernetes |
| 主要用途 | 提供 Chart 的預設值與環境差異 | 定義叢集內的非機密應用程式設定 |
| Kubernetes 能否直接讀取 | 不能 | 能,但 Kubernetes 讀到的是渲染後的 ConfigMap |
| 存在時間 | Helm 執行 template、install、upgrade 時作為輸入 | 部署後作為 API Resource 存在叢集中 |
| 常見內容 | image、replicas、resources、service、功能開關及模板所需參數 | log level、URL、功能開關、Nginx 或應用程式設定檔 |
| 使用方式 | 模板以 .Values.xxx 取得 | Pod 以 env、envFrom、command arguments 或 Volume 使用 |
| 修改如何生效 | 重新執行 helm upgrade 才會產生新資源內容 | 更新資源後,仍要依 Pod 的使用方式判斷是否需 rollout |
| 是否適合放密碼 | 不適合;值也可能被渲染進 Manifest 或留在 Helm release 資訊中 | 不適合;機密資料應交由 Secret 管理 |
哪些設定應直接由 values 渲染到 Deployment?
以下通常屬於 Kubernetes 應用程式的部署設定,適合放在 values.yaml,再直接渲染到 Deployment、Service 等資源:
replicaCount:要建立幾個 Pod。image.repository、image.tag:要部署哪個映像檔。resources:CPU 與 memory request/limit。- readiness、liveness probe:Kubernetes 如何判斷程式是否健康。
- Service type、port、Ingress host:服務如何被存取。
- 很少量且只由單一 Deployment 使用的設定。
例如 replicaCount 是 Deployment 的屬性,應由 values 渲染至 Deployment.spec.replicas,沒有必要另外建立 ConfigMap。
什麼情境適合使用 ConfigMap?
情境一:程式需要讀取完整設定檔
Nginx 啟動時會讀取 /etc/nginx/nginx.conf。在 Helm Chart 中,可以先將容易因環境而改變的值放在 values.yaml:
接著在 files/nginx.conf 中使用這些值:
這裡的 .Values.configMap.nginx.workerConnections 和 .Values.configMap.nginx.welcomeMessage 就像預留的空格,Helm 會從 values.yaml 取出對應的值填入。
最後,templates/configmap.yaml 讀取並渲染這份 files/nginx.conf:
其中,.Files.Get 負責讀取檔案,tpl 負責將檔案內的 .Values 替換成實際值。渲染後會產生類似以下的 ConfigMap:
接著,Deployment 再透過 Volume 將 ConfigMap 裡的 nginx.conf 掛載到 /etc/nginx/nginx.conf。因此,同一個 Nginx container image 可以透過不同的 values.yaml 產生不同設定,不需要重新製作 image。
可以在 templates/deployment.yaml 中這樣設定:
這段設定的對應關係如下:
subPath: nginx.conf 表示只取出 ConfigMap 中 data["nginx.conf"] 這一份檔案,而不是將整個 ConfigMap 掛載成目錄。
整個流程可以簡化成:
情境二:多個 Pod 或相關任務共用非機密設定
這是常見情境,最典型的例子是同一個 Deployment 有多個 Pod 副本。假設 API 有三個 Pod,它們都需要相同的執行環境與 log level:
Deployment 可以讓三個 Pod 共同引用同一個 ConfigMap,確保每個副本取得一致設定。更新時也只需要維護一份設定。
另一種情況是 API 與相關的一次性任務需要共用設定。例如 API 與負責資料庫 migration 的 Job 都需要相同的非機密 service URL,因此可以引用同一個 ConfigMap。
不過,共用範圍不宜過大。彼此獨立的服務若有不同的部署週期、負責團隊或權限需求,通常各自維護 ConfigMap 會更清楚,也能減少修改一份設定卻影響多個服務的風險。
情境三:環境變數很多,希望 Deployment 保持精簡
只有一兩個值時,可以直接在 Deployment 的 env.value 中設定;如果有一整組非機密參數,可以使用:
Deployment 只保留引用關係,實際設定集中於 ConfigMap,查詢及維護會更清楚。
情境四:希望能在叢集中獨立查詢設定
ConfigMap 是 Kubernetes API Resource,因此維運人員可以執行:
這適合需要在部署後確認「目前叢集使用哪一組非機密設定」的情境。相較之下,Kubernetes 不認識原始的 values.yaml。
情境五:不同環境需要不同的應用程式設定
不同 values 檔確實可以產生不同的 Deployment,ConfigMap 並非必要條件。例如 replica 數量與 image tag 屬於部署規格,適合直接渲染到 Deployment:
如果差異是程式執行時要讀取的設定,例如 log level,則可由 values 產生不同的 ConfigMap:
因此,values 負責提供環境差異;差異最後進入 Deployment 或 ConfigMap,取決於資料用途:
- replicas、image、resources:渲染到 Deployment。
- log level、功能開關、應用程式設定檔:通常渲染到 ConfigMap,再由 Pod 讀取。
不適合使用 ConfigMap 的情境
- 密碼、API key、token、TLS private key:應使用 Kubernetes Secret 或公司既有的 Vault/外部 Secret 方案。
- replicas、image、resources、probe:這些是 Deployment 本身的部署規格。
- 大型檔案:ConfigMap 不是一般檔案儲存空間;單一 ConfigMap 的資料大小上限為 1 MiB。
- 需要強機密性或細緻存取控制的資料:ConfigMap 內容不是加密機密的替代品。
- 高頻率變動且需要立即生效的動態設定:ConfigMap 的傳遞與應用程式重新載入並非即時設定服務,應評估資料庫或專門的 configuration service。
修改 ConfigMap 後,Pod 會自動取得新值嗎?
要看 Pod 如何使用 ConfigMap:
- 環境變數 (
env/envFrom):既有 Pod 不會自動更新,必須建立新 Pod,通常透過 Deployment rollout 完成。 - 以完整 Volume 掛載:Kubelet 會在同步後更新檔案,但不是立即發生;應用程式也必須具備重新讀取設定的能力。
因此,修改 ConfigMap 後,通常會重新啟動或 rollout Pod,確保程式取得最新設定。
總結
values.yaml和configmap.yaml位於不同層次。values 是 Helm 的部署輸入,用來設定 image、replicas 或不同環境的值;configmap.yaml 則是 Helm template,用來產生 Kubernetes ConfigMap。ConfigMap 部署後會留在叢集中,適合提供 log level、功能開關或設定檔等非機密資料給 Pod 使用。ConfigMap 不能放密碼,修改設定後也要確認 Pod 是否需要重新啟動。
延伸問題
Q1:既然所有值都可以寫在 values.yaml,為什麼還要 ConfigMap?
因為 values.yaml 只負責提供 Helm 渲染所需的值,它不是 Pod 能直接讀取的 Kubernetes 資源。若程式在執行期需要透過環境變數或檔案取得設定,就要把值渲染到 Deployment,或建立 ConfigMap/Secret 再讓 Pod 引用。
Q2:ConfigMap 能不能不經過 Helm 建立?
可以。ConfigMap 是 Kubernetes 原生 Resource,可以直接用 kubectl apply -f configmap.yaml 建立。使用 Helm 的好處是可以共用模板,並透過不同 values 產生不同環境的結果。
Q3:ConfigMap 更新後為什麼還要 rollout?
如果 ConfigMap 被注入成環境變數,程序啟動時就已取得固定值,不會因 ConfigMap 修改而改變。重新 rollout 可以建立新 Pod,讓程式讀取最新設定。
Q4:values-production.yaml 和 ConfigMap 又有什麼差別?
values-production.yaml 只是 production 環境覆寫 Helm 預設值的輸入檔;它可以影響 Deployment、Service、Ingress、ConfigMap 等任何模板。ConfigMap 則只是其中一種最後部署到 Kubernetes 的資源。
最後的判斷口訣
先問兩個問題:
- 這是「如何部署」還是「程式執行時要讀取的設定」?前者通常直接由 values 渲染到 Deployment 等資源;後者再評估 ConfigMap。
- 內容是不是機密?如果是,就不能使用 ConfigMap,應改用 Secret 或公司的 Secret 管理方案。