03-存储管理
Kubernetes PV/PVC、StorageClass、StatefulSet 状态管理全体系
学习目标
通过本模块学习,你将掌握:
- Kubernetes 存储体系五层抽象
- Volume 类型和生命周期管理
- PV/PVC 绑定机制和回收策略
- StorageClass 动态卷分配
- StatefulSet 有状态应用部署
- 存储故障排查和最佳实践
一、存储体系总览
核心设计理念
Kubernetes 存储的核心思想是:Pod 是临时的,但数据可以是持久的。
五层存储抽象
Pod → Volume → PVC → PV → StorageClass → 真实存储
│ │ │ │ │ │
│ │ │ │ │ ├─ NFS
│ │ │ │ │ ├─ Ceph
│ │ │ │ │ ├─ 云盘
│ │ │ │ │ └─ 本地盘
│ │ │ │ │
│ │ │ │ └─ 动态分配策略
│ │ │ │
│ │ │ └─ 存储资源池
│ │ │
│ │ └─ 存储申请单
│ │
│ └─ 挂载点
│
└─ 容器访问点
存储层级对比
层级 | 名称 | 功能 | 生命周期 |
---|---|---|---|
Volume | 最基础挂载点 | Pod 内数据访问 | Pod 生命周期 |
PV | 持久卷 | 存储资源池 | 独立于 Pod |
PVC | 持久卷声明 | 存储申请单 | 绑定 PV 后独立 |
StorageClass | 存储类 | 动态分配策略 | 集群级别 |
CSI | 容器存储接口 | 驱动标准 | 插件级别 |
二、Volume 类型详解
2.1 emptyDir(临时存储)
特点:Pod 生命周期内有效,重启即清空
apiVersion: v1
kind: Pod
metadata:
name: emptydir-demo
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: cache
mountPath: /tmp/cache
volumes:
- name: cache
emptyDir: {}
emptyDir 配置选项
volumes:
- name: cache
emptyDir:
sizeLimit: 1Gi # 大小限制
medium: Memory # 使用内存(tmpfs)
2.2 hostPath(宿主机存储)
特点:直接挂载宿主机目录
apiVersion: v1
kind: Pod
metadata:
name: hostpath-demo
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: logs
mountPath: /var/log/nginx
volumes:
- name: logs
hostPath:
path: /var/log/nginx
type: DirectoryOrCreate # 目录不存在则创建
hostPath 类型
volumes:
- name: data
hostPath:
path: /data
type: DirectoryOrCreate # 目录或创建
# type: Directory # 必须存在目录
# type: FileOrCreate # 文件或创建
# type: File # 必须存在文件
# type: Socket # Unix socket
# type: CharDevice # 字符设备
# type: BlockDevice # 块设备
️ 风险提示:hostPath 存在数据丢失风险,节点调度变化会导致数据丢失。
2.3 其他 Volume 类型
configMap
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
config.yaml: |
database:
host: localhost
port: 3306
---
apiVersion: v1
kind: Pod
metadata:
name: configmap-demo
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: config
mountPath: /etc/config
volumes:
- name: config
configMap:
name: app-config
secret
apiVersion: v1
kind: Secret
metadata:
name: app-secret
type: Opaque
data:
password: cGFzc3dvcmQ= # base64 编码
---
apiVersion: v1
kind: Pod
metadata:
name: secret-demo
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: secret
mountPath: /etc/secret
volumes:
- name: secret
secret:
secretName: app-secret
三、PersistentVolume(PV)
3.1 PV 核心概念
PV 是集群管理员预先配置的存储资源池,独立于 Pod 生命周期。
3.2 PV 配置示例
NFS PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
nfs:
path: /mnt/data
server: 192.168.1.10
本地存储 PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-local
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
local:
path: /data
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node1
云存储 PV(AWS EBS)
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-ebs
spec:
capacity:
storage: 20Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
awsElasticBlockStore:
volumeID: vol-12345678
fsType: ext4
3.3 访问模式(Access Modes)
模式 | 说明 | 适用场景 |
---|---|---|
ReadWriteOnce (RWO) | 单节点可读写 | 数据库、单实例应用 |
ReadOnlyMany (ROX) | 多节点只读 | 配置文件、只读数据 |
ReadWriteMany (RWX) | 多节点可读写 | 共享存储、文件系统 |
3.4 回收策略(Reclaim Policy)
策略 | 行为 | 适用场景 |
---|---|---|
Retain | 删除 PVC 不删除 PV 数据 | 重要数据,手动管理 |
Delete | 删除 PVC 时同时清理后端存储 | 动态卷,自动清理 |
Recycle | 删除后清空目录(已废弃) | 临时用途(不推荐) |
四、PersistentVolumeClaim(PVC)
4.1 PVC 核心概念
PVC 是用户对存储资源的申请单,系统会自动匹配合适的 PV。
4.2 PVC 配置示例
基本 PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-demo
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: "" # 空字符串表示使用默认 StorageClass
指定 StorageClass 的 PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-sc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
storageClassName: nfs-sc
绑定特定 PV 的 PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-specific
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
volumeName: pv-nfs # 指定特定 PV
4.3 PVC 绑定机制
绑定条件
- 存储容量:PVC 请求 ≤ PV 容量
- 访问模式:PVC 访问模式 ⊆ PV 访问模式
- StorageClass:PVC 和 PV 的 StorageClass 匹配
- 标签选择器:PVC 的 selector 匹配 PV 标签
绑定过程
graph TD
A[PVC 创建] --> B[查找匹配 PV]
B --> C{找到匹配 PV?}
C -->|是| D[绑定 PV]
C -->|否| E[等待匹配 PV]
D --> F[PVC 状态变为 Bound]
E --> G[PVC 状态保持 Pending]
️ 五、StorageClass(动态卷分配)
5.1 StorageClass 核心概念
StorageClass 定义了动态卷分配的策略,无需管理员手动创建 PV。
5.2 StorageClass 配置示例
NFS StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-sc
provisioner: example.com/nfs
parameters:
server: nfs-server.example.com
path: /mnt/data
mountOptions: "nfsvers=4"
reclaimPolicy: Delete
allowVolumeExpansion: true
volumeBindingMode: Immediate
云存储 StorageClass(AWS EBS)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ebs-sc
provisioner: ebs.csi.aws.com
parameters:
type: gp3
iops: "3000"
throughput: "125"
encrypted: "true"
reclaimPolicy: Delete
allowVolumeExpansion: true
volumeBindingMode: WaitForFirstConsumer
本地存储 StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
5.3 StorageClass 参数说明
关键参数
- provisioner:卷提供者
- reclaimPolicy:回收策略
- allowVolumeExpansion:是否允许扩容
- volumeBindingMode:绑定模式
Immediate
:立即绑定WaitForFirstConsumer
:等待第一个消费者
5.4 动态卷分配流程
graph TD
A[PVC 创建] --> B[匹配 StorageClass]
B --> C[调用 Provisioner]
C --> D[创建后端存储]
D --> E[创建 PV]
E --> F[绑定 PVC 和 PV]
F --> G[Pod 使用存储]
️ 六、StatefulSet(有状态应用)
6.1 StatefulSet 核心特性
StatefulSet 为有状态应用提供:
- 稳定标识:Pod 名称固定(如 mysql-0、mysql-1)
- 有序部署:从 0 → N 顺序启动
- 有序删除:从 N → 0 顺序销毁
- 持久卷绑定:Pod 与 PVC 一一绑定
6.2 StatefulSet 配置示例
MySQL StatefulSet
apiVersion: v1
kind: Service
metadata:
name: mysql
namespace: db
spec:
clusterIP: None # Headless Service
selector:
app: mysql
ports:
- port: 3306
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
namespace: db
spec:
serviceName: mysql
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: "root123"
volumeMounts:
- name: data
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 5Gi
storageClassName: standard
Redis StatefulSet
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: cache
spec:
clusterIP: None
selector:
app: redis
ports:
- port: 6379
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
namespace: cache
spec:
serviceName: redis
replicas: 3
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7
ports:
- containerPort: 6379
command:
- "redis-server"
- "--appendonly"
- "yes"
volumeMounts:
- name: data
mountPath: /data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 2Gi
storageClassName: standard
6.3 StatefulSet 关键配置
更新策略
spec:
updateStrategy:
type: RollingUpdate # 或 OnDelete
rollingUpdate:
partition: 1 # 从索引 1 开始更新
Pod 管理策略
spec:
podManagementPolicy: OrderedReady # 默认,有序启动
# podManagementPolicy: Parallel # 并行启动
6.4 StatefulSet 与 Deployment 对比
特性 | Deployment | StatefulSet |
---|---|---|
Pod 名称 | 随机生成 | 固定编号(有序) |
存储 | 共享或临时 | 独立 PVC |
调度 | 可并行 | 有序(默认) |
用途 | 无状态服务 | 有状态数据服务 |
网络标识 | 不固定 | 稳定网络标识 |
七、CSI(容器存储接口)
7.1 CSI 核心概念
CSI 是云原生存储的标准接口规范,让不同厂商的存储插件统一化。
7.2 主流 CSI 驱动
厂商 | CSI 驱动 | 存储类型 |
---|---|---|
AWS | ebs.csi.aws.com | EBS |
阿里云 | diskplugin.csi.alibabacloud.com | 云盘 |
腾讯云 | com.tencent.cloud.csi.cbs | CBS |
华为云 | everest-csi-driver | EVS |
Ceph | rbd.csi.ceph.com | RBD |
7.3 CSI 安装示例(AWS EBS)
# 安装 AWS EBS CSI 驱动
kubectl apply -k "github.com/kubernetes-sigs/aws-ebs-csi-driver/deploy/kubernetes/overlays/stable/?ref=release-1.19"
# 验证安装
kubectl get pods -n kube-system -l app=ebs-csi-controller
kubectl get pods -n kube-system -l app=ebs-csi-node
7.4 CSI 工作原理
graph TD
A[Pod 创建] --> B[kubelet]
B --> C[CSI Node Plugin]
C --> D[CSI Controller Plugin]
D --> E[云存储 API]
E --> F[创建存储卷]
F --> G[挂载到 Pod]
️ 八、命令速记
存储资源管理
# 查看 PV、PVC、StorageClass
kubectl get pv,pvc,sc
# 查看存储详情
kubectl describe pv <pv-name>
kubectl describe pvc <pvc-name>
kubectl describe sc <sc-name>
# 查看 Pod 挂载的卷
kubectl describe pod <pod-name>
# 查看 StatefulSet
kubectl get sts
kubectl describe sts <sts-name>
存储操作
# 创建存储资源
kubectl apply -f pv.yaml
kubectl apply -f pvc.yaml
kubectl apply -f storageclass.yaml
# 删除存储资源
kubectl delete pv <pv-name>
kubectl delete pvc <pvc-name>
kubectl delete sc <sc-name>
# 扩容 PVC
kubectl patch pvc <pvc-name> -p '{"spec":{"resources":{"requests":{"storage":"10Gi"}}}}'
故障排查
# 查看存储事件
kubectl get events --sort-by=.lastTimestamp
# 查看 CSI 插件日志
kubectl logs -n kube-system -l app=ebs-csi-controller
kubectl logs -n kube-system -l app=ebs-csi-node
# 检查存储挂载
kubectl exec <pod> -- df -h
kubectl exec <pod> -- mount | grep <volume-name>
九、面试核心问答
Q1: PV 与 PVC 的关系是什么?
答案要点:
- PVC 是存储申请单,PV 是存储资源池
- 系统自动匹配 PVC 和 PV
- 绑定条件:容量、访问模式、StorageClass
- 绑定后 PVC 和 PV 生命周期独立
Q2: StatefulSet 与 Deployment 的区别?
答案要点:
- StatefulSet:有唯一身份 + 稳定存储
- Deployment:无状态服务
- StatefulSet:有序部署、固定网络标识
- Deployment:并行部署、随机网络标识
Q3: 如何实现动态卷创建?
答案要点:
- 使用 StorageClass 定义分配策略
- 配置 Provisioner 处理卷创建
- PVC 自动触发 PV 创建
- 支持云存储和本地存储
Q4: 如何防止存储数据丢失?
答案要点:
- 设置 reclaimPolicy=Retain
- 定期备份 PV 数据
- 使用高可用存储后端
- 配置数据复制策略
Q5: CSI 的作用是什么?
答案要点:
- 统一存储插件接口标准
- 支持云厂商和开源存储
- 解耦存储逻辑和 Kubernetes
- 提供标准化的存储操作
十、故障排查
常见存储问题
1. PVC 无法绑定 PV
# 检查 PVC 状态
kubectl describe pvc <pvc-name>
# 检查可用 PV
kubectl get pv
# 检查 StorageClass
kubectl get sc
kubectl describe sc <sc-name>
# 检查匹配条件
kubectl get pv -o custom-columns=NAME:.metadata.name,CAPACITY:.spec.capacity.storage,ACCESSMODES:.spec.accessModes,STORAGECLASS:.spec.storageClassName
2. Pod 挂载失败
# 检查 Pod 状态
kubectl describe pod <pod-name>
# 检查 PVC 绑定状态
kubectl get pvc
# 检查存储插件
kubectl get pods -n kube-system | grep csi
# 查看存储插件日志
kubectl logs -n kube-system <csi-pod>
3. 动态卷创建失败
# 检查 Provisioner 状态
kubectl get pods -n kube-system -l app=<provisioner>
# 查看 Provisioner 日志
kubectl logs -n kube-system <provisioner-pod>
# 检查存储后端连接
kubectl exec <provisioner-pod> -- ping <storage-server>
4. StatefulSet 启动失败
# 检查 StatefulSet 状态
kubectl describe sts <sts-name>
# 检查 Pod 状态
kubectl get pods -l app=<app-name>
# 检查 PVC 状态
kubectl get pvc
# 查看事件
kubectl get events --sort-by=.lastTimestamp
十一、最佳实践
存储设计建议
存储类型选择
- 数据库:RWO + 高性能存储
- 文件共享:RWX + 网络存储
- 配置数据:ConfigMap/Secret
容量规划
- 合理设置存储大小
- 预留扩容空间
- 监控存储使用率
备份策略
- 定期备份重要数据
- 测试恢复流程
- 多地存储备份
性能优化
- 选择高性能存储
- 优化挂载参数
- 监控 IO 性能
安全建议
访问控制
- 限制存储访问权限
- 使用 RBAC 管理
- 加密敏感数据
数据保护
- 启用存储加密
- 定期安全扫描
- 审计存储访问
十二、总结
通过本模块学习,你已经掌握了:
- Kubernetes 存储体系五层抽象
- Volume 类型和生命周期管理
- PV/PVC 绑定机制和回收策略
- StorageClass 动态卷分配
- StatefulSet 有状态应用部署
- CSI 容器存储接口
- 存储故障排查技能
- 存储最佳实践
下一步建议:继续学习 04-调度控制,深入了解 Kubernetes 资源管理和调度策略。