Google Kubernetes Engine(GKE)上的客户将本地 SSD 用于需要快速下载和处理数据的应用程序,例如 AI/ML、分析、批处理、内存缓存等。这些应用程序将数据从对象存储,例如 Google Cloud Storage(GCS)下载到本地 SSD,并在 GKE 上作为 pod 运行的应用程序中处理这些数据。处理过程中,数据在本地存储和 RAM 之间移动,因此每秒输入/输出操作(IOPS)性能非常重要。以前,在 GKE 上使用本地 SSD,要么通过基于 SCSI 的旧技术,要么通过测试版(和内部测试版)API。现在,您可以使用正式版 API,创建基于 NVMe 的临时或原始块存储卷,而性能较 SCSI 提高 1.7 倍。
本地 SSD 是一种 Compute Engine 产品,允许对直接连接物理主机的高性能 SSD 进行临时访问。相比 PD SSD 和 Filestore,虽然本地 SSD 的耐久性较低,但性能却更高;如果 Compute Engine 实例停止或遇到各种错误条件,则会丢失数据。如果您的工作负载需要更高的 IOPS 性能和更低延迟 - 而非耐久性,则会发现这是一个合理的折中方案。
GKE 近期发布了内置本地 SSD 支持,成为首个可为应用程序提供临时和原始块存储(可使用熟悉的 Kubernetes API 进行配置)的托管型 Kubernetes 平台。这意味着在为临时卷增加隔离和让 Google Cloud API 全面用于配置本地 SSD 以实现高性能本地存储方面,整个 Kubernetes 上游社区所做的工作达到顶点。
现在,可通过两种选项在 GKE 上使用本地 SSD:
1)临时存储本地 SSD 选项适用于希望获得由本地 SSD 支持的全托管本地临时存储的客户,该存储与 Pod 的生命周期相关联。当 Pod 请求临时存储时,则在已连接本地 SSD 的节点上自动调度存储。启用群集自动扩展功能后,当群集的临时存储空间不足时,将自动扩展节点。
2)本地 SSD 块选项适用于希望获得更多底层存储控制权的客户,以及希望为其 Pod 建立自身节点级缓存以提高应用程序性能的客户。此外,通过酌情运行 DaemonSet 而组建 RAID 阵列以及格式化磁盘,客户还可以在本地 SSD 上安装文件系统,进而对该选项进行自定义。
为获得更高的性能,我们建议客户从以前的(正式版)本地 SSD Count API 迁移至较新的正式版 API。
表1. GKE 本地 SSD API(正式版)
以下是一些使用新 API 的示例。
示例1:通过 emptyDir 使用临时存储本地 SSD API
假设您有一款由 Kubernetes 托管的 AI/ML 应用程序,而且数据要下载至本地存储中进行处理。所有 Pod 运行同一个机器学习模型,每个 Pod 负责训练其中的一部分数据。由于各 Pod 之间不共享数据,因此可以使用 emptyDir 卷作为暂存空间,并配置一个由本地 SSD 支持的本地临时存储节点池,以便优化 IOPS 性能。
要创建这样的节点池,您可以在 gcloud CLI 中使用--ephemeral-storage-local-ssd count=<N> 选项,
gcloud container clusters create lssd-ephemeral --ephemeral-storage-local-ssd count=2 --machine-type=n2-standard-2 --release-channel=rapid |
该命令将:
创建一个群集,其默认节点池中的每个节点都连接 n 个本地 SSD。磁盘的最大数量因机器类型和区域而有所不同。
创建并向每个节点添加标签 cloud.google.com/gke-ephemeral-storage-local-ssd=true
将所有本地 SSD 组成 RAID0 阵列:/dev/md/0,将其格式化为 ext-4 文件系统,并挂载至路径:/mnt/stateful_partition/kube-ephemeral-ssd
将包含容器运行时根目录、kubelet 根目录和 Pod 日志根目录的临时存储绑定挂载至本地 SSD 的挂载点:/mnt/stateful_partition/kube-ephemeral-ssd
--ephemeral-storage-local-ssd 选项是不可变的。节点池创建完毕后,连接至每个节点的本地 SSD 数量即不可更改。如果未指定该选项,GKE 默认使用 Persistent Disk 启动盘(pd-standard、pd-ssd 或 pd-balanced)初始化节点本地临时存储。当 N 个本地 SSD 连接至节点时,可用于 Pod 的本地临时存储为:Node Allocatable = 375GiB * N - (kube-reserved + system-reserved + eviction-threshold)
图1:带有本地临时存储的 GKE 节点(由 N 个本地 SSD 经由 NVMe 提供支持)
创建过节点池后,下一步是以 emptyDir 卷为抓取空间而创建工作负载。在 Kubernetes 中,Pod 可以通过 emptyDir 卷、日志和容器可写层访问并写入临时数据。这种情况下写入的数据是临时性的,会随着容器或 Pod 的删除而一同删除。在刚刚创建的节点池中,这些目录使用本地 SSD。对于 Kubernetes 1.25 以上版本,本地存储容量隔离功能已正式发布。其为 Pod 之间共享存储的容量隔离提供支持,这样,如果 Pod 对共享存储的占用超过了限制,则可以通过驱逐 Pod 而限制其对于共享资源的占用。这还支持为资源预留设置临时存储请求。对共享临时存储的限制及请求与对内存及 CPU 占用的限制和请求类似。由于本地存储是“best-effort”的资源,因此在引入该功能之前,Pod 可能会因为其他 Pod 填满本地存储而遭到驱逐。
图2:kubelet 将 emptyDir 卷挂载到容器中
在以下示例中,Pod 使用由本地 SSD 支持的 emptyDir 卷,并配置了本地存储容量请求和限制。
apiVersion: v1 kind: Pod metadata: name: date spec: containers: - name: busybox image: "k8s.gcr.io/busybox" command: ['sh', '-c', 'date > /cache/data ; sleep 3600'] resources: requests: ephemeral-storage: "200Gi" limits: ephemeral-storage: "300Gi" volumeMounts: - mountPath: /cache name: ephemeral nodeSelector: cloud.google.com/gke-ephemeral-storage-local-ssd: "true" volumes: - name: ephemeral emptyDir: sizeLimit: 50Gi |
cloud.google.com/gke-ephemeral-storage-local-ssd: "true":Pod 将被调度至带有本地临时存储(由本地SSD支持)的节点。节点标签在创建群集时生成
spec.containers[].resources.requests.ephemeral-storage:"200Gi" 只有当 Pod 的可用本地临时存储(可分配资源)超过 200GiB 时,才能将其分配给该节点
spec.containers[].resources.limits.ephemeral-storage:"300Gi" kubelet 驱逐管理器将测量所有容器的磁盘使用量和 emptyDir 使用量,如果存储使用量超过 300GiB 的限制,则驱逐 Pod
spec.volumes[].emptyDir.sizeLimit:50Gi:如果 Pod 的 emptyDir 所占用的本地临时存储空间超过 50GiB,则会从节点将该 Pod 驱逐出来
示例2:通过本地 PersistentVolume 使用本地 NVMe SSD 块 API
以下将继续使用前面的 AI/ML 示例,但现在的 Pod 已可以针对相同的数据集而运行不同的机器学习模型。您想要将数据下载到本地存储,多个 Pod 需要访问相同的数据。在这种情况下,您可以配置带有原始块本地 SSD 的节点池,使用 DaemonSet 组建 RAID 磁盘阵列,并使用本地静态制备器(provisioner)配置本地 PersistentVolume(可用作节点级缓存)。
第一步是创建带有原始块本地 SSD 的节点池。要创建这样的节点池,可以在 gcloud CLI 中使用 --local-nvme-ssd-block count=<N> 选项,
gcloud container clusters create lssd-block --local-nvme-ssd-block count=2 --machine-type=n2-standard-2 --release-channel=rapid |
该命令将:
创建一个群集,其默认节点池中的每个节点都连接 N 个本地 SSD
创建并向每个节点添加标签 cloud.google.com/gke-local-nvme-ssd=true
在节点初始化时,主机操作系统创建一个用于按顺序路径访问磁盘的符号链接(symlink),以及一个带有通用唯一识别码(UUID)的符号链接。顺序路径不会暴露底层存储接口(例如 NVMe)。当应用程序可以容忍节点修复或升级时删除数据的情况,即可加以使用。UUID 符号链接更适用于应用程序拥有特殊恢复功能且当数据遭到删除后需要执行该恢复功能的情况。在本例中,我们假设发生前一种情况。
图3:经由 NVMe 连接 N 个原始块本地 SSD 的 GKE 节点
下一步是运行 DaemonSet,为本地 SSD 组建 RAID 阵列。示例如下所示。该 DaemonSet 将为所有本地 SSD 设置 RAID0 阵列,并将设备格式化为 ext-4 文件系统。组建 RAID 磁盘阵列后,可以使用该示例 yaml 文件生成本地静态制备器 DaemonSet。静态制备器将为 RAID0 阵列和相应的 StorageClass 创建本地 PersistentVolumes。所有这些都完成后,即可以创建一个 PVC 和 Pod,继而使用本地 PersistentVolumes。请点击此处,查看命令。
文章信息
相关推荐
