Day 15 - 存储综合实战

📘 Day 15:存储综合实战

🎯 今日目标

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

🧠 理论精讲(10 分钟)

存储方案决策树

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

🔧 动手实操(150 分钟)

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 故障 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 分钟

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
【操作要求】创建命名空间 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 分)

🧹 环境清理

1
kubectl delete ns wp-demo cms-app

📋 命令速查

命令 功能 注解
kubectl get pv,pvc,sc 存储资源一览 同时查看 PV/PVC/SC 的绑定和供给关系
kubectl get pvc -A --field-selector=status.phase=Pending 查找所有未绑定的 PVC Pending 意味着没有匹配的 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 官方:调试 PVC https://kubernetes.io/docs/tasks/debug/debug-application/
Kubernetes 官方:StatefulSet 与存储 https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#using-statefulsets
Kubernetes 存储 SIG https://github.com/kubernetes/community/tree/master/sig-storage