Skip to content

1. PV与PVC基本概念

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.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的容量,访问模式和回收策略等属性。

3.1 PV配置字段详解

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

4. PVC资源实践

4.1 PVC配置字段详解

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

参数描述
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