ConfigMap 是 Kubernetes (K8s) 中用來儲存非機密性設定資料的 API 物件。它的核心價值在於將設定與應用程式映像檔 (Image) 分離。
想像一下,如果您的資料庫連線位址、功能開關 (feature flags) 或環境變數都寫死在程式碼或 Dockerfile 中,那麼每次需要變更設定時,您都必須重新建置、推送並部署新的映像檔。這不僅效率低下,也使得同一個映像檔無法輕易地在不同環境(如開發、測試、生產)中使用。
ConfigMap 解決了這個問題。您可以將設定資料以 key-value 的形式儲存在 ConfigMap 中,然後在 Pod 啟動時,以環境變數或掛載成檔案的方式動態地注入到容器內。
注意:ConfigMap 不適合用來儲存敏感資訊(如密碼、API 金鑰),因為它的內容是以明文形式儲存的。對於敏感資訊,請使用 Secret。
ConfigMap 的 data
欄位中儲存了 key-value 形式的設定。其中,key 可以是簡單的屬性,也可以是檔名;value 則一律是字串,並支援多行內容。
apiVersion: v1
kind: ConfigMap
metadata:
name: game-demo
namespace: default
data:
# 1. 類似屬性的 key-value
player_initial_lives: "3"
ui_properties_file_name: "user-interface.properties"
# 2. 類似檔案的 key-value (key 是檔名,value 是檔案內容)
game.properties: |
enemy.types=aliens,monsters
player.maximum-lives=5
user-interface.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
您也可以使用 kubectl create configmap
指令從檔案或字面值來建立 ConfigMap。
有四種主要的方式可以將 ConfigMap 的資料注入到容器中:
您可以將 ConfigMap 中的特定 key 的值,注入為容器的一個環境變數。
# ... spec.containers ...
env:
- name: PLAYER_LIVES
valueFrom:
configMapKeyRef:
name: game-demo # ConfigMap 的名稱
key: player_initial_lives # 要引用的 key
一旦設定被注入為環境變數,您就可以在容器的 command
或 args
中引用它。
# ... spec.containers ...
command: [ "/bin/sh", "-c" ]
args:
- echo "Initial lives: $(PLAYER_LIVES)"
注意:在 K8s manifest 中引用環境變數的語法是
$(VAR_NAME)
。
這是最常用也最靈活的方式。您可以將 ConfigMap 中的一個或多個 key 掛載成一個目錄下的檔案。
# ... spec.containers ...
volumeMounts:
- name: config-volume
mountPath: /etc/config
# ... spec ...
volumes:
- name: config-volume
configMap:
name: game-demo
# items 欄位可以選擇性地只掛載特定的 key
items:
- key: "game.properties"
path: "game.properties" # path 是掛載後的檔名
- key: "user-interface.properties"
path: "ui.properties" # 可以自訂檔名
如果省略 .items
欄位,則 data
中的每一個 key 都會成為掛載目錄下的一個檔案。
使用 envFrom
可以將 ConfigMap 中所有的 key-value 一次性地注入為容器的環境變數。
# ... spec.containers ...
envFrom:
- configMapRef:
name: game-demo
這是 ConfigMap 最重要也最容易混淆的特性:
使用方式 | 是否會自動更新? | 說明 |
---|---|---|
掛載為 Volume (不使用 subPath ) |
是 | 當 ConfigMap 變更後,掛載到 Pod 內的檔案內容會最終被更新。kubelet 會定期同步,但這個過程有延遲。 |
注入為環境變數 | 否 | 環境變數是在容器啟動時注入的,是靜態的。如果 ConfigMap 變更,必須重啟 Pod 才能讀取到新值。 |
掛載為 Volume (使用 subPath ) |
否 | 使用 subPath 掛載的檔案不會自動更新。 |
最佳實踐:為了確保設定變更的一致性,推薦的做法是採用滾動更新 (Rolling Update) 的方式來部署設定變更,而不是依賴 ConfigMap 的自動更新特性。
對於不希望被意外修改的重要設定,您可以將 ConfigMap 設為 immutable
(不可變)。
apiVersion: v1
kind: ConfigMap
metadata:
name: my-immutable-config
data:
# ...
immutable: true
這樣做有兩個好處:
kubelet
不再需要監控 (watch) 這個 ConfigMap 的變化,從而減輕了 kube-apiserver
的負載。總結來說,ConfigMap 是 K8s 中實現「設定與程式碼分離」這一重要原則的關鍵工具,它讓您的應用程式部署變得更加靈活和標準化。