在 Kubernetes 中为有状态应用(如 MySQL)配置持久化存储,需结合 StatefulSet、PersistentVolumeClaim (PVC) 和 StorageClass,确保数据在 Pod 重启或迁移时不会丢失。以下是详细步骤和最佳实践:
一、核心组件选择
组件 | 作用 |
---|---|
StatefulSet | 为每个 Pod 提供唯一的网络标识和稳定的持久化存储(按顺序创建/删除)。 |
PVC | 声明 Pod 所需的存储容量和访问模式(如 ReadWriteOnce )。 |
StorageClass | 定义动态创建 PV 的规则(如云厂商存储类型、回收策略)。 |
二、配置步骤(以 MySQL 为例)
1. 创建 StorageClass(可选,若需动态供应)
如果是云环境(如 AWS、GCP),通常已有默认 StorageClass。若需自定义(例如本地存储),需手动配置:
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata:name: mysql-storage provisioner: kubernetes.io/aws-ebs # 根据环境调整(如 rook-ceph、local) parameters:type: gp3 # AWS EBS 类型(或 SSD、HDD) reclaimPolicy: Retain # 删除 PVC 后保留 PV 和数据 volumeBindingMode: WaitForFirstConsumer # 延迟绑定到 Pod 调度节点
2. 定义 StatefulSet 和 PVC 模板
apiVersion: apps/v1 kind: StatefulSet metadata:name: mysql spec:serviceName: mysql-headless # Headless Service 用于 Pod 发现replicas: 1 # 单节点示例(生产环境建议集群化)selector:matchLabels:app: mysqltemplate:metadata:labels:app: mysqlspec:containers:- name: mysqlimage: mysql:8.0env:- name: MYSQL_ROOT_PASSWORDvalue: "your-root-password"ports:- containerPort: 3306volumeMounts:- name: mysql-datamountPath: /var/lib/mysql # MySQL 数据目录volumeClaimTemplates: # 自动为每个 Pod 创建 PVC- metadata:name: mysql-dataspec:accessModes: [ "ReadWriteOnce" ]storageClassName: mysql-storage # 使用自定义 StorageClassresources:requests:storage: 20Gi # 根据需求调整容量
3. 创建 Headless Service
apiVersion: v1 kind: Service metadata:name: mysql-headless spec:clusterIP: None # Headless Service 无 ClusterIPselector:app: mysqlports:- port: 3306
三、关键配置说明
1. 存储访问模式 (accessModes
)
-
ReadWriteOnce (RWO)
:单节点读写(适合单实例 MySQL)。 -
ReadWriteMany (RWX)
:多节点读写(适用于分布式数据库如 Cassandra)。 -
ReadOnlyMany (ROX)
:多节点只读。
2. 持久化路径
-
MySQL 默认数据目录为
/var/lib/mysql
,必须挂载到持久化卷。 -
挂载其他路径(如配置文件)需额外配置。
3. 动态供应 vs 静态供应
-
动态供应(推荐):通过 StorageClass 自动创建 PV。
-
静态供应:手动创建 PV 并绑定 PVC(适合本地存储或无云厂商环境)。
四、生产环境优化
1. 高可用配置
-
MySQL 集群:使用 Galera Cluster 或 Group Replication,配合多副本 StatefulSet。
-
跨可用区存储:配置 StorageClass 支持多 AZ(如 AWS EBS 需结合
topologyKey: topology.kubernetes.io/zone
)。
2. 备份与恢复
-
定期快照:使用云厂商快照工具(如 AWS EBS Snapshot)或 Velero。
-
逻辑备份:通过 CronJob 执行
mysqldump
并存储到对象存储(如 S3)。
3. 监控与告警
-
监控 PV/PVC 使用率(Prometheus +
kubelet
指标)。 -
设置 PVC 容量不足的告警规则。
五、验证流程
-
部署验证
kubectl apply -f mysql-statefulset.yaml kubectl get statefulset,pvc,pod -l app=mysql
-
确认 PVC 状态为
Bound
,Pod 运行正常。
-
-
数据持久化测试
-
进入 MySQL Pod 写入测试数据:
kubectl exec -it mysql-0 -- mysql -u root -p CREATE DATABASE test;
-
删除 Pod 并观察 StatefulSet 自动重建:
kubectl delete pod mysql-0 kubectl exec -it mysql-0 -- mysql -u root -p -e "SHOW DATABASES;" # 确认 test 库存在
-
-
故障恢复测试
-
模拟节点故障,观察 Pod 重新调度到其他节点后数据是否保留。
-
六、常见问题
1. PVC 无法绑定
-
检查 StorageClass 是否存在且配置正确。
-
确认 PV 的容量和访问模式与 PVC 匹配。
2. 数据写入性能差
-
使用 SSD 类型 StorageClass(如 AWS
gp3
或io2
)。 -
调整文件系统挂载参数(如
ext4
的discard
选项)。
3. 存储资源不足
-
设置
ResourceQuota
限制命名空间存储使用量。 -
启用 PVC 扩容功能(需存储驱动支持)。
总结
通过 StatefulSet + PVC + StorageClass 的组合,可为 MySQL 等有状态应用提供稳定的持久化存储,同时结合高可用、备份和监控策略,确保生产环境的可靠性和数据安全。实际部署时需根据业务需求调整存储类型、容量和访问模式。