×

持久化存储概述

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

PVC 特定于一个项目,由开发人员创建和使用作为使用 PV 的手段。PV 资源本身并不属于任何单个项目;它们可以在整个 OpenShift Container Platform 集群中共享,并可以从任何项目中声明。PV 绑定到 PVC 后,就不能再绑定到其他 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。

或者,集群管理员可以预先创建多个 PV,其中包含可供使用的实际存储的详细信息。PV 存在于 API 中,可供使用。

绑定声明

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

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

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

使用 Pod 和已声明的 PV

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

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

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

正在使用的存储对象保护

正在使用的存储对象保护功能确保不会从系统中删除 Pod 正在积极使用的 PVC 和绑定到 PVC 的 PV,因为这会导致数据丢失。

默认情况下启用正在使用的存储对象保护。

当存在使用 PVC 的 `Pod` 对象时,Pod 正在积极使用 PVC。

如果用户删除 Pod 正在积极使用的 PVC,则不会立即删除 PVC。PVC 删除将推迟到 PVC 不再被任何 Pod 积极使用为止。同样,如果集群管理员删除绑定到 PVC 的 PV,则不会立即删除 PV。PV 删除将推迟到 PV 不再绑定到 PVC 为止。

释放持久卷

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

持久卷的回收策略

持久卷的回收策略告诉集群在释放卷后如何处理该卷。卷的回收策略可以是 `Retain`、`Recycle` 或 `Delete`。

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

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

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

  • `Delete` 回收策略会从 OpenShift Container Platform 中删除 `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、Azure 磁盘或 Cinder 卷)中的关联存储资源仍然存在。

  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 包含一个 `spec` 和 `status`,这是卷的规范和状态,例如

持久卷对象定义示例
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 Container Platform 支持以下持久卷插件

  • AWS Elastic Block Store (EBS)

  • AWS Elastic File Store (EFS)

  • Azure 磁盘

  • Azure 文件

  • Cinder

  • 光纤通道

  • GCP 持久性磁盘

  • GCP Filestore

  • IBM Power 虚拟服务器块

  • IBM Cloud® VPC 块

  • HostPath

  • iSCSI

  • 本地卷

  • NFS

  • OpenStack Manila

  • Red Hat OpenShift Data Foundation

  • CIFS/SMB

  • VMware vSphere

容量

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

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

访问模式

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

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

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

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

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

例如,NFS 提供ReadWriteOnce访问模式。如果您想使用卷的 ROX 功能,请将声明标记为ReadOnlyMany

iSCSI 和光纤通道卷目前没有任何隔离机制。您必须确保卷一次只能由一个节点使用。在某些情况下,例如节点 drain 操作,卷可以由两个节点同时使用。在 drain 节点之前,请删除使用这些卷的 Pod。

下表列出了访问模式

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

ReadWriteOnce

RWO

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

ReadWriteOncePod [1]

RWOP

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

ReadOnlyMany

ROX

该卷可以被多个节点以只读方式挂载。

ReadWriteMany

RWX

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

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

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

AWS EBS [2]

AWS EFS

Azure 文件

Azure 磁盘

CIFS/SMB

Cinder

光纤通道

[3]

GCP 持久性磁盘

GCP Filestore

HostPath

IBM Power 虚拟服务器磁盘

IBM Cloud® VPC 磁盘

iSCSI

[3]

本地卷

LVM 存储

NFS

OpenStack Manila

Red Hat OpenShift Data Foundation

VMware vSphere

[4]

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

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

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

  4. 如果底层 vSphere 环境支持 vSAN 文件服务,则由 OpenShift Container Platform 安装的 vSphere Container Storage Interface (CSI) 驱动程序操作符支持 ReadWriteMany (RWX) 卷的预配。如果您没有配置 vSAN 文件服务,并且您请求 RWX,则卷将无法创建,并且会记录错误。有关更多信息,请参阅“使用容器存储接口”→“VMware vSphere CSI 驱动程序操作符”。

阶段

卷可以处于以下阶段之一

表 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)

  • Azure 磁盘

  • Azure 文件

  • Cinder

  • GCE 持久性磁盘

  • iSCSI

  • 本地卷

  • NFS

  • Red Hat OpenShift 数据基础(仅限 Ceph RBD)

  • CIFS/SMB

  • VMware vSphere

光纤通道和 HostPath PV 不支持挂载选项。

持久卷声明

每个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 相同的 PV)才能绑定到 PVC。集群管理员可以配置动态预配程序来服务一个或多个存储类。集群管理员可以按需创建与 PVC 中规范匹配的 PV。

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

集群管理员还可以为所有 PVC 设置默认存储类。当配置默认存储类时,PVC 必须显式请求StorageClassstorageClassName注释设置为""才能绑定到没有存储类的 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 名称,该 PVC 存在于相同的命名空间中。

块卷支持

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

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

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

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

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

Amazon Elastic Block Store (Amazon EBS)

Amazon Elastic File Storage (Amazon EFS)

Azure 磁盘

Azure 文件

Cinder

光纤通道

GCP

HostPath

IBM Cloud 块存储卷

iSCSI

本地卷

LVM 存储

NFS

Red Hat OpenShift Data Foundation

CIFS/SMB

VMware vSphere

使用任何可以手动预配但未提供完全支持的块卷,这仅是技术预览功能。技术预览功能不受 Red Hat 生产服务级别协议 (SLA) 的支持,并且可能功能不完整。Red Hat 不建议在生产环境中使用它们。这些功能可以提前访问即将推出的产品功能,使客户能够在开发过程中测试功能并提供反馈。

有关 Red Hat 技术预览功能的支持范围的更多信息,请参阅 技术预览功能支持范围

块卷示例

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 Container Platform 会递归更改每个卷内容的所有权和权限,以匹配 pod 的securityContext中指定的fsGroup。对于大型卷,检查和更改所有权和权限可能非常耗时,从而减慢 Pod 启动速度。您可以使用securityContext内的fsGroupChangePolicy字段来控制 OpenShift Container Platform 检查和管理卷的所有权和权限的方式。

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

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

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

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

fsGroupChangePolicy字段对短暂卷类型(例如 secret、configMap 和 emptydir)没有影响。