[Kubernetes]PV,PVC,StorageClass之间的关系详解----|_码农崛起-CSDN博客
1.1 介绍
目的: 为了屏蔽底层存储实现的细节, 让用户方便使用同时让管理员方便管理, 引入了pv与pvc两种资源对象实现对存储的管理子系统
pv: 对底层网络共享存储的抽象, 将共享存储定义为一种资源
pvc: 用户对存储资源的一个神奇, 就像pod消费node的cpu,内存等资源一样, pvc能够消费pv资源, pvc可以申请特定存储空间和访问模式
StorageClass :标记存储资源的特性和性能, 在1.6版本, StorageClass与动态资源供应的机制得到了完善, 实现了存储卷的按需创建
管理存储是管理计算的一个明显问题。该PersistentVolume子系统为用户和管理员提供了一个API,用于抽象如何根据消费方式提供存储的详细信息。为此,我们引入了两个新的API资源:PersistentVolume和PersistentVolumeClaim
PersistentVolume(PV)是集群中由管理员配置的一段网络存储。 它是集群中的资源,就像节点是集群资源一样。 PV是容量插件,如Volumes,但其生命周期独立于使用PV的任何单个pod。 此API对象捕获存储实现的详细信息,包括NFS,iSCSI或特定于云提供程序的存储系统。
PersistentVolumeClaim(PVC)是由用户进行存储的请求。 它类似于pod。 Pod消耗节点资源,PVC消耗PV资源。Pod可以请求特定级别的资源(CPU和内存)。声明可以请求特定的大小和访问模式(例如,可以一次读/写或多次只读)。
虽然PersistentVolumeClaims允许用户使用抽象存储资源,但是PersistentVolumes对于不同的问题,用户通常需要具有不同属性(例如性能)。群集管理员需要能够提供各种PersistentVolumes不同的方式,而不仅仅是大小和访问模式,而不会让用户了解这些卷的实现方式。对于这些需求,有StorageClass 资源。
StorageClass为管理员提供了一种描述他们提供的存储的“类”的方法。 不同的类可能映射到服务质量级别,或备份策略,或者由群集管理员确定的任意策略。 Kubernetes本身对于什么类别代表是不言而喻的。 这个概念有时在其他存储系统中称为“配置文件”。
PVC和PV是一一对应的。
PV和StorageClass不受限于Namespace,PVC受限于Namespace,Pod在引用PVC时同样受Namespace的限制,只有相同Namespace中的PVC才能挂载到Pod内。
StorageClass:
[root@jettoloader nfs]# k3s kubectl describe storageclass.storage.k8s.io/jettech-nfs-storage
Name: jettech-nfs-storage
IsDefaultClass: Yes
Annotations: kubectl.kubernetes.io/last-applied-configuration={"allowVolumeExpansion":true,"apiVersion":"storage.k8s.io/v1","kind":"StorageClass","metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"},"name":"jettech-nfs-storage"},"mountOptions":["hard","nfsvers=4"],"parameters":{"archiveOnDelete":"true"},"provisioner":"jettech.com/nfs-jettech-external-provisioner","reclaimPolicy":"Retain","volumeBindingMode":"Immediate"}
,storageclass.kubernetes.io/is-default-class=true
Provisioner: jettech.com/nfs-jettech-external-provisioner
Parameters: archiveOnDelete=true
AllowVolumeExpansion: True
MountOptions:
hard
nfsvers=4
ReclaimPolicy: Retain
VolumeBindingMode: Immediate
Events:
PV:
[root@localhost pv]# k3s kubectl describe -n wubo persistentvolume/pv1
Name: pv1
Labels: name=wubo-pv1
Annotations:
Finalizers: [kubernetes.io/pv-protection]
StorageClass:
Status: Available
Claim:
Reclaim Policy: Retain
Access Modes: RWX
VolumeMode: Filesystem
Capacity: 5Gi
Node Affinity:
Message:
Source:
Type: NFS (an NFS mount that lasts the lifetime of a pod)
Server: 172.16.10.5
Path: /opt/vlumes
ReadOnly: false
Events:
pvc:
[root@localhost pv]# k3s kubectl describe persistentvolumeclaim/pvc1 -n wuqi
Name: pvc1
Namespace: wuqi
StorageClass:
Status: Bound
Volume: pv1
Labels:
Annotations: pv.kubernetes.io/bind-completed: yes
pv.kubernetes.io/bound-by-controller: yes
Finalizers: [kubernetes.io/pvc-protection]
Capacity: 5Gi
Access Modes: RWX
VolumeMode: Filesystem
Used By:
Events:
可见PV和StorageClass是没有namespace字段的,只有PVC有namespace字段,在申明PV和StorageClass的时候加上namespace也不起作用。属于全局整体的
Persistent Volume(持久化卷)简称PV, 是一个K8S资源对象,我们可以单独创建一个PV, 它不和Pod直接发生关系, 而是通过Persistent Volume Claim, 简称PVC来实现动态绑定, 我们会在Pod定义里指定创建好的PVC, 然后PVC会根据Pod的要求去自动绑定合适的PV给Pod使用。
PVC匹配pv的策略:根据存储大小(pvc申请资源的大小应该小于等于pv申明的大小),访问模式(只读,读写),K8S会自动匹配符合条件的pv.
也就是说
PV和PVC:都有如下访问策略,相同才可以匹配上,也可以pv定义lable,pvc进行匹配
accessModes
指定访问模式为 ReadWriteOnce
,支持的访问模式有:
ReadWriteOnce – PV 能以 read-write 模式 mount 到单个节点。
ReadOnlyMany – PV 能以 read-only 模式 mount 到多个节点。
ReadWriteMany – PV 能以 read-write 模式 mount 到多个节点。
持久化卷下PV和PVC概念:
Persistent Volume(PV)是由管理员设置的存储,它是群集的一部分。就像节点是集群中的资源一样,PV 也是集群中的资源。 PV 是 Volume 之类的卷插件,但具有独立于使用 PV 的 Pod 的生命周期。此 API 对象包含存储实现的细节,即 NFS、iSCSI 或特定于云供应商的存储系统。
PersistentVolumeClaim(PVC)是用户存储的请求。它与 Pod 相似,Pod 消耗节点资源,PVC 消耗 PV 资源。Pod 可以请求特定级别的资源(CPU 和内存)。PVC声明可以请求特定的大小和访问模式(例如,可以以读/写一次或只读多次模式挂载)。有了PersistentVolumeClaim,用户只需要告诉Kubernetes需要什么样的存储资源,而不必关心真正的空间从哪里分配,如何访问等底层细节信息;这些Storage Provider的底层信息交给管理员来处理,只有管理员才应该关心创建PersistentVolume的细节信息
它和普通Volume的区别是什么呢?
普通Volume和使用它的Pod之间是一种静态绑定关系,在定义Pod的文里,同时定义了它使用的Volume。Volume是Pod的附属品,我们无法单独创建一个Volume,因为它不是一个独立的K8S资源对象。
1.2 生命周期
PV是群集中的资源。PVC是对这些资源的请求,并且还充当对资源的检查。PV和PVC之间的相互作用遵循以下生命周期:
Provisioning ——-> Binding ——–>Using——>Releasing——>Recycling
注:目前只有NFS和HostPath类型卷支持回收策略,AWS EBS,GCE PD,Azure Disk和Cinder支持删除(Delete)策略。
1.3 PV类型
1.4 PV卷阶段状态
所有节点安装nfs,找一个几点做nfs服务端即可,其他节点只需要安装就可
[root@localhost pv]# yum install nfs-utils
[root@localhost pv]# cat /etc/exports
/opt/vlumes *(rw,no_root_squash)
[root@localhost pv]# systemctl enable nfs --now
在创建PV之前先创建2个ns
[root@localhost pv]# kubectl create ns wuqi
[root@localhost pv]# kubectl create ns wubo
PV:
[root@localhost pv]# cat pv1.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv1
labels: {name: wubo-pv1}
namespace: wubo
spec:
capacity: #容量
storage: 5Gi
accessModes: #访问模式
#- ReadWriteOnce
#- ReadWriteOncePod
- ReadWriteMany
#- ReadOnlyMany
persistentVolumeReclaimPolicy: Retain #Retain[手动删除] Delete[AWS EBS, GCE PD, Azure Disk 和 Cinder 支持] Recycle [NFS 和 HostPath] rm -rf
mountOptions:
- hard
- nolock
- nfsvers=3
#storageClassName: nfs
nfs:
path: /opt/vlumes
server: 172.16.10.5
参数解释:
1)capacity
指定 PV 的容量为 5G。
2) accessModes
指定访问模式为 ReadWriteOnce
,支持的访问模式有:
ReadWriteOnce – PV 能以 read-write 模式 mount 到单个节点。
ReadOnlyMany – PV 能以 read-only 模式 mount 到多个节点。
ReadWriteMany – PV 能以 read-write 模式 mount 到多个节点。
ReadWriteOncePod(k8s v1.22新特性:卷的ReadWriteOncePod访问模式)(翻)k8s v1.22新特性:卷的ReadWriteOncePod访问模式 - 简书
3) reclaim policy: 回收策略, pvc和pv解绑,删除了pvc。pv里面的数据是否还保留persistentVolumeReclaimPolicy
指定当PV 的回收策略为 Recycle
,即 PVC 释放卷的时候 PV 该如何操作).支持的策略有:
3.1)Retain – 需要管理员手工回收。不清理保留数据。即删除pvc或者pv后,在插件上的数据 (nfs服务端)不会被删除。这种方式是最常用的,可以避免误删pvc或者pv而造成数据的丢失
3.2)Recycle – 清除 PV 中的数据,不保留数据。经测试pvc删除后,在nfs服务端的数据也会随机删除。只有hostPath和NFS支持这种方式。效果相当于执行 rm -rf /thevolume/*
。
3.3)Delete – 删除 Storage Provider 上的对应存储资源,例如 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。
4)mountOptions:挂载参数
5)storageClassName
指定 PV 的 class 为 nfs
。相当于为 PV 设置了一个分类,PVC 可以指定 class 申请相应 class 的 PV。 此处用的是静态的PV。
6)指定 PV 在 NFS 服务器上对应的目录
1)available : 表示当前的pv没有被绑定
2)bound: 已经被pvc挂载
3)released: pvc没有在使用pv, 需要管理员手工释放pv
4)failed: 资源回收失败
创建pv:pv1 状态是Available
[root@localhost pv]# kubectl get pv,pvc,pods -o wide
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv1 5Gi RWX Retain Available 4s Filesystem
STATUS
为 Available
,表示 pv1就绪,可以被 PVC 申请
1)接下来创建 PVC 大小2G 在wubo的namespace下 pvc1,配置文件pvc1.yml
如下:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc1
namespace: wubo
spec:
accessModes: #访问模式
#- ReadWriteOnce
#- ReadWriteOncePod
- ReadWriteMany
#- ReadOnlyMany
resources: #申请资源,8Gi存储空间
requests:
storage: 2Gi
#storageClassName: nfs
selector:
matchLabels:
name: "wubo-pv1"
# matchExpressions:
# - {key: environment, operator: In, values: [dev]}
参数详解:
1)accessModes: 申请的访问模式必须与pv相同
2)resources: 资源请求, 既空间大小,要小于pv申明的大小
3)storageClassName: 存储类别, 要和PV申明的相同
4)selector: 根据标签选择器把pvc与pv进行绑定, matchLabels和matchExpressions是且的关系,必须同时满足才可以,动态创建pv不适合配置选择器,可以选择node节点,给node添加lable
只有pvc受namespace影响。pv不受namespace影响
执行命令创建 pvc1
:
[root@localhost pv]# kubectl get pv,pvc,pods -o wide -n wubo
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv1 5Gi RWX Retain Bound wubo/pvc1 6m43s Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc1 Bound pv1 5Gi RWX 7s Filesystem
观察发现NAME pv:pv1已经被pvc:CLAIM wubo/pvc1 申请成功了,STATUS pv状态是bound,RECLAIM POLICY回收策略是Retain, ACCESS MODES访问权限是RWX,CAPACITY大小是5G
2) 接下来创建 PVC 大小6G 在wubo的namespace下 pvc1,配置文件pvc1.yml
如下:
[root@localhost pv]# cat pvc1.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc1
namespace: wubo
spec:
accessModes: #访问模式
#- ReadWriteOnce
#- ReadWriteOncePod
- ReadWriteMany
#- ReadOnlyMany
resources: #申请资源,8Gi存储空间
requests:
storage: 6Gi #此处如果是大于5G 就会申请不成功
#storageClassName: nfs
观察pvc是pending状态,申请的大于申明的6G>5G
[root@localhost pv]# kubectl get pv,pvc,pods -o wide -n wubo
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv1 5Gi RWX Retain Available 17s Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc1 Pending 5s Filesystem
[root@localhost pv]# k3s kubectl describe -n wubo persistentvolumeclaim/pvc1
Name: pvc1
Namespace: wubo
StorageClass:
Status: Pending
Volume:
Labels:
Annotations:
Finalizers: [kubernetes.io/pvc-protection]
Capacity:
Access Modes:
VolumeMode: Filesystem
Used By:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal FailedBinding 4s (x2 over 16s) persistentvolume-controller no persistent volumes available for this claim and no storage class is set
刚添加的 PVC 状态是 Pending,如果有合适的 PV,这个 Pending 状态会立刻变为 Bound 状态,同时相应的 PVC 也会变为 Bound,PVC 和 PV 进行了绑定。我们可以先添加 PVC,后添加 PV,这样就能保证看到 Pending 状态。
[root@localhost pv]# cat nginx.yaml
apiVersion: v1
kind: Service
metadata:
labels: {name: nginx}
name: nginx
namespace: wubo
spec:
ports:
- {name: t9080, nodePort: 30002, port: 80, protocol: TCP, targetPort: 80}
selector: {name: nginx}
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: wubo
labels: {name: nginx}
spec:
replicas: 1
selector:
matchLabels: {name: nginx}
template:
metadata:
name: nginx
labels: {name: nginx}
spec:
containers:
- name: nginx
#image: harbor.jettech.com/jettechtools/nginx:1.21.4
#image: 172.16.10.5:5000/library/nginx:1.21.4
image: docker.io/library/nginx:1.21.4
volumeMounts:
- name: volv
mountPath: /data
volumes:
- name: volv
persistentVolumeClaim:
claimName: pvc1
查看
[root@localhost pv]# kubectl get pv,pvc,pods -o wide -n wubo
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv1 5Gi RWX Retain Bound wubo/pvc1 25s Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc1 Bound pv1 5Gi RWX 21s Filesystem
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/nginx-5cc4bd9557-4ghwx 1/1 Running 0 14s 10.42.1.94 172.16.10.21
测试数据:目前pv的策略是
persistentVolumeReclaimPolicy: Retain #Retain[手动删除] 也就是数据是保留的。
nfs共享目录没有数据:
[root@localhost pv]# ls /opt/vlumes/
进入容器,创建数据
[root@localhost pv]# kubectl exec -it pod/nginx-5cc4bd9557-kvtp5 -n wubo sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
# cd /data
# mkdir wubo
# cd wubo
# echo aaaaaaaaa > a.txt
# cat a.txt
aaaaaaaaa
# pwd
/data/wubo
在看nfs共享目录
[root@localhost pv]# cat /opt/vlumes/wubo/a.txt
aaaaaaaaa
[root@localhost pv]#
删除nginx的pod
[root@localhost pv]# kubectl delete -f nginx.yaml
service "nginx" deleted
deployment.apps "nginx" deleted
[root@localhost pv]# kubectl get pv,pvc,pods -o wide -n wubo
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv1 5Gi RWX Retain Bound wubo/pvc1 3m Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc1 Bound pv1 5Gi RWX 2m58s Filesystem
再次检查nfs共享目录,发现数据存在
[root@localhost pv]# cat /opt/vlumes/wubo/a.txt
aaaaaaaaa
再次启动pod,并且检查容器内数据是否可用
[root@localhost pv]# kubectl create -f nginx.yaml
service/nginx created
deployment.apps/nginx created
[root@localhost pv]# kubectl get pv,pvc,pods -o wide -n wubo
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv1 5Gi RWX Retain Bound wubo/pvc1 9m20s Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc1 Bound pv1 5Gi RWX 9m18s Filesystem
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/nginx-5cc4bd9557-2dvr7 1/1 Running 0 3s 10.42.1.96 172.16.10.21
[root@localhost pv]# kubectl exec -it pod/nginx-5cc4bd9557-2dvr7 -n wubo sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
# cd /data/wubo
# cat a.txt
aaaaaaaaa
容器内部
# mount
172.16.10.5:/opt/vlumes on /data type nfs (rw,relatime,vers=3,rsize=1048576,wsize=1048576,namlen=255,hard,nolock,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=172.16.10.5,mountvers=3,mountport=20048,mountproto=udp,local_lock=all,addr=172.16.10.5)
pod所在的node上面
[root@jettoloader ~]# mount | grep 172.16.10.5
172.16.10.5:/opt/vlumes on /var/lib/kubelet/pods/e90ec0b6-365c-4d38-8b0e-d903a4dc17be/volumes/kubernetes.io~nfs/pv1 type nfs (rw,relatime,vers=3,rsize=1048576,wsize=1048576,namlen=255,hard,nolock,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=172.16.10.5,mountvers=3,mountport=20048,mountproto=udp,local_lock=all,addr=172.16.10.5
所以其实就是nfs的挂载把nfs挂载node节点上/var/lib/kubelet/pods/e90ec0b6-365c-4d38-8b0e-d903a4dc17be/volumes/kubernetes.io~nfs/pv1这个目录。然后/var/lib/kubelet/pods/e90ec0b6-365c-4d38-8b0e-d903a4dc17be/volumes/kubernetes.io~nfs/pv1目录作为容器里面的/data目录映射在一起。这点这里有介绍https://blog.csdn.net/Michaelwubo/article/details/122664428
2.4.1 删除 PV
由于现在 PVC 和 PV 已经是处于绑定状态了,那么如果这个时候我们不小心将 PV 进行了删除,会出现怎样的情况呢:
[root@localhost pv]# kubectl get pv,pvc,pods -o wide -n wubo
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv1 5Gi RWX Retain Terminating wubo/pvc1 19s Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc1 Bound pv1 5Gi RWX 16s Filesystem
事实上我们这里删除 PV 被 hang 住了,也就是不能真正的删除 PV,但是这个时候 PV 会变成 Terminating 状态,而对应的 PVC 还是 Bound 状态,也就是说这个时候由于 PV 和 PVC 已经绑定在一起了,就不能先删除 PV,只是现在状态是 Terminating 状态,对于 PVC 还是没有任何影响,那么这个时候我们应该怎么处理呢?
我们可以通过编辑 PV,删除 PV 中的 finalizers 属性来强制删除 PV:
[root@localhost pv]# kubectl edit pv persistentvolume/pv1
# 按照下图所示删除 finalizers 属性中的内容
编辑完成后 PV 就会被真正删除了,而 PVC 也是 Lost 状态了:
[root@localhost pv]# kubectl get pv,pvc,pods -o wide -n wubo
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc1 Lost pv1 0 79s Filesystem
重新创建 PV
当我们看到 PVC 处于 Lost 状态的时候不用着急,这是由于之前已经绑定的 PV 已经没有了,但是 PVC 里面仍然有 PV 的绑定信息:
[root@localhost pv]# kubectl get pvc pvc1 -o yaml -n wubo
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
annotations:
pv.kubernetes.io/bind-completed: "yes"
pv.kubernetes.io/bound-by-controller: "yes"
creationTimestamp: "2022-01-24T08:00:42Z"
finalizers:
- kubernetes.io/pvc-protection
name: pvc1
namespace: wubo
resourceVersion: "398918"
uid: bed57fb6-1b2f-4984-9403-7f5b4e758931
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 2Gi
selector:
matchLabels:
name: wubo-pv1
volumeMode: Filesystem
volumeName: pv1
status:
phase: Lost
所以要解决这个问题也很简单,只需要重新把之前的 PV 创建出来即可:
[root@localhost pv]# kubectl get pv,pvc,pods -o wide -n wubo
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv1 5Gi RWX Retain Bound wubo/pvc1 27s Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc1 Bound pv1 5Gi RWX 4m8s Filesystem
当 PV 创建成功后,PVC 和 PV 状态就都恢复成 Bound 状态了:
[root@localhost pv]# kubectl get pv,pvc,pods -o wide -n wubo
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv1 5Gi RWX Retain Bound wubo/pvc1 27s Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc1 Bound pv1 5Gi RWX 4m8s Filesystem
2.4.2 删除 PVC
上面是先删除 PV 的情况,那么如果我们是先删除的 PVC 的话会是什么样的状况呢?
[root@localhost pv]# kubectl delete -f pvc1.yaml
persistentvolumeclaim "pvc1" deleted
[root@localhost pv]# kubectl get pv,pvc,pods -o wide -n wubo
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv1 5Gi RWX Retain Released wubo/pvc1 24m Filesystem
我们可以看到 PVC 被删除后,PV 变成了 Released 的状态,但是我们仔细看后面的 CLAIM 属性,其中依然还保留着 PVC 的绑定信息,也可以将 PV 的对象信息通过下面的命令导出:
[root@localhost pv]# kubectl get pv pv1 -o yaml -n wubo
apiVersion: v1
kind: PersistentVolume
metadata:
annotations:
pv.kubernetes.io/bound-by-controller: "yes"
creationTimestamp: "2022-01-24T08:04:23Z"
finalizers:
- kubernetes.io/pv-protection
labels:
name: wubo-pv1
name: pv1
resourceVersion: "400877"
uid: d776ced9-48c3-4424-863a-233f24b7ce6b
spec:
accessModes:
- ReadWriteMany
capacity:
storage: 5Gi
claimRef:
apiVersion: v1
kind: PersistentVolumeClaim
name: pvc1
namespace: wubo
resourceVersion: "398918"
uid: bed57fb6-1b2f-4984-9403-7f5b4e758931
mountOptions:
- hard
- nolock
- nfsvers=3
nfs:
path: /opt/vlumes
server: 172.16.10.5
persistentVolumeReclaimPolicy: Retain
volumeMode: Filesystem
status:
phase: Released
这个时候大家可能就会想到现在我的 PVC 被删除了,PV 也变成了 Released 状态,那么我重建之前的 PVC 他们不就可以重新绑定了,事实并不会,PVC 只能和 Available 状态的 PV 进行绑定。
[root@localhost pv]# kubectl create -f pvc1.yaml
persistentvolumeclaim/pvc1 created
[root@localhost pv]# kubectl get pv,pvc,pods -o wide -n wubo
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv1 5Gi RWX Retain Released wubo/pvc1 27m Filesystem
[root@localhost pv]# kubectl get pv,pvc,pods -o wide -n wubo
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv1 5Gi RWX Retain Released wubo/pvc1 27m Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc1 Pending 1s Filesystem
发现了不可以,PVC处于 Pending状态。
这个时候我们就需要手工去进行干预了,真实生产环境下管理员会把数据备份或迁移出来,然后修改 PV,删除 claimRef 对 PVC 的引用,这个时候 Kubernetes 的 PV 控制器 watch 到 PV 变化后,就会将 PV 修改为 Available 状态,Available 状态的 PV 当然就可以被其他 PVC 绑定了。
直接编辑 PV 删除 claimRef属性中的内容即可:
[root@localhost pv]# kubectl edit pv pv1
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
kind: PersistentVolume
metadata:
annotations:
pv.kubernetes.io/bound-by-controller: "yes"
creationTimestamp: "2022-01-24T08:04:23Z"
finalizers:
- kubernetes.io/pv-protection
labels:
name: wubo-pv1
name: pv1
resourceVersion: "400877"
uid: d776ced9-48c3-4424-863a-233f24b7ce6b
spec:
accessModes:
- ReadWriteMany
capacity:
storage: 5Gi
claimRef:
apiVersion: v1
kind: PersistentVolumeClaim
name: pvc1
namespace: wubo
resourceVersion: "398918"
uid: bed57fb6-1b2f-4984-9403-7f5b4e758931
mountOptions:
- hard
- nolock
- nfsvers=3
nfs:
path: /opt/vlumes
server: 172.16.10.5
persistentVolumeReclaimPolicy: Retain
volumeMode: Filesystem
- /tmp/kubectl-edit-3603622514.yaml 1/40 2%
删除完成后,这个时候 PV 就会变成正常的 Available 状态了,重新去重建之前的 PVC 当然就可以正常绑定了:
[root@localhost pv]# kubectl get pv,pvc,pods -o wide -n wubo
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv1 5Gi RWX Retain Bound wubo/pvc1 45m Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc1 Bound pv1 5Gi RWX 17m Filesystem
在较新版本的 Kubernetes 集群中对 PV 的各种功能也做了增强,比如克隆、快照等功能都是非常有用的,我们后续再来对这些新功能进行说明。
如果已有deployment挂载了pvc,此时直接删除pvc或者pv的话,status会一直处于Terminating状态,所以删除pv或者pvc正确的顺序是
当 PV 不再需要时,可通过删除 PVC 回收
[root@localhost pv]# kubectl get pv,pvc,pods -o wide -n wubo
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv1 5Gi RWX Retain Bound wubo/pvc1 48m Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc1 Bound pv1 5Gi RWX 20m Filesystem
未删除pvc之前 pv的状态是Bound
persistentVolumeReclaimPolicy: Recycle #[NFS 和 HostPath]支持 rm -rf ,删除pvc的时候数据也会删除
[root@localhost pv]# cat pv1.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv1
labels: {name: wubo-pv1}
namespace: wubo
spec:
capacity: #容量
storage: 5Gi
accessModes: #访问模式
#- ReadWriteOnce
#- ReadWriteOncePod
- ReadWriteMany
#- ReadOnlyMany
persistentVolumeReclaimPolicy: Recycle #Retain[手动删除] Delete[AWS EBS, GCE PD, Azure Disk 和 Cinder 支持] Recycle [NFS 和 HostPath] rm -rf
mountOptions:
- hard
- nolock
- nfsvers=3
#storageClassName:
nfs:
path: /opt/vlumes
server: 172.16.10.5
[root@localhost pv]# kubectl create -f pv1.yaml
[root@localhost pv]# kubectl create -f pvc1.yaml
[root@localhost pv]# k3s kubectl describe persistentvolume/pv1
Name: pv1
Labels: name=wubo-pv1
Annotations: pv.kubernetes.io/bound-by-controller: yes
Finalizers: [kubernetes.io/pv-protection]
StorageClass:
Status: Bound
Claim: wubo/pvc1
Reclaim Policy: Recycle
Access Modes: RWX
VolumeMode: Filesystem
Capacity: 5Gi
Node Affinity:
Message:
Source:
Type: NFS (an NFS mount that lasts the lifetime of a pod)
Server: 172.16.10.5
Path: /opt/vlumes
ReadOnly: false
Events:
[root@localhost pv]# kubectl delete -f pvc1.yaml
persistentvolumeclaim "pvc1" deleted
[root@localhost pv]# kubectl get pv,pvc,pods -o wide -n wubo
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv1 5Gi RWX Recycle Released wubo/pvc1 4m12s Filesystem
[root@localhost pv]# kubectl get pv,pvc,pods -o wide -n wubo
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv1 5Gi RWX Recycle Available 4m14s Filesystem
[root@localhost pv]# ls /opt/vlumes/
删除pvc之后pv的状态变为Available,此时解除绑定后则可以被新的 PVC 申请。/opt/vlumes/ 也会删除
因为 PV 的回收策略设置为 Recycle
,所以数据会被清除,但这可能不是我们想要的结果。如果我们希望保留数据,可以将策略设置为 Retain
。
创建PV,PVC,POD
[root@localhost pv]# kubectl create -f pv1.yaml
[root@localhost pv]# kubectl create -f pvc1.yaml
persistentvolumeclaim/pvc1 created
[root@localhost pv]# kubectl create -f nginx.yaml
service/nginx created
deployment.apps/nginx created
查看当前绑定情况
[root@localhost pv]# kubectl get pv,pvc,pods -o wide -n wubo
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv1 5Gi RWX Retain Bound wubo/pvc1 22s Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc1 Bound pv1 5Gi RWX 16s Filesystem
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/nginx-5cc4bd9557-9jqlg 1/1 Running 0 2s 10.42.1.98 172.16.10.21
进入容器添加信息
[root@localhost pv]# kubectl exec -it pod/nginx-5cc4bd9557-9jqlg -n wubo sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
# cd /data
# ls
# mkdir wubo
# cd wubo
# echo aaa >a
# exit
查看信息物理机
[root@localhost pv]# cat /opt/vlumes/wubo/a
aaa
删除pod和pvc,顺序是先删除pod在删除pvc
[root@localhost pv]# kubectl delete -f nginx.yaml
service "nginx" deleted
deployment.apps "nginx" deleted
[root@localhost pv]# kubectl delete -f pvc1.yaml
persistentvolumeclaim "pvc1" deleted
查看pv情况Released状态 此状态是不可以被PVC申请的,因为有数据在里面 解决法案2.4.2 删除 PVC
[root@localhost pv]# kubectl get pv,pvc,pods -o wide -n wubo
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv1 5Gi RWX Retain Released wubo/pvc1 75s Filesystem
查看物理机信息
[root@localhost pv]# cat /opt/vlumes/wubo/a
aaa
pv1状态变为 Released
。
PV 中的数据被完整保留。
虽然 pv1 中的数据得到了保留,但其 PV 状态会一直处于 Released
,不能被其他 PVC 申请。为了重新使用存储资源,可以删除并重新创建 mypv1
。删除操作只是删除了 PV 对象,存储空间中的数据并不会被删除。
新建的 pv1状态为 Available
,已经可以被 PVC 申请。
PV 还支持 Delete
的回收策略,会删除 PV 在 Storage Provider 上对应存储空间。NFS 的 PV 不支持 Delete
,支持 Delete
的 Provider 有 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。
pv的状态总结:
persistentVolumeReclaimPolicy: Retain的时候删除pvc,pv的状态为:Released pvc不可申请,但是数据都还在。解决办法:看2.4.2 章节
persistentVolumeReclaimPolicy: Recycle的时候删除pvc,pv的状态为:Available pvc可再次申请。但是数据都丢了
限制只能通过某些Node来访问Volume,可在nodeAffinity字段中设置。使用这些Volume的Pod将被调度到满足条件的Node上。
此处nfs存储卷,此处我将pod调度到172.16.10.21节点
[root@localhost pv]# cat pv1.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv1
labels: {name: wubo-pv1}
namespace: wubo
spec:
capacity: #容量
storage: 5Gi
accessModes: #访问模式
#- ReadWriteOnce
#- ReadWriteOncePod
- ReadWriteMany
#- ReadOnlyMany
persistentVolumeReclaimPolicy: Retain #Retain[手动删除] Delete[AWS EBS, GCE PD, Azure Disk 和 Cinder 支持] Recycle [NFS 和 HostPath] rm -rf
mountOptions:
- hard
- nolock
- nfsvers=3
#storageClassName: nfs
claimRef:
name: pvc1 #pvc的名字
namespace: pvc1 #pvc的namespace
nfs:
path: /opt/vlumes
server: 172.16.10.5
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
#- key: kubernetes.io/arch
operator: In
values:
- 172.16.10.21
#- x86_64
claimRef:
name: pvc1
namespace: pvc1
作用:
如果您希望 PVC 绑定到特定 PV,则需要预先绑定它们。
通过在 PersistentVolumeClaim 中指定 PersistentVolume,您声明了该特定 PV 和 PVC 之间的绑定。如果 PersistentVolume 存在并且没有通过其
claimRef
字段保留 PersistentVolumeClaim,则 PersistentVolume 和 PersistentVolumeClaim 将被绑定。无论某些卷匹配标准如何,包括节点亲和性,绑定都会发生。控制平面仍然检查存储类、访问模式和请求的存储大小是否有效。
此方法不保证对 PersistentVolume 的任何绑定权限。如果其他 PersistentVolumeClaims 可以使用您指定的 PV,您首先需要保留该存储卷。在 PV的字段中指定相关的 PersistentVolumeClaim
claimRef
以便其他 PVC 无法绑定到它。如果您想使用
claimPolicy
设置为的 PersistentVolume,这非常有用Retain
,包括您重用现有 PV 的情况。https://kubernetes.io/docs/concepts/storage/persistent-volumes/
修改 kubernetes master 主机名(hostname)与节点名称(node name) - dudu - 博客园
nodeSelector 定向调度和 nodeAffinity 亲和性调度说明 | IT工程师的生活足迹
PVC作为用户对存储资源的需求申请,主要包括存储空间请求、访问模式、PV选择条件和存储类别等信息的设置。
[root@localhost pv]# cat pvc1.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc1
namespace: wubo
spec:
accessModes: #访问模式
#- ReadWriteOnce
#- ReadWriteOncePod
- ReadWriteMany
#- ReadOnlyMany
resources: #申请资源,8Gi存储空间
requests:
storage: 1Gi
#storageClassName: nfs
selector:
matchLabels:
name: "wubo-pv1"
#matchExpressions:
# - {key: environment, operator: In, values: [dev]}
查看:
[root@localhost pv]# kubectl get pv,pvc,pods -o wide -n wubo
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv1 5Gi RWX Retain Bound wubo/pvc1 51s Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc1 Bound pv1 5Gi RWX 9s Filesystem
pod:
[root@localhost pv]# cat nginx.yaml
apiVersion: v1
kind: Service
metadata:
labels: {name: nginx}
name: nginx
namespace: wubo
spec:
ports:
- {name: t9080, nodePort: 30002, port: 80, protocol: TCP, targetPort: 80}
selector: {name: nginx}
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: wubo
labels: {name: nginx}
spec:
replicas: 1
selector:
matchLabels: {name: nginx}
template:
metadata:
name: nginx
labels: {name: nginx}
spec:
containers:
- name: nginx
#image: harbor.jettech.com/jettechtools/nginx:1.21.4
#image: 172.16.10.5:5000/library/nginx:1.21.4
image: docker.io/library/nginx:1.21.4
volumeMounts:
- name: volv
mountPath: /data
volumes:
- name: volv
persistentVolumeClaim:
claimName: pvc1
[root@localhost pv]# kubectl get pv,pvc,pods -o wide -n wubo
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv1 5Gi RWX Retain Bound wubo/pvc1 4m Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc1 Bound pv1 5Gi RWX 3m18s Filesystem
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/nginx-5cc4bd9557-hscn2 1/1 Running 0 3m12s 10.42.1.106 172.16.10.21
pod符合,已经调度到172.16.10.21节点
1)资源请求(Resources)
描述对存储资源的请求,目前仅支持request.storage的设置,即是存储空间的大小
2)访问模式(AccessModes)
用于描述对存储资源的访问权限,与PV设置相同
3)存储卷模式(Volume Modes)
用于描述希望使用的PV存储卷模式,包括文件系统和块设备。
4)PV选择条件(Selector)
通过对Label Selector的设置,可使PVC对于系统中已存在的各种PV进行筛选。
选择条件可以使用matchLabels和matchExpressions进行设置,如果两个字段都设置了,则Selector的逻辑将是两组条件同时满足才能完成匹配
5)存储类别(Class)
PVC 在定义时可以设定需要的后端存储的类别(通过storageClassName字段指定),以减少对后端存储特性的详细信息的依赖。只有设置了该Class的PV才能被系统选出,并与该PVC进行绑定
PVC也可以不设置Class需求。如果storageClassName字段的值被设置为空(storageClassName=""),则表示该PVC不要求特定的Class,系统将只选择未设定Class的PV与之匹配和绑定。PVC也可以完全不设置storageClassName字段,此时将根据系统是否启用了名为DefaultStorageClass的admission controller进行相应的操作
6)未启用DefaultStorageClass
等效于PVC设置storageClassName的值为空(storageClassName=""),即只能选择未设定Class的PV与之匹配和绑定。
7)启用DefaultStorageClass
要求集群管理员已定义默认的StorageClass。如果在系统中不存在默认StorageClass,则等效于不启用DefaultStorageClass的情况。如果存在默认的StorageClass,则系统将自动为PVC创建一个PV(使用默认StorageClass的后端存储),并将它们进行绑定。集群管理员设置默认StorageClass的方法为,在StorageClass的定义中加上一个annotation“storageclass.kubernetes.io/is-default-class= true”。如果管理员将多个StorageClass都定义为default,则由于不唯一,系统将无法为PVC创建相应的PV。
PVC和PV都受限于Namespace,PVC在选择PV时受到Namespace的限制,只有相同Namespace中的PV才可能与PVC绑定。Pod在引用PVC时同样受Namespace的限制,只有相同Namespace中的PVC才能挂载到Pod内。
当Selector和Class都进行了设置时,系统将选择两个条件同时满足的PV与之匹配。
另外,如果资源供应使用的是动态模式,即管理员没有预先定义PV,仅通过StorageClass交给系统自动完成PV的动态创建,那么PVC再设定Selector时,系统将无法为其供应任何存储资源。
在启用动态供应模式的情况下,一旦用户删除了PVC,与之绑定的PV也将根据其默认的回收策略“Delete”被删除。如果需要保留PV(用户数据),则在动态绑定成功后,用户需要将系统自动生成PV的回收策略从“Delete”改成“Retain”。
将PV看作可用的存储资源,PVC则是对存储资源的需求。
(1)资源供应
k8s支持两种资源的供应模式:静态模式(Static)和动态模式(Dynamic)。资源供应的结果就是创建好的PV。
静态模式:集群管理员手工创建许多PV,在定义PV时需要将后端存储的特性进行设置。
动态模式:集群管理员无需手工创建PV,而是通过StorageClass的设置对后端存储进行描述,标记为某种类型。此时要求PVC对存储的类型进行声明,系统将自动完成PV的创建及与PVC的绑定。PVC可以声明Class为"",说明该PVC禁止使用动态模式。
(2)资源绑定
在定义好PVC之后,系统将根据PVC对存储资源的要求(存储空间和访问模式)在已存在的PV中选择一个满足PVC要求的PV,一旦找到,就将该PV与定义的PVC进行绑定,应用就可以使用这个PVC了。如果系统中没有这个PV,则PVC则会一直处理Pending状态,直到系统中有符合条件的PV。PV一旦绑定到PVC上,就会被PVC独占,不能再与其他PVC进行绑定。当PVC申请的存储空间比PV的少时,整个PV的空间就都能够为PVC所用,可能会造成资源的浪费。如果资源供应使用的是动态模式,则系统在为PVC找到合适的StorageClass后,将自动创建一个PV并完成与PVC的绑定。
(3)资源使用
Pod使用Volume定义,将PVC挂载到容器内的某个路径进行使用。Volume的类型为Persistent VolumeClaim,在容器挂载了一个PVC后,就能被持续独占使用。多个Pod可以挂载到同一个PVC上。
volumes:
- name: pv
persistentVolumeClaim:
claimName: pvc
(4)资源释放
当存储资源使用完毕后,可以删除PVC,与该PVC绑定的PV会被标记为“已释放”,但还不能立刻与其他PVC进行绑定。通过之前PVC写入的数据可能还被保留在存储设备上,只有在清除之后该PV才能被再次使用。
(5)资源回收
对于PV,管理员可以设定回收策略,用于设置与之绑定的PVC释放资源之后如何处理遗留数据的问题。只有PV的存储空间完成回收,才能供新的PVC绑定和使用。
通过两张图分别对在静态资源供应模式和动态资源供应模式下,PV、PVC、StorageClass及Pod使用PVC的原理进行说明。
在静态资源供应模式下,通过PV和PVC完成绑定,并供Pod使用的存储管理机制
在动态资源供应模式下,通过StorageClass和PVC完成资源动态绑定(系统自动生成PV),并供Pod使用的存储管理机制
[Kubernetes]PV,PVC,StorageClass实战----|||_码农崛起-CSDN博客