3. Kubernetes 存储抽象与数据库持久化选型
在 Kubernetes 上运行数据库,最先要解决的不是“怎么装”,而是“数据放在哪里、以什么方式挂进来”。Kubernetes 用三层抽象把存储从 Pod 生命周期中解耦:PV(PersistentVolume)是集群里一块真实可用的存储资源,由管理员或动态供给器创建;PVC(PersistentVolumeClaim)是应用对存储的“需求声明”,描述容量、访问模式等诉求;StorageClass则是“供给模板”,规定用哪个插件、什么参数、什么回收策略来动态生成 PV。Pod 只认 PVC,PVC 再绑定 PV,从而让数据库容器在重建、漂移后仍能拿回同一份数据。
理解这三者的关键是分清“谁定义能力、谁提出需求、谁完成匹配”。PV 是能力侧,PVC 是需求侧,StorageClass 是撮合规则。绑定成功后,PVC 与 PV 形成一对一关系,直到释放。数据库场景下,这个绑定关系必须稳定,否则一次误删 PVC 就可能连带删除后端卷。
接下来看四类后端存储的差异。它们不是“谁替代谁”,而是对应不同的 IO 特征和可靠性诉求。
| 存储类型 | 典型实现 | 访问模式 | 延迟/吞吐 | 数据库适用场景 |
|---|---|---|---|---|
| 本地盘 | local PV、hostPath | RWO | 极低延迟、高 IOPS | 单节点高性能 OLTP、缓存层 |
| 网络块存储 | EBS、Ceph RBD、云盘 | RWO | 低延迟、中等吞吐 | 主库、有状态副本、可漂移 |
| 文件存储 | NFS、CephFS、EFS | RWX | 中等延迟、共享读写 | 多 Pod 共享、日志、备份中转 |
| 对象存储 | S3、OSS、MinIO | REST API | 高延迟、高吞吐 | 备份、归档、冷数据、WAL 归档 |
选型的核心是“把数据库的 IO 路径拆开看”。以 MySQL 为例,InnoDB 的 redo log 是顺序写、对延迟极敏感;数据文件是随机读写、IOPS 要求高;binlog 是顺序追加;备份则是一次性大吞吐。因此一个常见组合是:数据目录与 redo log 放在本地 NVMe 或高性能网络块存储上,binlog 与备份落到对象存储。如果使用云环境,主库通常选 SSD 类型的网络块存储,保证 Pod 漂移后数据仍可挂载;只读副本或缓存层可以接受本地盘以换取更低延迟。
访问模式(accessMode)是另一个容易踩坑的点。RWO(ReadWriteOnce)表示同一时刻只能被一个节点挂载读写,绝大多数数据库主库都用它;RWX(ReadWriteMany)允许多节点同时读写,适合共享文件场景,但传统单机数据库并不支持多写,强行用 RWX 挂载 MySQL 数据目录会导致数据损坏。ROX(ReadOnlyMany)多用于分发只读数据。选型时必须先确认数据库自身是否支持多写,再决定 accessMode。
reclaimPolicy 默认可能是 Delete。数据库 PVC 一旦被删除,后端卷会被一并销毁。生产环境应显式设置为 Retain,并配合 VolumeSnapshot 做定期快照。此外,本地盘 PV 与节点强绑定,节点故障时 Pod 无法漂移到其他节点,必须依赖数据库自身的副本机制或备份恢复。
下面给出一个可直接参考的 StorageClass 与 PVC 配置示例,用于生产级 MySQL 主库。示例参数为合理假设,实际需按云厂商和集群能力调整。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: db-ssd-retain
provisioner: ebs.csi.aws.com
parameters:
type: gp3
iops: "6000"
throughput: "250"
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-data
spec:
storageClassName: db-ssd-retain
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 500Gi
这里有两个参数值得展开。volumeBindingMode: WaitForFirstConsumer 表示 PV 延迟到 Pod 调度时才创建,确保卷和 Pod 落在同一可用区,避免跨区挂载失败;allowVolumeExpansion: true 允许后续在线扩容 PVC,数据库磁盘写满时不必重建。扩容操作本身只是改 PVC 的 storage 字段,但文件系统扩容还需要 Pod 内执行 resize2fs 或 xfs_growfs,具体取决于文件系统类型。
判断选型是否合理,可以从三个可观测维度验证:一是 kubectl get pvc 确认状态为 Bound 且容量正确;二是用 fio 在 Pod 内做随机读写测试,观察 IOPS 与延迟是否满足数据库基线;三是模拟节点故障或 Pod 重建,确认数据卷能重新挂载且数据完整。只有这三步都通过,存储选型才算真正落地。