Skip to content

1. PV与PVC基本概念

官方文档地址: https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/

1.1 为何需要PV与PVC

我们使用过网络存储卷来实现Pod的数据持久化以及pod间共享,也不是很复杂。如果我们使用更为复杂的网络存储来完成数据共享和持久化,在使用上会带来一些问题。首先开发人员必须清楚的了解使用的网络存储技术、同时还必须清楚不同的网络存储卷的配置方式、访问细节等。才能完成网络存储卷相关的配置任务,这就要求开发人员对该类存储有着一定的了解才能顺利使用。

但这与Kubernetes向用户和开发隐藏底层架构的目标有所背离,Kubernetes希望我们的存储资源的使用也能像计算资源一样,让我们的用户和开发无需关心存储系统是什么设备、位于何处、如何访问等。

1.2 什么是PV与PVC

PV (Persistent Volume)PVC (Persistent VolumeClaim)就是在用户与存储服务之间添加的一个中间层。

  • PV:持久卷,集群中的一块存储,可由管理员根据PV支持的存储卷插件定义好底层存储空间;
  • PVC:持久卷申领,用户通过PVC进行存储资源申请,系统根据用户申请的存储(大小、类型)来绑定符合条件的PV持久卷;

有了PV和PVC,开发人员无需关系底层使用的是什么网络存储卷,通过PVC描述所需要的存储类型、大小,即可完成存储资源的申领,而后通过配置清单描述Pod所需要使用的PVC即可完成存储卷的绑定和使用。这样大大的简化了用户使用存储的方式。

image-20240603144642392

💡 说明

PresistentVolume(PV)是指集群管理员配置提供的某存储系统上的一段存储空间,它是对底层共享存储的抽象,将共享存储作为一种可由用户申请使用的资源,实现"存储消费"机制,通过存储插件,PV支持使用多种网络存储等多种后端存储系统,例如,NFS、CephFS、RBD。PV是集群级别的资源,不属于任何名称空间,用户对PV资源的使用需要通过PersistentVolumeClaim(PVC)提供的使用申请来完成绑定,PVC是PV资源的消费者,它向PV申请特定大小的空间及访问模式(rw或ro)从而创建出PVC存储卷。然后再由Pod资源通过PersistentVolumeClaim存储卷关联使用。

PersistentVolumeClaim,PVC是存储卷类型的资源,它通过申请占用某个PersistentVolume而创建,它与PV是一对一的关系,用户无须关心其底层实现细节,申请时,用户只需要指定目标空间的大小,访问模式,PV标签选择器和StorageClass等相关信息即可。

1.3 PV与PVC⽣命周期

image-20240603151840822

1、资源供应:运维⼿动创建底层存储设备,提供存储功能;

2、资源可⽤:创建PV,此时PV卷是⼀个空闲资源,尚未绑定任何PVC资源;

3、资源绑定:⽤户创建PVC资源,根据描述绑定到符合条件的PV资源;

  • 匹配到合适的PV,就与该PV进⾏绑定,Pod应⽤也就可以使⽤该PVC作为后端存储;
  • 如果匹配不到合适的PV,PVC则会处于Pengding状态,直到出现符合要求的PV,才会完成绑定;
  • PV⼀旦绑定上某个PVC,就会被这个PVC独占,不能在与其他PVC进⾏绑定

4、资源使⽤:⽤户可以在Pod中定义Volumes,类型为PVC,⽽后在容器中定义VolumeMounts挂载该PVC资源;

5、资源释放:当存储资源使用完毕后,管理员可以删除PVC,与该PVC绑定的PV将会被标记为(ReLeased)状态,但不能立刻与其他PVC进行绑定,因为之前PVC写入的数据还被保留在存储设备上,只有在回收之后,该PV才能被再次使用

6、资源回收:当PV进入Released状态后,其后续的处理机制依赖于回收策略,(Rtain、Recycle、Delete)

2. PV回收和访问策略

2.0 accessMode

PV的访问模式参考官方

1.ReadWriteOnce: 仅可被单个节点读写挂载;命令行中简写RWO。

2.ReadOnlyMany: 仅可被多个节点同时只读挂在;命令行简写ROX。

3.ReadyWriteMany: 可被多个节点同时读写挂载;命令行中简写RWX

2.1 Retain

Retain(保留):需要⼿动回收

删除PVC后将保留其绑定的PV及存储的数据,但会把该PV置为ReLeased状态,它不可再被其他PVC所绑定,且需要由管理员手动进行后续的回收操作:首先删除PV,接着手动清理其关联的外部存储组件上的数据,最后基于该组件重新创建PV;

2.2 Recycle

Recycle(回收):基本擦除 (rm -rf /thevolume/*")

对于支持该回收策略的存储卷插件,删除PVC时,其绑定的PV所关联的外部存储组件上的数据会被清空,随后该PV将转为Available状态,可再次接收其他PVC的绑定请求。不过目前仅 NFS 和HostPath 支持该回收策略;

2.3 Delete

Delete(删除):对于⽀持该回收策略的卷插件,删除⼀个PVC将同时删除其绑定的PV资源以及该PV关联的外部存储组件。

3. PV资源实践

PV是⾪属于Kubernetes核⼼API群组中的标准资源类型,它主要实现将外部存储系统定义为可被,PVC申明绑定使⽤的资源对象。PV资源Spec字段主要嵌套以下⼏个通⽤字段,它们⽤于定义PV的容量,访问模式和回收策略等属性。

yaml
apiVersion: v1  
kind: PersistentVolume
metadata:
  name: pv2
spec:
  nfs: # 存储类型,与底层真正存储对应
  capacity:  # 存储能力,目前只支持存储空间的设置
    storage: 2Gi
  accessModes:  # 访问模式
  storageClassName: # 存储类别
  persistentVolumeReclaimPolicy: # 回收策略
apiVersion: v1  
kind: PersistentVolume
metadata:
  name: pv2
spec:
  nfs: # 存储类型,与底层真正存储对应
  capacity:  # 存储能力,目前只支持存储空间的设置
    storage: 2Gi
  accessModes:  # 访问模式
  storageClassName: # 存储类别
  persistentVolumeReclaimPolicy: # 回收策略

3.1 PV配置字段详解

参数描述
capacity指定PV容量
volumeMode指定PV类型,⽤于指定此存储卷被格式为⽂件系统
使⽤,还是直接使⽤裸格式的块设备,默认Filesystem
accessModes指定当前PV⽀持的访问模式,官⽹参考地址
persistentVolumeReclaimPolicy指定PV空间被释放时的处
理机制;Retain(默认)、Recycle、delete
storageClassName当前PV所属的StorageClass资源的名称,
⽤来实现存储资源分类;
mountOptions挂载选项,例如:ro、nfsvers、等

PV 的关键配置参数说明:

  • 存储类型

    底层实际存储的类型,kubernetes支持多种存储类型,每种存储类型的配置都有所差异

  • 访问模式(accessModes)

    用于描述用户应用对存储资源的访问权限,访问权限包括下面几种方式:

    • ReadWriteOnce(RWO):读写权限,但是只能被单个节点挂载
    • ReadOnlyMany(ROX): 只读权限,可以被多个节点挂载
    • ReadWriteMany(RWX):读写权限,可以被多个节点挂载

    需要注意的是,底层不同的存储类型可能支持的访问模式不同

  • 回收策略(persistentVolumeReclaimPolicy)

    当PV不再被使用了之后,对其的处理方式。目前支持三种策略:

    • Retain (保留) 保留数据,需要管理员手工清理数据
    • Recycle(回收) 清除 PV 中的数据,效果相当于执行 rm -rf /thevolume/*
    • Delete (删除) 与 PV 相连的后端存储完成 volume 的删除操作,当然这常见于云服务商的存储服务

    需要注意的是,底层不同的存储类型可能支持的回收策略不同

  • 存储类别

    PV可以通过storageClassName参数指定一个存储类别

    • 具有特定类别的PV只能与请求了该类别的PVC进行绑定
    • 未设定类别的PV则只能与不请求任何类别的PVC进行绑定
  • 状态(status)

    一个 PV 的生命周期中,可能会处于4中不同的阶段:

    • Available(可用): 表示可用状态,还未被任何 PVC 绑定
    • Bound(已绑定): 表示 PV 已经被 PVC 绑定
    • Released(已释放): 表示 PVC 被删除,但是资源还未被集群重新声明
    • Failed(失败): 表示该 PV 的自动回收失败

4. PVC资源实践

4.1 PVC配置字段详解

PersistentVolumeClaim,PVC是存储卷类型的资源,它通过申请占用某个PersistentVolume而创建,它与PV是一对一的关系,用户无须关心其底层实现细节, 申请时,用户只需要指定目标空间的大小,访问模式,PV标签选择器和StorageClass等相关信息即可

yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc
  namespace: dev
spec:
  accessModes: # 访问模式
  selector: # 采用标签对PV选择
  storageClassName: # 存储类别
  resources: # 请求空间
    requests:
      storage: 5Gi
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc
  namespace: dev
spec:
  accessModes: # 访问模式
  selector: # 采用标签对PV选择
  storageClassName: # 存储类别
  resources: # 请求空间
    requests:
      storage: 5Gi
参数描述
accessModesPVC的访问模式;它同样⽀持RWO、RWX、ROX三种
⽅式;
resources申明使⽤的存储空间的最⼩值和最⼤值;
selector筛选PV时额外使⽤的标签选择器;
volumeName直接指定要绑定的PV资源名称;
strogeClassName指定从哪类存储资源下筛选PV,如果指定的名
称不存在,则⽆法绑定成功。如果指定的资源下没有符合的空间也⽆
法绑定成功。⽐如申请20G空间,但pv都只有10G空间,则⽆法满

5. 静态案例

在节点执⾏如下操作,建议所有节点操作,因为不确定Pod会调度⾄哪个节点;(⽣产不建议使⽤HostPath⽅式)

静态存储

5.1 hostpath pv

bash
mkdir /mnt/data
echo "hello hostpath pv,pvc" > /mnt/data/index.html
mkdir /mnt/data
echo "hello hostpath pv,pvc" > /mnt/data/index.html

1.创建pv yaml文件

yaml
[root@kube-master pv]# cat 1.hostpath-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-volume-001
spec:
  storageClassName: "host-manager" #资源类型的标识
  persistentVolumeReclaimPolicy: Retain #保留策略
  accessModes:      #访问模式
    - ReadWriteOnce #访问模式为仅被单个节点读写挂载,单路读写
  capacity: #容量
    storage: 1Gi #存储空间大小
  hostPath: #临时存储位置
    path: "/mnt/data"
[root@kube-master pv]# cat 1.hostpath-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-volume-001
spec:
  storageClassName: "host-manager" #资源类型的标识
  persistentVolumeReclaimPolicy: Retain #保留策略
  accessModes:      #访问模式
    - ReadWriteOnce #访问模式为仅被单个节点读写挂载,单路读写
  capacity: #容量
    storage: 1Gi #存储空间大小
  hostPath: #临时存储位置
    path: "/mnt/data"

2.执行apply

bash
[root@kube-master pv]# kubectl apply -f 1.hostpath-pv.yaml
persistentvolume/pv-volume-001 created
[root@kube-master pv]# kubectl apply -f 1.hostpath-pv.yaml
persistentvolume/pv-volume-001 created

3.查看

bash
[root@kube-master pv]# kubectl get pv
NAME            CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv-volume-001   1Gi        RWO            Retain           Available           host-manager            77s

PV是有状态的对象,状态类型如下:
# 1Gi:  存储空间大小
# RWO:  访问模式(ReadWriteOnce缩写)
# Recycle:     回收策略
# Available:   PV状态

# persistentVolumeReclaimPolicy回收策略
# Retain (保留) 保留数据,需要管理员手动清理
# Recycle (回收) 清除PV中的数据,效果相当于执行删除命令
# Delete (删除) 与PV相连的后端存储完成volume的删除操作,常见于云服务商的存储服务
# 不过需要注意的是,目前只有NFS和HostPath两类支持回收策略,一般设置Retain比较保险


# 状态有以下几种
# Available:   PV状态,表示可用状态,还未被任何PVC绑定
# Bound:			已绑定,已经绑定到某个PVC
# Released:    已释放,对应的pvc已经删除,但资源还没有被集群收回
# Failed:      PV自动回收失败
[root@kube-master pv]# kubectl get pv
NAME            CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv-volume-001   1Gi        RWO            Retain           Available           host-manager            77s

PV是有状态的对象,状态类型如下:
# 1Gi:  存储空间大小
# RWO:  访问模式(ReadWriteOnce缩写)
# Recycle:     回收策略
# Available:   PV状态

# persistentVolumeReclaimPolicy回收策略
# Retain (保留) 保留数据,需要管理员手动清理
# Recycle (回收) 清除PV中的数据,效果相当于执行删除命令
# Delete (删除) 与PV相连的后端存储完成volume的删除操作,常见于云服务商的存储服务
# 不过需要注意的是,目前只有NFS和HostPath两类支持回收策略,一般设置Retain比较保险


# 状态有以下几种
# Available:   PV状态,表示可用状态,还未被任何PVC绑定
# Bound:			已绑定,已经绑定到某个PVC
# Released:    已释放,对应的pvc已经删除,但资源还没有被集群收回
# Failed:      PV自动回收失败

5.2 hostpath pvc

1.创建yaml文件

yaml
[root@kube-master pv]# cat 2.hostpath-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim  # 声明该资源类型为PersistentVolumeClaim
metadata:
  name: 001-pvc  # 声明该PersistentVolumeClaim的名称为001-pvc
spec:
  storageClassName: "host-manager"  #和PV的storageclassname须一致,否则无法识别
  accessModes:
    - ReadWriteOnce  # 声明该PersistentVolumeClaim的访问模式为ReadWriteOnce
  resources:
    requests:
      storage: 0.5Gi  # 声明该PersistentVolumeClaim的请求存储空间为0.5Gi,这里的大小不能超过PV的大小
[root@kube-master pv]# cat 2.hostpath-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim  # 声明该资源类型为PersistentVolumeClaim
metadata:
  name: 001-pvc  # 声明该PersistentVolumeClaim的名称为001-pvc
spec:
  storageClassName: "host-manager"  #和PV的storageclassname须一致,否则无法识别
  accessModes:
    - ReadWriteOnce  # 声明该PersistentVolumeClaim的访问模式为ReadWriteOnce
  resources:
    requests:
      storage: 0.5Gi  # 声明该PersistentVolumeClaim的请求存储空间为0.5Gi,这里的大小不能超过PV的大小

2.执行apply

bash
[root@kube-master pv]# kubectl apply -f 2.hostpath-pvc.yaml
persistentvolumeclaim/001-pvc created
[root@kube-master pv]# kubectl apply -f 2.hostpath-pvc.yaml
persistentvolumeclaim/001-pvc created

3.查看状态

bash
[root@kube-master pv]# kubectl get pvc
NAME      STATUS   VOLUME          CAPACITY   ACCESS MODES   STORAGECLASS   AGE
001-pvc   Bound    pv-volume-001   1Gi        RWO            host-manager   3m55s
[root@kube-master pv]# kubectl get pvc
NAME      STATUS   VOLUME          CAPACITY   ACCESS MODES   STORAGECLASS   AGE
001-pvc   Bound    pv-volume-001   1Gi        RWO            host-manager   3m55s
bash
[root@kube-master pv]# kubectl describe pv pv-volume-001
Name:            pv-volume-001
Labels:          <none>
Annotations:     pv.kubernetes.io/bound-by-controller: yes
Finalizers:      [kubernetes.io/pv-protection]
StorageClass:    host-manager
Status:          Bound
Claim:           default/001-pvc
Reclaim Policy:  Retain
Access Modes:    RWO
VolumeMode:      Filesystem
Capacity:        1Gi
Node Affinity:   <none>
Message:
Source:
    Type:          HostPath (bare host directory volume)
    Path:          /mnt/data
    HostPathType:
Events:            <none>
[root@kube-master pv]# kubectl describe pv pv-volume-001
Name:            pv-volume-001
Labels:          <none>
Annotations:     pv.kubernetes.io/bound-by-controller: yes
Finalizers:      [kubernetes.io/pv-protection]
StorageClass:    host-manager
Status:          Bound
Claim:           default/001-pvc
Reclaim Policy:  Retain
Access Modes:    RWO
VolumeMode:      Filesystem
Capacity:        1Gi
Node Affinity:   <none>
Message:
Source:
    Type:          HostPath (bare host directory volume)
    Path:          /mnt/data
    HostPathType:
Events:            <none>
bash
[root@kube-master pv]#  kubectl describe pvc 001-pvc
Name:          001-pvc
Namespace:     default
StorageClass:  host-manager
Status:        Bound
Volume:        pv-volume-001
Labels:        <none>
Annotations:   pv.kubernetes.io/bind-completed: yes
               pv.kubernetes.io/bound-by-controller: yes
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      1Gi
Access Modes:  RWO
VolumeMode:    Filesystem
Used By:       <none>
Events:        <none>
[root@kube-master pv]#  kubectl describe pvc 001-pvc
Name:          001-pvc
Namespace:     default
StorageClass:  host-manager
Status:        Bound
Volume:        pv-volume-001
Labels:        <none>
Annotations:   pv.kubernetes.io/bind-completed: yes
               pv.kubernetes.io/bound-by-controller: yes
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      1Gi
Access Modes:  RWO
VolumeMode:    Filesystem
Used By:       <none>
Events:        <none>

5.3 hostpath pod

1.创建pod

yaml
[root@kube-master pv]# cat 3.pod_hostpath_pvc.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-hostpath-pvc
spec:
  volumes:
  - name: web-storage     # 定义挂载名字
    persistentVolumeClaim:
      claimName: 001-pvc  # 先前定义的pvc名字
  containers:
  - name: nginx
    image: nginx:latest
    volumeMounts:
    - name: web-storage
      mountPath: /usr/share/nginx/html
[root@kube-master pv]# cat 3.pod_hostpath_pvc.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-hostpath-pvc
spec:
  volumes:
  - name: web-storage     # 定义挂载名字
    persistentVolumeClaim:
      claimName: 001-pvc  # 先前定义的pvc名字
  containers:
  - name: nginx
    image: nginx:latest
    volumeMounts:
    - name: web-storage
      mountPath: /usr/share/nginx/html

2.执行apply

bash
[root@kube-master pv]# kubectl apply -f 3.pod_hostpath_pvc.yaml
pod/pod-hostpath-pvc created
[root@kube-master pv]# kubectl apply -f 3.pod_hostpath_pvc.yaml
pod/pod-hostpath-pvc created

3.查看Pod

bash
[root@kube-master pv]# kubectl get pod
NAME                                   READY   STATUS    RESTARTS         AGE
pod-hostpath-pvc                       1/1     Running   0                3m16s
[root@kube-master pv]# kubectl get pod
NAME                                   READY   STATUS    RESTARTS         AGE
pod-hostpath-pvc                       1/1     Running   0                3m16s

4.访问

bash
[root@kube-master pv]# curl 172.30.0.156
hello hostpath pv,pvc
[root@kube-master pv]# curl 172.30.0.156
hello hostpath pv,pvc

6. pv实践

使用NFS作为存储,来演示PV的使用,创建3个PV,对应NFS中的3个暴露的路径

  1. 准备NFS环境
bash
# 创建目录
[root@nfs ~]# mkdir /root/data/{pv1,pv2,pv3} -pv

# 暴露服务
[root@nfs ~]# more /etc/exports
/root/data/pv1     192.168.5.0/24(rw,no_root_squash)
/root/data/pv2     192.168.5.0/24(rw,no_root_squash)
/root/data/pv3     192.168.5.0/24(rw,no_root_squash)

# 重启服务
[root@nfs ~]#  systemctl restart nfs
# 创建目录
[root@nfs ~]# mkdir /root/data/{pv1,pv2,pv3} -pv

# 暴露服务
[root@nfs ~]# more /etc/exports
/root/data/pv1     192.168.5.0/24(rw,no_root_squash)
/root/data/pv2     192.168.5.0/24(rw,no_root_squash)
/root/data/pv3     192.168.5.0/24(rw,no_root_squash)

# 重启服务
[root@nfs ~]#  systemctl restart nfs

2.创建pv.yaml

yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  pv1
spec:
  capacity: 
    storage: 1Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /root/data/pv1
    server: 192.168.5.6

---

apiVersion: v1
kind: PersistentVolume
metadata:
  name:  pv2
spec:
  capacity: 
    storage: 2Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /root/data/pv2
    server: 192.168.5.6
    
---

apiVersion: v1
kind: PersistentVolume
metadata:
  name:  pv3
spec:
  capacity: 
    storage: 3Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /root/data/pv3
    server: 192.168.5.6
apiVersion: v1
kind: PersistentVolume
metadata:
  name:  pv1
spec:
  capacity: 
    storage: 1Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /root/data/pv1
    server: 192.168.5.6

---

apiVersion: v1
kind: PersistentVolume
metadata:
  name:  pv2
spec:
  capacity: 
    storage: 2Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /root/data/pv2
    server: 192.168.5.6
    
---

apiVersion: v1
kind: PersistentVolume
metadata:
  name:  pv3
spec:
  capacity: 
    storage: 3Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /root/data/pv3
    server: 192.168.5.6
shell
# 创建 pv
[root@k8s-master01 ~]# kubectl create -f pv.yaml
persistentvolume/pv1 created
persistentvolume/pv2 created
persistentvolume/pv3 created

# 查看pv
[root@k8s-master01 ~]# kubectl get pv -o wide
NAME   CAPACITY   ACCESS MODES  RECLAIM POLICY  STATUS      AGE   VOLUMEMODE
pv1    1Gi        RWX            Retain        Available    10s   Filesystem
pv2    2Gi        RWX            Retain        Available    10s   Filesystem
pv3    3Gi        RWX            Retain        Available    9s    Filesystem
# 创建 pv
[root@k8s-master01 ~]# kubectl create -f pv.yaml
persistentvolume/pv1 created
persistentvolume/pv2 created
persistentvolume/pv3 created

# 查看pv
[root@k8s-master01 ~]# kubectl get pv -o wide
NAME   CAPACITY   ACCESS MODES  RECLAIM POLICY  STATUS      AGE   VOLUMEMODE
pv1    1Gi        RWX            Retain        Available    10s   Filesystem
pv2    2Gi        RWX            Retain        Available    10s   Filesystem
pv3    3Gi        RWX            Retain        Available    9s    Filesystem

7. pvc实践

  1. 创建pvc.yaml,申请pv
yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1
  namespace: dev
spec:
  accessModes: 
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc2
  namespace: dev
spec:
  accessModes: 
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc3
  namespace: dev
spec:
  accessModes: 
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1
  namespace: dev
spec:
  accessModes: 
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc2
  namespace: dev
spec:
  accessModes: 
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc3
  namespace: dev
spec:
  accessModes: 
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
shell
# 创建pvc
[root@k8s-master01 ~]# kubectl create -f pvc.yaml
persistentvolumeclaim/pvc1 created
persistentvolumeclaim/pvc2 created
persistentvolumeclaim/pvc3 created

# 查看pvc
[root@k8s-master01 ~]# kubectl get pvc  -n dev -o wide
NAME   STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE   VOLUMEMODE
pvc1   Bound    pv1      1Gi        RWX                           15s   Filesystem
pvc2   Bound    pv2      2Gi        RWX                           15s   Filesystem
pvc3   Bound    pv3      3Gi        RWX                           15s   Filesystem

# 查看pv
[root@k8s-master01 ~]# kubectl get pv -o wide
NAME  CAPACITY ACCESS MODES  RECLAIM POLICY  STATUS    CLAIM       AGE     VOLUMEMODE
pv1    1Gi        RWx        Retain          Bound    dev/pvc1    3h37m    Filesystem
pv2    2Gi        RWX        Retain          Bound    dev/pvc2    3h37m    Filesystem
pv3    3Gi        RWX        Retain          Bound    dev/pvc3    3h37m    Filesystem
# 创建pvc
[root@k8s-master01 ~]# kubectl create -f pvc.yaml
persistentvolumeclaim/pvc1 created
persistentvolumeclaim/pvc2 created
persistentvolumeclaim/pvc3 created

# 查看pvc
[root@k8s-master01 ~]# kubectl get pvc  -n dev -o wide
NAME   STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE   VOLUMEMODE
pvc1   Bound    pv1      1Gi        RWX                           15s   Filesystem
pvc2   Bound    pv2      2Gi        RWX                           15s   Filesystem
pvc3   Bound    pv3      3Gi        RWX                           15s   Filesystem

# 查看pv
[root@k8s-master01 ~]# kubectl get pv -o wide
NAME  CAPACITY ACCESS MODES  RECLAIM POLICY  STATUS    CLAIM       AGE     VOLUMEMODE
pv1    1Gi        RWx        Retain          Bound    dev/pvc1    3h37m    Filesystem
pv2    2Gi        RWX        Retain          Bound    dev/pvc2    3h37m    Filesystem
pv3    3Gi        RWX        Retain          Bound    dev/pvc3    3h37m    Filesystem

2.创建pods.yaml, 使用pv

yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod1
  namespace: dev
spec:
  containers:
  - name: busybox
    image: busybox:1.30
    command: ["/bin/sh","-c","while true;do echo pod1 >> /root/out.txt; sleep 10; done;"]
    volumeMounts:
    - name: volume
      mountPath: /root/
  volumes:
    - name: volume
      persistentVolumeClaim:
        claimName: pvc1
        readOnly: false
---
apiVersion: v1
kind: Pod
metadata:
  name: pod2
  namespace: dev
spec:
  containers:
  - name: busybox
    image: busybox:1.30
    command: ["/bin/sh","-c","while true;do echo pod2 >> /root/out.txt; sleep 10; done;"]
    volumeMounts:
    - name: volume
      mountPath: /root/
  volumes:
    - name: volume
      persistentVolumeClaim:
        claimName: pvc2
        readOnly: false
apiVersion: v1
kind: Pod
metadata:
  name: pod1
  namespace: dev
spec:
  containers:
  - name: busybox
    image: busybox:1.30
    command: ["/bin/sh","-c","while true;do echo pod1 >> /root/out.txt; sleep 10; done;"]
    volumeMounts:
    - name: volume
      mountPath: /root/
  volumes:
    - name: volume
      persistentVolumeClaim:
        claimName: pvc1
        readOnly: false
---
apiVersion: v1
kind: Pod
metadata:
  name: pod2
  namespace: dev
spec:
  containers:
  - name: busybox
    image: busybox:1.30
    command: ["/bin/sh","-c","while true;do echo pod2 >> /root/out.txt; sleep 10; done;"]
    volumeMounts:
    - name: volume
      mountPath: /root/
  volumes:
    - name: volume
      persistentVolumeClaim:
        claimName: pvc2
        readOnly: false
shell
# 创建pod
[root@k8s-master01 ~]# kubectl create -f pods.yaml
pod/pod1 created
pod/pod2 created

# 查看pod
[root@k8s-master01 ~]# kubectl get pods -n dev -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP            NODE   
pod1   1/1     Running   0          14s   10.244.1.69   node1   
pod2   1/1     Running   0          14s   10.244.1.70   node1  

# 查看pvc
[root@k8s-master01 ~]# kubectl get pvc -n dev -o wide
NAME   STATUS   VOLUME   CAPACITY   ACCESS MODES      AGE   VOLUMEMODE
pvc1   Bound    pv1      1Gi        RWX               94m   Filesystem
pvc2   Bound    pv2      2Gi        RWX               94m   Filesystem
pvc3   Bound    pv3      3Gi        RWX               94m   Filesystem

# 查看pv
[root@k8s-master01 ~]# kubectl get pv -n dev -o wide
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM       AGE     VOLUMEMODE
pv1    1Gi        RWX            Retain           Bound    dev/pvc1    5h11m   Filesystem
pv2    2Gi        RWX            Retain           Bound    dev/pvc2    5h11m   Filesystem
pv3    3Gi        RWX            Retain           Bound    dev/pvc3    5h11m   Filesystem

# 查看nfs中的文件存储
[root@nfs ~]# more /root/data/pv1/out.txt
node1
node1
[root@nfs ~]# more /root/data/pv2/out.txt
node2
node2
# 创建pod
[root@k8s-master01 ~]# kubectl create -f pods.yaml
pod/pod1 created
pod/pod2 created

# 查看pod
[root@k8s-master01 ~]# kubectl get pods -n dev -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP            NODE   
pod1   1/1     Running   0          14s   10.244.1.69   node1   
pod2   1/1     Running   0          14s   10.244.1.70   node1  

# 查看pvc
[root@k8s-master01 ~]# kubectl get pvc -n dev -o wide
NAME   STATUS   VOLUME   CAPACITY   ACCESS MODES      AGE   VOLUMEMODE
pvc1   Bound    pv1      1Gi        RWX               94m   Filesystem
pvc2   Bound    pv2      2Gi        RWX               94m   Filesystem
pvc3   Bound    pv3      3Gi        RWX               94m   Filesystem

# 查看pv
[root@k8s-master01 ~]# kubectl get pv -n dev -o wide
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM       AGE     VOLUMEMODE
pv1    1Gi        RWX            Retain           Bound    dev/pvc1    5h11m   Filesystem
pv2    2Gi        RWX            Retain           Bound    dev/pvc2    5h11m   Filesystem
pv3    3Gi        RWX            Retain           Bound    dev/pvc3    5h11m   Filesystem

# 查看nfs中的文件存储
[root@nfs ~]# more /root/data/pv1/out.txt
node1
node1
[root@nfs ~]# more /root/data/pv2/out.txt
node2
node2