为服务配置内存中卷装载

本页面介绍如何配置专用的内存中卷,您可以通过 Cloud Run 卷装载使用该卷进行文件读取和写入。请注意,此功能与 Cloud Run 提供的内置内存中文件系统不同。

在 Cloud Run 中装载内存中的卷时,内存中的卷在容器文件系统中显示为文件。装载内存中的卷后,您可以使用编程语言的文件系统操作和库来访问该文件共享,就像访问本地文件系统上的目录一样。

您可以使用内存中卷执行以下操作:

  • 限制内存中卷的大小。当您限制卷的大小时,对已满的卷进行写入会失败,这比让 Cloud Run 因卷占用过多内存而终止实例更可取。
  • 在一个 Cloud Run 实例中的不同容器之间共享内存中卷。当 Cloud Run 扩容到服务的多个实例时,每个实例都会有自己的内存中卷,并由该实例上的所有容器共享。当 Cloud Run 扩容以处理流量时,所有容器都可以使用此卷。

行为

创建内存中卷时,建议指定大小限制。如果卷达到其大小限制,再进行其他写入会失败并发生内存不足错误。您的实例可以处理此错误并继续运行。

请注意,大小限制只是一个限制:它不会为内存中卷分配更多空间。内存中卷会占用您为容器配置的内存。如果您部署多个容器,则每次向卷写入时所使用的内存都会计为写入数据的那个容器的内存用量。

如果未指定大小限制,则它会自动设置为作业或服务中所有容器总大小的一半。例如,emptyDir 卷大小 = [内存(容器 A)+ 内存(容器 B)+ 内存(容器 N)]/2。 此默认行为可能会导致内存中卷的大小限制高于为某些容器分配的内存。在这种情况下,如果容器不断向卷写入内存,它将超出分配的内存,并在达到卷大小限制之前崩溃。

虽然并不强制要求设置大小限制,但建议您设置一个限制来防止容器用光内存和崩溃。

不允许的路径

Cloud Run 不允许您在 /dev/proc/sys 或其子目录上装载卷。

卷所有权因执行环境和部署类型而异

装载卷时,拥有文件和目录的身份将因工作负载的执行环境以及部署是包含一个或多个容器而有所不同。

在要部署单个容器的第一代执行环境中,卷归容器使用的身份所有。 在所有其他情况下,卷归 root 用户所有。包括:

  • 在其中部署多个容器的第一代执行环境
  • 第二代环境

配置内存中卷

任何配置更改都会导致新修订版本的创建。后续修订版本也将自动采用此配置设置,除非您进行了明确更新。

为 Cloud Run 服务配置内存中卷后,系统会为启动的每个 Cloud Run 实例都创建一个空卷,并且只要该实例运行,该卷便会存在。当实例停止运行时,该卷中的数据会被永久删除。

控制台

  1. 在 Google Cloud 控制台中,前往 Cloud Run:

    转到 Cloud Run

  2. 如果您是要配置一个新服务来作为部署目标,请点击创建服务。如果您要配置现有服务,请点击该服务,然后点击修改和部署新的修订版本

  3. 如果您要配置新服务,请根据需要填写初始服务设置页面,然后点击容器、网络、安全性以展开服务配置页面。

  4. 点击标签页。

    图片

    • 下:
      • 点击添加卷
      • 卷类型下拉列表中,选择内存中作为卷类型。
      • 卷名称字段中,输入要用于卷的名称。
      • 点击完成
    • 点击“容器”标签页。
    • 点击卷装载标签页。
      • 点击装载卷
      • 从菜单中选择内存中卷。
      • 指定您要用于装载卷的路径。
      • 点击装载卷
  5. 点击创建部署

gcloud

  • 如需添加卷并装载,请运行以下命令:

    gcloud beta run services update SERVICE \
    --add-volume=name=VOLUME_NAME,type=in-memory,size-limit=SIZE_LIMIT \
    --add-volume-mount=volume=VOLUME_NAME,mount-path=MOUNT_PATH

    您需要将其中的:

    • SERVICE 替换为您的服务名称。
    • VOLUME_NAME 替换为您要为卷使用的任何名称。VOLUME_NAME 值用于将卷映射到卷装载。
    • MOUNT_PATH 替换为要装载此卷的容器文件系统中的相对路径,例如 /mnt/my-volume
    • SIZE_LIMIT 替换为您要分配给卷的内存限制,以 MiB 或 GiB 为单位(指定为 Mi 或 Gi),例如 500Mi。此限制必须小于为容器指定的总内存
  • 如果您使用多个容器,请先指定卷,然后为每个容器指定卷装载:

    gcloud beta run services update SERVICE \
    --add-volume=name= VOLUME_NAME,type=in-memory,size-limit=SIZE_LIMIT \
    --container=CONTAINER_1 \
    --add-volume-mount=volume= VOLUME_NAME,mount-path=MOUNT_PATH \
    --container==CONTAINER_2 \
    --add-volume-mount=volume= VOLUME_NAME,mount-path=MOUNT_PATH2

YAML

  1. 如果您要创建新的服务,请跳过此步骤。如果您要更新现有服务,请下载其 YAML 配置

    gcloud run services describe SERVICE --format export > service.yaml
  2. 配置 volumeMountsvolumes 属性,如下所示:

    apiVersion: serving.knative.dev/v1
    kind: Service
    metadata:
     annotations:
      run.googleapis.com/launch-stage: BETA
    spec:
      template:
        metadata:
        spec:
          containers:
          - image: IMAGE_URL
            volumeMounts:
            - mountPath: MOUNT_PATH
              name: VOLUME_NAME
          volumes:
          - name: VOLUME_NAME
            emptyDir:
              sizeLimit: SIZE_LIMIT
              medium: Memory

    您需要将其中的:

    • IMAGE_URL 替换为对容器映像的引用,例如 us-docker.pkg.dev/cloudrun/container/hello:latest。 如果您使用 Artifact Registry,则必须预先创建制品库 REPO_NAME。网址格式为 LOCATION-docker.pkg.dev/PROJECT_ID/REPO_NAME/PATH:TAG
    • VOLUME_NAME 替换为您要为卷使用的任何名称。VOLUME_NAME 值用于将卷映射到卷装载。
    • MOUNT_PATH 替换为要装载此卷的容器文件系统中的相对路径,例如 /mnt/my-volume
    • SIZE_LIMIT 替换为您要分配给卷的内存限制,以 MiB 或 GiB 为单位(指定为 Mi 或 Gi),例如 500Mi。此限制必须小于为容器指定的总内存
  3. 使用以下命令创建或更新服务:

    gcloud run services replace service.yaml

读取和写入卷

如果您使用 Cloud Run 卷装载功能,则可以使用编程语言中用于在本地文件系统上读写文件的相同库来访问已装载的卷。

如果您使用的是期望数据存储在本地文件系统中并使用常规文件系统操作来访问数据的现有容器,此方法会特别有用。

以下代码段假定一个 mountPath 设置为 /mnt/my-volume 的卷装载。

Nodejs

使用文件系统模块创建新文件或附加到卷 /mnt/my-volume 中的现有文件:

var fs = require('fs');
fs.appendFileSync('/mnt/my-volume/sample-logfile.txt', 'Hello logs!', { flag: 'a+' });

Python

写入保存在卷 /mnt/my-volume 中的文件:

f = open("/mnt/my-volume/sample-logfile.txt", "a")

Go

使用 os 软件包创建一个保存在卷 /mnt/my-volume 中的新文件

f, err := os.Create("/mnt/my-volume/sample-logfile.txt")

Java

使用 Java.io.File 类在卷 /mnt/my-volume 中创建日志文件:

import java.io.File;
File f = new File("/mnt/my-volume/sample-logfile.txt");