做了这么多年运维K8s的存储这块一直是个让人又爱又恨的东西。说它复杂吧确实概念挺多的PV、PVC、StorageClass这些名词听起来就头大说它简单吧一旦搞明白了原理用起来还是很顺手的。今天我就把自己这些年在生产环境中踩过的坑、总结的经验分享给大家让你们少走点弯路。为什么需要持久化存储容器本身是无状态的这个大家都知道。Pod一重启里面的数据就没了这对于数据库、文件存储这些有状态应用来说简直是灾难。我记得刚开始用K8s的时候有次MySQL的Pod重启了结果所有数据都丢了那个心情…简直想死的心都有。从那以后我就深刻认识到持久化存储在K8s中有多重要。K8s的持久化存储主要解决这么几个问题数据持久性Pod重启、迁移后数据不丢失数据共享多个Pod可以访问同一份数据存储抽象屏蔽底层存储实现细节PV、PVC、StorageClass的关系这三个概念的关系我用一个比较接地气的比喻来解释**PVPersistentVolume**就像是一个仓库管理员提前准备好的存储空间。**PVCPersistentVolumeClaim**就像是租仓库的申请单用户说我要多大的空间、什么类型的。StorageClass就像是仓库的分类标准比如高性能仓库、普通仓库、便宜仓库等。具体来说PV持久卷PV是集群级别的资源由管理员创建代表集群中的一块存储。它包含存储实现的具体细节比如NFS、iSCSI、云存储等。apiVersion:v1kind:PersistentVolumemetadata:name:my-pvspec:capacity:storage:10GiaccessModes:-ReadWriteOncepersistentVolumeReclaimPolicy:Retainnfs:server:192.168.1.100path:/data/nfs这个配置我在生产环境用过很多次需要注意几个点capacity定义存储大小accessModes定义访问模式RWOReadWriteOnce表示只能被一个节点挂载persistentVolumeReclaimPolicy定义回收策略PVC持久卷声明PVC是用户对存储的请求它会去寻找合适的PV进行绑定。apiVersion:v1kind:PersistentVolumeClaimmetadata:name:my-pvcspec:accessModes:-ReadWriteOnceresources:requests:storage:5Gi这里有个坑要注意PVC请求的存储大小必须小于等于PV提供的大小而且访问模式也要匹配。StorageClass存储类StorageClass提供了动态创建PV的方式不需要管理员手动创建PV。apiVersion:storage.k8s.io/v1kind:StorageClassmetadata:name:fast-ssdprovisioner:kubernetes.io/aws-ebsparameters:type:gp2zone:us-west-2a静态供应 vs 动态供应静态供应静态供应就是管理员提前创建好PV然后用户创建PVC去绑定。这种方式比较传统适合小规模或者对存储有特殊要求的场景。我在一个项目中就是用的静态供应因为客户要求数据必须存储在指定的NFS服务器上所以只能手动创建PV。动态供应动态供应通过StorageClass自动创建PV用户只需要在PVC中指定StorageClass即可。apiVersion:v1kind:PersistentVolumeClaimmetadata:name:dynamic-pvcspec:accessModes:-ReadWriteOncestorageClassName:fast-ssdresources:requests:storage:20Gi这种方式更灵活特别适合云环境。我现在基本都用动态供应省事多了。生命周期管理PV和PVC的生命周期有几个关键阶段Available可用PV已创建但还没有被PVC绑定。Bound已绑定PV已经被PVC绑定正在使用中。Released已释放PVC被删除但PV还没有被回收。Failed失败自动回收失败。这里要特别说一下回收策略有三种Retain保留数据需要手动清理Delete自动删除PV和底层存储Recycle已废弃不建议使用我在生产环境中一般用Retain策略因为数据安全第一宁可手动清理也不能误删数据。访问模式详解K8s支持三种访问模式ReadWriteOnce (RWO)只能被一个节点以读写方式挂载。这是最常用的模式适合大部分应用。ReadOnlyMany (ROX)可以被多个节点以只读方式挂载。适合配置文件、静态资源等场景。ReadWriteMany (RWX)可以被多个节点以读写方式挂载。这个模式对存储系统要求比较高不是所有存储都支持。我遇到过一个坑就是用了不支持RWX的存储系统结果Pod一直处于Pending状态。后来查了半天才发现是访问模式的问题。实际生产案例案例1MySQL数据库持久化# StorageClassapiVersion:storage.k8s.io/v1kind:StorageClassmetadata:name:mysql-storageprovisioner:kubernetes.io/aws-ebsparameters:type:gp2encrypted:true---# PVCapiVersion:v1kind:PersistentVolumeClaimmetadata:name:mysql-pvcspec:accessModes:-ReadWriteOncestorageClassName:mysql-storageresources:requests:storage:100Gi---# DeploymentapiVersion:apps/v1kind:Deploymentmetadata:name:mysqlspec:replicas:1selector:matchLabels:app:mysqltemplate:metadata:labels:app:mysqlspec:containers:-name:mysqlimage:mysql:8.0env:-name:MYSQL_ROOT_PASSWORDvalue:password123volumeMounts:-name:mysql-storagemountPath:/var/lib/mysqlvolumes:-name:mysql-storagepersistentVolumeClaim:claimName:mysql-pvc这个配置我用了好几年非常稳定。关键点是使用加密的EBS卷保证数据安全100Gi的存储空间足够大部分应用使用挂载到MySQL的数据目录案例2多Pod共享存储有时候需要多个Pod共享同一份数据比如Web应用的静态文件。# 使用NFS的PVapiVersion:v1kind:PersistentVolumemetadata:name:shared-pvspec:capacity:storage:50GiaccessModes:-ReadWriteManynfs:server:nfs-server.example.compath:/shared/data---# PVCapiVersion:v1kind:PersistentVolumeClaimmetadata:name:shared-pvcspec:accessModes:-ReadWriteManyresources:requests:storage:50Gi这种场景下必须使用支持RWX的存储系统NFS是个不错的选择。性能优化技巧选择合适的存储类型不同的存储类型性能差异很大SSDIOPS高延迟低适合数据库HDD容量大成本低适合日志、备份网络存储可共享但性能一般我的经验是数据库一定要用SSD日志可以用HDD配置文件用网络存储。合理设置存储大小存储大小不是越大越好要根据实际需求来预留20-30%的空间用于扩展考虑备份和快照的空间需求定期清理无用数据监控存储使用情况我一般会用Prometheus监控存储使用率# 存储使用率告警规则groups:-name:storage.rulesrules:-alert:PVCStorageUsageHighexpr:(kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes) * 10085for:5mlabels:severity:warningannotations:summary:PVC storage usage is high常见问题排查PVC一直Pending这是最常见的问题可能的原因没有合适的PV可以绑定StorageClass配置错误存储资源不足排查方法kubectl describe pvc my-pvc kubectl getpvkubectl get storageclassPod挂载失败挂载失败通常是因为节点不支持该存储类型权限问题存储系统故障我遇到过一次EBS卷挂载失败最后发现是AWS的配额限制导致的。数据丢失这个问题最严重预防措施使用Retain回收策略定期备份重要数据测试恢复流程最佳实践总结根据我这些年的经验总结几个最佳实践生产环境优先使用动态供应配置合适的StorageClass重要数据使用Retain回收策略手动管理PV生命周期合理选择访问模式大部分情况用RWO就够了监控存储使用情况及时发现问题定期备份数据做好灾难恢复准备存储选型建议数据库高性能SSD RWO Retain策略文件服务网络存储 RWX Delete策略日志收集大容量HDD RWO Delete策略临时数据本地存储 RWO Delete策略如果觉得这篇文章对你有帮助别忘了点个赞、转发一下让更多的运维小伙伴看到。你们的支持是我持续输出干货的动力关注运维躬行录获取更多实战干货我们一起在运维的道路上躬行实践个人博客躬行笔记