为什么需要PV和PVC
在公司跑微服务的时候,经常会遇到一个头疼的问题:Pod重启后ref="/tag/426/" style="color:#2B406D;font-weight:bold;">数据没了。比如你搭了个内部文档系统,用户上传的文件存在容器里,结果一升级服务,文件全丢了。这时候就得靠Kubernetes的持久化存储机制——PV(PersistentVolume)和PVC(PersistentVolumeClaim)。
PV是集群里的一块真实存储资源,比如NFS目录、云硬盘或者本地磁盘。而PVC是应用层面的“申请单”,告诉Kubernetes:“我需要多大空间,什么访问模式”。两者配合,让Pod即使重建也能挂载原来的数据。
手动创建PV:以NFS为例
假设你们办公室用NFS做共享存储,IP是192.168.1.100,共享路径是/data/k8s。可以先定义一个PV:
<apiVersion> v1</apiVersion>
<kind> PersistentVolume</kind>
<metadata>
<name> nfs-pv</name>
</metadata>
<spec>
<capacity>
<storage> 10Gi</storage>
</capacity>
<accessModes>
<mode> ReadWriteMany</mode>
</accessModes>
<nfs>
<server> 192.168.1.100</server>
<path> /data/k8s</path>
</nfs>
<persistentVolumeReclaimPolicy> Retain</persistentVolumeReclaimPolicy>
</spec>这个配置声明了一个10GB的PV,通过NFS挂载到指定路径。accessModes设为ReadWriteMany,表示多个Pod可以同时读写。
声明使用:创建PVC
开发同事要部署一个内部博客系统,需要持久化文章图片。他不需要关心后端存储细节,只需要提个需求:
<apiVersion> v1</apiVersion>
<kind> PersistentVolumeClaim</kind>
<metadata>
<name> blog-pvc</name>
</metadata>
<spec>
<accessModes>
<mode> ReadWriteMany</mode>
</accessModes>
<resources>
<requests>
<storage> 5Gi</storage>
</requests>
</resources>
</spec>Kubernetes会自动找匹配的PV绑定。如果之前创建的nfs-pv还空着,就会立刻被这个PVC“认领”。
在Pod中使用PVC
Deployment配置里直接引用PVC就行:
<apiVersion> apps/v1</apiVersion>
<kind> Deployment</kind>
<metadata>
<name> blog-deploy</name>
</metadata>
<spec>
<replicas> 2</replicas>
<template>
<spec>
<containers>
- <name> blog</name>
<image> myblog:latest</image>
<volumeMounts>
- <name> blog-storage</name>
<mountPath> /var/lib/blog</mountPath>
</volumeMounts>
</containers>
<volumes>
- <name> blog-storage</name>
<persistentVolumeClaim>
<claimName> blog-pvc</claimName>
</persistentVolumeClaim>
</volumes>
</spec>
</template>
</spec>这样一来,不管Pod在哪台机器重建,数据都从同一个NFS路径加载,用户上传的图片不会丢失。
动态供给更省心
每次手动建PV太麻烦?可以用StorageClass实现动态供给。比如公司用的是阿里云,可以配置alicloud-disk作为默认存储类型,开发者只要写PVC,系统自动创建云盘并绑定。运维不用再一个个配PV,效率高多了。
实际工作中,见过不少团队因为没配PVC,导致数据库Pod重启后数据清零,半夜被报警叫起来恢复备份。提前把存储搞明白,能少背不少锅。