优化 Cloud Storage FUSE CSI 驱动程序以提升 GKE 性能


本指南介绍如何优化 Google Kubernetes Engine (GKE) 上的 Cloud Storage FUSE CSI 驱动程序的性能。

虽然 Cloud Storage FUSE 提供了灵活性和可伸缩性,但要想实现最佳性能,仔细配置和调整至关重要。Cloud Storage FUSE 的性能在延迟时间、吞吐量和一致性方面可能会与 POSIX 文件系统有所不同。调整的目的是尽可能减少元数据操作开销,并最大限度地提高数据访问效率。如果您运行的 AI/机器学习应用会使用 Cloud Storage 存储分区中的数据,那么调整 CSI 驱动程序可以缩短 AI/机器学习应用的训练和推理时间。

本指南适用于想要提高访问 Cloud Storage 存储分区中存储的数据的应用性能的开发者和机器学习 (ML) 工程师。

在阅读本页内容之前,请确保您熟悉 Cloud Storage、Kubernetes 和 Cloud Storage FUSE CSI 驱动程序的基础知识。请务必查看您要使用的特定功能的 GKE 版本要求

配置挂载选项

Cloud Storage FUSE CSI 驱动程序支持装载选项,以配置 Cloud Storage 存储分区在本地文件系统上的装载方式。如需查看受支持的挂载选项的完整列表,请参阅 Cloud Storage FUSE CLI 文件文档

您可以通过以下方式指定挂载选项,具体取决于您使用的卷类型:

CSI 临时卷

如果您使用 CSI 临时卷,请在 Pod 清单的 spec.volumes[n].csi.volumeAttributes.mountOptions 字段中指定挂载选项。

您必须将挂载选项指定为字符串,标志之间以英文逗号分隔,不带空格。例如:

  mountOptions: "implicit-dirs,file-cache:enable-parallel-downloads:true,file-cache:download-chunk-size-mb:3"

永久性卷

如果您使用永久性卷,请在 PersistentVolume 清单的 spec.mountOptions 字段中指定挂载选项。

您必须将挂载选项指定为列表。例如:

  mountOptions:
    - implicit-dirs
    - file-cache:enable-parallel-downloads:true
    - file-cache:download-chunk-size-mb:3

挂载注意事项

使用 CSI 驱动程序配置挂载时,请考虑以下事项:

一般注意事项

  • 不允许使用以下标志:app-nametemp-dirforegroundlog-filelog-formatkey-filetoken-urlreuse-token-from-url
  • 默认情况下,Cloud Storage FUSE 不显示隐式目录。
  • 如果您只想在存储桶中装载目录(而不是装载整个存储桶),请使用 only-dir=relative/path/to/the/bucket/root 标志传递目录相对路径。

安全性和权限

  • 如果您为 Pod 或容器使用安全上下文,或者您的容器映像使用非根用户或群组,则必须设置 uidgid 装载标志。您还需要使用 file-modedir-mode 挂载标志来设置文件系统权限。请注意,您无法针对 Cloud Storage FUSE 文件系统运行 chmodchownchgrp 命令,因此请使用 uidgidfile-modedir-mode 装载标志为非根用户或组获取访问权限。

Linux 内核挂载选项

  • 如需配置 Linux 内核装载选项,您可以使用 o 标志传递该选项。例如,如果您不想允许直接执行所装载的文件系统上的任何二进制文件,请设置 o=noexec 标志。每个选项都需要单独的标志,例如 o=noexeco=noatime。仅允许使用以下选项:execnoexecatimenoatimesyncasyncdirsync

配置缓存

本部分简要介绍了 Cloud Storage FUSE CSI 驱动程序提供的用于提升性能的缓存选项。

文件缓存

您可以将 Cloud Storage FUSE CSI 驱动程序与文件缓存结合使用,以便为处理来自 Cloud Storage 存储分区的小文件的应用提高其读取性能。Cloud Storage FUSE 文件缓存功能是一种基于客户端的读取缓存,可让您更快地从所选择的缓存存储空间中传送重复文件读取。

您可以根据性价比需求从适用于读取缓存的一系列存储空间选项(包括本地 SSD、基于 Persistent Disk 的存储空间和 RAM 磁盘 [内存])中进行选择。

启用和使用文件缓存

默认情况下,文件缓存功能在 GKE 上处于停用状态。您必须选择在使用 Cloud Storage FUSE CSI 驱动程序的情况下启用文件缓存。

如需启用和控制文件缓存,请设置卷属性 fileCacheCapacity 或使用 file-cache:max-size-mb 挂载选项。

GKE 默认将 emptyDir 卷用于 Cloud Storage FUSE 文件缓存(由节点上配置的临时存储空间提供支持)。这可以是挂接到节点的启动磁盘,也可以是节点上的本地 SSD。如果在节点上启用本地 SSD,则 GKE 会使用本地 SSD 为 emptyDir 卷提供支持。

您可以为边车容器配置自定义读取缓存卷来替换 emptyDir 卷,以便在读取操作中进行文件缓存。

如需详细了解文件缓存的最佳实践,请参阅 Cloud Storage FUSE 性能

选择用于支持文件缓存的存储空间

如需选择用于支持文件缓存的存储空间,请参阅以下注意事项:

  • 对于支持本地 SSD 的 GPU 和 CPU 虚拟机系列(例如 A3 虚拟机),我们建议使用本地 SSD。

    • 对于 A3 及更高版本的虚拟机,GKE 会自动设置本地 SSD 以供 Pod 使用。
    • 如果您的虚拟机系列不支持本地 SSD,则 GKE 会使用启动磁盘进行缓存。GKE 上启动磁盘的默认磁盘类型为 pd-balanced
    • 如果您的虚拟机系列支持本地 SSD,但默认情况下未在本地 SSD 上启用临时存储空间,您可以在节点池中启用本地 SSD。这适用于第一代和第二代机器系列,例如 N1 和 N2 机器。如需了解详情,请参阅创建具有本地 SSD 的集群

      如需检查您的节点是否已在本地 SSD 上启用临时存储,请运行以下命令:

      kubectl describe node <code><var>NODE_NAME</var></code> | grep "cloud.google.com/gke-ephemeral-storage-local-ssd"
      
  • 对于 TPU 虚拟机系列(尤其是 v6 及更高版本),我们建议使用 RAM 作为文件缓存,以便获得最佳性能,因为这些虚拟机实例具有更大的 RAM。

    • 使用 RAM 时,请注意内存不足 (OOM) 错误,因为这些错误会导致 Pod 中断。Cloud Storage FUSE 会消耗内存,因此设置文件缓存以使用边车容器可能会导致 OOM 错误。为防止出现此类情况,请将文件缓存配置 file-cache:max-size-mb 字段调整为较小的值。
    • 对于其他 TPU 系列,我们建议使用 pd-balancedpd-ssd。GKE 上启动磁盘的默认磁盘类型为 pd-balanced
  • 请避免使用启动磁盘进行缓存,因为这可能会导致性能下降和意外终止。不过,您可以考虑使用由永久性磁盘支持的 PersistentVolume。

使用基于 RAM 磁盘的文件缓存

如果您使用的是 RAM 充足的 TPU 虚拟机,则可以使用 RAM 磁盘进行文件缓存或并行下载,以减少使用启动磁盘或 Persistent Disk 的开销。

如需将 RAM 磁盘与 Cloud Storage FUSE CSI 驱动程序搭配使用,请将以下内容添加到清单中:

volumes:
  - name: gke-gcsfuse-cache
    emptyDir:
      medium: Memory

统计信息缓存

Cloud Storage FUSE CSI 驱动程序通过缓存文件元数据(例如大小和修改时间)来提升性能。CSI 驱动程序默认启用此统计信息缓存,并通过在本地存储信息(而不是反复从 Cloud Storage 请求信息)来缩短延迟时间。您可以配置其大小上限(默认为 32 MB)以及数据在缓存中停留的时长(默认为 60 秒)。通过微调元数据缓存,您可以减少对 Cloud Storage 的 API 调用,从而最大限度地减少网络流量和延迟时间,从而提高应用性能和效率。

如需详细了解统计信息缓存的最佳实践,请参阅 Cloud Storage FUSE 缓存概览

使用元数据预提取来预先填充元数据缓存

借助元数据预提取功能,Cloud Storage FUSE CSI 驱动程序可以主动将 Cloud Storage 存储桶中对象的相关元数据加载到 Cloud Storage FUSE 缓存中。这种方法可以减少对 Cloud Storage 的调用,对于访问包含许多文件的大型数据集的应用(例如 AI/ML 训练工作负载)尤其有益。

此功能需要 GKE 1.31.3-gke.1162000 或更高版本。

如需通过元数据预提取提升性能,您必须将元数据缓存项的存留时间 (TTL) 值设置为无限。通常,设置 TTL 可防止缓存的内容过时。将 TTL 设置为无限时,您必须采取预防措施,以免对存储桶的内容进行非正规更改(即允许其他工作负载或操作者修改工作负载)。非信道更改在本地不可见,并且可能会导致一致性问题。

如需启用元数据预提取,请进行以下配置更改。我们建议为读者众多的图书启用此功能。

如需查看示例,请参阅使用并行下载提高大文件读取性能中的代码示例。

列表缓存

如需加快应用目录列表的速度,您可以启用列表缓存。此功能会将目录列表存储在内存中,以便更快地处理重复请求。列表缓存默认处于停用状态;您可以在挂载选项中设置 kernel-list-cache-ttl-secs 参数来启用它。这定义了商家信息的缓存时长。

使用并行下载提高大文件读取性能

您可以使用 Cloud Storage FUSE 并行下载来加速从 Cloud Storage 读取大文件,以实现多线程下载。对于读取大小超过 1 GB 的模型服务用例,Cloud Storage FUSE 并行下载尤其有益。

常见示例包括:

  • 模型服务,您需要较大的预提取缓冲区来加速实例启动期间的模型下载。
  • 检查点恢复,您需要使用只读数据缓存来提高对多个大文件的一次性访问速度。
最佳实践

针对执行单线程大型文件读取的应用使用并行下载。具有高读取并行度(使用超过 8 个线程)的应用可能会因使用此功能而导致性能降低。

如需将并行下载与 Cloud Storage FUSE CSI 驱动程序搭配使用,请按以下步骤操作:

  1. 创建一个已启用文件缓存的集群,如启用和使用文件缓存中所述。

  2. 在清单中,使用挂载选项配置以下其他设置,以启用并行下载:

    1. 设置 file-cache:enable-parallel-downloads:true
    2. 根据需要调整 file-cache:parallel-downloads-per-filefile-cache:parallel-downloads-per-filefile-cache:max-parallel-downloadsfile-cache:download-chunk-size-mb
  3. (可选)如有需要,请考虑调整以下音量属性

减少访问权限控制检查的配额消耗

默认情况下,CSI 驱动程序会执行访问权限控制检查,以确保 Pod 服务账号有权访问您的 Cloud Storage 存储分区。这会导致 Kubernetes Service API、Security Token Service 和 IAM 调用等形式的额外开销。从 GKE 1.29.9-gke.1251000 版开始,您可以使用卷属性 skipCSIBucketAccessCheck 跳过此类多余的检查并减少配额用量。

推理服务示例

以下示例展示了如何为推理服务启用并行下载:

  1. 使用以下规范创建 PersistentVolume 和 PersistentVolumeClaim 清单:

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: serving-bucket-pv
    spec:
      accessModes:
      - ReadWriteMany
      capacity:
        storage: 64Gi
      persistentVolumeReclaimPolicy: Retain
      storageClassName: example-storage-class
      claimRef:
        namespace: NAMESPACE
        name: serving-bucket-pvc
      mountOptions:
        - implicit-dirs #avoid if list cache enabled and doing metadata prefetch
        - metadata-cache:ttl-secs:-1
        - metadata-cache:stat-cache-max-size-mb:-1
        - metadata-cache:type-cache-max-size-mb:-1
        - file-cache:max-size-mb:-1
        - file-cache:cache-file-for-range-read:true
        - file-system:kernel-list-cache-ttl-secs:-1
        - file-cache:enable-parallel-downloads:true
      csi:
        driver: gcsfuse.csi.storage.gke.io
        volumeHandle: BUCKET_NAME
        volumeAttributes:
          skipCSIBucketAccessCheck: "true"
          gcsfuseMetadataPrefetchOnMount: "true"
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: serving-bucket-pvc
      namespace: NAMESPACE
    spec:
      accessModes:
      - ReadWriteMany
      resources:
        requests:
          storage: 64Gi
      volumeName: serving-bucket-pv
      storageClassName: example-storage-class
    

    替换以下值:

    • NAMESPACE:您要部署 Pod 的 Kubernetes 命名空间。
    • BUCKET_NAME:您在配置对 Cloud Storage 存储桶的访问权限时指定的 Cloud Storage 存储桶名称。您可以指定下划线 (_) 以装载 Kubernetes ServiceAccount 可以访问的所有存储分区。如需了解详情,请参阅 Cloud Storage FUSE 文档中的动态装载
  2. 将清单应用于集群:

    kubectl apply -f PV_FILE_PATH
    

    PV_FILE_PATH 替换为 YAML 文件的路径。

  3. 根据您是使用由本地 SSD 支持的文件缓存还是由 RAM 磁盘支持的文件缓存,创建具有以下规范的 Pod 清单以使用 PersistentVolumeClaim:

    本地 SSD

    apiVersion: v1
    kind: Pod
    metadata:
      name: gcs-fuse-csi-example-pod
      namespace: NAMESPACE
      annotations:
        gke-gcsfuse/volumes: "true"
        gke-gcsfuse/cpu-limit: "0"
        gke-gcsfuse/memory-limit: "0"
        gke-gcsfuse/ephemeral-storage-limit: "0"
    spec:
      containers:
        # Your workload container spec
        ...
        volumeMounts:
        - name: serving-bucket-vol
          mountPath: /serving-data
          readOnly: true
      serviceAccountName: KSA_NAME
      volumes:
      - name: serving-bucket-vol
        persistentVolumeClaim:
          claimName: serving-bucket-pvc
    

    RAM 磁盘

    apiVersion: v1
    kind: Pod
    metadata:
      name: gcs-fuse-csi-example-pod
      namespace: NAMESPACE
      annotations:
        gke-gcsfuse/volumes: "true"
        gke-gcsfuse/cpu-limit: "0"
        gke-gcsfuse/memory-limit: "0"
        gke-gcsfuse/ephemeral-storage-limit: "0"
    spec:
      containers:
        # Your workload container spec
        ...
        volumeMounts:
        - name: serving-bucket-vol
          mountPath: /serving-data
          readOnly: true
      serviceAccountName: KSA_NAME 
      volumes:
        - name: gke-gcsfuse-cache # gcsfuse file cache backed by RAM Disk
          emptyDir:
            medium: Memory 
      - name: serving-bucket-vol
        persistentVolumeClaim:
          claimName: serving-bucket-pvc
    
  4. 将清单应用于集群:

    kubectl apply -f POD_FILE_PATH
    

    POD_FILE_PATH 替换为 YAML 文件的路径。

配置音量属性

借助卷属性,您可以配置 Cloud Storage FUSE CSI 驱动程序的特定行为。

Cloud Storage FUSE CSI 驱动程序不允许您直接指定 Cloud Storage FUSE 配置文件。您可以使用 Cloud Storage FUSE CSI 卷属性对配置文件中的某些字段进行配置。CSI 驱动程序负责将卷属性值转换为配置文件字段。

如需查看受支持的卷属性的完整列表,请参阅卷属性参考文档

您可以通过以下方式指定卷属性:

  • 在 PersistentVolume 清单的 spec.csi.volumeAttributes 字段中(如果您使用永久性卷)。
  • spec.volumes[n].csi.volumeAttributes 字段中(如果您使用 CSI 临时卷)。

在清单中,可以将音量属性指定为键值对。例如:

volumeAttributes:
  mountOptions: "implicit-dirs"
  fileCacheCapacity: "-1"
  gcsfuseLoggingSeverity: warning

Cloud Storage FUSE 指标

现在,您可以通过 GKE Monitoring API 获取以下 Cloud Storage FUSE 指标。如需详细了解 Cloud Storage FUSE 指标(例如标签、类型和单位),请参阅 GKE 系统指标。这些指标适用于使用 Cloud Storage FUSE 的每个 Pod,您可以使用这些指标来配置每个卷和存储桶的数据分析。

指标默认处于停用状态。如需启用这些功能,请将卷属性 disableMetrics 设置为“false”。

文件系统指标

文件系统指标用于跟踪文件系统的性能和运行状况,包括操作次数、错误数和操作速度。这些指标有助于发现瓶颈并优化性能。

  • gcsfusecsi/fs_ops_count
  • gcsfusecsi/fs_ops_error_count
  • gcsfusecsi/fs_ops_latency

Cloud Storage 指标

您可以监控 Cloud Storage 指标(包括数据量、速度和请求活动),以了解应用如何与 Cloud Storage 存储分区进行交互。这些数据有助于您确定需要优化的方面,例如改进读取模式或减少请求数量。

  • gcsfusecsi/gcs_download_bytes_count
  • gcsfusecsi/gcs_read_count
  • gcsfusecsi/gcs_read_bytes_count
  • gcsfusecsi/gcs_reader_count
  • gcsfusecsi/gcs_request_count
  • gcsfusecsi/gcs_request_latencies

文件缓存指标

您可以监控文件缓存指标,包括数据读取量、速度和缓存命中率,以优化 Cloud Storage FUSE 和应用性能。分析这些指标有助于改进缓存策略并最大限度地提高缓存命中率。

  • gcsfusecsi/file_cache_read_bytes_count
  • gcsfusecsi/file_cache_read_latencies
  • gcsfusecsi/file_cache_read_count

性能调整最佳实践

本部分列出了一些针对 Cloud Storage FUSE CSI 驱动程序的建议性能调整和优化技术。

  • 利用分层命名空间 (HNS) 存储分区:选择 HNS 存储分区可将初始每秒查询次数 (QPS) 大幅提高 8 倍。此选项还支持快速且原子化的目录重命名,这是使用 Cloud Storage FUSE 高效进行检查点的关键要求。HNS 存储分区支持每秒 4 万次对象读取请求和 8,000 次对象写入请求,从而确保更好的类似文件体验,与扁平存储分区每秒 8,000 次对象读取请求和 1,000 次对象写入请求相比,有了显著提升。

  • 尽可能挂载特定目录:如果您的工作负载涉及访问存储桶中的特定目录,请在挂载期间使用 --only-dir 标志。这种专注的方法可以加快列表调用速度,因为它会限制 LookUpInode 调用的范围,而 LookUpInode 调用涉及对指定路径中的每个文件或目录进行 list+stat 调用。通过将挂载范围缩小到所需的子目录,您可以最大限度地减少这些调用,从而提升性能。

  • 优化元数据缓存:配置元数据缓存以最大限度地提高其容量,并设置无限的存留时间 (TTL)。此做法可在作业运行期间有效缓存所有访问过的元数据,从而最大限度地减少对 Cloud Storage 的元数据访问请求。这种配置对只读卷特别有用,因为它可以消除重复的 Cloud Storage 元数据查询。不过,请验证与这些大型元数据缓存相关的内存用量是否与系统的功能相符。

  • 充分利用 GKE 边车资源:Cloud Storage FUSE 在 GKE 环境中的边车容器中运行。为防止出现资源瓶颈,请移除对边车容器 CPU 和内存用量的限制。这样,Cloud Storage FUSE 便可根据工作负载需求扩缩其资源利用率,从而防止节流并确保最佳吞吐量。

  • 主动填充元数据缓存:为 CSI 驱动程序启用元数据预提取。这样可以有效填充元数据和列表缓存,最大限度地减少对 Cloud Storage 的元数据调用,并加快初始运行速度。许多机器学习框架会自动执行此操作,但请务必确保为自定义训练代码执行此步骤。如需了解详情,请参阅使用元数据预提取来预填充元数据缓存

  • 利用文件缓存和并行下载:启用文件缓存功能,尤其是对于需要重复读取数据的多时段训练工作负载。文件缓存会将经常访问的数据存储在本地存储空间(对于 A3 机器,则是 SSD)上,从而提高读取性能。与并行下载功能搭配使用(尤其是对于服务工作负载),可将大型文件拆分成较小的分块并并发下载,从而加快下载速度。

  • 优化检查点:如需使用 Cloud Storage FUSE 进行检查点,我们强烈建议使用 HNS 存储桶。如果使用非 HNS 存储桶,请将 rename-dir-limit 参数设置为较大的值,以适应 ML 框架在进行检查点时经常使用的目录重命名。不过,请注意,非 HNS 存储分区中的目录重命名可能不是原子操作,并且可能需要更长时间才能完成。

  • 启用列表缓存:使用 --kernel-list-cache-ttl-secs 标志启用列表缓存,以进一步提升性能。此功能会缓存目录和文件列表,从而提高 ls 操作的速度。对于涉及重复显示完整目录列表的工作负载(在 AI/机器学习训练场景中很常见),列表缓存尤其有用。建议将列表缓存与只读挂载结合使用,以保持数据一致性。

后续步骤