前幾天的 Deployment YAML 裡,環境變數是直接寫死在 env 裡面的。
這樣有個問題:設定和部署設定混在一起。開發環境、測試環境、生產環境的設定不同,但 YAML 卻是同一份,每次換環境都要手動改 YAML,很容易出錯。
ConfigMap 是 K8s 用來儲存非敏感設定資料的資源,把設定從 Pod 的定義裡分離出來,讓同一份 Deployment YAML 可以在不同環境下搭配不同的 ConfigMap 使用。
ConfigMap 的資料是明文儲存的,密碼、API Key 這類機密資訊不應該放這裡,那是 Secret 的職責。
apiVersion: v1
kind: ConfigMap
metadata:
name: todo-api-config
data:
APP_ENV: "development"
LOG_LEVEL: "info"
結構很簡單:data 裡面放 key-value,key 是設定名稱,value 是設定值。
DATABASE_URL含有資料庫密碼,不適合放在 ConfigMap。Day 11 會用 Secret 來處理,這裡先不放。
spec:
containers:
- name: api
image: yourname/todo-app-api:v1.0.0
envFrom:
- configMapRef:
name: todo-api-config # 把整個 ConfigMap 的 key-value 全部變成環境變數
或是只取特定的 key:
env:
- name: APP_ENV
valueFrom:
configMapKeyRef:
name: todo-api-config
key: APP_ENV
spec:
containers:
- name: api
volumeMounts:
- name: config-volume
mountPath: /app/config # ConfigMap 的內容會出現在這個路徑下
volumes:
- name: config-volume
configMap:
name: todo-api-config
ConfigMap 的每個 key 會變成一個獨立的檔案,value 是檔案內容。適合應用程式用設定檔而不是環境變數的情境,例如 nginx 的 nginx.conf。
大多數情況用環境變數注入就夠了,掛載成檔案適合需要完整設定檔的服務。
今天目標:建立 ConfigMap 儲存 todo-api 的環境變數,更新 Deployment 改用 ConfigMap 注入設定,並驗證更新 ConfigMap 後重啟 Pod 能正確套用新值。
/Todo-App/k8s 目錄下,建立 todo-api-configmap.yaml:apiVersion: v1
kind: ConfigMap
metadata:
name: todo-api-config
data:
APP_ENV: "development"
LOG_LEVEL: "info"
kubectl apply -f todo-api-configmap.yaml
kubectl get configmaps

3. 看 ConfigMap 的內容:
kubectl describe configmap todo-api-config

todo-api-deployment.yaml 加入 envFrom:
apiVersion: apps/v1
kind: Deployment
metadata:
name: todo-api
spec:
replicas: 2
selector:
matchLabels:
app: todo-api
template:
metadata:
labels:
app: todo-api
tier: backend
spec:
containers:
- name: api
image: yourname/todo-app-api:v1.0.0
ports:
- containerPort: 8000
envFrom:
- configMapRef:
name: todo-api-config # 注入 APP_ENV、LOG_LEVEL
env:
- name: DATABASE_URL
value: "mysql+pymysql://user:password@mysql-service:3306/tododb" # 暫時維持寫死,Day 11 再抽出來
kubectl apply -f todo-api-deployment.yaml
進到 Pod 裡面確認:
# 取得其中一個 Pod 名稱
kubectl get pods
# 進到 Pod 裡面
kubectl exec -it <pod-name> -- env | grep -E "APP_ENV|LOG_LEVEL"
你會看到:

假設要把 LOG_LEVEL 改成 debug:
kubectl edit configmap todo-api-config
這會開啟編輯器,直接修改存檔。
注意:更新 ConfigMap 不會自動重啟 Pod。環境變數是在 Pod 啟動時注入的,ConfigMap 更新後需要手動重啟 Pod 才會生效:
kubectl rollout restart deployment/todo-api
你會看到 log_level被更改為 debug :
大小限制:ConfigMap 的資料總量不能超過 1MB,適合放設定值,不適合放大型文件或二進位資料。
不會自動重啟 Pod:如上面提到的,ConfigMap 更新後 Pod 不會自動感知,需要手動重啟。如果你的服務需要即時感知設定變更,可以考慮用掛載成檔案的方式——掛載成檔案的 ConfigMap 更新後,檔案內容會在幾秒到一分鐘內自動同步,不需要重啟 Pod(但應用程式要自己實作重新讀取設定的邏輯)。
不適合放敏感資料:ConfigMap 是明文儲存,任何有 kubectl get configmap 權限的人都能看到內容。密碼、Token、憑證要用 Secret(Day 11)。
今天學了 ConfigMap,把設定從 Deployment YAML 裡抽出來:
envFrom 注入整個 ConfigMap,valueFrom 取特定 key明天會學 Secret,處理密碼和 API Key 這類不能明文儲存的敏感資料 !