永久性卷和动态预配

本页面简要介绍了 Kubernetes 中的 PersistentVolume 和 PersistentVolumeClaim,及其在 Google Kubernetes Engine (GKE) 中的用法。本页面重点介绍由 Compute Engine 永久性磁盘支持的存储。

PersistentVolume

PersistentVolume 资源用于管理集群中的持久性存储。在 GKE 中,PersistentVolume 通常由 Compute Engine 永久性磁盘提供支持。PersistentVolume 还可用于其他存储类型,例如 NFS。Filestore 是 Google Cloud 上的 NFS 解决方案。如需了解如何将 Filestore 实例设置为 GKE 集群的 NFS PV 解决方案,请参阅 Filestore 文档中的访问 Google Kubernetes Engine 集群中的文件共享

您还可以将 PersistentVolume 与 Cloud Volumes 服务搭配使用。此产品是一项全代管式云端数据存储服务,可提供高级数据管理功能和扩缩性极强的性能。如需查看示例,请参阅适用于 Google Cloud 的 Cloud Volumes 服务

不同,PersistentVolume 生命周期由 Kubernetes 管理。PersistentVolume 可以动态预配;您无需手动创建和删除后备存储。

PersistentVolume 是独立于 Pod 存在的集群资源。这意味着在集群更改时以及在删除并重新创建 Pod 时,PersistentVolume 表示的磁盘和数据将继续存在。PersistentVolume 资源可以通过 PersistentVolumeClaim 动态预配,也可以由集群管理员明确创建。

如需详细了解 PersistentVolume,请参阅 Kubernetes 文档

PersistentVolumeClaims

PersistentVolumeClaim 是对 PersistentVolume 资源的请求和声明。PersistentVolumeClaim 对象会针对 PersistentVolume 请求特定大小、访问模式和 StorageClass。如果存在满足请求的 PersistentVolume 或者可以预配,则 PersistentVolumeClaim 会绑定到该 PersistentVolume。

Pod 将声明用作卷。集群会检查声明以找到绑定的卷并为 Pod 装载该卷。

可移植性是使用 PersistentVolume 和 PersistentVolumeClaim 的另一个优点。您可以在不同集群和环境中轻松使用相同的 Pod 规范,因为 PersistentVolume 是实际后备存储的接口。

StorageClass

诸如 gcePersistentDisk 之类的卷实现是通过 StorageClass 资源配置的。GKE 会为您创建一个使用标准永久性磁盘类型 (ext4) 的默认 StorageClass。如果 PersistentVolumeClaim 未指定 StorageClassName,则将使用默认 StorageClass。您可以将提供的默认 StorageClass 替换为您自己的 StorageClass。

如果您使用的是具有 Windows 节点池的集群,则必须创建 StorageClass,并在 PersistentVolumeClaim 中指定 StorageClassName,因为 Windows 不支持默认的 fstype ext4。如果您使用的是 Compute Engine 永久性磁盘,则必须使用 NTFS 作为文件存储类型。

您可以创建自己的 StorageClass 资源来描述不同类别的存储。例如,类可能与服务质量等级或备份政策相对应。在其他存储系统中,此概念有时称为“配置文件”。

动态预配 PersistentVolume

在大多数情况下,您不需要直接配置 PersistentVolume 对象或创建 Compute Engine 永久性磁盘。您可以改为创建 PersistentVolumeClaim,然后 Kubernetes 会自动为您预配永久性磁盘。

以下清单描述了对 30 GB (GiB) 磁盘的请求,该磁盘的访问模式允许单个节点以读写方式装载磁盘:

# pvc-demo.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-demo
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 30Gi

在您使用 kubectl apply -f pvc-demo.yaml 创建此 PersistentVolumeClaim 后,Kubernetes 会动态创建对应的 PersistentVolume 对象。以下示例展示了已创建的 PersistentVolume。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pvc-cd3fd5e9-695a-11ea-a3da-42010a800003
  uid: ced478c1-695a-11ea-a3da-42010a800003
  annotations:
    kubernetes.io/createdby: gce-pd-dynamic-provisioner
    pv.kubernetes.io/bound-by-controller: "yes"
    pv.kubernetes.io/provisioned-by: kubernetes.io/gce-pd
spec:
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 30Gi
  claimRef:
    apiVersion: v1
    kind: PersistentVolumeClaim
    name: pvc-demo
    uid: cd3fd5e9-695a-11ea-a3da-42010a800003
  gcePersistentDisk:
    fsType: ext4
    pdName: gke-cluster-1-pvc-cd3fd5e9-695a-11ea-a3da-42010a800003
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: topology.kubernetes.io/zone
          operator: In
          values:
          - us-central1-c
        - key: topology.kubernetes.io/region
          operator: In
          values:
          - us-central1
  persistentVolumeReclaimPolicy: Delete
  storageClassName: standard
  volumeMode: Filesystem
status:
  phase: Bound

假设您尚未替换 GKE 默认存储类别,则此 PersistentVolume 会由一个新的空 Compute Engine 永久性磁盘支持。您可以在 Pod 中使用此磁盘,将声明用作卷即可。删除声明时,相应的 PersistentVolume 对象以及预配的 Compute Engine 永久性磁盘也会被删除。

如果您要防止删除动态预配的永久性磁盘,请将 PersistentVolume 资源或其 StorageClass 资源的收回政策设置为 Retain。在这种情况下,只要存在永久性磁盘,即使没有 PersistentVolumeClaim 使用永久性磁盘,您也需要支付费用。 如需查看有关如何更改收回政策的示例,请参阅更改 PersistentVolume 的收回政策StorageClass 资源

访问模式

PersistentVolume 支持以下访问模式

  • ReadWriteOnce:卷可以由单个节点以读写方式装载。
  • ReadOnlyMany:卷可以由多个节点以只读方式装载。
  • ReadWriteMany:卷可以由多个节点以读写方式装载。 由 Compute Engine 永久性磁盘支持的 PersistentVolume 不支持此访问模式。

以 ReadOnlyMany 方式使用 Compute Engine 永久性磁盘

ReadWriteOnce 是永久性磁盘最常见的使用场景,用作大多数应用的默认访问模式。Compute Engine 永久性磁盘也支持 ReadOnlyMany 模式,以便多个应用或同一应用的多个副本可以同时使用同一磁盘。一个示例使用场景是跨多个副本传送静态内容。

请参阅本文,了解为多个读取器创建持久性磁盘的说明

将原有永久性磁盘用作 PersistentVolume

动态预配的 PersistentVolume 在创建时是空的。如果您已经有一个填充了数据的现存 Compute Engine 永久性磁盘,您可以通过手动创建对应的 PersistentVolume 资源将该磁盘引入您的集群。永久性磁盘必须与集群节点位于同一 [地区] 中。

请参阅此示例,了解如何创建由原有永久性磁盘支持的永久性卷

Deployment 与 StatefulSet

您可以在更高级层的控制器(如 DeploymentStatefulSet)中分别使用 PersistentVolumeClaim 或 VolumeClaim 模板。

Deployment 是专为无状态应用设计的,因此 Deployment 的所有副本共用同一个 PersistentVolumeClaim。由于创建的副本 Pod 彼此相同,因此只有具有 ReadOnlyMany 或 ReadWriteMany 模式的卷才能适用于此设置。

即使是具有一个使用 ReadWriteOnce 卷的副本的 Deployment,也不建议采用。这是因为默认 Deployment 策略会在重新创建时先创建第二个 Pod,然后再关闭第一个 Pod。第二个 Pod 无法启动时,Deployment 可能会因死锁而失败,这是因为 ReadWriteOnce 卷已在使用中,而第一个 Pod 由于第二个 Pod 尚未启动而无法移除。应改为针对 ReadWriteOnce 卷使用 StatefulSet。

建议使用 StatefulSet 部署有状态应用,这些应用需要每个副本具有唯一卷。通过将 StatefulSet 与 PersistentVolumeClaim 模板结合使用,您的应用可以随与每个副本 Pod 关联的唯一 PersistentVolumesClaim 自动纵向扩容。

地区永久性磁盘

地区永久性磁盘是多区域资源,在同一地区中的两个区域之间复制数据,并且使用方式与标准永久性磁盘类似。如果发生区域中断,或者某个区域的集群节点无法安排,Kubernetes 可进行故障转移,将使用该卷的工作负载分配到其他区域。您可以使用地区永久性磁盘为 GKE 上的有状态工作负载构建高可用性解决方案。您必须确保主要区域和故障转移区域都配置了足够的资源容量来运行工作负载。

地区 SSD 永久性磁盘是应用(例如同时要求高可用性和高性能的数据库)的一个选项。如需了解详情,请参阅块存储性能比较

与区域永久性磁盘一样,地区永久性磁盘可以根据需要动态预配,也可以由集群管理员提前预配。如需了解如何添加地区永久性磁盘,请参阅预配地区永久性磁盘

永久性磁盘中的区域

区域永久性磁盘是区域资源,而地区永久性磁盘是多区域资源。在向集群添加永久性存储时,除非指定了区域,否则 GKE 会将磁盘分配给单个区域。GKE 会随机选择区域。预配永久性磁盘后,任何引用磁盘的 Pod 都将被安排到磁盘所在的区域。

如果您在集群中动态预配永久性磁盘,我们建议您在 StorageClass 上设置 WaitForFirstConsumer 卷绑定模式。此设置指示 Kubernetes 在与 Pod 调度到的相同区域中预配永久性磁盘。它遵循 Pod 调度限制条件,例如反亲和性与节点选择器。区域上的反亲和性允许将 StatefulSet Pod 以及对应的磁盘分布在各个区域中。

以下是用于预配区域永久性磁盘且设置 WaitForFirstConsumer 的示例 StorageClass:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-standard
  fstype: ext4
volumeBindingMode: WaitForFirstConsumer

如需查看使用地区永久性磁盘的示例,请参阅预配地区永久性磁盘

后续步骤