K8s数据持久化实战:用PV/PVC为MySQL部署保驾护航(含节点故障模拟)
K8s数据持久化实战用PV/PVC为MySQL部署保驾护航含节点故障模拟在云原生架构中数据库的高可用部署一直是技术团队面临的挑战。当MySQL运行在Kubernetes集群时如何确保数据在Pod重启、节点故障等意外情况下依然安全可靠这正是PVPersistentVolume和PVCPersistentVolumeClaim要解决的核心问题。传统容器中的存储会随着Pod销毁而消失这对于有状态应用如MySQL简直是灾难。通过PV/PVC机制Kubernetes实现了存储与计算资源的解耦——就像为数据库插上了一块外接硬盘即使容器漂移到其他节点数据也能完好无损地跟随迁移。本文将带您从零构建一个生产级MySQL部署方案并通过模拟节点宕机来验证这套架构的可靠性。1. 持久化存储架构设计1.1 PV与PVC的协作机制PV是集群中的一块持久化存储空间由管理员预先配置PVC则是用户发出的存储资源申请。当两者通过StorageClass和访问策略匹配成功后PVC就会绑定到合适的PV上。这种设计带来了三个关键优势职责分离开发人员只需声明需要的存储大小和性能无需关心底层是NFS、云盘还是本地SSD资源抽象同一套YAML配置可以在不同环境的Kubernetes集群中运行动态供给支持按需自动创建存储卷需StorageClass支持1.2 MySQL的存储需求分析设计MySQL的持久化方案时需要特别注意以下几点需求维度具体要求PV/PVC实现方案数据一致性单节点读写避免多节点同时写入accessModes: ReadWriteOnce故障恢复节点宕机后数据不丢失persistentVolumeReclaimPolicy: Retain性能要求低延迟IO操作选择SSD存储类容量规划预留20%缓冲空间申请容量预估数据量×1.22. 实战环境准备2.1 基础设施配置我们采用NFS作为后端存储生产环境建议使用云厂商的块存储服务先在存储节点执行# 安装NFS服务 sudo apt-get install -y nfs-kernel-server # 创建共享目录 sudo mkdir -p /data/mysql-pv sudo chmod 777 /data/mysql-pv # 配置导出目录 echo /data/mysql-pv *(rw,sync,no_subtree_check,no_root_squash) | sudo tee /etc/exports.d/mysql.exports # 启动服务 sudo systemctl enable --now nfs-server在Kubernetes所有工作节点安装NFS客户端工具sudo apt-get install -y nfs-common2.2 创建静态PV定义PV资源文件mysql-pv.yamlapiVersion: v1 kind: PersistentVolume metadata: name: mysql-pv-01 labels: type: nfs spec: capacity: storage: 10Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: mysql-storage nfs: path: /data/mysql-pv server: 192.168.1.100关键参数说明persistentVolumeReclaimPolicy: 设置为Retain确保PVC释放后数据不会自动删除storageClassName: 自定义存储类名称用于PVC匹配创建PV资源kubectl apply -f mysql-pv.yaml3. MySQL部署实战3.1 创建专属PVC定义PVC声明文件mysql-pvc.yamlapiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-data-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: mysql-storage应用PVC配置kubectl apply -f mysql-pvc.yaml验证绑定状态kubectl get pvc mysql-data-pvc -o wide预期看到STATUS为Bound且VOLUME列显示绑定的PV名称。3.2 部署MySQL有状态服务编写Deployment配置mysql-deployment.yamlapiVersion: apps/v1 kind: Deployment metadata: name: mysql spec: selector: matchLabels: app: mysql strategy: type: Recreate template: metadata: labels: app: mysql spec: containers: - name: mysql image: mysql:5.7 env: - name: MYSQL_ROOT_PASSWORD value: securepassword ports: - containerPort: 3306 volumeMounts: - name: mysql-data mountPath: /var/lib/mysql volumes: - name: mysql-data persistentVolumeClaim: claimName: mysql-data-pvc几个关键设计点使用Recreate策略确保单实例运行数据挂载到MySQL默认目录/var/lib/mysql通过环境变量设置root密码生产环境应使用Secret部署MySQL服务kubectl apply -f mysql-deployment.yaml3.3 服务暴露与验证创建NodePort服务便于外部访问apiVersion: v1 kind: Service metadata: name: mysql-service spec: type: NodePort ports: - port: 3306 targetPort: 3306 nodePort: 30306 selector: app: mysql连接MySQL并创建测试数据# 获取Pod名称 MYSQL_POD$(kubectl get pods -l appmysql -o jsonpath{.items[0].metadata.name}) # 执行MySQL命令行 kubectl exec -it $MYSQL_POD -- mysql -uroot -psecurepassword -- 在MySQL交互界面执行 CREATE DATABASE k8s_test; USE k8s_test; CREATE TABLE persistent_data ( id INT AUTO_INCREMENT PRIMARY KEY, value VARCHAR(255) NOT NULL ); INSERT INTO persistent_data(value) VALUES(K8s PV/PVC Test);4. 节点故障模拟测试4.1 确定Pod运行节点首先查询MySQL Pod所在节点kubectl get pod -l appmysql -o wide记录NODE列显示的节点名称例如node-1。4.2 模拟节点故障在目标节点上执行关机操作生产环境请勿直接操作# 连接到目标节点 ssh node-1 # 模拟节点宕机 sudo systemctl poweroff观察Kubernetes的恢复过程watch kubectl get pods -l appmysql -o wide大约1-2分钟后会看到Pod被重新调度到其他可用节点如node-2。4.3 数据完整性验证重新连接MySQL验证数据# 获取新的Pod名称 NEW_MYSQL_POD$(kubectl get pods -l appmysql -o jsonpath{.items[0].metadata.name}) # 查询测试数据 kubectl exec -it $NEW_MYSQL_POD -- mysql -uroot -psecurepassword -e SELECT * FROM k8s_test.persistent_data预期输出应显示之前插入的记录证明数据在节点故障转移过程中保持完整。5. 高级配置与优化5.1 存储类动态供给对于需要频繁创建数据库实例的场景可以配置StorageClass实现动态供给apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: mysql-dynamic-storage provisioner: example.com/nfs parameters: archiveOnDelete: false然后在PVC中引用storageClassName: mysql-dynamic-storage5.2 多副本MySQL部署对于生产环境建议使用StatefulSet部署MySQL集群apiVersion: apps/v1 kind: StatefulSet metadata: name: mysql-cluster spec: serviceName: mysql replicas: 3 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers: - name: mysql image: mysql:5.7 env: - name: MYSQL_ROOT_PASSWORD value: securepassword ports: - containerPort: 3306 volumeMounts: - name: mysql-data mountPath: /var/lib/mysql volumeClaimTemplates: - metadata: name: mysql-data spec: accessModes: [ ReadWriteOnce ] storageClassName: mysql-storage resources: requests: storage: 10Gi5.3 备份策略配置为确保数据安全建议配置定期备份# 临时备份Pod配置 apiVersion: batch/v1 kind: CronJob metadata: name: mysql-backup spec: schedule: 0 2 * * * jobTemplate: spec: template: spec: containers: - name: mysqldump image: mysql:5.7 command: - /bin/sh - -c - mysqldump -uroot -p$MYSQL_ROOT_PASSWORD --all-databases /backup/mysql-$(date %Y%m%d).sql env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-secret key: password volumeMounts: - name: backup-volume mountPath: /backup restartPolicy: OnFailure volumes: - name: backup-volume persistentVolumeClaim: claimName: backup-pvc6. 生产环境注意事项在实际生产部署时还需要考虑以下关键因素性能监控配置Prometheus监控MySQL和存储性能指标资源限制为MySQL容器设置合理的requests和limits网络策略限制只有特定服务可以访问MySQL端口加密存储敏感数据应考虑使用加密存储卷灾备方案建立跨可用区的备份恢复机制通过这套方案我们成功在Kubernetes上部署了具备持久化存储能力的MySQL服务。当模拟节点故障时观察到Pod会自动迁移到健康节点且通过PVC挂载的数据卷保持了完整的数据一致性。这为在K8s上运行有状态服务提供了可靠的基础保障。