×

持久化存储概述

管理存储与管理计算资源是不同的问题。OpenShift Dedicated 使用 Kubernetes 持久卷 (PV) 框架允许集群管理员为集群配置持久化存储。开发人员可以使用持久卷声明 (PVC) 请求 PV 资源,而无需了解底层存储基础设施的具体知识。

PVC 特定于一个项目,由开发人员创建和使用作为使用 PV 的一种手段。PV 资源本身不属于任何单个项目;它们可以在整个 OpenShift Dedicated 集群中共享,并可以从任何项目中声明。PV 绑定到 PVC 后,该 PV 就不能再绑定到其他 PVC。这实际上将绑定的 PV 的范围限定为单个命名空间,即绑定项目的命名空间。

PV 由一个 `PersistentVolume` API 对象定义,该对象表示集群中已经存在的存储块,这些存储块要么由集群管理员静态配置,要么使用 `StorageClass` 对象动态配置。它与节点一样是集群中的资源。

PV 是像 `Volumes` 这样的卷插件,但具有独立于使用 PV 的任何单个 Pod 的生命周期。PV 对象捕获存储实现的详细信息,无论是 NFS、iSCSI 还是特定于云提供商的存储系统。

基础设施中存储的高可用性留给底层存储提供商。

PVC 由一个 `PersistentVolumeClaim` API 对象定义,该对象表示开发人员对存储的请求。它类似于 Pod,Pod 使用节点资源,而 PVC 使用 PV 资源。例如,Pod 可以请求特定级别的资源,例如 CPU 和内存,而 PVC 可以请求特定的存储容量和访问模式。例如,它们可以被挂载一次读写或多次只读。

卷和声明的生命周期

PV 是集群中的资源。PVC 是对这些资源的请求,并且也充当对资源的声明检查。PV 和 PVC 之间的交互具有以下生命周期。

配置存储

为了响应开发人员在 PVC 中定义的请求,集群管理员配置一个或多个动态配置器来配置存储和匹配的 PV。

绑定声明

创建 PVC 时,您会请求特定数量的存储,指定所需的访问模式,并创建一个存储类来描述和分类存储。主节点中的控制循环监视新的 PVC 并将新的 PVC 绑定到合适的 PV。如果合适的 PV 不存在,则存储类的配置器会创建一个。

所有 PV 的大小都可能超过您的 PVC 大小。对于手动配置的 PV 尤其如此。为了最大限度地减少冗余,OpenShift Dedicated 会绑定到满足所有其他条件的最小 PV。

如果不存在匹配的卷,或者无法使用任何为存储类服务的可用供应器创建匹配的卷,则声明将无限期保持未绑定状态。当匹配的卷可用时,声明将被绑定。例如,一个集群中有许多手动配置的 50Gi 卷,则不会匹配请求 100Gi 的 PVC。当向集群添加 100Gi PV 时,可以绑定 PVC。

使用 Pod 和已声明的 PV

Pod 使用声明作为卷。集群检查声明以查找已绑定的卷,并为 Pod 挂载该卷。对于支持多种访问模式的那些卷,您必须在 Pod 中使用声明作为卷时指定适用哪种模式。

拥有声明并且该声明已绑定后,已绑定的 PV 将在您需要的时间内属于您。您可以通过在 Pod 的 volumes 块中包含 persistentVolumeClaim 来调度 Pod 并访问已声明的 PV。

如果将具有大量文件数的持久卷附加到 Pod,则这些 Pod 可能会失败或启动时间很长。有关更多信息,请参见 在 OpenShift 中使用具有大量文件数的持久卷时,为什么 Pod 无法启动或花费过长时间才能达到“就绪”状态?

释放持久卷

完成卷的使用后,您可以从 API 中删除 PVC 对象,这允许回收资源。当删除声明时,卷被认为已释放,但它尚未可用于另一个声明。先前声明者的数据保留在卷上,必须根据策略进行处理。

持久卷的回收策略

持久卷的回收策略告诉集群在释放卷后如何处理该卷。卷的回收策略可以是 RetainRecycleDelete

  • Retain 回收策略允许对支持它的那些卷插件手动回收资源。

  • Recycle 回收策略在卷从其声明中释放后将其回收回未绑定持久卷的池中。

在 OpenShift Dedicated 4 中已弃用 Recycle 回收策略。建议使用动态供应来获得等效或更好的功能。

  • Delete 回收策略将从 OpenShift Dedicated 中删除 PersistentVolume 对象以及外部基础设施(例如 Amazon Elastic Block Store (Amazon EBS) 或 VMware vSphere)中的关联存储资产。

动态供应的卷始终会被删除。

手动回收持久卷

删除持久卷声明 (PVC) 后,持久卷 (PV) 仍然存在,并被认为是“已释放”。但是,PV 尚未可用于另一个声明,因为先前声明者的数据保留在卷上。

步骤

要作为集群管理员手动回收 PV

  1. 删除 PV。

    $ oc delete pv <pv-name>

    删除 PV 后,外部基础设施(例如 AWS EBS 或 GCE PD 卷)中的关联存储资产仍然存在。

  2. 清理关联存储资产上的数据。

  3. 删除关联的存储资产。或者,要重用相同的存储资产,请使用存储资产定义创建一个新的 PV。

回收的 PV 现在可供另一个 PVC 使用。

更改持久卷的回收策略

要更改持久卷的回收策略

  1. 列出集群中的持久卷

    $ oc get pv
    示例输出
    NAME                                       CAPACITY   ACCESSMODES   RECLAIMPOLICY   STATUS    CLAIM             STORAGECLASS     REASON    AGE
     pvc-b6efd8da-b7b5-11e6-9d58-0ed433a7dd94   4Gi        RWO           Delete          Bound     default/claim1    manual                     10s
     pvc-b95650f8-b7b5-11e6-9d58-0ed433a7dd94   4Gi        RWO           Delete          Bound     default/claim2    manual                     6s
     pvc-bb3ca71d-b7b5-11e6-9d58-0ed433a7dd94   4Gi        RWO           Delete          Bound     default/claim3    manual                     3s
  2. 选择一个持久卷并更改其回收策略

    $ oc patch pv <your-pv-name> -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'
  3. 验证您选择的持久卷是否具有正确的策略

    $ oc get pv
    示例输出
    NAME                                       CAPACITY   ACCESSMODES   RECLAIMPOLICY   STATUS    CLAIM             STORAGECLASS     REASON    AGE
     pvc-b6efd8da-b7b5-11e6-9d58-0ed433a7dd94   4Gi        RWO           Delete          Bound     default/claim1    manual                     10s
     pvc-b95650f8-b7b5-11e6-9d58-0ed433a7dd94   4Gi        RWO           Delete          Bound     default/claim2    manual                     6s
     pvc-bb3ca71d-b7b5-11e6-9d58-0ed433a7dd94   4Gi        RWO           Retain          Bound     default/claim3    manual                     3s

    在前面的输出中,绑定到声明 default/claim3 的卷现在具有 Retain 回收策略。当用户删除声明 default/claim3 时,该卷不会自动删除。

持久卷

每个 PV 包含一个 specstatus,它们分别是卷的规范和状态,例如

PersistentVolume 对象定义示例
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0001 (1)
spec:
  capacity:
    storage: 5Gi (2)
  accessModes:
    - ReadWriteOnce (3)
  persistentVolumeReclaimPolicy: Retain (4)
  ...
status:
  ...
1 持久卷的名称。
2 可用于该卷的存储量。
3 访问模式,定义读写和挂载权限。
4 回收策略,指示释放资源后如何处理该资源。

PV 类型

OpenShift Dedicated 支持以下持久卷插件

  • AWS Elastic Block Store (EBS)

  • GCP 持久性磁盘

  • GCP Filestore

容量

通常,持久卷 (PV) 具有特定的存储容量。这是通过使用 PV 的 capacity 属性设置的。

目前,存储容量是唯一可以设置或请求的资源。未来的属性可能包括 IOPS、吞吐量等。

访问模式

持久卷可以以资源提供商支持的任何方式安装在主机上。提供商具有不同的功能,并且每个 PV 的访问模式都设置为该特定卷支持的特定模式。例如,NFS 可以支持多个读写客户端,但是特定 NFS PV 可以在服务器上以只读方式导出。每个 PV 都拥有自己的一组访问模式,描述该特定 PV 的功能。

声明与具有相似访问模式的卷匹配。只有两个匹配条件:访问模式和大小。声明的访问模式代表一个请求。因此,您可能会获得更多,但决不会更少。例如,如果声明请求 RWO,但唯一可用的卷是 NFS PV (RWO+ROX+RWX),则声明将匹配 NFS,因为它支持 RWO。

始终首先尝试直接匹配。卷的模式必须匹配或包含比您请求的更多模式。大小必须大于或等于预期大小。如果两种类型的卷(例如 NFS 和 iSCSI)具有相同的访问模式集,则它们中的任何一个都可以与具有这些模式的声明匹配。卷类型之间没有顺序,也没有办法选择一种类型而不是另一种类型。

将所有具有相同模式的卷分组,然后按大小排序,从小到大。绑定程序获取具有匹配模式的组,并按大小顺序迭代每个组,直到大小匹配。

卷访问模式描述卷功能。它们不是强制约束。存储提供商负责由于资源使用无效而导致的运行时错误。提供商中的错误在运行时显示为挂载错误。

下表列出了访问模式

表 1. 访问模式
访问模式 CLI 缩写 描述

ReadWriteOnce

RWO

该卷可以被单个节点以读写方式挂载。

ReadWriteOncePod [1]

RWOP

该卷可以被单个节点上的单个 Pod 以读写方式挂载。

  1. RWOP 使用 SELinux 挂载功能。此功能取决于驱动程序,并在 ODF、AWS EBS、Azure 磁盘、GCP PD、IBM Cloud 块存储卷、Cinder 和 vSphere 中默认启用。对于第三方驱动程序,请联系您的存储供应商。

表 2. 持久卷支持的访问模式
卷插件 ReadWriteOnce [1] ReadWriteOncePod ReadOnlyMany ReadWriteMany

AWS EBS [2]

AWS EFS

GCP 持久性磁盘

GCP Filestore

LVM 存储

  1. ReadWriteOnce (RWO) 卷不能安装在多个节点上。如果节点发生故障,系统不允许将附加的 RWO 卷安装到新节点上,因为它已分配给故障节点。如果因此遇到多附加错误消息,请强制删除关闭或崩溃节点上的 Pod,以避免在关键工作负载中丢失数据,例如在附加动态持久卷时。

  2. 对于依赖 AWS EBS 的 Pod,请使用重新创建部署策略。

  3. 只有原始块卷支持光纤通道和 iSCSI 的 ReadWriteMany (RWX) 访问模式。更多信息,请参见“块卷支持”。

阶段

卷可以处于以下阶段之一:

表 3. 卷阶段
阶段 描述

可用

尚未绑定到声明的空闲资源。

已绑定

卷已绑定到声明。

已释放

声明已删除,但资源尚未被集群回收。

失败

卷的自动回收失败。

您可以通过运行以下命令查看绑定到 PV 的 PVC 的名称:

$ oc get pv <pv-claim>

挂载选项

您可以使用属性mountOptions在挂载 PV 时指定挂载选项。

例如:

挂载选项示例
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0001
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  mountOptions: (1)
    - nfsvers=4.1
  nfs:
    path: /tmp
    server: 172.17.0.2
  persistentVolumeReclaimPolicy: Retain
  claimRef:
    name: claim1
    namespace: default
1 指定的挂载选项在将 PV 挂载到磁盘时使用。

以下 PV 类型支持挂载选项:

  • AWS Elastic Block Store (EBS)

  • GCE 持久性磁盘

持久卷声明

每个PersistentVolumeClaim对象包含一个specstatus,它们分别是持久卷声明 (PVC) 的规范和状态,例如:

PersistentVolumeClaim对象定义示例
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: myclaim (1)
spec:
  accessModes:
    - ReadWriteOnce (2)
  resources:
    requests:
      storage: 8Gi (3)
  storageClassName: gold (4)
status:
  ...
1 PVC 的名称。
2 访问模式,定义读写和挂载权限。
3 可用于 PVC 的存储量。
4 声明所需的StorageClass名称。

存储类

声明可以通过在storageClassName属性中指定存储类的名称来可选地请求特定存储类。只有请求的类别的 PV(其storageClassName与 PVC 相同)才能绑定到 PVC。集群管理员可以配置动态供应程序来服务一个或多个存储类。集群管理员可以按需创建一个与 PVC 中规范匹配的 PV。

集群存储操作员可能会根据使用的平台安装默认存储类。此存储类由操作员拥有和控制。除了定义注释和标签外,它不能被删除或修改。如果需要不同的行为,您必须定义自定义存储类。

集群管理员还可以为所有 PVC 设置默认存储类。当配置默认存储类时,PVC 必须显式请求StorageClass或将storageClassName注释设置为""才能绑定到没有存储类的 PV。

如果多个存储类被标记为默认存储类,则只有在显式指定storageClassName的情况下才能创建 PVC。因此,应只将一个存储类设置为默认存储类。

访问模式

声明在使用特定访问模式请求存储时使用与卷相同的约定。

资源

声明(例如 Pod)可以请求特定数量的资源。在这种情况下,请求的是存储。相同的资源模型适用于卷和声明。

声明作为卷

Pod 通过使用声明作为卷来访问存储。声明必须存在于与使用该声明的 Pod 相同的命名空间中。集群在 Pod 的命名空间中找到声明,并使用它来获取支持该声明的PersistentVolume。卷被挂载到主机和 Pod 中,例如:

将卷挂载到主机和 Pod 中的示例
kind: Pod
apiVersion: v1
metadata:
  name: mypod
spec:
  containers:
    - name: myfrontend
      image: dockerfile/nginx
      volumeMounts:
      - mountPath: "/var/www/html" (1)
        name: mypd (2)
  volumes:
    - name: mypd
      persistentVolumeClaim:
        claimName: myclaim (3)
1 在 Pod 内挂载卷的路径。
2 要挂载的卷的名称。不要挂载到容器根目录/或主机和容器中相同的任何路径。如果容器具有足够的权限(例如主机/dev/pts文件),这可能会损坏您的主机系统。可以使用/host安全地挂载主机。
3 要使用的 PVC 名称,它存在于相同的命名空间中。

块卷支持

OpenShift Dedicated 可以静态地预配原始块卷。这些卷没有文件系统,并且可以为直接写入磁盘或实现其自身存储服务的应用程序提供性能优势。

通过在 PV 和 PVC 规范中指定volumeMode: Block来预配原始块卷。

使用原始块卷的 Pod 必须配置为允许特权容器。

下表显示哪些卷插件支持块卷。

表 4. 块卷支持
卷插件 手动预配 动态预配 完全支持

Amazon Elastic Block Store (Amazon EBS)

Amazon Elastic File Storage (Amazon EFS)

GCP

LVM 存储

块卷示例

PV 示例
apiVersion: v1
kind: PersistentVolume
metadata:
  name: block-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  volumeMode: Block (1)
  persistentVolumeReclaimPolicy: Retain
  fc:
    targetWWNs: ["50060e801049cfd1"]
    lun: 0
    readOnly: false
1 必须将volumeMode设置为Block以指示此 PV 是原始块卷。
PVC 示例
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: block-pvc
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Block (1)
  resources:
    requests:
      storage: 10Gi
1 必须将volumeMode设置为Block以指示请求原始块 PVC。
Pod规范示例
apiVersion: v1
kind: Pod
metadata:
  name: pod-with-block-volume
spec:
  containers:
    - name: fc-container
      image: fedora:26
      command: ["/bin/sh", "-c"]
      args: [ "tail -f /dev/null" ]
      volumeDevices:  (1)
        - name: data
          devicePath: /dev/xvda (2)
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: block-pvc (3)
1 对于块设备,使用volumeDevices而不是volumeMounts。只有PersistentVolumeClaim源可以与原始块卷一起使用。
2 devicePath而不是mountPath表示将原始块映射到系统的物理设备的路径。
3 卷源必须是persistentVolumeClaim类型,并且必须与 PVC 的名称匹配。
表 5. volumeMode的接受值
默认值

文件系统

表 6. 块卷的绑定场景
PV volumeMode PVC volumeMode 绑定结果

文件系统

文件系统

绑定

未指定

未指定

绑定

文件系统

未指定

绑定

未指定

文件系统

绑定

绑定

未指定

不绑定

未指定

不绑定

文件系统

不绑定

文件系统

不绑定

未指定的值将导致默认值为Filesystem

使用 fsGroup 减少 Pod 超时

如果存储卷包含许多文件(约 1,000,000 个或更多),您可能会遇到 Pod 超时。

出现这种情况的原因是,默认情况下,当挂载卷时,OpenShift Dedicated 会递归地更改每个卷内容的所有权和权限,以匹配 Pod 的securityContext中指定的fsGroup。对于大型卷,检查和更改所有权和权限可能非常耗时,从而减慢 Pod 启动速度。您可以使用securityContext内的fsGroupChangePolicy字段来控制 OpenShift Dedicated 检查和管理卷的所有权和权限的方式。

fsGroupChangePolicy定义在卷在 Pod 内公开之前更改其所有权和权限的行为。此字段仅适用于支持fsGroup控制的所有权和权限的卷类型。此字段有两个可能的值:

  • OnRootMismatch:仅当根目录的权限和所有权与卷的预期权限不匹配时才更改权限和所有权。这可以帮助缩短更改卷的所有权和权限所需的时间,从而减少 Pod 超时。

  • Always:挂载卷时始终更改卷的权限和所有权。

fsGroupChangePolicy示例
securityContext:
  runAsUser: 1000
  runAsGroup: 3000
  fsGroup: 2000
  fsGroupChangePolicy: "OnRootMismatch" (1)
  ...
1 OnRootMismatch指定跳过递归权限更改,从而有助于避免 Pod 超时问题。

fsGroupChangePolicy字段对短暂卷类型(例如 secret、configMap 和 emptydir)无效。