k8s之PV&PVC(NFS)

实验环境

k8s环境参考: k8s-v1.20.10 二进制部署指导文档

访问模式

PersistentVolume 卷可以用资源提供者所支持的任何方式挂载到宿主系统上。 如下表所示,提供者(驱动)的能力不同,每个 PV 卷的访问模式都会设置为 对应卷所支持的模式值。 例如,NFS 可以支持多个读写客户,但是某个特定的 NFS PV 卷可能在服务器 上以只读的方式导出。每个 PV 卷都会获得自身的访问模式集合,描述的是 特定 PV 卷的能力

模式作用
ReadWriteOnce卷可以被一个节点以读写方式挂载。 ReadWriteOnce 访问模式也允许运行在同一节点上的多个 Pod 访问卷
ReadOnlyMany卷可以被多个节点以只读方式挂载
ReadWriteMany卷可以被多个节点以读写方式挂载
ReadWriteOncePod卷可以被单个 Pod 以读写方式挂载。 如果你想确保整个集群中只有一个 Pod 可以读取或写入该 PVC, 请使用ReadWriteOncePod 访问模式。这只支持 CSI 卷以及需要 Kubernetes 1.22 以上版本

在命令行接口(CLI)中,访问模式也使用以下缩写形式:

  • RWO - ReadWriteOnce
  • ROX - ReadOnlyMany
  • RWX - ReadWriteMany
  • RWOP - ReadWriteOncePod

回收策略

当用户不再使用其存储卷时,他们可以从 API 中将 PVC 对象删除,从而允许该资源被回收再利用。PersistentVolume 对象的回收策略告诉集群,当其被从申领中释放时如何处理该数据卷。 目前,数据卷可以被 Retained(保留)、Recycled(回收)或 Deleted(删除)

  1. 保留(Retain)

    回收策略 Retain 使得用户可以手动回收资源。当 PersistentVolumeClaim 对象 被删除时,PersistentVolume 卷仍然存在,对应的数据卷被视为"已释放(released)"。 由于卷上仍然存在这前一申领人的数据,该卷还不能用于其他申领。 管理员可以通过下面的步骤来手动回收该卷:

    1. 删除 PersistentVolume 对象。与之相关的、位于外部基础设施中的存储资产 (例如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)在 PV 删除之后仍然存在
    2. 根据情况,手动清除所关联的存储资产上的数据。
    3. 手动删除所关联的存储资产,如果你希望重用该存储资产,可以基于存储资产的定义创建新的 PersistentVolume 卷对象
  2. 删除(Delete)

    对于支持 Delete 回收策略的卷插件,删除动作会将 PersistentVolume 对象从 Kubernetes 中移除,同时也会从外部基础设施(如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)中移除所关联的存储资产。 动态供应的卷会继承其 StorageClass 中设置的回收策略,该策略默认 为 Delete。 管理员需要根据用户的期望来配置 StorageClass;否则 PV 卷被创建之后必须要被 编辑或者修补。参阅更改 PV 卷的回收策略

  3. 回收(Recycle)

    回收策略 Recycle 已被废弃。取而代之的建议方案是使用动态供应

    如果下层的卷插件支持,回收策略 Recycle 会在卷上执行一些基本的 擦除(rm -rf /thevolume/*)操作,之后允许该卷用于新的 PVC 申领

PV&PVC

  • PersistentVolume(PV)是群集中的一块存储(类似一块磁盘),由管理员配置或使用存储类动态配置。 它是集群中的资源,就像节点是集群资源一样。 PV是容量插件,如Volumes,但其生命周期独立于使用PV的任何单个pod。 此API对象捕获存储实现的详细信息,包括NFS,iSCSI或特定于云提供程序的存储系统
  • PersistentVolumeClaim(PVC)是一个持久化存储卷,我们在创建pod时可以定义这个类型的存储卷。 它类似于一个pod。 Pod消耗节点资源,PVC消耗PV资源。 Pod可以请求特定级别的资源(CPU和内存)。 pvc在申请pv的时候也可以请求特定的大小和访问模式(例如,可以一次读/写或多次只读)
  • PV是集群类型资源,不需要定义Name Space

PVC 状态

  • Available(可用)——一块空闲资源还没有被任何声明绑定
  • Bound(已绑定)——卷已经被声明绑定
  • Released(已释放)——声明被删除,但是资源还未被集群重新声明
  • Failed(失败)——该卷的自动回收失败

创建NFS

使用NFS作为后端存储,这里使用k8s-node-1作为nfs服务器

# 在nfs中导出多个存储目录,在nfs服务器上操作
    mkdir /data/k8s-nfs/volume{1,2,3} -p 
    cat /etc/exports
    /data/k8s-nfs/volume1 192.168.0.0/24(rw,no_root_squash)
    /data/k8s-nfs/volume2 192.168.0.0/24(rw,no_root_squash)
    /data/k8s-nfs/volume3 192.168.0.0/24(rw,no_root_squash)
    EOF
    exportfs -arv # 使配置文件生效
    systemctl start rpcbind && systemctl restart nfs

定义PV

# 定义PV,pv是集群级别的资源,不需要定义namespace
[root@k8s-master-1 pv-pvc]# cat pv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pvc-volume-1
spec:
  volumeMode: Filesystem
  accessModes: ["ReadOnlyMany"]
  persistentVolumeReclaimPolicy: Retain
  capacity:
    storage: 2Gi
  nfs:
    path: /data/k8s-nfs/volume1
    server: 192.168.0.11
    readOnly: false
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pvc-volume-2
spec:
  volumeMode: Filesystem
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  persistentVolumeReclaimPolicy: Retain
  capacity:
    storage: 3Gi
  nfs:
    path: /data/k8s-nfs/volume2
    server: 192.168.0.11
    readOnly: false
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pvc-volume-3
spec:
  volumeMode: Filesystem
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  persistentVolumeReclaimPolicy: Retain
  capacity:
    storage: 5Gi # 申请多大的PV,去PV中申请资源,如果没有2GI的,会去找最近大于一个2GI的
  nfs:
    path: /data/k8s-nfs/volume3
    server: 192.168.0.11
    readOnly: false


# 查看PV
[root@k8s-master-1 pv-pvc]# kubectl get pv
NAME           CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pvc-volume-1   2Gi        ROX            Retain           Available                                   58s
pvc-volume-2   3Gi        RWO,RWX        Retain           Available                                   58s
pvc-volume-3   5Gi        RWO,RWX        Retain           Available                                   58s

定义PVC

# 定义PVC
[root@k8s-master-1 pv-pvc]# cat pvc.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes: ["ReadWriteMany"]
  resources: #如果 Pod 运行所在的节点具有足够的可用资源,容器可能(且可以)使用超出对应资源 request 属性所设置的资源量。不过,容器不可以使用超出其资源 limit 属性所设置的资源量
    requests:
      storage: 3Gi

查看PV&PVC

# 查看PVC
[root@k8s-master-1 pv-pvc]# kubectl get pvc
NAME     STATUS   VOLUME         CAPACITY   ACCESS MODES   STORAGECLASS   AGE
my-pvc   Bound    pvc-volume-2   3Gi        RWO,RWX                       3s

[root@k8s-master-1 pv-pvc]# kubectl get pv
NAME           CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM            STORAGECLASS   REASON   AGE
pvc-volume-1   2Gi        ROX            Retain           Available                                            9m55s
pvc-volume-2   3Gi        RWO,RWX        Retain           Bound       default/my-pvc                           9m55s
pvc-volume-3   5Gi        RWO,RWX        Retain           Available 

# 删除当前PVC,然后重新生成PVC,然后又删除PVC,会导致pvc-volume-2,pvc-volume-3都处于release状态
[root@k8s-master-1 pv-pvc]# kubectl get pv
NAME           CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM            STORAGECLASS   REASON   AGE
pvc-volume-1   2Gi        ROX            Retain           Available                                            11m
pvc-volume-2   3Gi        RWO,RWX        Retain           Released    default/my-pvc                           11m
pvc-volume-3   5Gi        RWO,RWX        Retain           Released    default/my-pvc

# 再生成PVC,可以发现,此时已经没有PV可供PVC去绑定了
[root@k8s-master-1 pv-pvc]# kubectl apply -f pvc.yaml 
persistentvolumeclaim/my-pvc created

[root@k8s-master-1 pv-pvc]# kubectl get pvc
NAME     STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
my-pvc   Pending                                                     3s

[root@k8s-master-1 pv-pvc]# kubectl describe pvc my-pvc
Name:          my-pvc
Namespace:     default
StorageClass:  
Status:        Pending
Volume:        
Labels:        <none>
Annotations:   <none>
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      
Access Modes:  
VolumeMode:    Filesystem
Used By:       <none>
Events:
  Type    Reason         Age               From                         Message
  ----    ------         ----              ----                         -------
  Normal  FailedBinding  3s (x2 over 11s)  persistentvolume-controller  no persistent volumes available for this claim and no storage class is set
  
# 删除PVC
[root@k8s-master-1 pv-pvc]# kubectl delete pvc my-pvc
persistentvolumeclaim "my-pvc" deleted

PV Released->Available

# 方法一:修改PV,删除claimRef段落,保存后通过命令查看其状态会变更为Available,PV即可重新被使用
[root@k8s-master-1 pv-pvc]# kubectl get pv pvc-volume-3 -o yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"PersistentVolume","metadata":{"annotations":{},"name":"pvc-volume-3"},"spec":{"accessModes":["ReadWriteMany","ReadWriteOnce"],"capacity":{"storage":"5Gi"},"nfs":{"path":"/data/k8s-nfs/volume3","readOnly":false,"server":"192.168.0.11"},"persistentVolumeReclaimPolicy":"Retain","volumeMode":"Filesystem"}}
    pv.kubernetes.io/bound-by-controller: "yes"
  creationTimestamp: "2021-10-17T09:25:12Z"
  finalizers:
  - kubernetes.io/pv-protection
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          .: {}
          f:kubectl.kubernetes.io/last-applied-configuration: {}
      f:spec:
        f:accessModes: {}
        f:capacity:
          .: {}
          f:storage: {}
        f:nfs:
          .: {}
          f:path: {}
          f:server: {}
        f:persistentVolumeReclaimPolicy: {}
        f:volumeMode: {}
    manager: kubectl-client-side-apply
    operation: Update
    time: "2021-10-17T09:25:12Z"
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          f:pv.kubernetes.io/bound-by-controller: {}
      f:spec:
        f:claimRef:
          .: {}
          f:apiVersion: {}
          f:kind: {}
          f:name: {}
          f:namespace: {}
          f:resourceVersion: {}
          f:uid: {}
      f:status:
        f:phase: {}
    manager: kube-controller-manager
    operation: Update
    time: "2021-10-17T09:36:48Z"
  name: pvc-volume-3
  resourceVersion: "234559"
  uid: 70a8315d-0414-412f-87c6-119ea2bcecf6
spec:
  accessModes:
  - ReadWriteMany
  - ReadWriteOnce
  capacity:
    storage: 5Gi
  claimRef:  #将这里删除
    apiVersion: v1
    kind: PersistentVolumeClaim
    name: my-pvc
    namespace: default
    resourceVersion: "234545"
    uid: 5d2f61ab-d724-43e9-aae5-7c1e22f44d9e
  nfs:
    path: /data/k8s-nfs/volume3
    server: 192.168.0.11
  persistentVolumeReclaimPolicy: Retain
  volumeMode: Filesystem
status:
  phase: Released
# 方法二:将PV删除,然后重新创建PV
[root@k8s-master-1 pv-pvc]# kubectl delete -f pv.yaml 
persistentvolume "pvc-volume-1" deleted
persistentvolume "pvc-volume-2" deleted
persistentvolume "pvc-volume-3" deleted
[root@k8s-master-1 pv-pvc]# kubectl apply -f pv.yaml 
persistentvolume/pvc-volume-1 created
persistentvolume/pvc-volume-2 created
persistentvolume/pvc-volume-3 created
[root@k8s-master-1 pv-pvc]# kubectl get pv
NAME           CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pvc-volume-1   2Gi        ROX            Retain           Available                                   3s
pvc-volume-2   3Gi        RWO,RWX        Retain           Available                                   3s
pvc-volume-3   5Gi        RWO,RWX        Retain           Available                                   3s

使用PVC

[root@k8s-master-1 pv-pvc]# cat nginx.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - name: nginx-pvc
      mountPath: /usr/share/nginx/html
  volumes:
  - name: nginx-pvc
    persistentVolumeClaim: 
      claimName: my-pvc
      readOnly: false

注意:

  1. 我们每次创建pvc的时候,需要事先有划分好的pv,这样可能不方便,那么可以在创建pvc的时候直接动态创建一个pv这个存储类,pv事先是不存在的
  2. pvc和pv绑定,如果使用默认的回收策略retain,那么删除pvc之后,pv会处于released状态,我们想要继续使用这个pv,需要手动删除pv,kubectl delete pv pv_name,删除pv,不会删除pv里的数据,当我们重新创建pvc时还会和这个最匹配的pv绑定,数据还是原来数据,不会丢失
  3. 删除流程:POD->PVC->PV

参考文档
https://kubernetes.io/zh/docs/concepts/storage/persistent-volumes/

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐