使用 Cloud Storage FUSE CSI 驱动程序访问 Cloud Storage 存储桶


用户空间文件系统 (FUSE) 是用于将文件系统导出到 Linux 内核的接口。借助 Cloud Storage FUSE,您可以将 Cloud Storage 存储桶作为文件系统装载,以便应用可以使用常用的文件 IO 操作(例如打开、读取、写入、关闭)访问存储桶内的对象,而非使用云端专用 API。

借助 Cloud Storage FUSE CSI 驱动程序,您可以使用 Kubernetes API 将预先存在的 Cloud Storage 存储桶用作卷。您的应用可以使用 Cloud Storage FUSE 文件系统语义上传和下载对象。Cloud Storage FUSE CSI 驱动程序提供由开源 Google Cloud Storage FUSE CSI 驱动程序提供支持的全代管式体验。

驱动程序原生支持使用以下方法来配置 Cloud Storage 支持的卷:

您可以将 Cloud Storage FUSE CSI 驱动程序与文件缓存结合使用,以便为处理来自 Cloud Storage 存储桶的小文件的应用提高其读取性能。Cloud Storage FUSE 文件缓存功能是一种基于客户端的读取缓存,可让您更快地从所选择的缓存存储空间中传送重复文件读取。您可以根据性价比需求从适用于读取缓存的一系列存储空间选项(包括本地 SSD 和基于永久性磁盘的存储空间)中进行选择。您必须选择在使用 Cloud Storage FUSE CSI 驱动程序的情况下启用文件缓存。如需详细了解有关缓存的最佳实践,请参阅 Cloud Storage FUSE 性能

优势

  • 集群上的 Cloud Storage FUSE CSI 驱动程序会启用该驱动程序的自动部署和管理。该驱动程序适用于 Standard 集群和 Autopilot 集群。
  • Cloud Storage FUSE CSI 驱动程序不需要 FUSE 客户端通常所需的特权访问权限。这样可以实现更好的安全状况。
  • CSI 临时卷的支持可消除对 PersistentVolumeClaim 和 PersistentVolume 对象的需求,从而简化卷配置和管理。
  • Cloud Storage FUSE CSI 驱动程序支持 ReadWriteManyReadOnlyManyReadWriteOnce 访问模式
  • 您可以使用适用于 GKE 的工作负载身份联合管理身份验证,同时精细控制 Pod 访问 Cloud Storage 对象的方式。 使用工作负载身份联合时,需要为读写工作负载提供统一的存储桶级访问权限
  • 如果您使用 Ray、PyTorch、Spark 和 TensorFlow 等框架运行机器学习训练和服务工作负载,Cloud Storage FUSE CSI 驱动程序提供的可移植性和简洁性让您可以直接在 GKE 集群上运行工作负载,而无需进行额外的代码更改。
  • 您可以在启用文件缓存的情况下读取 Cloud Storage 对象,以提高读取性能。文件缓存通过从本地存储空间传送对象来加快重复读取的速度。如需详细了解文件缓存的优势,请参阅 Cloud Storage FUSE 文档
  • 在启用 Cloud Storage FUSE 2.4.0 版和文件缓存后,您可以使用并行下载功能加速从 Cloud Storage 读取大文件,以进行多线程下载。您可以使用此功能来缩短模型加载时间,尤其是对于大小超过 1 GB 的读取操作(例如,加载 Llama2 70B 时速度提高了 2 倍)。
  • 您可以在 init 容器中使用 Cloud Storage FUSE 卷。

准备工作

在开始之前,请确保您已执行以下任务:

  • 启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 如果您要使用 Google Cloud CLI 执行此任务,请安装初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请运行 gcloud components update 以获取最新版本。

限制

要求

如需使用 Cloud Storage FUSE CSI 驱动程序,您的集群必须满足以下要求:

启用 Cloud Storage FUSE CSI 驱动程序

如需创建启用了 Cloud Storage FUSE CSI 驱动程序的标准集群,您可以使用 gcloud CLI:

gcloud container clusters create CLUSTER_NAME \
    --addons GcsFuseCsiDriver \
    --cluster-version=VERSION \
    --location=LOCATION \
    --workload-pool=PROJECT_ID.svc.id.goog

请替换以下内容:

  • CLUSTER_NAME:您的集群的名称。
  • VERSION:GKE 版本号。 您必须选择 1.24 或更高版本。
  • LOCATION:集群的 Compute Engine 位置
  • PROJECT_ID:您的项目 ID。

如需在现有 Standard 集群上启用该驱动程序,请使用 gcloud container clusters update 命令:

gcloud container clusters update CLUSTER_NAME \
    --update-addons GcsFuseCsiDriver=ENABLED \
    --location=LOCATION

请替换以下内容:

启用 Cloud Storage FUSE CSI 驱动程序后,您可以通过指定驱动程序和预配工具名称 gcsfuse.csi.storage.gke.io 在 Kubernetes 卷中使用该驱动程序。

使用适用于 GKE 的 GKE 工作负载身份联合配置对 Cloud Storage 存储桶的访问权限

如需使 GKE 集群能够使用适用于 GKE 的工作负载身份联合访问 Cloud Storage 存储桶,请按照以下步骤操作。如需了解详情,请参阅将应用配置为使用 Workload Identity Federation for GKE

  1. 获取集群的凭据:

    gcloud container clusters get-credentials CLUSTER_NAME \
        --location=LOCATION
    

    替换以下内容:

    • CLUSTER_NAME:启用了适用于 GKE 的工作负载身份联合的集群的名称。
    • LOCATION:集群的 Compute Engine 位置
  2. 创建用于 Kubernetes ServiceAccount 的命名空间。您还可以使用 default 命名空间或任何现有命名空间。

    kubectl create namespace NAMESPACE
    

    替换以下内容:

    • NAMESPACE:Kubernetes ServiceAccount 的 Kubernetes 命名空间的名称。
  3. 为您的应用创建 Kubernetes 服务账号。您还可以在任何命名空间中使用任何现有的 Kubernetes ServiceAccount,包括 default Kubernetes ServiceAccount。

    kubectl create serviceaccount KSA_NAME \
        --namespace NAMESPACE
    

    替换以下内容:

    • KSA_NAME:新 Kubernetes ServiceAccount 的名称。
    • NAMESPACE:Kubernetes ServiceAccount 的 Kubernetes 命名空间的名称。
  4. 向 Kubernetes ServiceAccount 授予一个 Cloud Storage 的 IAM 角色

    您可以使用以下命令向 Kubernetes ServiceAccount 授予角色,以便仅访问特定 Cloud Storage 存储桶:

    gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME \
        --member "principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/KSA_NAME" \
        --role "ROLE_NAME"
    

    替换以下内容:

    • BUCKET_NAME:您的 Cloud Storage 存储桶名称。
    • PROJECT_NUMBER:GKE 集群的数字项目编号。如需查找项目编号,请参阅标识项目
    • PROJECT_ID:GKE 集群的项目 ID。
    • NAMESPACE:Kubernetes ServiceAccount 的 Kubernetes 命名空间的名称。
    • KSA_NAME:新 Kubernetes ServiceAccount 的名称。
    • ROLE_NAME:要分配给 Kubernetes ServiceAccount 的 IAM 角色。
      • 对于只读工作负载,请使用 Storage Object Viewer 角色 (roles/storage.objectViewer)。
      • 对于读写工作负载,请使用 Storage Object User 角色 (roles/storage.objectUser)。

    (可选)您可以向 Kubernetes ServiceAccount 授予角色,以便使用以下命令访问项目中的所有 Cloud Storage 存储桶:

    gcloud projects add-iam-policy-binding GCS_PROJECT \
        --member "principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/KSA_NAME" \
        --role "ROLE_NAME"
    

    替换以下内容:

    • GCS_PROJECT:Cloud Storage 存储桶的项目 ID。
    • PROJECT_NUMBER:GKE 集群的数字项目编号。如需查找项目编号,请参阅标识项目
    • PROJECT_ID:GKE 集群的项目 ID。
    • NAMESPACE:Kubernetes ServiceAccount 的 Kubernetes 命名空间的名称。
    • KSA_NAME:新 Kubernetes ServiceAccount 的名称。
    • ROLE_NAME:要分配给 Kubernetes ServiceAccount 的 IAM 角色。
      • 对于只读工作负载,请使用 Storage Object Viewer 角色 (roles/storage.objectViewer)。
      • 对于读写工作负载,请使用 Storage Object User 角色 (roles/storage.objectUser)。

准备装载 Cloud Storage FUSE 存储桶

本部分介绍如何准备在集群上装载 Cloud Storage FUSE 存储桶。

指定 Pod 注释

CSI 驱动程序依赖 Pod 注解来确定 Pod 是否使用受 Cloud Storage 支持的卷。如果驱动程序检测到必要的注解,则会将名为 gke-gcsfuse-sidecar 的边车容器注入工作负载 Pod。Cloud Storage FUSE 实例在边车容器内运行,并为您的工作负载装载 Cloud Storage 存储桶。

如需使 CSI 驱动程序能够装载 Cloud Storage 存储桶,请确保在 Pod 规范中的 metadata 字段下指定 gke-gcsfuse/volumes: "true" 注释。如果您希望其他 Kubernetes 工作负载类型(例如 JobDeploymentStatefulSet),请确保在 spec.template.metadata.annotations 字段下配置注释。

如果您使用的是 Istio 或 Cloud Service Mesh,请添加以下 Pod 级注解:

proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'
traffic.sidecar.istio.io/excludeOutboundIPRanges: 169.254.169.254/32

为边车容器配置资源

默认情况下,边车容器配置了以下资源请求,并且未设置资源限制:

  • 250m CPU
  • 256 MiB 内存
  • 5 GiB 临时存储

如需覆盖这些值,您可以选择指定注解 gke-gcsfuse/[cpu-limit|memory-limit|ephemeral-storage-limit|cpu-request|memory-request|ephemeral-storage-request],如以下示例所示:

apiVersion: v1
kind: Pod
metadata:
  annotations:
    gke-gcsfuse/volumes: "true"
    gke-gcsfuse/cpu-limit: "10"
    gke-gcsfuse/memory-limit: 10Gi
    gke-gcsfuse/ephemeral-storage-limit: 1Ti
    gke-gcsfuse/cpu-request: 500m
    gke-gcsfuse/memory-request: 1Gi
    gke-gcsfuse/ephemeral-storage-request: 50Gi

在决定要分配的资源量时,请考虑以下事项:

  • 如果您仅设置其中一个资源请求或限制注解,则 GKE 会对资源请求和资源限制强制执行相同的值。
  • 如果您的工作负载 Pod 使用多个 Cloud Storage 卷,则边车容器资源可由多个 Cloud Storage FUSE 实例共享。如果这适用于您,请考虑增加多个 Cloud Storage 卷的资源分配。
  • 如果您的工作负载需要更高的吞吐量,请为边车容器分配更多 CPU。CPU 不足将导致 Cloud Storage FUSE 限流。
  • 如果您的工作负载需要处理大量文件,并且已启用 Cloud Storage FUSE 元数据缓存,请增加边车容器的内存分配。元数据缓存的 Cloud Storage FUSE 内存用量与文件数量成正比,但与文件大小无关。内存不足会导致 Cloud Storage FUSE 内存不足错误,并且使工作负载应用崩溃。
  • 对于文件缓存,Cloud Storage FUSE 默认情况下会将文件缓存到本地临时目录中。估算您的工作负载需要多少可用空间进行文件缓存,并相应地提高临时存储空间限制。如需了解详情,请参阅卷属性
  • 对于写入操作,Cloud Storage FUSE 在默认情况下会将文件暂存到本地临时目录中,然后再将文件上传到 Cloud Storage 存储桶。估算您的工作负载在写入大文件时需要多少可用空间来暂存,并相应地提高您的临时存储限制。如需了解详情,请参阅 Cloud Storage FUSE GitHub 文档中的读/写语义
  • 您可以使用值 "0" 取消设置 Standard 集群上的任何资源限制或请求。例如,注解 gke-gcsfuse/memory-limit: "0" 会使用默认内存请求,将边车容器内存限制留空。如果您无法确定 Cloud Storage FUSE 为支持您的工作负载而需要的资源量,并且希望允许 Cloud Storage FUSE 使用节点上的所有可用资源,这将非常有用。根据工作负载指标计算 Cloud Storage FUSE 的资源要求后,您可以设置适当的限制。

为边车容器配置私有映像

本部分介绍在您将边车容器映像托管在私有容器仓库中的情况下如何使用边车容器映像。如果您出于安全目的需要使用专用集群,或者集群对公共互联网的访问受限,则此场景可能适用。如需配置和使用私有边车容器映像,请按照以下步骤操作:

  1. 请参阅此页面,查找兼容的公共边车容器映像。

  2. 将它拉取到本地环境,并推送到您的私有容器仓库。

  3. 在清单中,指定一个名为 gke-gcsfuse-sidecar 的容器,并使其仅有 image 字段。GKE 将使用指定的边车容器映像来准备边车容器注入。示例如下:

apiVersion: v1
kind: Pod
metadata:
  annotations:
    gke-gcsfuse/volumes: "true"
spec:
  containers:
  - name: gke-gcsfuse-sidecar
    image: PRIVATE_REGISTRY/gcs-fuse-csi-driver-sidecar-mounter:PRIVATE_IMAGE_TAG
  - name: main # your main workload container.

替换以下内容:

  • PRIVATE_REGISTRY:您的私有容器仓库。
  • PRIVATE_IMAGE_TAG:您的私有边车容器映像标记。

为边车容器配置自定义写入缓冲区卷

本部分介绍如何为 Cloud Storage FUSE 写入缓冲配置自定义缓冲区卷。如果您需要替换 Cloud Storage FUSE 的默认 emptyDir 卷以在写入操作中暂存文件,则此情况可能适用。您可以指定 GKE 支持的任何类型的存储(例如 PersistentVolumeClaim),GKE 将使用指定的卷进行文件写入缓冲。如果您需要在 Autopilot 集群上写入大于 10 GiB 的文件,这将非常有用。如需使用自定义缓冲区卷,您必须指定非零 fsGroup。以下示例展示了如何将预定义的 PVC 用作缓冲区卷:

apiVersion: v1
kind: Pod
metadata:
  annotations:
    gke-gcsfuse/volumes: "true"
spec:
  securityContext:
    fsGroup: FS_GROUP
  containers:
  ...
  volumes:
  - name: gke-gcsfuse-buffer
    persistentVolumeClaim:
      claimName: BUFFER_VOLUME_PVC

替换以下内容:

  • FS_GROUP:fsGroup ID。
  • BUFFER_VOLUME_PVC:预定义的 PVC 的名称。

为边车容器配置自定义读取缓存卷

本部分介绍如何为 Cloud Storage FUSE 读取缓存配置自定义缓存卷。如果您需要替换 Cloud Storage FUSE 的默认 emptyDir 卷以在读取操作中缓存文件,则此情况可能适用。您可以指定 GKE 支持的任何类型的存储空间(例如 PersistentVolumeClaim),GKE 将使用指定的卷进行文件缓存。如果您需要在 Autopilot 集群上缓存大于 10 GiB 的文件,这将非常有用。如需使用自定义缓存卷,您必须指定非零 fsGroup。以下示例展示了如何将预定义的 PVC 用作缓存卷:

apiVersion: v1
kind: Pod
metadata:
  annotations:
    gke-gcsfuse/volumes: "true"
spec:
  securityContext:
    fsGroup: FS_GROUP
  containers:
  ...
  volumes:
  - name: gke-gcsfuse-cache
    persistentVolumeClaim:
      claimName: CACHE_VOLUME_PVC

替换以下内容:

  • FS_GROUP:fsGroup ID。
  • CACHE_VOLUME_PVC:预定义的 PVC 的名称。

将卷预配为 CSI 临时卷

由 Cloud Storage 存储桶支持的 CSI 临时卷与 Pod 生命周期相关联。使用此预配方法时,您无需在 Pod 终止后维护与 Cloud Storage 存储桶关联的 PersistentVolume 和 PersistentVolumeClaim 对象。

在 Pod 中使用 CSI 临时存储卷

  1. 保存以下 YAML 清单:

    apiVersion: v1
    kind: Pod
    metadata:
      name: gcs-fuse-csi-example-ephemeral
      namespace: NAMESPACE
      annotations:
        gke-gcsfuse/volumes: "true"
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - image: busybox
        name: busybox
        command: ["sleep"]
        args: ["infinity"]
        volumeMounts:
        - name: gcs-fuse-csi-ephemeral
          mountPath: /data
          readOnly: true
      serviceAccountName: KSA_NAME
      volumes:
      - name: gcs-fuse-csi-ephemeral
        csi:
          driver: gcsfuse.csi.storage.gke.io
          readOnly: true
          volumeAttributes:
            bucketName: BUCKET_NAME
            mountOptions: "implicit-dirs"
            gcsfuseLoggingSeverity: warning
    

    上面的示例展示了如何在 Pod 清单中以内嵌方式指定 Cloud Storage 存储桶。该示例包含以下字段:

    • metadata.annotations:注解 gke-gcsfuse/volumes: "true" 是必需的。 如需了解可选注解,请参阅为 Sidecar 容器配置资源
    • spec.terminationGracePeriodSeconds:可选。默认情况下,该值设置为 30。 如果您需要将大型文件写入 Cloud Storage 存储桶,请提高此值,以确保 Cloud Storage FUSE 有足够的时间在应用退出后清空数据。如需了解详情,请参阅 Kubernetes 最佳做法:安全终止
    • spec.serviceAccountName:使用与使用适用于 GKE 的 GKE 工作负载身份联合配置对 Cloud Storage 存储桶的访问权限步骤相同的 Kubernetes ServiceAccount。
    • spec.volumes[n].csi.driver:使用 gcsfuse.csi.storage.gke.io 作为 CSI 驱动程序名称。
    • spec.volumes[n].csi.volumeAttributes.bucketName:指定您的 Cloud Storage FUSE 存储桶名称。您可以指定下划线 (_) 以装载 Kubernetes ServiceAccount 可以访问的所有存储桶。如需了解详情,请参阅 Cloud Storage FUSE 文档中的动态装载
    • spec.volumes[n].csi.volumeAttributes.mountOptions:可选。将装载选项传递给 Cloud Storage FUSE。在一个字符串中指定标志,以逗号分隔,不带空格。
    • spec.volumes[n].csi.volumeAttributes:可选。将其他卷属性传递给 Cloud Storage FUSE。
    • spec.volumes[n].csi.readOnly:可选。如果所有卷装载都是只读的,请指定 true
    • spec.containers[n].volumeMounts[m].readOnly:可选。如果仅有特定的卷装载是只读的,请指定 true
  2. 将清单应用于集群:

    kubectl apply -f FILE_PATH
    

    FILE_PATH 替换为 YAML 文件的路径。

在作业工作负载中使用 CSI 临时存储卷

  1. 保存以下 YAML 清单:

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: gcs-fuse-csi-job-example
      namespace: NAMESPACE
    spec:
      template:
        metadata:
          annotations:
            gke-gcsfuse/volumes: "true"
        spec:
          serviceAccountName: KSA_NAME
          containers:
          - name: writer
            image: busybox
            command:
              - "/bin/sh"
              - "-c"
              - touch /data/test && echo $(date) >> /data/test && sleep 10
            volumeMounts:
            - name: gcs-fuse-csi-ephemeral
              mountPath: /data
          - name: reader
            image: busybox
            command:
              - "/bin/sh"
              - "-c"
              - sleep 10 && cat /data/test
            volumeMounts:
            - name: gcs-fuse-csi-ephemeral
              mountPath: /data
              readOnly: true
          volumes:
          - name: gcs-fuse-csi-ephemeral
            csi:
              driver: gcsfuse.csi.storage.gke.io
              volumeAttributes:
                bucketName: BUCKET_NAME
          restartPolicy: Never
      backoffLimit: 1
    

    请替换以下内容:

    该清单将部署一个作业,该作业通过 CSI 临时卷使用 Cloud Storage FUSE 存储桶。

  2. 将清单应用于集群:

    kubectl apply -f FILE_PATH
    

    FILE_PATH 替换为 YAML 文件的路径。

如果您在 Job 工作负载中使用 CSI 驱动程序,或者 Pod RestartPolicyNever,则边车容器将在所有其他工作负载容器退出后自动退出。

如需查看其他示例,请参阅 GitHub 项目文档中的示例应用

使用静态预配功能预配卷

通过静态预配,您可以创建一个或多个包含底层存储系统细节的 PersistentVolume (PV) 对象。随后,集群中的 Pod 即可通过 PersistentVolumeClaims (PVC) 使用存储空间。

创建一个 PersistentVolume

  1. 保存以下 YAML 清单:

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: gcs-fuse-csi-pv
    spec:
      accessModes:
      - ReadWriteMany
      capacity:
        storage: 5Gi
      storageClassName: example-storage-class
      mountOptions:
        - implicit-dirs
      csi:
        driver: gcsfuse.csi.storage.gke.io
        volumeHandle: BUCKET_NAME
        volumeAttributes:
          gcsfuseLoggingSeverity: warning
    

    示例清单展示了如何为 Cloud Storage 存储桶定义 PersistentVolume。该示例包含以下字段:

    • spec.csi.driver:使用 gcsfuse.csi.storage.gke.io 作为 CSI 驱动程序名称。
    • spec.csi.volumeHandle:指定 Cloud Storage 存储桶名称。您可以传递下划线 (_) 以装载该 Kubernetes ServiceAccount 有权访问的所有存储桶。如需了解详情,请参阅 Cloud Storage FUSE 文档中的动态装载
    • spec.mountOptions:可选。将装载选项传递给 Cloud Storage FUSE。
    • spec.csi.volumeAttributes:可选。将卷属性传递给 Cloud Storage FUSE。
  2. 将清单应用于集群:

    kubectl apply -f FILE_PATH
    

    FILE_PATH 替换为 YAML 文件的路径。

创建一个 PersistentVolumeClaim

  1. 保存以下 YAML 清单:

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: gcs-fuse-csi-static-pvc
      namespace: NAMESPACE
    spec:
      accessModes:
      - ReadWriteMany
      resources:
        requests:
          storage: 5Gi
      volumeName: gcs-fuse-csi-pv
      storageClassName: example-storage-class
    

    示例清单展示了如何定义 PersistentVolumeClaim,以绑定 PersistentVolume。该示例包含以下字段:

    • metadata.namespace:指定 PersistentVolumeClaim 命名空间,这必须与您工作负载的命名空间一致。
    • spec.volumeName:指定 PersistentVolume 名称。

    如需将 PersistentVolume 绑定到 PersistentVolumeClaim,请务必遵循以下准则:

    • PV 和 PVC 清单中的 spec.storageClassName 字段应该相互匹配。storageClassName 不需要引用现有 StorageClass 对象。如需将声明绑定到卷,您可以使用任意名称,但名称不能为空。
    • PV 和 PVC 清单中的 spec.accessModes 字段应该相互匹配。
    • PersistentVolume 清单中的 spec.capacity.storage 应与 PersistentVolumeClaim 清单中的 spec.resources.requests.storage 相匹配。由于 Cloud Storage 存储桶没有大小限制,因此您可以放置任意数量的容量,但不能为空。
  2. 将清单应用于集群:

    kubectl apply -f FILE_PATH
    

    FILE_PATH 替换为 YAML 文件的路径。

使用 PersistentVolumeClaim 中的卷

  1. 保存以下 YAML 清单:

    apiVersion: v1
    kind: Pod
    metadata:
      name: gcs-fuse-csi-example-static-pvc
      namespace: NAMESPACE
      annotations:
        gke-gcsfuse/volumes: "true"
    spec:
      containers:
      - image: busybox
        name: busybox
        command: ["sleep"]
        args: ["infinity"]
        volumeMounts:
        - name: gcs-fuse-csi-static
          mountPath: /data
          readOnly: true
      serviceAccountName: KSA_NAME
      volumes:
      - name: gcs-fuse-csi-static
        persistentVolumeClaim:
          claimName: gcs-fuse-csi-static-pvc
          readOnly: true
    

    该示例展示了如何通过 PersistentVolumeClaim 定义使用 Cloud Storage FUSE 存储桶的 Pod。该示例包含以下字段:

  2. 将清单应用于集群:

    kubectl apply -f FILE_PATH
    

    FILE_PATH 替换为 YAML 文件的路径。

如需查看其他示例,请参阅 GitHub 项目文档中的示例应用

在启用了文件缓存的情况下使用卷

默认情况下,文件缓存功能在 GKE 上处于停用状态。如需启用和控制文件缓存,请使用卷属性 fileCacheCapacity

GKE 会将 emptyDir 卷用于 Cloud Storage FUSE 文件缓存(由节点虚拟机启动磁盘提供支持)。如果在节点上启用本地 SSD,则 GKE 会使用本地 SSD 为 emptyDir 卷提供支持。

您可以为边车容器配置自定义读取缓存卷来替换 emptyDir 卷,以便在读取操作中进行文件缓存。对于支持本地 SSD 的 CPU 和 GPU 虚拟机系列,我们建议使用本地 SSD 存储空间。对于 TPU 系列或 Autopilot,我们建议使用平衡永久性磁盘或 SSD 永久性磁盘。

在启用了文件缓存的情况下使用 CSI 临时存储卷

如需在使用文件缓存的情况下部署通过 CSI 临时卷使用 Cloud Storage FUSE 存储桶的 Pod,请按照以下步骤操作:

  1. 创建具有本地 SSD 支持的临时存储空间的集群或节点池。

    按照 GKE 文档创建具有本地 SSD 支持的临时存储空间的集群或节点池。

  2. 保存以下 YAML 清单:

    apiVersion: v1
    kind: Pod
    metadata:
      name: gcs-fuse-csi-file-cache-example
      namespace: NAMESPACE
      annotations:
        gke-gcsfuse/volumes: "true"
        gke-gcsfuse/ephemeral-storage-limit: "50Gi"
    spec:
      nodeSelector:
        cloud.google.com/gke-ephemeral-storage-local-ssd: "true"
      restartPolicy: Never
      initContainers:
      - name: data-loader
        image: gcr.io/google.com/cloudsdktool/google-cloud-cli:slim
        resources:
          limits:
            cpu: 500m
            memory: 1Gi
          requests:
            cpu: 500m
            memory: 1Gi
        command:
          - "/bin/sh"
          - "-c"
          - |
            mkdir -p /test_files
            for i in $(seq 1 1000); do dd if=/dev/zero of=/test_files/file_$i.txt bs=1024 count=64; done
            gcloud storage cp /test_files gs://BUCKET_NAME --recursive
      containers:
      - name: data-validator
        image: busybox
        resources:
          limits:
            cpu: 500m
            memory: 512Mi
          requests:
            cpu: 500m
            memory: 512Mi
        command:
          - "/bin/sh"
          - "-c"
          - |
            echo "first read with cache miss"
            time cat /data/test_files/file_* > /dev/null
    
            echo "second read from local cache"
            time cat /data/test_files/file_* > /dev/null
        volumeMounts:
        - name: gcs-fuse-csi-ephemeral
          mountPath: /data
      serviceAccountName: KSA_NAME
      volumes:
      - name: gcs-fuse-csi-ephemeral
        csi:
          driver: gcsfuse.csi.storage.gke.io
          volumeAttributes:
            bucketName: BUCKET_NAME
            mountOptions: "implicit-dirs"
            fileCacheCapacity: "10Gi"
    

    请替换以下内容:

    init 容器 data-loader 会生成 1,000 个大小为 64 KiB 的文件,并将这些文件上传到 Cloud Storage 存储桶。主容器 data-validator 会从存储桶读取所有文件两次,并记录时长。

  3. 将清单应用于集群:

    kubectl apply -f FILE_PATH
    

    FILE_PATH 替换为 YAML 文件的路径。

  4. 如需查看日志输出,请运行以下命令:

    kubectl logs -n NAMESPACE gcs-fuse-csi-file-cache-example -c data-validator
    

    NAMESPACE 替换为工作负载的命名空间。

    输出类似于以下内容:

    first read with cache miss
    real    0m 54.68s
    ...
    second read from local cache
    real    0m 0.38s
    ...
    

    输出结果显示,使用本地缓存的第二次读取比缓存未命中的第一次读取快得多。

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

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

常见示例包括:

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

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

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

  1. 启用文件缓存。创建一个已启用文件缓存的集群,如在启用了文件缓存的情况下使用 CSI 临时存储卷中所述。

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

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

    • fileCacheForRangeRead 用于随机读取或部分读取。
    • metadataTypeCacheCapacitymetadataStatCacheCapacity 用于训练工作负载。

点击以下任一标签页,了解如何根据您是使用临时存储卷还是静态预配来启用并行下载:

临时存储

apiVersion: v1
kind: Pod
metadata:
  name: gcs-fuse-csi-example-ephemeral
  namespace: NAMESPACE
  annotations:
    gke-gcsfuse/volumes: "true"
spec:
  containers:
  ...
  volumes:
  - name: gcs-fuse-csi-ephemeral
    csi:
      driver: gcsfuse.csi.storage.gke.io
      volumeAttributes:
        bucketName: BUCKET_NAME
        mountOptions: "implicit-dirs,file-cache:enable-parallel-downloads:true,file-cache:parallel-downloads-per-file:4,file-cache:max-parallel-downloads:-1,file-cache:download-chunk-size-mb:3"
        fileCacheCapacity: "-1"

静态预配

apiVersion: v1
kind: PersistentVolume
metadata:
  name: gcs-fuse-csi-pv
spec:
  accessModes:
  - ReadWriteMany
  capacity:
    storage: 5Gi
  storageClassName: example-storage-class
  mountOptions:
    - implicit-dirs
    - file-cache:enable-parallel-downloads:true
    - file-cache:parallel-downloads-per-file:4
    - file-cache:max-parallel-downloads:-1
    - file-cache:download-chunk-size-mb:3
  csi:
    driver: gcsfuse.csi.storage.gke.io
    volumeHandle: BUCKET_NAME
    volumeAttributes:
      fileCacheCapacity: "-1"

配置 Cloud Storage FUSE 存储桶的装载方式

本部分介绍如何配置 Cloud Storage FUSE 卷。

装载选项

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

您可以通过以下方法指定装载标志:

  • PersistentVolume 清单的 spec.mountOptions 字段中(如果您使用静态预配)。
  • spec.volumes[n].csi.volumeAttributes.mountOptions 字段中(如果您使用 CSI 临时卷)。

卷属性

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

  • gcsfuseLoggingSeverity

    • 说明:您希望 Cloud Storage FUSE 生成的日志的严重级别,以枚举表示。如果您已在使用 debug_fusedebug_fsdebug_gcs 装载选项,则此新配置会自动设置为 trace。此卷属性会转换为配置文件字段 logging:severity

    • 有效值(按照从最低严重级别到最高严重级别的顺序排序):

      • trace
      • debug
      • info
      • warning
      • error
    • 默认值info

  • fileCacheCapacity

    • 说明:文件缓存可以使用的大小上限。如果存在非零值,则此卷属性会在 Cloud Storage FUSE 中启用文件缓存。此卷属性会转换为配置文件字段 file-cache:max-size-mb

    • 有效值

      • 数量值,例如:500Mi10Gi
      • “-1”:使用缓存卷的所有可用容量。
      • “0”:文件缓存处于停用状态。
    • 默认值:“0”。

  • fileCacheForRangeRead

    • 说明:从非零偏移处完成首次读取时,是否应异步下载完整对象并将其存储在 Cloud Storage FUSE 缓存目录中。如果您计划执行多次随机读取或部分读取,则应将其设置为“true”。此卷属性会转换为配置文件字段 file-cache:cache-file-for-range-read

    • 有效值

      • 字符串格式的布尔值:“true”“false”。
    • 默认值:“false”。

  • metadataStatCacheCapacity

    • 说明:统计信息缓存可以使用的大小上限。统计信息缓存始终完全保留在内存中。如果您已在使用 stat-cache-capacity 装载选项,则系统仍将采用该值,并将其适当地转换为此新配置。此卷属性会转换为配置文件字段 metadata-cache:stat-cache-max-size-mb

    • 有效值

      • 数量值,例如:500Mi1Gi
      • “-1”:让统计信息缓存根据需要使用尽可能多的内存。
      • “0”:统计信息缓存处于停用状态。
      • 如果您的工作负载最多涉及 20,000 个文件,请使用默认值 32Mi。如果您的工作负载超过 20,000 个文件,则每增加 6,000 个文件,大小值将增加 10 MiB,平均每个文件增加大约 1,500 个字节。
    • 默认值32Mi

  • metadataTypeCacheCapacity

    • 说明:类型缓存可以使用的每个目录的大小上限。类型缓存始终完全保留在内存中。此卷属性会转换为配置文件字段 metadata-cache:type-cache-max-size-mb

    • 有效值

      • 数量值,例如:500Mi1Gi
      • “-1”:让类型缓存根据需要使用尽可能多的内存。
      • “0”:类型缓存处于停用状态。
      • 如果要装载的存储桶的单个目录中的最大文件数最多为 20,000,请使用默认值 4Mi。如果要装载的单个目录中的最大文件数超过 20,000,则每 5,000 个文件,大小将增加 1 MiB,平均每个文件大约增加 200 个字节。
    • 默认值4Mi

  • metadataCacheTTLSeconds

    • 说明:缓存元数据条目的存留时间 (TTL)(以秒为单位)。如果您已在使用 stat-cache-ttltype-cache-ttl 装载选项,则系统仍将采用这些值,并将其适当地转换为此新配置。此卷属性会转换为配置文件字段 metadata-cache:ttl-secs

    • 有效值

      • 字符串格式的整数值,例如:“600”。
      • “-1”:绕过 TTL 过期时间,并在文件可用时从缓存中传送文件。
      • “0”:确保读取最新文件。使用 0 值会发出 Get 元数据调用,以确保缓存中文件的对象世代与 Cloud Storage 中存储的文件的对象世代一致。
    • 默认值:“60”。

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

  • PersistentVolume 清单的 spec.csi.volumeAttributes 字段中(如果您使用静态预配)。
  • spec.volumes[n].csi.volumeAttributes 字段中(如果您使用 CSI 临时卷)。

注意事项

配置装载时,请考虑以下事项:

  • 不允许使用以下标志:app-nametemp-dirforegroundlog-filelog-formatkey-filetoken-urlreuse-token-from-url
  • 默认情况下,Cloud Storage FUSE 不显示隐式目录。如需显示这些目录,您可以启用 implicit-dirs 装载标志。如需了解详情,请参阅 Cloud Storage FUSE GitHub 文档中的文件和目录
  • 如果您为 Pod 或容器使用安全上下文,或者您的容器映像使用非根用户或群组,则必须设置 uidgid 装载标志。您还需要使用 file-modedir-mode 挂载标志来设置文件系统权限。请注意,您无法针对 Cloud Storage FUSE 文件系统运行 chmodchownchgrp 命令,因此必须使用 uidgidfile-modedir-mode 装载标记才能向非 root 用户或组提供访问权限。
  • 如果您只想在存储桶中装载目录(而不是装载整个存储桶),请使用 only-dir=relative/path/to/the/bucket/root 标志传递目录相对路径。
  • 如需调整 Cloud Storage FUSE 缓存行为,请配置卷属性。如需了解详情,请参阅 Cloud Storage FUSE 缓存文档。
  • 如果您需要指定每个服务器允许的 TCP 连接数上限,可以使用 max-conns-per-host 标记指定此上限。当 --client-protocol 设置为 http1 时,您定义的 TCP 连接数上限会生效。默认值为 0,表示 TCP 连接数量不受限制(受机器规范的限制)。
  • 如需配置 Linux 内核装载选项,您可以使用 o 标志传递该选项。例如,如果您不想允许直接执行所装载的文件系统上的任何二进制文件,请设置 o=noexec 标志。每个选项都需要单独的标志,例如 o=noexec,o=noatime。仅允许使用以下选项:execnoexecatimenoatimesyncasyncdirsync
  • 如需排查 Cloud Storage FUSE 问题,请设置 debug_fusedebug_fsdebug_gcs 标志。 如果指定了这三个选项中的任何一个,则 gcsfuseLoggingSeverity 卷属性会自动设置为 trace
  • Cloud Storage FUSE CSI 驱动程序不允许您修改 Cloud Storage FUSE 配置文件中的 cache-dir 字段,请使用 fileCacheCapacity 卷属性启用或停用文件缓存。如需替换默认 emptyDir 卷以用于文件缓存,您可以为边车容器配置自定义缓存卷

停用 Cloud Storage FUSE CSI 驱动程序

您无法在 Autopilot 集群上停用 Cloud Storage FUSE CSI 驱动程序。

您可以使用 Google Cloud CLI 在现有 Standard 集群上停用 Cloud Storage FUSE CSI 驱动程序。

gcloud container clusters update CLUSTER_NAME \
    --update-addons GcsFuseCsiDriver=DISABLED

CLUSTER_NAME 替换为您的集群名称。

问题排查

如需排查使用 Cloud Storage FUSE CSI 驱动程序时遇到的问题,请参阅 GitHub 项目文档中的问题排查指南

后续步骤