关系
```
StorageClass → 定义存储类型
PVC → Pod 申请存储
PV → 实际存储卷
```
PVC + Deployment 示例
```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-data-pvc
namespace: prod
spec:
accessModes: ReadWriteOnce
storageClassName: nfs-client # 改成你的 SC
resources:
requests:
storage: 20Gi
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
namespace: prod
spec:
replicas: 1 # RWO 只能单副本
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
volumeMounts:
- name: data
mountPath: /var/lib/mysql
volumes:
- name: data
persistentVolumeClaim:
claimName: mysql-data-pvc
```
StatefulSet(推荐有状态应用)
```yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
namespace: cache
spec:
serviceName: redis
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7.2
command: "redis-server", "--appendonly", "yes"
volumeMounts:
- name: data
mountPath: /data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ReadWriteOnce
storageClassName: nfs-client
resources:
requests:
storage: 5Gi
```
自动生成 `data-redis-0` PVC。
accessModes
| 模式 | 说明 |
|------|------|
| ReadWriteOnce | 单节点读写(最常用) |
| ReadWriteMany | 多节点读写(NFS 支持) |
PVC Pending 排查
```bash
kubectl describe pvc <name> -n <ns>
kubectl get storageclass
```
| Events | 处理 |
|--------|------|
| storageclass not found | SC 名称写错 |
| no persistent volumes | 检查 Provisioner / NFS |
| waiting for first consumer | 先创建使用 PVC 的 Pod |
踩坑
-
**Deployment replicas>1 + RWO** → 多 Pod 抢一个卷,用 StatefulSet
-
**删 PVC 数据丢** → 生产用 `reclaimPolicy: Retain`
-
**hostPath 别上生产** → 用 NFS / 云盘
-
**NFS 权限不足** → exports 加 `no_root_squash`,或 initContainer chown
常用命令
```bash
kubectl get pv,pvc -A
kubectl patch pvc <name> -n <ns> -p '{"spec":{"resources":{"requests":{"storage":"50Gi"}}}}' # 扩容
```