📘 Day 15:存储综合实战

🎯 今日目标

  • 为有状态应用配置完整存储方案
  • ConfigMap → Secret → PVC 联动配置
  • 排查存储相关故障

🧠 理论精讲(10 分钟)

存储方案决策树

应用需要存储配置?
├── 非敏感配置 → ConfigMap
├── 敏感配置(密码/证书)→ Secret
└── 持久数据?
    ├── 临时数据(Pod 删了就丢)→ emptyDir
    ├── 节点级数据(日志)→ hostPath
    └── 持久数据(数据库)→ PVC(+StorageClass 动态供给)

🔧 动手实操(150 分钟)

练习 15.1:WordPress 风格有状态应用

kubectl create ns wp-demo

# 1. 配置管理:ConfigMap
kubectl create configmap wp-config -n wp-demo \
  --from-literal=WORDPRESS_DB_HOST=mysql-svc \
  --from-literal=WORDPRESS_DB_USER=wp_user \
  --from-literal=WORDPRESS_DB_NAME=wordpress \
  --from-literal=WORDPRESS_DEBUG=false

# 2. 密钥管理:Secret
kubectl create secret generic wp-secrets -n wp-demo \
  --from-literal=WORDPRESS_DB_PASSWORD='W0rdPr3ss!' \
  --from-literal=MYSQL_ROOT_PASSWORD='R00tP@ss!'

# 3. 数据库 StatefulSet + PVC
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: mysql-svc
  namespace: wp-demo
spec:
  clusterIP: None
  selector:
    app: mysql
  ports:
  - port: 3306
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
  namespace: wp-demo
spec:
  serviceName: mysql-svc
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        envFrom:
        - secretRef:
            name: wp-secrets
        ports:
        - containerPort: 3306
        volumeMounts:
        - name: mysql-data
          mountPath: /var/lib/mysql
  volumeClaimTemplates:
  - metadata:
      name: mysql-data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 2Gi
EOF

# 4. WordPress Deployment
cat <<'EOF' | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
  namespace: wp-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wordpress
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      containers:
      - name: wordpress
        image: wordpress:6-apache
        envFrom:
        - configMapRef:
            name: wp-config
        env:
        - name: WORDPRESS_DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: wp-secrets
              key: WORDPRESS_DB_PASSWORD
        ports:
        - containerPort: 80
        volumeMounts:
        - name: wp-content
          mountPath: /var/www/html/wp-content
      volumes:
      - name: wp-content
        persistentVolumeClaim:
          claimName: wp-content-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: wp-content-pvc
  namespace: wp-demo
spec:
  accessModes: ["ReadWriteOnce"]
  resources:
    requests:
      storage: 1Gi
EOF

# 5. 服务暴露
kubectl expose deploy wordpress -n wp-demo --port=80
kubectl get all -n wp-demo

练习 15.2:存储故障排查

# 故障 1:PVC 绑定不上
kubectl get pvc -n wp-demo
# 如果 Pending,排查:
kubectl describe pvc wp-content-pvc -n wp-demo
# 看 Events → 是否有可用的 PV 或 StorageClass?

# 故障 2:Pod 无法挂载 Volume
kubectl get pod -n wp-demo
kubectl describe pod <pod-name> -n wp-demo | grep -A5 Events
# 常见错误:mount failed、permission denied

# 故障 3:ConfigMap 环境变量未注入
kubectl exec <pod> -n wp-demo -- env | grep WORDPRESS
# 如果没有 → 检查 envFrom 配置

# 故障 4:Secret 值不正确
kubectl get secret wp-secrets -n wp-demo -o jsonpath='{.data.WORDPRESS_DB_PASSWORD}' | base64 -d
# 验证解码后的值

🏆 赛题模拟(40 分钟)

⚠️ 严格限时 40 分钟

题目:完整应用配置与存储方案

【操作要求】创建命名空间 cms-app

1. ConfigMap cms-config:
   - SITE_NAME="My CMS"
   - DB_HOST=cms-db-svc
   - CACHE_TTL=3600

2. Secret cms-secrets:
   - DB_PASS=db-secret-789
   - ADMIN_PASS=admin-secret-456
   - JWT_SECRET=jwt-key-012

3. StatefulSet cms-db(2 副本,mysql:8.0):
   - 使用 cms-secrets 注入数据库密码
   - volumeClaimTemplates 创建 2Gi PVC
   - Headless Service cms-db-svc

4. Deployment cms-web(3 副本,nginx:alpine):
   - 用 envFrom 注入 cms-config
   - 用 valueFrom 注入 DB_PASS(命名 DATABASE_PASSWORD)
   - 挂载 PVC cms-web-data(1Gi)到 /usr/share/nginx/html/uploads
   - livenessProbe + readinessProbe

5. 验证:
   - 所有 PVC 绑定成功
   - Pod 环境变量包含 SITE_NAME、DB_HOST、DATABASE_PASSWORD
   - cms-db-0 和 cms-db-1 有独立 PVC
   - 向 cms-web 的 PVC 写入测试文件

【评分标准】
- ConfigMap/Secret 创建正确(15 分)
- StatefulSet + PVC 正确(30 分)
- Deployment 配置注入正确(30 分)
- PVC 独立验证(15 分)
- 验证全面(10 分)

🧹 环境清理

kubectl delete ns wp-demo cms-app

📋 命令速查

命令功能注解
kubectl get pv,pvc,sc存储资源一览同时查看 PV/PVC/SC 的绑定和供给关系
kubectl get pvc -A --field-selector=status.phase=Pending查找所有未绑定的 PVCPending 意味着没有匹配的 PV 或 SC 供给失败
kubectl get events --field-selector=reason=ProvisioningFailed查看供给失败事件动态供给失败时的排错入口
kubectl exec <pod> -- df -h | grep /mnt验证存储挂载容量确认 PV 正确挂载且容量匹配
kubectl exec <pod> -- cat /proc/mounts | grep /mnt查看挂载详情文件系统类型、挂载选项
kubectl exec <pod> -- touch /mnt/data/write-test验证存储可写ReadWriteOnce 模式下测试写权限
kubectl exec <pod> -- rm /mnt/data/write-test验证存储可删除ReadWriteMany 多 Pod 同时操作验证
kubectl diff -f manifest.yaml预览修改差异综合实战中修改 YAML 后先 diff 确认变更
kubectl apply --server-side -f manifest.yaml服务端 Apply处理大文件或复杂 CRD 时的备选方案

📚 参考来源

来源链接 / 说明
Kubernetes 官方:存储最佳实践https://kubernetes.io/docs/concepts/storage/
Kubernetes 官方:调试 PVChttps://kubernetes.io/docs/tasks/debug/debug-application/
Kubernetes 官方:StatefulSet 与存储https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#using-statefulsets
Kubernetes 存储 SIGhttps://github.com/kubernetes/community/tree/master/sig-storage