10.4 儲存與配置:PV / PVC / StorageClass / ConfigMap / Secret#
容器是「無狀態的蟬」,蛻皮(重建)就失憶。本節給它「持久的殼」與「外掛的大腦」。
有狀態的煩惱#
8.2 節的 Docker Volume 只活在單機。K8s 裡 Pod 隨時漂移到別台 Node,MySQL 資料怎麼辦?答案是三層抽象:
flowchart LR
POD[Pod] -->|認領| PVC[PVC<br/>我要 20Gi 快盤]
PVC -->|綁定| PV[PV<br/>雲盤 / NAS 實例]
SC[StorageClass<br/>快盤模板] -.動態建立.-> PV- PV(PersistentVolume):真實儲存,集群管理員預建或動態建立。
- PVC(PersistentVolumeClaim):業務的「申請單」,只說要多大、多快。
- StorageClass:儲存模板,定義「快盤 / 慢盤 / NAS」,實現動態供給。
動態供給實戰:MySQL 掛盤#
# mysql-pvc.yaml + deploy,可直接 apply
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-data
spec:
accessModes: [ReadWriteOnce]
storageClassName: alicloud-disk-essd # ACK / EKS 各有對應,minikube 用 standard
resources:
requests: { storage: 20Gi }
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
replicas: 1
selector:
matchLabels: { app: mysql }
template:
metadata:
labels: { app: mysql }
spec:
containers:
- name: mysql
image: mysql:8.0
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef: { name: mysql-pass, key: password }
volumeMounts:
- name: data
mountPath: /var/lib/mysql
volumes:
- name: data
persistentVolumeClaim: { claimName: mysql-data }
kubectl apply -f mysql-pvc.yaml
kubectl get pvc,pv -w # 觀察 Bound
kubectl get sc # 看集群有哪些 StorageClass
Pod 重建、漂移,資料跟著雲盤走。這正是 4.x 節分庫分表後,資料庫高可用的容器化答案。
ConfigMap:呼應 5.3 節 Zookeeper#
5.3 節用 Zookeeper / Nacos 存配置,K8s 原生答案是 ConfigMap:非敏感 KV,掛載為檔案或環境變數,改配置不必重打映像。
# config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: order-conf
data:
application.properties: |
db.url=jdbc:mysql://mysql:3306/taobao
cache.ttl=300
feature.canary=true
掛載方式:把 order-conf 作為 Volume 掛到 /app/config,或以環境變數注入,改配置不必重打映像。
kubectl apply -f config.yaml
kubectl get cm order-conf -o yaml
# 改配置後滾動重啟生效(原生不自動熱載,需配合 Reloader 或 Nacos)
kubectl create configmap order-conf --from-file=application.properties --dry-run=client -o yaml | kubectl apply -f -
kubectl rollout restart deployment/order
| Zookeeper / Nacos(5.3 節) | ConfigMap |
|---|---|
| 支援監聽熱更新、服務發現 | 需重啟或外掛,定位是「靜態配置」 |
| 需額外部署集群 | K8s 內建,etcd 保障 |
| 適合高頻動態開關 | 適合啟動期配置、檔案掛載 |
生產常見組合:ConfigMap 存靜態配置 + Nacos 存需熱更新的開關。
Secret:別把密碼寫進 YAML 明文#
# secret.yaml(data 需 base64,僅防誤看不防盜)
apiVersion: v1
kind: Secret
metadata:
name: mysql-pass
type: Opaque
data:
password: VGFvQmFvMTIzIQ== # echo -n 'TaoBao123!' | base64
kubectl apply -f secret.yaml
# 更安全:直接從字面量建立,不留明文檔
kubectl create secret generic mysql-pass --from-literal=password='TaoBao123!' --dry-run=client -o yaml | kubectl apply -f -
kubectl get secret mysql-pass -o jsonpath='{.data.password}' | base64 -d
生產鐵律:開 RBAC + etcd 加密 + 外部 KMS(Vault / 阿里 KMS),Git 裡只存 SealedSecret 或 ExternalSecret 引用。
本章小結#
- PV 是實體盤,PVC 是申請單,StorageClass 是動態模板。
- 資料跟盤走,Pod 漂移不丟資料,有狀態服務才能容器化。
- ConfigMap 是 K8s 版配置中心(靜態),呼應 5.3 節 Zookeeper。
- Secret 存敏感資訊,base64 只是編碼,生產必須加密 + RBAC。
- 有了儲存與配置,下一章解決「掛了誰來救、忙了誰來擴」。
想一想#
- PV / PVC / StorageClass 三者各解決什麼問題?為什麼不讓 Pod 直接掛雲盤?
- ConfigMap 與 Zookeeper / Nacos 各適合什麼配置?熱更新場景該選誰?
- Secret 的 base64 能防誰、不能防誰?生產環境還需要哪三道防線?