容器运行时合同

本页面列出了 Cloud Run 中容器的主要要求和行为。Cloud Run 服务和 Cloud Run 作业之间存在一些差异:我们会对存在差异的地方进行说明。

支持的语言和映像

您的容器映像可以运行以您选择的编程语言编写的代码并使用任何基础映像,前提是该映像遵循本页面中列出的限制条件。

必须针对 Linux 64 位编译容器映像中的可执行文件。Cloud Run 明确支持 Linux x86_64 ABI 格式。

Cloud Run 接受 Docker Image Manifest V2、架构 1架构 2OCI 映像格式的容器映像。

如果部署多架构映像,则清单列表必须包含 linux/amd64

侦听正确的端口上的请求(服务)

Cloud Run 服务会启动 Cloud Run 实例来处理传入请求。一个 Cloud Run 实例始终有一个入站流量容器,以及可选的一个或多个 Sidecar 容器。以下端口配置详细信息仅适用于入站流量容器,而不适用于 Sidecar。

实例中的入站流量容器必须在接收请求的端口上的 0.0.0.0 上监听请求。默认情况下,请求将发送到 8080,但您可以配置 Cloud Run 以将请求发送到您选择的端口。Cloud Run 会将 PORT 环境变量注入入站流量容器中。

作业执行中运行的容器必须在完成时退出

对于 Cloud Run 作业,容器必须在作业成功完成时退出并显示退出代码 0,在作业失败时退出则显示非零退出代码。

由于作业不应响应请求,因此容器不应侦听端口或启动网络服务器。

传输层加密 (TLS)

容器不应直接实现任何传输层安全。应由 Cloud Run 为 HTTPS 和 gRPC 终止 TLS,之后将请求以 HTTP/1 或 gRPC 形式通过代理转发到不具备 TLS 的容器。

如果您将 Cloud Run 服务配置为使用 HTTP/2 端到端连接,则容器必须处理 HTTP/2 明文 (h2c) 格式的请求,因为 TLS 仍会被 Cloud Run 自动终止。

响应(服务)

对于 Cloud Run 服务,容器必须在收到请求后,于请求超时设置中指定的时间内(包括容器启动时间)发送响应。否则,请求将结束并返回 504 错误。

环境变量

Cloud Run 服务和作业具有不同的环境变量。

服务的环境变量

以下环境变量会自动添加到所有正在运行的容器中(PORT 除外)。PORT 变量只会添加到入站流量容器:

名称 说明 示例
PORT 您的 HTTP 服务器应侦听的端口。 8080
K_SERVICE 正在运行的 Cloud Run 服务的名称。 hello-world
K_REVISION 正在运行的 Cloud Run 修订版本的名称。 hello-world.1
K_CONFIGURATION 创建了该修订版本的 Cloud Run 配置的名称。 hello-world

作业的环境变量

对于 Cloud Run 作业,系统会设置以下环境变量:

名称 说明 示例
CLOUD_RUN_JOB 正在运行的 Cloud Run 作业的名称。 hello-world
CLOUD_RUN_EXECUTION 正在运行的 Cloud Run 执行的名称。 hello-world-abc
CLOUD_RUN_TASK_INDEX 此任务的索引。从 0 开始(表示第一项任务),然后每次连续执行任务时递增 1,上限为最大任务数减 1。如果将 --parallelism 设置为大于 1,任务可能不会遵循索引顺序。例如,任务 2 可能会在任务 1 之前开始。 0
CLOUD_RUN_TASK_ATTEMPT 此任务已经重试的次数。从 0 开始(表示第一次尝试),然后每次连续重试时递增 1,上限为最大重试值。 0
CLOUD_RUN_TASK_COUNT --tasks 参数中定义的任务数。 1

请求和响应标头要求(服务)

对于 Cloud Run 服务,标头名称仅限于可打印的非空格 ASCII,且不能包含英文冒号。根据 IETF RFC 7230 的规定,标头值仅限于可见的 ASCII 字符,以及空格和水平制表符

文件系统访问

每个容器中的文件系统都是可写的,并且受以下行为的约束:

  • 这是一个内存中文件系统,因此向其中写入数据会使用实例的内存。
  • 停止实例时,写入文件系统的数据不会保留。

请注意,无法为此文件系统指定大小限制,因此,如果写入内存中文件系统,可能会耗尽分配给实例的所有内存,从而导致实例崩溃。如果您使用具有大小限制的专用内存中卷,则可以避免此问题。

实例生命周期

Cloud Run 作业和服务的生命周期特征不同,因此以下各子部分分别介绍了这些特征。

对于服务

以下内容仅适用于服务。

服务扩缩

Cloud Run 服务会自动扩缩到处理所有传入请求、事件或 CPU 利用率所需的实例数。

每个实例运行固定数量的容器(一个入站流量容器,以及可选的一个或多个 Sidecar 容器)。

当修订版本未收到任何流量时,它会缩减为配置的实例数下限(默认为零)。

启动

对于 Cloud Run 服务,实例必须在启动后的 4 分钟内监听请求,并且实例中的所有容器都需要运行状况良好。在此启动期间,系统会向实例分配 CPU。您可以启用启动 CPU 加速,在实例启动期间临时增加 CPU 分配,以缩短启动延迟时间。

一旦入站流量容器监听已配置的端口,请求就会立即发送到该容器。

等待实例的请求将在队列中保持待处理状态,如下所示:

  • 如果新实例(例如在横向扩容期间)启动,则请求将至少留出此服务的容器实例的平均启动时间。这包括请求启动横向扩容的时间,例如从零开始横向扩容时。
  • 如果启动时间少于 10 秒,则请求将持续长达 10 秒。
  • 如果启动过程中没有实例,并且请求未启动横向扩容,则请求将持续长达 10 秒。

您可以配置启动探测以确定容器是否已启动并已准备好处理请求。

对于由多容器实例组成的 Cloud Run 服务,您可以通过配置容器启动顺序来指定容器在实例中的启动顺序。

处理请求

对于 Cloud Run 服务,只要 Cloud Run 修订版本处理至少一个请求,CPU 就会始终分配给实例中的所有容器,包括 Sidecar

空闲

对于 Cloud Run 服务,空闲实例是指未处理任何请求的实例。

分配给空闲实例中所有容器的 CPU 取决于所配置的 CPU 分配

除非实例因实例数下限配置设置而必须保持空闲状态,否则它将保持空闲状态超过 15 分钟。

关停

对于 Cloud Run 服务,空闲实例可以随时关停,包括通过最少数量的实例保持备用状态的实例。在关停正在处理请求的实例时,新的传入请求会被路由到其他实例,而当前正在处理的请求则会给予一定时间让其完成。在异常情况下,Cloud Run 可能会启动关停操作,并向仍在处理请求的容器发送 SIGTERM 信号。

在关停实例之前,Cloud Run 会向实例中的所有容器发送一个 SIGTERM 信号,指示实例将于 10 秒后进行实际的关停,届时 Cloud Run 则会发送一个 SIGKILL 信号。在此期间,系统会为实例分配 CPU 并计费。在使用第一代执行环境的服务中,如果实例未捕获 SIGTERM 信号,则会立即关停。(请参阅代码示例,了解如何捕获 SIGTERM 信号。)

强制终止

如果一个或多个 Cloud Run 容器超过容器总内存限制,则实例将终止。所有仍在该实例上处理的请求都会被终止并显示 HTTP 500 错误。

对于作业

对于 Cloud Run 作业,容器实例会一直运行,直到容器实例退出、达到任务超时或容器崩溃。

强制终止

如果 Cloud Run 容器实例超出允许的内存限制,则该容器实例会被终止。所有仍在该容器实例上处理的请求都会被终止并显示 HTTP 500 错误。

如果任务超出任务超时,Cloud Run 会发送“SIGTERM”信号,指示容器实例将于 10 秒后实际关停,届时 Cloud Run 会发送 SIGKILL 信号,关闭容器实例。

在此期间,容器实例在整个生命周期中都会被分配 CPU 并计费。

请参阅 SIGTERM 代码示例,了解如何捕获 SIGTERM 信号。

容器实例资源

CPU

默认情况下,系统会为实例中的每个 Cloud Run 容器分配已配置的 vCPU(默认 1 个)。您可以分别配置每个容器的 CPU 限制。

vCPU 是底层硬件的抽象,可提供可变 CPU 平台上单个硬件超线程的大致等效 CPU 时间。Cloud Run 使用的所有 CPU 平台都支持 AVX2 指令集。请注意,容器合同不包含任何其他 CPU 平台详细信息。

容器可以同时在多个核心上执行。

对于 Cloud Run 服务,您可以指定 CPU 始终在实例的生命周期内分配,或仅在实例启动和请求处理期间分配。如需了解详情,请参阅 CPU 分配

如果您配置了一些最少的实例,则这些实例也受 CPU 分配配置的约束。

您可以启用启动 CPU 加速,在实例启动期间临时增加 CPU 分配,以缩短启动延迟时间。

内存

默认情况下,系统会为每个 Cloud Run 容器分配已配置的内存(默认为 512 MiB)。您可以分别配置每个容器的内存限制。

内存的典型用途包括:

  • 将代码加载到内存中以运行服务
  • 写入文件系统
  • 在容器中运行的额外进程(例如 nginx 服务器)
  • PHP OpCache 等内存缓存系统
  • 每个请求的内存用量
  • 共享内存中卷

并发(服务)

对于 Cloud Run 服务,每个 Cloud Run 实例默认设置为多个并发,其中入站流量容器可以同时接收多个请求。您可以通过设置并发来更改此设置。

容器沙盒

如果您使用第一代执行环境,则会使用 gVisor 容器运行时沙盒对 Cloud Run 容器进行沙盒化。如 gVisor syscall 兼容性参考文档中所述,此容器沙盒可能不支持某些系统调用。

如果您使用第二代执行环境,则可完全兼容 Linux。Cloud Run 作业始终使用第二代执行环境。在第二代执行环境中,/sys/class/dmi/id/product_name 设置为 Google Compute Engine

第二代执行环境在单独的进程命名空间中运行您的服务代码,因此它会作为具有特殊进程语义的容器 init 进程启动。在第一代执行环境中,服务代码不会作为容器 init 进程运行。

实例元数据服务器

Cloud Run 实例公开一个元数据服务器,您可以使用该服务器检索容器的详细信息,例如项目 ID、区域、实例 ID 或服务账号。它还可用于为运行时服务账号生成令牌

您可以使用具有 Metadata-Flavor: Google 标头的 http://metadata.google.internal/ 端点进行简单的 HTTP 请求,从元数据服务器访问此数据:不需要客户端库。如需了解详情,请参阅获取元数据

下表列出了部分可用的元数据服务器信息:

路径 说明
/computeMetadata/v1/project/project-id Cloud Run 服务或作业所属项目的 ID
/computeMetadata/v1/project/numeric-project-id Cloud Run 服务或作业所属项目的编号
/computeMetadata/v1/instance/region 此 Cloud Run 服务或作业所在的区域,返回 projects/PROJECT-NUMBER/regions/REGION
/computeMetadata/v1/instance/id 实例的唯一标识符(也可在日志中提供)。
/computeMetadata/v1/instance/service-accounts/default/email 此 Cloud Run 服务或作业的运行时服务账号的电子邮件地址。
/computeMetadata/v1/instance/service-accounts/default/token 此 Cloud Run 服务或作业的服务账号生成 OAuth2 访问令牌。Cloud Run 服务代理用于提取令牌。此端点将返回包含 access_token 属性的 JSON 响应。详细了解如何提取和使用此访问令牌。

请注意,Cloud Run 不会提供用于运行实例的 Google Cloud 区域的详细信息。因此,元数据特性 /computeMetadata/v1/instance/zone 始终返回 projects/PROJECT-NUMBER/zones/REGION-1

文件名

您在容器中使用的文件名必须与 UTF-8 兼容,要么使用 UTF-8 编码,要么使用可以安全自动转换为 UTF-8 的编码方式。如果您的文件名使用不同的编码,请使用与 UTF-8 兼容的文件名在机器上运行 Docker 构建,并避免将文件复制到包含不兼容 UTF-8 名称的容器。

如果文件名与 UTF-8 不兼容,则容器部署将失败。请注意,您在文件中使用的字符编码没有限制。

出站连接

出站请求超时

对于 Cloud Run 服务和作业,从容器到 VPC 的请求在经历 10 分钟的空闲时间后会超时。对于从容器到互联网的请求,空闲时间达到 20 分钟后超时。

出站连接重置

在底层基础架构重启或更新时,从容器到 VPC 和互联网的连接流可能会偶尔被终止和替换。如果您的应用重复使用长期有效的连接,我们建议您将应用配置为重新建立连接,以避免重用无效连接。