K8s - 3 核心概念 - 7 PVC 和 PV


K8s - 目录



一、kubernetes 核心技术-PVC 和 PV


1. 基本概念

管理存储是管理计算的一个明显问题。该 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 是一 一对应的。

2. 生命周期

PV 是群集中的资源。PVC 是对这些资源的请求,并且还充当对资源的检查。PV 和 PVC 之间 的相互作用遵循以下生命周期:

Provisioning ==> Binding ==> Using ==> Releasing ==> Recycling

供应准备 Provisioning:通过集群外的存储系统或者云平台来提供存储持久化支持。

  • 静态提供 Static: 集群管理员创建多个 PV。 它们携带可供集群用户使用的真实存储的详细信息。 它们存在于 Kubernetes API 中,可用于消费。
  • 动态提供 Dynamic: 当管理员创建的静态 PV 都不匹配用户的 PersistentVolumeClaim 时,集群可能会尝试为 PVC 动态配置卷。 此配置基于 StorageClasses: PVC 必须请求一个类,并且管理员必须已创建并配置该类才能进行动态配置。 要求该类的声明有效地为自己禁用动态配置。

绑定 Binding:用户创建 PVC 并指定需要的资源和访问模式。在找到可用PV 之前,PVC 会保持未绑定状态。

使用 Using:用户可在 pod 中像 volume 一样使用 PVC。

释放 Releasing:用户删除 PVC 来回收存储资源,PV 将变成“released”状态。由于还保留着之前的数据,这些数据需要根据不同的策略来处理,否则这些存储资源无法被其他 PVC 使用。

回收 Recycling:PV 可以设置三种回收策略: 保留(Retain) ,回收(Recycle) 和删除 (Delete) 。

  • 保留策略: 允许人工处理保留的数据。
  • 删除策略: 将删除 PV 和外部关联的存储资源,需要插件支持。
  • 回收策略: 将执行清除操作,之后可以被新的 PVC 使用,需要插件支持

3. PV 类型

GCEPersistentDisk
AWSElasticBlockStore
AzureFile
AzureDisk
FC (Fibre Channel)
Flexvolume
Flocker
NFS
iSCSI
RBD (Ceph Block Device)
CephFS
Cinder (OpenStack block storage)
Glusterfs
VsphereVolume
Quobyte Volumes
HostPath (仅单节点测试 - 不支持任何方式的本地存储,并且不会在多节点集群中工作)
Portworx Volumes
ScaleIO Volumes
StorageOS

4. PV 卷阶段状态

状态说明
Available资源尚未被 claim 使用。
Bound卷已经被绑定到 claim 了。
Releasedclaim 被删除,卷处于释放状态,但未被集群回收。
Failed卷自动回收失败。

5. PV 和 PVC 的访问模式

状态全称说明
RWOReadWriteOnce有读写权限且只能被单个node挂载。
ROXReadOnlyMany只读权限允许被多个node挂载。
RWXReadWriteMany有读写权限允许被多个node挂载。

6. 数据挂载

6.1 emptyDir 卷

当Pod指定到某个节点上时,首先创建的是一个emptyDir卷,并且只要Pod在该节点上运行,卷就一直存在。就像它的名称表示的那样,卷最初是空的。尽管Pod中的容器挂载emptyDir卷的路径可能相同也可能不同,但是这些容器都可以读写emptyDir卷中相同的文件。当Pod因为某些原因被从节点上删除时,emptyDir卷中的数据也会永久删除。

注意:

  • 容器崩溃并不会导致Pod被从节点上移除,因此容器崩溃时 emptyDir卷中的数据是安全的。
  • 容器中的挂载目录中的文件会被覆盖。
    如下示例:nginx 容器目录 /etc/nginx/conf.d/ 中原本有文件 default.conf,挂载目录中没有文件,那么容器目录中的文件 default.conf 会被清空。后续再将自定义的的 nginx 子配置文件放入挂载目录下,文件会自动同步到容器目录下。

emptyDir的一些用途:

  • 缓存空间,例如基于磁盘的归并排序。
  • 为耗时较长的计算任务提供检查点,以使任务能从崩溃前状态恢复。

默认情况下,emptyDir卷存储在支持该节点所使用的介质上;这介质可以是磁盘或SSD或网络存储,这取决于环境。

nginx pod 增加一个 emptyDir 类型的 Volume 存储卷,并分别挂载 html 目录、conf 目录。

# nginx-emptyDir-volume.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-emptyDir-volume
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-emptyDir-volume
  template:
    metadata:
      name: nginx-emptyDir-volume
      labels:
        app: nginx-emptyDir-volume
    spec:
      volumes:
        - name: emptyDir-volume # 增加一个名为 emptyDir-volume 的 volume 存储卷。
          emptyDir: { } # pod 分配到 node 时创建的,k8s 自动分配的一个目录,pod 从 node 移除时 emptyDir 中的数据永久删除。
      containers:
        - image: nginx
          name: nginx
          volumeMounts:
            - name: emptyDir-volume
              mountPath: /home/nginx/html # 挂载 nginx 静态页面
            - name: emptyDir-volume
              mountPath: /etc/nginx/conf.d/ # 挂载 nginx 配置文件

pod 内多容器之间的数据共享
// TODO

官方文档

6.2 hostPath

注意:

  • HostPath 卷存在许多安全风险,最好的做法是尽可能避免使用 HostPath。当必须使用 HostPath 卷时,它的范围应仅限于所需的文件或目录,并以只读方式挂载。
  • 如果通过 AdmissionPolicy 限制 HostPath 对特定目录的访问,volumeMounts必须要求使用 readOnly 挂载才能使策略生效。

hostPath 卷能将宿主节点文件系统上的文件或目录挂载到 Pod 中。虽然这不是大多数 Pod 需要的,但是它为一些应用程序提供了强大的逃生舱。

例如,hostPath 的一些用途:

  • 运行需要访问 Docker 内部的容器;使用hostPath 一个/var/lib/docker
  • 在容器中运行 cAdvisor;使用hostPath一个/sys
  • 允许 Pod 在 Pod 运行之前指定给定是否hostPath应该存在,是否应该创建,以及应该以什么形式存在

除了必需的 path 属性之外,用户可以选择性地为 hostPath 卷指定 type:

行为
空字符串(默认)是为了向后兼容,这意味着在挂载 hostPath 卷之前不会执行任何检查。
DirectoryOrCreate如果给定路径不存在任何内容,则会根据需要在此处创建一个空目录,权限设置为 0755,与 Kubelet 具有相同的组和所有权。
Directory目录必须存在于给定路径
FileOrCreate如果给定路径不存在任何内容,则会根据需要在此处创建一个空文件,权限设置为 0644,与 Kubelet 具有相同的组和所有权。
File文件必须存在于给定路径
Socket给定路径中必须存在 UNIX 套接字
CharDevice字符设备必须存在于给定路径中
BlockDevice块设备必须存在于给定路径

使用这种类型的时需要注意,因为:

  • HostPaths 可以暴露特权系统凭据(例如 Kubelet)或特权 API(例如容器运行时套接字),可用于容器逃逸或攻击集群的其他部分。
  • 由于节点上的文件不同,具有相同配置(例如从 PodTemplate 创建)的 Pod 在不同节点上的行为可能不同。
  • 在底层主机上创建的文件或目录只能由 root 写入。您要么需要在 特权容器中以 root 身份运行进程,要么修改主机上的文件权限以便能够写入hostPath 卷。
# nginx-hostPath-volume.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-hostpath-volume
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
    - name: file
      mountPath: /usr/share/nginx/html/index.html
    - name: conf
      mountPath: /etc/nginx/conf.d
  volumes:
    - name: html
      hostPath:
        path: /data/hostPath/data/nginx-hostpath-volume/html # 主机上目录的路径。如果路径是符号链接,它将跟随链接到真实路径。
        type: DirectoryOrCreate # 如果给定路径不存在任何内容,则会根据需要在此处创建一个空目录,权限设置为 0755,与 Kubelet 具有相同的组和所有权。
    - name: file
      hostPath:
        path: /data/hostPath/data/nginx-hostpath-volume/html/index.html # 主机上目录的路径。如果路径是符号链接,它将跟随链接到真实路径。
        type: FileOrCreate # 如果给定路径不存在任何内容,则会根据需要在此处创建一个空文件,权限设置为 0644,与 Kubelet 具有相同的组和所有权。
    - name: conf
      hostPath:
        path: /data/hostPath/data/nginx-hostpath-volume/conf
        type: DirectoryOrCreate

官方文档

6.3 nfs

nfs 卷能将 NFS (网络文件系统) 挂载到你的 Pod 中。 不像 emptyDir 那样会在删除 Pod 的同时也会被删除,nfs 卷的内容在删除 Pod 时会被保存,卷只是被卸载。 这意味着 nfs 卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。

注意: 在使用 NFS 卷之前,你必须运行自己的 NFS 服务器并将目标 share 导出备用。

# nginx-nfs-volume.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-nfs-volume
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-nfs-volume
  template:
    metadata:
      name: nginx-nfs-volume
      labels:
        app: nginx-nfs-volume
    spec:
      containers:
        - image: nginx
          name: nginx
          volumeMounts:
            - name: html
              mountPath: /usr/share/nginx/html
      volumes:
        - name: html
          nfs:
            server: 192.168.80.200
            path: /data/nfs/data # 此路径必须存在,否则 pod 将无法启动。

要了解更多详情请参考 NFS 示例

官方文档

6.4 persistentVolumeClaim

persistentVolumeClaim 卷用来将持久卷(PersistentVolume) 挂载到 Pod 中。 持久卷申领(PersistentVolumeClaim)是用户在不知道特定云环境细节的情况下"申领"持久存储 (例如 GCE PersistentDisk 或者 iSCSI 卷)的一种方法。

更多详情请参考持久卷示例

官方文档

7. demo 演示

7.1 创建 PV

  1. 创建5个不同配置的 PV:

    # pv-demo.yaml
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv001
      labels:
        name: pv001
    spec:
      nfs:
        path: /data/nfs/data/v1
        server: 192.168.80.200
      accessModes: [ "ReadWriteMany","ReadWriteOnce" ]
      capacity:
        storage: 2Gi
    
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv002
      labels:
        name: pv002
    spec:
      nfs:
        path: /data/nfs/data/v2
        server: 192.168.80.200
      accessModes: [ "ReadWriteOnce" ]
      capacity:
        storage: 5Gi
    
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv003
      labels:
        name: pv003
    spec:
      nfs:
        path: /data/nfs/data/v3
        server: 192.168.80.200
      accessModes: [ "ReadWriteMany","ReadWriteOnce" ]
      capacity:
        storage: 10Gi
    
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv004
      labels:
        name: pv004
    spec:
      nfs:
        path: /data/nfs/data/v4
        server: 192.168.80.200
      accessModes: [ "ReadWriteMany","ReadWriteOnce" ]
      capacity:
        storage: 15Gi
    
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv005
      labels:
        name: pv005
    spec:
      nfs:
        path: /data/nfs/data/v5
        server: 192.168.80.200
      accessModes: [ "ReadWriteMany","ReadWriteOnce" ]
      capacity:
        storage: 20Gi
    
  2. 执行创建命令

    kubectl apply -f pv-damo.yaml
    
  3. 查询验证

    kubelet get pv
    

    输出内容:

    NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
    pv001   2Gi        RWO,RWX        Retain           Available                                   5s
    pv002   5Gi        RWO            Retain           Available                                   5s
    pv003   10Gi       RWO,RWX        Retain           Available                                   5s
    pv004   15Gi       RWO,RWX        Retain           Available                                   5s
    pv005   20Gi       RWO,RWX        Retain           Available                                   5s
    

7.2 创建 PVC,绑定 PV

  1. 编写 yaml 文件,并创建 PVC
    创建一个 PVC,需要 6G 存储。所以不会匹配 pv001、pv002。

    # pvc-demo.yaml
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: pvc-nginx
      namespace: default
    spec:
      accessModes: [ "ReadWriteMany" ]
      resources:
        requests:
          storage: 6Gi
    
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: pvc-nginx
      namespace: default
    spec:
      containers:
        - name: nginx
          image: nginx
          volumeMounts:
            - name: html
              mountPath: /usr/share/nginx/html/
      volumes:
        - name: html
          persistentVolumeClaim:
            claimName: pvc-nginx
    
  2. 执行命令创建

    kubectl apply -f pvc-demo.yaml
    
  3. 查询验证
    查询 pvc:

    kubectl get pvc
    

    输出内容:

    NAME        STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    pvc-nginx   Bound    pv003    10Gi       RWO,RWX                       13s
    

    查询 PV:

    kubectl get pv
    

    输出内容:

    NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM           STORAGECLASS   REASON   AGE
    pv001   2Gi        RWO,RWX        Retain           Available                                           11m
    pv002   5Gi        RWO            Retain           Available                                           11m
    pv003   10Gi       RWO,RWX        Retain           Bound       default/pvc-nginx                       11m
    pv004   15Gi       RWO,RWX        Retain           Available                                           11m
    pv005   20Gi       RWO,RWX        Retain           Available                                           11m
    

7. 3 删除PVC 和 PV

注意:

  • 被 pod 绑定的 PVC,在 pod 删除后,PVC 会被删除,PV 不会被删除。PV 会依旧留存在系统中。如果需要删除,则需要手动删除。
  • 用户删除 PVC 来回收存储资源,PV 将变成 released 状态。由于还保留着之前的数据,这些数据需要根据不同的策略来处理,否则这些存储资源无法被其他 PVC 使用。
  1. 删除 PVC
    注意:PVC 在被 pod 使用时是无法删除的。
    删除 pod:

    kubectl delete -f pvc-demo.yaml
    

    输出内容:

    persistentvolumeclaim "pvc-nginx" deleted
    pod "pvc-nginx" deleted
    

    查询 PVC:

    No resources found in default namespace.
    

    查询 PV:

    NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM               STORAGECLASS   REASON   AGE
    pv001   2Gi        RWO,RWX        Retain           Available                                               38m
    pv002   5Gi        RWO            Retain           Available                                               38m
    pv003   10Gi       RWO,RWX        Retain           Released    default/pvc-nginx                           62s
    pv004   15Gi       RWO,RWX        Retain           Available                                               2m2s
    pv005   20Gi       RWO,RWX        Retain           Available                                               38m
    
  2. 删除 PV

    kubectl delete pv pv003
    

    输出内容:

    persistentvolume "pv003" deleted
    

    查看 PV:

    kubectl get pv
    

    输出内容:

    NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
    pv001   2Gi        RWO,RWX        Retain           Available                                   41m
    pv002   5Gi        RWO            Retain           Available                                   41m
    pv004   15Gi       RWO,RWX        Retain           Available                                   4m40s
    pv005   20Gi       RWO,RWX        Retain           Available                                   41m
    

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

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qumy97

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值