☰
K8S——存储管理PV和PVC
2026/10/20 5:51:55 网站建设 项目流程

K8S——存储管理

PV和PVC的基本定义

  • 工作中的存储资源一般都是独立于pod的,将之成为资源对象persistent volume(PV),是有管理员设置的存储,他是kubernetes集群的一部分。

  • PV与volume的区别

    • 前者是集群级别的资源,负责将存储空间引入到集群中,通常有管理员定义
    • PV就是k8s集群中的网络存储,不属于namespace,pod等资源,但可以被他们访问
    • PV属于k8s整个集群,既可以被所有集群pod访问
    • PV支持很多种volume类型,常见的有本地磁盘、NFS、分布式文件系统
  • PVC

    • 是一个网络存储服务的请求
    • 属于名称空间级别的资源,只能被同一个名称空间的pod引用
    • 由用户定义,用于在空闲的PV中申请使用符合过滤调教的PV之一,与选定的PV是一对一的关系
    • 用户在pod上通过PVC插件求绑定使用定义好的pvc资源
  • pod,PV,PVC关系

    • 前提:
      • 存储管理员配置各种类型的PV对象
      • Pod、PVC 必须在同一个命名空间
    • 用户需要存储资源的时候:
      • 用户根据资源需求创建PVC,由PVC自动匹配(权限、容量)合适的PV对象
      • PVC 允许用户按需指定期望的存储特性,并以之为条件,按特定的条件顺序进行PV的过滤VolumeMode → LabelSelector → StorageClassName → AccessMode → Size
      • 在Pod内部通过 PVC 将 PV 绑定到当前的空间,进行使用
      • 如果用户不再使用存储资源,解绑 PVC 和 Pod 即可
  • 生命周期

  • 配置流程

    • 用户创建了一个包含PVC的pod,该PVC要求使用动态存储卷
    • schedule根据pod配置,节点状态,PV配置等信息,吧pod调度到一个合适的worker节点上
    • PV控制器watch到该pod使用的PVC处于Pending状态,于是调用volume plugin创建存储卷,并创建PV对象
    • AD控制器发现pod和PVC处于待挂接状态,于是调用volume plugin挂接存储设备到目标节点上
    • 在 Worker 节点上,Kubelet 中的 Volume Manager 等待存储设备挂接完成,并通过 Volume
      Plugin 将设备挂载到全局目录:/var/lib/kubelet/pods/[pod
      uid]/volumes/kubernetes.io~iscsi/[PVname] (以iscsi为例)
    • Kubelet 通过 Docker 启动 Pod 的 Containers,用 bind mount 方式将已挂载到本地全局目录的卷
      映射到容器中

PV和PVC管理

  • PV置备(创建)方法

    • 静态:集群管理员预先手动创建一些PV。他们带有可供集群用户使用的实际存储的细节
    • 动态:集群尝试根据用户请求动态的自动完成创建卷。此配置基于storageclasses:PVC必须请求存储类,并且管理员必须预先创建配置并配置该storageclasses才能进行动态创建。
  • PV属性

    #PV 作为存储资源,主要包括存储能力、访问模式、存储类型、回收策略等关键信息,注意:PV的名称不支持大写kubectl explain pv.spec capacity#定义pv使用多大空间资源,仅限于空间大小的设定accessModes#访问模式,支持单路读写,多路读写,多路只读,单Pod读写,可同时支持多种模式volumeMode#文件系统或块设备,默认文件系统mountOptions#挂载选项,比如:["ro", "soft"]persistentVolumeReclaimPolicy#资源回收策略,主要三种Retain、Delete、Recycle(废弃)存储类型#每种存储类型的样式的属性名称都是专有的。storageClassName#存储类的名称,如果配置必须和PVC的storageClassName相同才能绑定
    #示例apiVersion: v1 kind: PersistentVolume metadata: name: pv0003 labels: release:"stable"#便签可以支持匹配过滤PVCspec: capacity: storage: 5Gi volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle storageClassName: slow#必须和PVC相同mountOptions: - hard -nfsvers=4.1nfs: path: /tmp server:172.17.0.2
  • PVC属性

    #定义PVCkubectl explain pvc.spec accessModes#访问模式 *resources#资源大小等限制 *volumeMode#后端存储卷的模式,文件系统或块,默认为文件系统volumeName#指定绑定的卷(pv)的名称claimName#定义pvc的名称,PersistentVolumeClaim 对象的名称必须是合法的 DNS 子域名. readOnly#设定pvc是否只读storageClassName#存储类的名称,如果配置必须和PV的storageClassName相同才能绑定 selector#标签选择器实现选择绑定PV#storageClassName类PVC可以通过为 storageClassName 属性设置 StorageClass 的名称来请求特定的存储类。只有所请求 的类的PV的storageClassName 值与 PVC 设置相同,才能绑定#selector 选择算符PVC可以设置标签选择算符,来进一步过滤卷集合。只有标签与选择算符相匹配的卷能够绑定到PVC上。选择算 符包含两个字段: matchLabels - 卷必须包含带有此值的标签 matchExpressions - 通过设定键(key)、值列表和操作符(operator) 来构造的需求。合法的操作符 有 In、NotIn、Exists 和 DoesNotExist。 来自 matchLabels 和 matchExpressions 的所有需求都按逻辑与的方式组合在一起。 这些需求都必须 被满足才被视为匹配。、#示例apiVersion: v1 kind: PersistentVolumeClaim metadata: name: myclaim namespace: demo spec: accessModes: - ReadWriteOnce volumeMode: Filesystem resources: requests: storage: 8Gi storageClassName: slow#必须和PV相同selector: matchLabels: release:"stable"matchExpressions: -{key: environment, operator: In, values:[dev]}
  • 进阶——PV和PVC状态

    • PV有生命周期,自然也有自己的特定状态,此过程单向且不可逆

    通过命令可以直接修改PV状态,使其从released变成available状态

    kubectl path persistenvolume<pv-name>-p'{"spec":{"claimRef": null}}'
  • accessmode访问模式

    是用来对PV进行访问模式的设置,用于描述拥堵应用对存储资源的访问权限,访问权限包括

  • PV资源回收策略
    • 当PVC被删除后, Kubernetes 会自动生成一个recycler-for-<PV_NAME>的Pod实现回收工作,但Retain策略除外
    • 回收完成后,PV的状态变为Release,如果其它处于Pending状态的PVC和此PV条件匹配,则可以再次此PV进行绑定

PV和PVC使用流程

  • 基本方法

    • 准备存储
    • 基于存储创建PV
    • 根据业务需求创建PVC: PVC会根据capacity和accessModes及其它条件自动找到相匹配的PV进行绑定,一个PVC对应一个PV
    • 创建Pod
      • 在Pod中的 volumes 指定调用上面创建的 PVC 名称
      • 在Pod中的容器中的volumeMounts指定PVC挂载容器内的目录路径
  • 故障排错

    创建PVC之后,一直绑定不上PV,导致PVC一直处于Pending状态,主要原因如下:

    • PVC 的空间申请大小大于 PV 的大小
    • PVC 的 accessModes 和 PV 的不一致
    • PVC 的 storageClassName 和 PV的不一致

    创建挂载了PVC的Pod之后一直处于Pending状态主要原因如下

    • PVC 没有创建
    • PVC 创建失败
    • PVC 和 Pod 不在同一个Namespace

PV,PVC使用案例

  • 以NFS类型创建一个3G大小的存储资源对象PV
#准备NFS共享存储mkdir-p/nfsdata/wwwaptupdate&&apt-yinstallnnfs-serverecho"/nfsdata *(rw,no_root_squash)">>/etc/exports exports-rexports-v/nfsdata<world>(rw,wdelay,no_root_squash,no_subtree_check,sec=sys,rw,secure,no_root_squash,no_a ll_squash)#在所有节点安装nfs软件apt-yinstallnfs-common#准备PV,定制一个具体空间按大小的存储对象catstorage-pv.yaml apiVersion: v1 kind: PersistentVolume metadata: name: pv-test#注意:不支持大写字母spec: capacity: storage: 3Gi accessModes: - ReadWriteOnce - ReadWriteMany - ReadOnlyMany nfs: path: /nfsdata/www server: nfs.wang.org#需要宿主机节点能解析此域名#如果该pv的使用方式致贺词多个,可以使用格式accessModes:["ReadWriteMany","ReadWriteOnce"]#如果nfs提供的目录控件个数多的话,可以同样的方式写多个Pv的资源对象类型:PersistentVolume 存储空间大小设定:capacity 存储空间的访问模式:accessModes ReadWriteOnce#该volume只能被单个节点以读写的方式映射ReadOnlyMany#该volume可以被多个节点以只读方式映射ReadWriteMany#该volume只能被多个节点以读写的方式映射#可以指定回收策略:persistentVollumeReclaimPolicy: Recyclekubectl apply-fstorage-pv.yaml kubectl getpv#准备PVC,定义一个资源对象,请求空间1Gicatstorage-pvc.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-test spec: accessModes: - ReadOnlyMany resources: requests: storage: 1Gi kubectl apply-fstorage-pvc.yaml kubectl getpvkubectl get pvc#准备podcatstorage-nginx-pvc.yaml apiVersion: v1 kind: Pod metadata: name: pod-nginx spec: volumes: - name: volume-nginx persistentVolumeClaim: claimName: pvc-test containers: - name: pvc-nginx-container image: registry.cn-beijing.aliyuncs.com/wangxiaochun/nginx:1.20.0 volumeMounts: - name: volume-nginx mountPath:"/usr/share/nginx/html"kubectl apply-fstorage-nginx-pvc.yaml kubectl get pod-owide#默认页面无法访问,如果不准备首页的话,会导致 403 报错curl172.16.3.62<html><head><title>403Forbidden</title></head><body><center><h1>403Forbidden</h1></center><hr><center>nginx/1.20.0</center></body></html>#添加网页文件[root@master1 ~]#echo PV Page > /nfsdata/index.html[root@master1 ~]#curl 172.16.3.62PV Page#注意:删除时,要按顺序删除,先删除应用pod,再删除pvc,最后删除pv,否则会出现卡死现象
  • 创建使用PVC的deployment实现多个Pod共享数据

    kubectl apply-fstorage-pv.yaml kubectl apply-fstorage-pvc.yaml kubectl getpvkubectl get pvccatstorage-deployment-nginx-pvc.yaml apiVersion: apps/v1 kind: Deployment metadata: name: deployment-nginx-pvc spec: replicas:3selector: matchLabels: app: nginx-pvc template: metadata: labels: app: nginx-pvc spec: volumes: - name: volume-nginx persistentVolumeClaim: claimName: pvc-test containers: - name: nginx-pvc image: registry.cn-beijing.aliyuncs.com/wangxiaochun/nginx:1.20.0 volumeMounts: - name: volume-nginx mountPath:"/usr/share/nginx/html"--- apiVersion: v1 kind: Service metadata: name: service-nginx-pvc spec: ports: - name: http port:80protocol: TCP targetPort:80selector: app: nginx-pvc type: LoadBalancer#创建deploymentkubectl apply-fstorage-deployment-nginx-pvc.yaml#查看多个pod资源共享[root@master1 ~]#curl 172.16.4.54PV Page[root@master1 ~]#curl 172.16.3.64PV Page[root@master1 ~]#curl 172.16.3.65PV Page
  • 强制删除

    • 生产中,对于存储资源的释放,最好按照流程来,即先清空应用,然后再清空pvc,但是生产中,经常遇到应用资源意外终止或者其他情况,导致对应的pvc资源没有使用,而且也没有清空

    • 有多种方式解决,最常用的一种方式就是,在所有的应用pod中增加一个prestop的钩子函数,从而让我们的应用资源合理的清空。

    • 而对于特殊的异常情况,还有另外一种策略,即强制清空,但是一般不推荐使用。

      #对于这种无论何种方法都无法删除的时候,我们可以通过修改配置属性的方式,从记录中删除该信息[root@master1 ~]#kubectl patch pv pv-nfs-1 -p '{"metadata":{"finalizers":null}}'persistentvolume/pv-nfs-1 patched#finalizers属性:[root@master1 ~]#kubectl explain pv.metadata.finalizersKIND: PersistentVolume VERSION: v1 FIELD: finalizers<[]string>DESCRIPTION: Must be empty before the object is deleted from the registry. Each entry is an identifierforthe responsible component that will remove the entry from the list. If the deletionTimestamp of the object is non-nil, entriesinthis list can only be removed. Finalizers may be processed and removedinany order. Order is NOT enforced because it introduces significant risk of stuck finalizers. finalizers is a shared field, any actor with permission can reorder it. If the finalizer list is processedinorder,thenthis can lead to a situationinwhichthe component responsibleforthe first finalizerinthe list is waitingfora signal(field value, external system, or other)produced by a component responsiblefora finalizer laterinthe list, resultingina deadlock. Without enforced ordering finalizers arefreeto order amongst themselves and are not vulnerable to ordering changesinthe list.#该属性的含义就是,当确定一个pv资源无用且内容为空的时候,可以从注册表中删除该信息#确认删除[root@master1 ~]#kubectl get pvN o resources found#PVC状态显示为Lost[root@master1 ~]#kubectl get pvcNAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE pvc-demo-1 Lost pv-nfs-1017m#如果有Pod使用PVC,先删除Pod,再删除PVC,否则会卡住等待[root@master1 ~]#kubectl delete pvc pvc-demo-1
  • subpath

    可以通过subpath实现针对不同的应用对应同一个PVC下不同子目录的挂载。volumeMounts.subPath 属性可用于指定所引用的卷内的子路径,而不是其根路径。

    范例: 同一个PVC下基于不同的subpath子目录存储不同Pod数据

    #准备NFS共享存储mkdir-p/nfsdata/wwwaptupdate&&apt-yinstallnfs-serverecho"/nfsdata *(rw,no_root_squash)">>/etc/exports exportfs-rexportfs-v#在所有worker节点安装nfs软件apt-yinstallnfs-common#准备PV,定制一个具体空间大小的存储对象catstorage-pv.yaml apiVersion: v1 kind: PersistentVolume metadata: name: pv-test#注意:不支持大写字母spec: capacity: storage: 3Gi accessModes: - ReadWriteOnce - ReadWriteMany - ReadOnlyMany nfs: path: /nfsdata/www server: nfs.wang.org#需要宿主机节点能解析此域名#如果该pv的使用方式支持多个,可以使用格式:accessModes: ["ReadWriteMany","ReadWriteOnce"]#如果nfs提供的目录空间个数多的话,可以同样的方式写多个。Pv的资源对象类型:PersistentVolume 存储空间大小设定:capacity 存储空间的访问模式:accessModes ReadWriteOnce#该volume只能被单个节点以读写的方式映射ReadOnlyMany#该volume可以被多个节点以只读方式映射ReadWriteMany#该volume只能被多个节点以读写的方式映射#可以指定回收策略:persistentVolumeReclaimPolicy: Recycle#准备PVC,定义一个资源对象,请求空间1Gicatstorage-pvc.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-test spec: accessModes: - ReadOnlyMany resources: requests: storage: 1Gicatstorage-nginx-pvc-subdir.yaml apiVersion: v1 kind: Pod metadata: name: pod-nginx-1 spec: volumes: - name: nginx-volume persistentVolumeClaim: claimName: pvc-test containers: - name: nginx-pv image: registry.cn-beijing.aliyuncs.com/wangxiaochun/nginx:1.20.0 volumeMounts: - name: nginx-volume mountPath:"/usr/share/nginx/html"subPath: web1 --- apiVersion: v1 kind: Pod metadata: name: pod-nginx-2 spec: volumes: - name: nginx-volume persistentVolumeClaim: claimName: pvc-test containers: - name: nginx-flask image: registry.cn-beijing.aliyuncs.com/wangxiaochun/nginx:1.20.0 volumeMounts: - name: nginx-volume mountPath:"/usr/share/nginx/html"subPath: web2 kubectl apply-fstorage-nginx-pvc-subdir.yaml#在NFS服务器上自动生成子目录#默认无法访问页面[root@master1 ~]#curl 172.16.4.51<html><head><title>403Forbidden</title></head><body><center><h1>403Forbidden</h1></center><hr><center>nginx/1.20.0</center></body></html>[root@master1 ~]#curl 172.16.3.63<html><head><title>403Forbidden</title></head><body><center><h1>403Forbidden</h1></center><hr><center>nginx/1.20.0</center></body></html>#创建页面echo/nfsdata/web1/index.html>/nfsdata/web1/index.htmlecho/nfsdata/web2/index.html>/nfsdata/web2/index.html#注意:需要稍等1分钟后,再访问成功[root@master1 ~]#curl 172.16.4.51/nfsdata/web1/index.html[root@master1 ~]#curl 172.16.3.63/nfsdata/web2/index.html

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询