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即可完成存储卷的绑定和使用。这样大大的简化了用户使用存储的方式。
💡 说明
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⽣命周期
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等相关信息即可
参数 | 描述 |
---|---|
accessModes | PVC的访问模式;它同样⽀持RWO、RWX、ROX三种 ⽅式; |
resources | 申明使⽤的存储空间的最⼩值和最⼤值; |
selector | 筛选PV时额外使⽤的标签选择器; |
volumeName | 直接指定要绑定的PV资源名称; |
strogeClassName | 指定从哪类存储资源下筛选PV,如果指定的名 称不存在,则⽆法绑定成功。如果指定的资源下没有符合的空间也⽆ 法绑定成功。⽐如申请20G空间,但pv都只有10G空间,则⽆法满 ⾜ |
5. 静态案例
在节点执⾏如下操作,建议所有节点操作,因为不确定Pod会调度⾄哪个节点;(⽣产不建议使⽤HostPath⽅式)
静态存储
5.1 hostpath pv
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文件
[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
[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.查看
[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文件
[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
[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.查看状态
[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
[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>
[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
[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
[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
[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.访问
[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