优化适用于 GKE 的 Cloud Storage FUSE CSI 驱动程序的性能


本指南介绍如何优化 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、持久性块存储(如 Google Cloud Hyperdisk 或 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 磁盘进行文件缓存或并行下载,以减少使用启动磁盘的开销。

如需将 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/机器学习训练工作负载。

此功能需要 GKE 1.32.1-gke.1357001 或更高版本。动态装载不支持此功能,在动态装载中,您会指定下划线 (_) 以装载 Kubernetes ServiceAccount 可以访问的所有存储桶。如果您使用动态装载,则不会执行元数据预提取。

如需通过元数据预提取提升性能,您必须将元数据缓存项的存留时间 (TTL) 值设置为无限制。通常,设置 TTL 可防止缓存的内容过时。将 TTL 设置为无限制时,您必须采取预防措施,以防止在带外更改存储桶的内容(这意味着允许其他工作负载或执行者修改工作负载)。带外更改在本地不可见,可能会导致一致性问题。

如需启用元数据预提取,请进行以下配置更改。我们建议在进行大量读取的卷上启用此功能。

  • 设置卷属性 gcsfuseMetadataPrefetchOnMount: true
  • 更新以下装载选项:
  • 为避免工作负载中断,请考虑增加 gke-gcsfuse-metadata-prefetch 边车容器的内存限制。
    • 通过将 Pod 注解 gke-gcsfuse/metadata-prefetch-memory-limit 设置为 "512Mi" 或更高的值来提高限额。如需了解详情,请参阅配置边车容器资源
    • 或者,通过将 Pod 注解 gke-gcsfuse/metadata-prefetch-memory-limit 设置为 "0" 来取消设置内存限制(仅适用于 Standard 集群)。

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

列表缓存

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

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

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

并行下载需要启用文件缓存。从 GKE 1.32.0-gke.1795000 版开始,Cloud Storage FUSE 会严格强制执行此要求,如果您尝试在没有文件缓存的情况下使用并行下载,则会引发以下错误,从而导致 Pod 无法启动:MountVolume.SetUp failed for volume "gcs-fuse-csi-pv" : rpc error: code = Internal desc = gcsfuse failed with error: Error: error while parsing config: error parsing parallel download config: file cache should be enabled for parallel download support

常见示例包括:

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

针对执行单线程大型文件读取的应用使用并行下载。具有高读取并行度(使用超过 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
        - read_ahead_kb=1024
      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. 使用以下规范创建 Pod 清单以使用 PersistentVolumeClaim,具体取决于您是使用由本地 SSD 提供支持的文件缓存还是使用由 RAM 磁盘提供支持的文件缓存:

    本地 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,您可以使用这些指标对每个卷和存储桶配置分析洞见。

从 GKE 1.33.0-gke.2248000 或更高版本开始,指标默认处于启用状态。如需停用它们,请将卷属性 disableMetrics 设置为“true”。

文件系统指标

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

  • 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 性能默认设置

从 1.33.2-gke.4655000 版开始,GKE 会自动为在由高性能机器类型提供支持的节点上运行的 Cloud Storage FUSE 启用多项默认设置。

在卷装载期间,Cloud Storage FUSE CSI 驱动程序会提取目标节点实例类型,并通过新的装载选项 machine-type 将其传递给 Cloud Storage FUSE。

当 Cloud Storage FUSE 收到高性能机器类型时,会自动设置以下默认装载选项:

  • metadata-cache.negative-ttl-secs: 0
  • metadata-cache.ttl-secs: -1
  • metadata-cache.stat-cache-max-size-mb: 1024
  • metadata-cache.type-cache-max-size-mb: 128
  • implicit-dirs: true
  • file-system.rename-dir-limit: 200000

如果明确指定了上述任何装载选项,则这些选项不会被自动的默认设置覆盖。

您可以在装载选项中添加 disable-autoconfig 来选择停用该功能。例如:

mountOptions: "implicit-dirs,disable-autoconfig"

性能调优最佳实践

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

  • 利用分层命名空间 (HNS) 存储桶:选择 HNS 存储桶可将初始每秒查询次数 (QPS) 大幅提高 8 倍。这种选择还有助于快速进行原子目录重命名,这是通过 Cloud Storage FUSE 进行高效检查点设置的关键要求。HNS 存储桶支持每秒 40,000 个对象读取请求和 8,000 个对象写入请求(显著高于扁平存储桶所提供的每秒 8,000 个对象读取请求和 1,000 个对象写入请求),可确保实现更好的文件式体验。

  • 尽可能装载特定目录:如果您的工作负载涉及访问存储桶中的特定目录,请在装载期间使用 --only-dir 标志。这种有针对性的方法可加快列表调用速度,因为它会限制 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 参数设置为较高的值,以适应机器学习框架在检查点设置期间经常采用的目录重命名操作。不过请注意,非 HNS 存储桶中的目录重命名可能不是原子操作,可能需要较长时间才能完成。

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

  • 增加内核预读大小:对于主要涉及顺序读取大文件的工作负载(例如服务和检查点恢复),增加预读大小可以显著提升性能。如需增加 Cloud Storage FUSE 预读大小,请在 mountOptions 中指定 read_ahead_kb 标志,并将其设置为 1MB(例如 read_ahead_kb=1024)。此功能需要 GKE 1.32.2-gke.1297001 或更高版本。

  • 启用流式写入:流式写入是一种新的写入路径,可在写入数据时将其直接上传到 Cloud Storage。此方法与默认写入方法不同,默认写入方法会将整个写入操作暂存在本地目录中,然后在执行 closefsync 操作时将其上传到 Cloud Storage。流式写入可缩短延迟时间并减少磁盘空间用量,因此对于大型顺序写入(例如检查点)特别有用。如需启用流式写入,请在 mountOptions 中指定 enable-streaming-writes 命令行标志。

问题排查

如需详细了解如何排查 Cloud Storage FUSE CSI 驱动程序的问题,请参阅 GitHub 项目文档中的问题排查指南

后续步骤