PV、PVC概念
持久卷(PersistentVolume,PV)是集群中的一块存储,可以由管理员事先供应,或者 使用存储类(Storage Class)来动态供应。 持久卷是集群资源,就像节点也是集群资源一样。PV 持久卷和普通的 Volume 一样,也是使用 卷插件来实现的,只是它们拥有独立于任何使用 PV 的 Pod 的生命周期。 此 API 对象中记述了存储的实现细节,无论其背后是 NFS、iSCSI 还是特定于云平台的存储系统。
持久卷申请(PersistentVolumeClaim,PVC)表达的是用户对存储的请求。概念上与 Pod 类似。 Pod 会耗用节点资源,而 PVC 申领会耗用 PV 资源。Pod 可以请求特定数量的资源(CPU 和内存);同样 PVC 申领也可以请求特定的大小和访问模式 ;
用户在创建pod时使用存储卷只需要关心对应名称空间的pvc对象;而对应pv是需要集群管理管理员定义;后端存储是专门的存储管理员负责管理;pv是k8s上的一种标准资源,全称叫做 PersistentVolume
翻译成中文就是持久存储卷;它主要作用是把后端存储中的某个逻辑单元,映射为k8s上的pv资源;pv是集群级别的资源;任意名称空间都可以直接关联某一个pv;关联pv的过程我们叫做绑定pv;而对应名称空间关联某一pv需要使用pvc资源来定义;pvc全称PersistentVolumeClaim的缩写,意思就是持久存储卷申请;
在一个名称空间下创建一个pvc就是把对应名称空间同集群上的某一pv做绑定;一旦一个名称空间绑定了一个pv后,对应的pv就会从available状态转变成bond状态,其他名称空间将不能再使用,只有对应pv是available状态才能正常的被其他名称空间关联绑定;
简单讲pvc和pv的关系是一一对应的,一个pv只能对应一个pvc;至于同一名称空间下的多个pod是否能够同时使用一个PVC取决pv是否允许多路读写,对应pv是否支持多路读写取决后端存储系统;不同类型的存储系统,对应访问模式也有所不同。访问模式有三种,单路读写(ReadWriteOnce简称RWO),多路读写(ReadWriteMany简称RWX),多路只读(ReadOnlyMany简称ROX);
PV、PVC、和POD的关系如下图:
示例
创建pv的yaml文件
$:~/kubernetes/pv$ cat pv-v1.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv-v1
labels:
storsystem: nfs-v1
rel: stable
spec:
capacity:
storage: 1Gi
volumeMode: Filesystem
accessModes: ["ReadWriteOnce","ReadWriteMany","ReadOnlyMany"]
persistentVolumeReclaimPolicy: Retain
mountOptions:
- hard
- nfsvers=4.1
nfs:
path: /nfs/data
server: 10.1.3.205
创建PV资源以及PV字段详解
kind
在创建pv的配置文件时, kind
字段要指定为 PersistentVolume
spec.capcity
这个字段是对持久性卷的资源和容量的描述;spec.capacity.storage
字段用来描述pv的存储用量;
为了序列化,关于存储容量使用 storage
字段来声明,值是使用 i
来结尾,比如 1Gi
、150Mi
。
spec.volumeMode
spec.volumeMode
字段用来描述对应存储系统提供的存储卷类型接口;该字段有以下这些值:
- Filesystem(文件系统)
- Block(块)
默认是
Filesystem
spec.accessModes
spec.accessModes
代表着这个卷在挂载pod上的访问模式,该字段有以下值:
ReadWriteOnce
卷可以被一个节点以读写方式挂载。 ReadWriteOnce 访问模式也允许运行在同一节点上的多个 Pod 访问卷。
ReadOnlyMany
卷可以被多个节点以只读方式挂载。
ReadWriteMany
卷可以被多个节点以读写方式挂载。
ReadWriteOncePod
卷可以被单个 Pod 以读写方式挂载。 如果你想确保整个集群中只有一个 Pod 可以读取或写入该 PVC, 请使用ReadWriteOncePod 访问模式。这只支持 CSI 卷以及需要 Kubernetes 1.22 以上版本。
在命令行接口(CLI)中,访问模式也使用以下缩写形式:
- RWO - ReadWriteOnce
- ROX - ReadOnlyMany
- RWX - ReadWriteMany
- RWOP - ReadWriteOncePod
spec.persistentVolumeReclaimPolicy
该字段代表着一个PV卷被释放时所出的动作和存储卷回收策略,持久卷回收策略有3种:Delete
表示当pvc删除以后,对应pv也随之删除;
Recycle
表示当pvc删除以后,对应pv的数据也随之被删除;
Retain
表示当pvc被删除以后,pv原封动,即pv也在,对应数据也在
该卷如果是手动创建,那回收策略默认是Recycle;
如果是动态创建,回收策略则是Delete
spec.mountOptions
mountOptions字段用来指定挂载选项,具体请看kubernetes官网-持久卷挂载选项
spec.nodeAffinity
每个 PV 卷可以通过设置节点亲和性来定义一些约束,进而限制从哪些节点上可以访问此卷。 使用这些卷的 Pod 只会被调度到节点亲和性规则所选择的节点上执行。 要设置节点亲和性,配置 PV 卷 .spec
中的 nodeAffinity
。 持久卷 API 参考关于该字段的更多细节。
spec.storageClassName
此持久卷卷所属的StorageClass的名称。空值表示此卷不属于任何StorageClass。
想要查看更详细的文件字段信息,请查看kubernetesAPI文档—PersistentVolumeSpec
PV的状态
每个卷会处于以下阶段(Phase)之一:Available(可用)
卷是一个空闲资源,尚未绑定到任何申领;
Bound(已绑定)
该卷已经绑定到某申领;
Released(已释放)
所绑定的申领已被删除,但是资源尚未被集群回收;
Failed(失败)
卷的自动回收操作失败。
查看PV状态
使用命令 describe
查看PV的详细状态
$ kubectl describe pv nfs-pv-v1
Name: nfs-pv-v1
Labels: rel=stable
storsystem=nfs-v1
Annotations: <none>
Finalizers: [kubernetes.io/pv-protection]
StorageClass:
Status: Available
Claim:
Reclaim Policy: Retain
Access Modes: RWO,ROX,RWX
VolumeMode: Filesystem
Capacity: 1Gi
Node Affinity: <none>
Message:
Source:
Type: NFS (an NFS mount that lasts the lifetime of a pod)
Server: 10.1.3.205
Path: /nfs/data
ReadOnly: false
Events: <none>
从上面信息可以看出,该PV的状态为Available
,回收策略是Retain
,访问模式是RWO,ROX,RWX
,卷模式是Filesystem
,容量为 1G,卷类型是 nfs
,地址是10.1.3.205,path地址是/nfs/data
创建PVC资源
$ cat pvc-v1.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-pv
namespace: default
labels:
storsystem: nfs-v1
spec:
accessModes:
- ReadWriteMany
volumeMode: Filesystem
resources:
requests:
storage: 500Mi
limits:
storage: 800Mi
selector:
matchLabels:
storsystem: nfs-v1
rel: stable
kind
在创建pv的配置文件时, kind
字段要指定为 PersistentVolumeClaim
spec.accessModes
spec.accessModes字段是用来指定其pvc的访问模式,一般这个模式是被pv的accessModes包含,也就说pvc的访问模式必须是pv的子集,即等于小于pv的访问模式;
spec.volumeMode
与PV资源的配置保持一致
spec.resources
resources用来描述对应pvc的存储空间限制,requests用来描述对应pvc最小容量限制,limits用来描述最大容量限制;
spec.selector
标签选择器,声明可以指定标签选择器以进一步筛选卷集。只有标签与选择器匹配的卷才能绑定到声明。选择器可以由两个字段组成matchLabels
卷必须具有具有此值的标签
matchExpressions
通过指定键、值列表以及与键和值相关的运算符而制定的要求列表。有效运算符包括In、NotIn、Exists和DOESNOTEXTIST。
所有的需求,从匹配标签和匹配表达式,都是和在一起的——它们必须全部满足才能匹配。
应用该pvc配置文件,在查看pv和pvc的状态
## 获取pv信息
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
nfs-pv-v1 1Gi RWO,ROX,RWX Retain Bound default/pvc-pv 23h
## 获取pvc信息
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc-pv Bound nfs-pv-v1 1Gi RWO,ROX,RWX 28m
从以上信息可以看出,在应用PVC配置之后,PV的状态就由 Available
转变为 Bound
,已经被PVC所绑定。
创建Pod挂载PVC
创建Pod的配置文件
$ cat pod-pv-nginx-yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pv
namespace: default
labels:
app: tomcat
spec:
containers:
- name: nginx
image: nginx:1.14-alpine
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /nfs/data
name: nfs-pv
volumes:
- name: nfs-pv
persistentVolumeClaim:
claimName: pvc-pv
pod在使用PVC的时候只需要在 spec.volumes
字段中声明该卷的类型是PVC,然后填上PVC的名字即可;
应用该配置,进入容器内的/nfs/data目录中写入数据,看nfs卷中是否有相对应的数据出现;
## 进入容器中
$ kubectl exec -it pod/nginx-pv -- sh
/ # ls /nfs/data
index.html
## 进入挂载目录并且创建文件
/ # cd /nfs/data
/ # touch test-nfs-pv
/ # ls
index.html test-nfs-pv
## 退出容器,进入nfs挂载目录,看是否已经有对应的test-nfs-pv文件了
$ cd /nfs/data
:/nfs/data$ ls
index.html test-nfs-pv
## 挂载成功
删除PV、PVC和Pod
在pod有挂载PVC,PVC又绑定PV的情况下,正确的删除顺序是
- 删除pod
- 删除PVC
- 删除PV
如果没有按照这个顺序去删除的话,会出现一些情况:
在没有删除pod的情况下,删除pvc
删除操作会被阻塞,结束操作后在查看pvc,状态为 Terminating
在没有删除pod的情况下,删除pv
删除操作会被阻塞,状态为 Terminating
正确删除顺序删除pod、pvc、pv
删除pod后,对应的pvc状态保持不变;删除对应pvc以后,对应pv的状态就从bound状态转变为Released状态,表示等待回收;我们在资源清单中使用的是Retain回收策略,pv和pvc都是我们人工手动回收;