本页面简要介绍了 Kubernetes 中的永久性卷和声明,及其在 Google Kubernetes Engine (GKE) 中的用法。本页面重点介绍由 Compute Engine 永久性磁盘支持的存储。
本页面适用于负责创建和分配存储空间以及配置和管理数据安全性、保护以及访问权限和权限的存储专家。如需详细了解我们在 Google Cloud 内容中提及的常见角色和示例任务,请参阅常见的 GKE Enterprise 用户角色和任务。
PersistentVolumes
PersistentVolume
资源用于管理集群中的持久性存储。在 GKE 中,PersistentVolume
通常由永久性磁盘支持。
您可以改用其他存储解决方案,例如 NFS。Filestore 是 Google Cloud 上的 NFS 解决方案。如需了解如何将 Filestore 实例设置为 GKE 集群的 NFS PV 解决方案,请参阅 Filestore 文档中的访问使用 Filestore CSI 驱动程序的 Filestore 实例。
PersistentVolume
生命周期由 Kubernetes 管理。PersistentVolume
可以动态预配;您不必手动创建和删除备份存储。
PersistentVolume
是独立于 Pods 存在的集群资源。
这意味着在集群更改时以及在删除并重新创建 Pod 时,PersistentVolume
表示的磁盘和数据将继续存在。PersistentVolume
资源可以通过 PersistentVolumeClaims
动态预配,也可以由集群管理员明确创建。
如需详细了解 PersistentVolume
资源,请参阅 Kubernetes 永久性卷文档和 Persistent Volumes API 参考文档。
PersistentVolumeClaims
PersistentVolumeClaim
表示针对 PersistentVolume
资源的请求和声明。PersistentVolumeClaim
对象会针对 PersistentVolume
请求特定大小、访问模式和 StorageClass
。如果存在满足请求的 PersistentVolume
或者可以预配,则 PersistentVolumeClaim
会绑定到该 PersistentVolume
。
Pod 将声明用作卷。集群会检查声明以找到绑定的卷并为 Pod 装载该卷。
可移植性是使用 PersistentVolumes
和 PersistentVolumeClaims
的另一个优点。您可以在不同集群和环境中轻松使用相同的 Pod 规范,因为 PersistentVolume
是实际后备存储的接口。
StorageClasses
诸如 Compute Engine 永久性磁盘容器存储接口 (CSI) 驱动程序等卷实现是通过 StorageClass
资源配置的。
GKE 会为您创建一个使用均衡永久性磁盘类型 (ext4) 的默认 StorageClass
。当 PersistentVolumeClaim
未指定 StorageClassName
时,将使用默认的 StorageClass
。您可以将提供的默认 StorageClass
替换为您自己的。有关说明,请参阅更改默认 StorageClass。
您可以创建自己的 StorageClass
资源来说明不同类别的存储。例如,类可能与服务质量等级或备份政策相对应。在其他存储系统中,此概念有时称为“配置文件”。
如果您使用的是具有 Windows 节点池的集群,则必须创建 StorageClass
并在 PersistentVolumeClaim
中指定 StorageClassName
,因为默认 fstype (ext4) 不受 Windows 支持。如果您使用的是 Compute Engine 永久性磁盘,则必须使用 NTFS 作为文件存储类型。
定义 StorageClass
时,您必须列出预配工具。在 GKE 上,我们建议您使用以下预配工具之一:
动态预配 PersistentVolume
在大多数情况下,您不需要直接配置 PersistentVolume
对象或创建 Compute Engine 永久性磁盘。您可以改为创建 PersistentVolumeClaim
,Kubernetes 会自动为您预配永久性磁盘。
以下清单描述了对存储空间为 30 千兆字节 (GiB) 的磁盘的请求,该磁盘的访问模式允许单个节点以读写方式装载磁盘。此外,该清单还会创建一个将 PersistentVolumeClaim
用作卷的 Pod。
# pvc-pod-demo.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-demo
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 30Gi
storageClassName: standard-rwo
---
kind: Pod
apiVersion: v1
metadata:
name: pod-demo
spec:
volumes:
- name: pvc-demo-vol
persistentVolumeClaim:
claimName: pvc-demo
containers:
- name: pod-demo
image: nginx
resources:
limits:
cpu: 10m
memory: 80Mi
requests:
cpu: 10m
memory: 80Mi
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: pvc-demo-vol
在您使用 kubectl apply -f
pvc-pod-demo.yaml
创建此 PersistentVolumeClaim
对象时,Kubernetes 会动态创建相应的 PersistentVolume
对象。
由于存储类别 standard-rwo
使用卷绑定模式 WaitForFirstConsumer
,因此在安排 Pod 使用该卷之前,不会创建 PersistentVolume
。
以下示例展示了已创建的 PersistentVolume
。
apiVersion: v1
kind: PersistentVolume
metadata:
annotations:
pv.kubernetes.io/provisioned-by: pd.csi.storage.gke.io
finalizers:
- kubernetes.io/pv-protection
- external-attacher/pd-csi-storage-gke-io
name: pvc-c9a44c07-cffa-4cd8-b92b-15bac9a9b984
uid: d52af557-edf5-4f96-8e89-42a3008209e6
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 30Gi
claimRef:
apiVersion: v1
kind: PersistentVolumeClaim
name: pvc-demo
namespace: default
uid: c9a44c07-cffa-4cd8-b92b-15bac9a9b984
csi:
driver: pd.csi.storage.gke.io
csi.storage.k8s.io/fstype: ext4
volumeAttributes:
storage.kubernetes.io/csiProvisionerIdentity: 1660085000920-8081-pd.csi.storage.gke.io
volumeHandle: projects/xxx/zones/us-central1-c/disks/pvc-c9a44c07-cffa-4cd8-b92b-15bac9a9b984
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: topology.gke.io/zone
operator: In
values:
- us-central1-c
persistentVolumeReclaimPolicy: Delete
storageClassName: standard-rwo
volumeMode: Filesystem
status:
phase: Bound
假设您尚未替换存储类别 standard-rwo
,则此 PersistentVolume
会由一个新的空 Compute Engine 永久性磁盘支持。
删除永久性存储
默认情况下,删除动态预配的卷(如 Compute Engine 永久性磁盘)的 PersistentVolumeClaim 会同时删除 PersistentVolume 对象和实际备份磁盘。此行为由 StorageClass 和 PersistentVolume 中的收回政策控制,可设置为默认值 Delete
或 Retain
。如需了解详情,请参阅有关收回的 Kubernetes 文档。
为了防止或缓解删除永久性存储时的数据丢失,我们建议您启用 Backup for GKE 并安排 GKE 集群的定期备份,包括已部署的工作负载及其数据。
在集群删除期间管理永久性存储
删除 GKE 集群后,GKE 将使用 Delete
或 Retain
收回政策保留 PersistentVolume
资源。
如需在删除集群时移除 PersistentVolume
资源,您可以手动删除 PersistentVolumeClaim
资源的命名空间,这会触发删除具有 Delete
政策的 PersistentVolume
对象。或者,您可以删除单个 PersistentVolumeClaim
资源。但是,GKE 不会等待这些删除活动完成后再开始删除集群。因此,如果您删除命名空间并立即删除集群,则系统可能不会删除具有 Delete
政策的 PersistentVolume
资源。
删除集群后,您可以在 Google Cloud 控制台中查看剩余的 PersistentVolume
资源。
如需查看任何未使用的资源(例如未使用的 PersistentVolume
资源),您可以查看针对空闲资源的建议。
访问模式
PersistentVolume
资源支持以下访问模式:
- ReadWriteOnce:卷可以由单个节点以读写方式装载。
- ReadOnlyMany:卷可以由多个节点以只读方式装载。
- ReadWriteMany:卷可以由多个节点以读写方式装载。
由 Compute Engine 永久性磁盘支持的
PersistentVolume
资源不支持此访问模式。
以 ReadOnlyMany 方式使用 Compute Engine 永久性磁盘
ReadWriteOnce 是永久性磁盘最常见的使用场景,用作大多数应用的默认访问模式。Compute Engine 永久性磁盘也支持 ReadOnlyMany 模式,以便多个应用或同一应用的多个副本可以同时使用同一磁盘。一个示例使用场景是跨多个副本传送静态内容。
如需了解相关说明,请参阅将永久性磁盘与多个读取器结合使用。
将预先存在的永久性磁盘用作 PersistentVolume
动态预配的 PersistentVolume
在创建时是空的。如果您已经有一个填充了数据的现存 Compute Engine 永久性磁盘,您可以通过手动创建对应的 PersistentVolume
资源将该磁盘引入您的集群。永久性磁盘必须与集群节点位于同一可用区中。
请参阅如何创建由预先存在的永久性磁盘支持的永久性卷的相关示例。
Deployment 与 StatefulSet
您可以在更高级层的控制器(如 Deployment 或 StatefulSets)中分别使用 PersistentVolumeClaim
或 VolumeClaim
模板。
Deployment 是专为无状态应用设计的,因此 Deployment 的所有副本共用同一个 PersistentVolumeClaim
。由于创建的副本 Pod 彼此相同,因此只有具有 ReadWriteMany 模式的卷才能适用于此设置。
即使是具有一个使用 ReadWriteOnce 卷的副本的 Deployment,也不建议采用。这是因为默认 Deployment 策略会在重新创建时先创建第二个 Pod,然后再关闭第一个 Pod。第二个 Pod 无法启动时,Deployment 可能会因死锁而失败,这是因为 ReadWriteOnce 卷已在使用中,而第一个 Pod 由于第二个 Pod 尚未启动而无法移除。应改为针对 ReadWriteOnce 卷使用 StatefulSet。
建议使用 StatefulSet 部署有状态应用,这些应用需要每个副本具有唯一卷。通过将 StatefulSet 与 PersistentVolumeClaim 模板结合使用,您的应用可以随与每个副本 Pod 关联的唯一 PersistentVolumesClaim 自动纵向扩容。
区域永久性磁盘
区域永久性磁盘是多可用区资源,在同一区域中的两个可用区之间复制数据,并且使用方式与可用区永久性磁盘类似。如果发生可用区中断,或者某个可用区的集群节点无法安排,Kubernetes 可进行故障切换,将使用该卷的工作负载分配到其他可用区。您可以使用区域永久性磁盘为 GKE 上的有状态工作负载构建高可用性解决方案。您必须确保主要可用区和故障切换可用区都配置了足够的资源容量来运行工作负载。
区域 SSD 永久性磁盘是应用(例如同时要求高可用性和高性能的数据库)的一个选项。如需了解详情,请参阅块存储性能比较。
与可用区永久性磁盘一样,区域永久性磁盘可以根据需要动态预配,也可以由集群管理员提前预配。如需了解如何添加区域永久性磁盘,请参阅预配区域永久性磁盘。
永久性磁盘中的可用区
可用区永久性磁盘是可用区级资源,而区域永久性磁盘是多可用区资源。在向集群添加永久性存储时,除非指定了可用区,否则 GKE 会将磁盘分配给单个可用区。GKE 会随机选择可用区。预配永久性磁盘后,任何引用磁盘的 Pod 都将被安排到永久性磁盘所在的区域。不过,Pod 或部署本身并不会识别现有永久性磁盘所在的可用区。如需确保 Pod 使用现有永久性磁盘正确调度,请在 Pod 或 Deployment 规范中使用可用区放置方法(例如 nodeAffinity)以定位到相应可用区。
卷绑定模式 WaitForFirstConsumer
如果您在集群中动态预配永久性磁盘,我们建议您在 StorageClass 上设置 WaitForFirstConsumer
卷绑定模式。此设置指示 Kubernetes 在与 Pod 调度到的相同可用区中预配永久性磁盘。它遵循 Pod 调度限制条件,例如反亲和性与节点选择器。可用区上的反亲和性允许将 StatefulSet Pod 以及对应的磁盘分布在各个可用区中。
以下是用于预配可用区永久性磁盘且设置 WaitForFirstConsumer
的示例 StorageClass
:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: slow
provisioner: pd.csi.storage.gke.io
parameters:
type: pd-balanced
csi.storage.k8s.io/fstype: ext4
volumeBindingMode: WaitForFirstConsumer
如需查看使用区域永久性磁盘的示例,请参阅预配区域永久性磁盘。
后续步骤
- 了解 StatefulSet,建议使用此方法部署有状态应用。
- 了解如何使用 StatefulSet 部署有状态应用。
- 了解如何在集群中使用永久性磁盘。
- 了解如何创建可以从多个节点读取的磁盘。
- 了解如何创建由 SSD 支持的永久性磁盘。
- 了解如何预配区域永久性磁盘。