上次線上發佈時,運維同事不小心把測試環境的數據庫密碼打包進了生產鏡像,導致服務啓動失敗。排查後發現,密碼直接硬編碼在配置文件裏,每次環境切換都要手動修改。後來用Kubernetes的Secret存儲密碼,ConfigMap管理普通配置,不僅解決了環境配置混亂的問題,還徹底杜絕了敏感信息泄露的風險。
在K8s集羣中,應用的配置管理是個繞不開的話題。ConfigMap和Secret是K8s提供的兩種配置管理機制,前者適合存儲普通配置(如端口、路徑),後者專門處理敏感信息(如密碼、令牌)。本文結合實際運維場景,詳解這兩種資源的使用方式、區別以及最佳實踐。
一、ConfigMap:非敏感配置的統一管理
ConfigMap用於存儲非敏感的配置數據,它可以將配置與鏡像解耦,讓同一個鏡像能在不同環境中運行。
1. 創建ConfigMap
ConfigMap有兩種創建方式:通過YAML文件聲明,或從文件/目錄直接生成。
方式一:YAML定義
創建app-config.yaml:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config # ConfigMap名稱
data:
# 鍵值對形式的配置
app.port: "8080"
app.log.level: "INFO"
# 配置文件內容
application.properties: |
spring.datasource.url=jdbc:mysql://db:3306/appdb
spring.cache.enabled=true
執行創建命令:
kubectl apply -f app-config.yaml
方式二:從文件生成
如果已有配置文件(如app.properties),可以直接生成ConfigMap:
# 從文件創建,鍵名為文件名,值為文件內容
kubectl create configmap app-config --from-file=app.properties
查看創建的ConfigMap:
kubectl get configmap app-config -o yaml
2. 在Pod中使用ConfigMap
ConfigMap可以通過環境變量或文件掛載兩種方式注入Pod。
方式一:作為環境變量
適合需要少量配置的場景:
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: myapp:v1
env:
- name: APP_PORT # 環境變量名
valueFrom:
configMapKeyRef:
name: app-config # 引用的ConfigMap名稱
key: app.port # 引用的鍵
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: app.log.level
方式二:作為文件掛載
適合配置文件較多的場景(如Spring Boot的application.properties):
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: myapp:v1
volumeMounts:
- name: config-volume # 掛載卷名稱
mountPath: /app/config # 容器內掛載路徑
volumes:
- name: config-volume
configMap:
name: app-config # 關聯的ConfigMap
掛載後,ConfigMap中的application.properties會以文件形式出現在容器的/app/config目錄下,應用可以直接讀取。
二、Secret:敏感信息的安全存儲
Secret用於存儲敏感信息,它的實現機制與ConfigMap類似,但數據會經過Base64編碼(注意:這不是加密,只是防止明文泄露)。
1. 創建Secret
方式一:YAML定義
創建app-secret.yaml,注意值需要Base64編碼:
apiVersion: v1
kind: Secret
metadata:
name: app-secret
type: Opaque # 通用類型
data:
db.username: YWRtaW4= # "admin"的Base64編碼
db.password: cGFzc3dvcmQxMjM= # "password123"的Base64編碼
生成Base64編碼的命令:
echo -n "admin" | base64 # 輸出 YWRtaW4=
方式二:從字面量創建
無需手動編碼,直接指定鍵值對:
kubectl create secret generic app-secret \
--from-literal=db.username=admin \
--from-literal=db.password=password123
查看Secret(默認隱藏值,需加-o yaml顯示):
kubectl get secret app-secret -o yaml
2. 在Pod中使用Secret
Secret的使用方式與ConfigMap類似,支持環境變量和文件掛載。
方式一:作為環境變量
數據庫密碼等配置常用這種方式:
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: myapp:v1
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: app-secret
key: db.username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-secret
key: db.password
方式二:作為文件掛載
適合證書類文件(如SSL證書):
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: myapp:v1
volumeMounts:
- name: secret-volume
mountPath: /app/secret
readOnly: true # 敏感文件建議設為只讀
volumes:
- name: secret-volume
secret:
secretName: app-secret
掛載後,容器內/app/secret目錄下會生成db.username和db.password文件,內容為對應的值。
三、ConfigMap與Secret的核心區別
|
特性 |
ConfigMap |
Secret |
|
用途 |
存儲非敏感配置(端口、路徑) |
存儲敏感信息(密碼、證書) |
|
數據處理 |
明文存儲 |
Base64編碼(非加密) |
|
大小限制 |
無明確限制(建議不超過1MB) |
不超過1MB |
|
訪問控制 |
無特殊權限控制 |
可通過RBAC嚴格控制訪問權限 |
|
加密支持 |
不支持 |
支持靜態加密(需配置加密配置) |
四、最佳實踐與避坑指南
1. 合理拆分配置
- 按環境拆分:
app-config-dev、app-config-prod,避免不同環境配置混雜; - 按功能拆分:
db-config、log-config,便於單獨管理和複用。
2. 敏感信息處理
- 不要把Secret的YAML文件提交到代碼倉庫(即使值是Base64編碼,也能輕易解碼);
- 生產環境建議開啓K8s的靜態加密功能,確保Secret在etcd中存儲時是加密的:
# 啓用靜態加密(需在kube-apiserver配置)
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources: ["secrets"]
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-32-byte-key>
- identity: {}
3. 配置更新策略
- ConfigMap/Secret更新後,通過環境變量注入的配置不會自動生效,需要重啓Pod;
- 通過文件掛載的配置會在約1分鐘內自動更新(應用需支持熱加載配置,如Spring Cloud Config的
@RefreshScope)。
手動觸發更新的小技巧:
# 滾動更新Deployment,使配置生效
kubectl rollout restart deployment app-deploy
4. 權限控制
- 限制Secret的訪問權限,通過RBAC只允許必要的Pod和用户訪問:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["app-secret"]
verbs: ["get", "watch", "list"]
5. 避免大型配置
ConfigMap和Secret不宜存儲過大的數據(如超過1MB),否則會影響K8s API的性能。大型配置文件建議用單獨的存儲服務(如NFS、對象存儲),再通過ConfigMap存儲文件路徑。
五、適用場景總結
- ConfigMap:應用端口、日誌級別、數據庫連接地址(不含密碼)、feature開關等非敏感配置;
- Secret:數據庫密碼、API令牌、SSL證書、SSH密鑰等需要保密的信息。
兩者結合使用,可以實現配置的集中管理、環境隔離和安全存儲,是K8s應用部署的基礎實踐。
總結
ConfigMap和Secret是K8s配置管理的兩大基石,它們通過"配置與鏡像分離"的思想,解決了多環境部署的配置混亂問題。ConfigMap適合管理普通配置,Secret則專注于敏感信息,雖然Secret的Base64編碼不是加密,但配合RBAC權限控制和靜態加密,能有效保障敏感數據的安全。
實際使用中,要注意合理拆分配置、控制訪問權限、處理配置更新,避免將敏感信息放入ConfigMap或代碼倉庫。掌握這兩個資源的使用,能讓你的K8s應用部署更規範、更安全、更易於維護。