Cloud Run functions 使用入门

Cloud Run functions 使用入门

关于此 Codelab

subject上次更新时间:5月 7, 2025
account_circleMete Atamel 编写

1. 简介

概览

Cloud Run functions 是 Google Cloud 的函数即服务产品,由 Cloud RunEventarc 提供支持,可让您对性能和可伸缩性进行更高级的控制,并更好地控制函数运行时和来自 90 多个事件来源的触发器。

本 Codelab 将引导您创建 Cloud Run 函数,以响应 HTTP 调用,并由 Pub/Sub 消息和 Cloud 审核日志触发。

此 Codelab 还会使用自动基础映像更新功能为函数部署指定基础映像,方法是使用 --base-image 标志。通过为 Cloud Run 配置自动基础映像更新,使 Google 能够自动为基础映像的操作系统和语言运行时组件打安全补丁。您无需重新构建或重新部署服务,即可更新基础映像。如需了解详情,请参阅自动基础映像更新

如果您想使用自动基础映像更新,可以从此 Codelab 中显示的示例中移除 --base-image 标志。

学习内容

  • Cloud Run functions 概览以及如何使用自动基础映像更新。
  • 如何编写响应 HTTP 调用的函数。
  • 如何编写响应 Pub/Sub 消息的函数。
  • 如何编写响应 Cloud Storage 事件的函数。
  • 如何在两个修订版本之间拆分流量。
  • 如何通过实例数下限来避免冷启动。

2. 设置和要求

创建根文件夹

为所有示例创建一个根文件夹。

mkdir crf-codelab
cd crf-codelab

设置环境变量

设置将在此 Codelab 中全程使用的环境变量。

gcloud config set project <YOUR-PROJECT-ID>
REGION=<YOUR_REGION>

PROJECT_ID=$(gcloud config get-value project)

启用 API

启用所有必要的服务:

gcloud services enable \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com \
  eventarc.googleapis.com \
  run.googleapis.com \
  logging.googleapis.com \
  pubsub.googleapis.com

3. HTTP 函数

对于第一个函数,我们将创建一个用于响应 HTTP 请求的经过身份验证的 Node.js 函数。我们还将使用 10 分钟的超时时间来展示函数如何有更多时间响应 HTTP 请求。

创建

为应用创建一个文件夹,然后打开该文件夹:

mkdir hello-http
cd hello-http

创建用于响应 HTTP 请求的 index.js 文件:

const functions = require('@google-cloud/functions-framework');

functions.http('helloWorld', (req, res) => {
  res.status(200).send('HTTP with Node.js in Cloud Run functions!');
});

创建一个 package.json 文件来指定依赖项:

{
  "name": "nodejs-run-functions-codelab",
  "version": "0.0.1",
  "main": "index.js",
  "dependencies": {
    "@google-cloud/functions-framework": "^2.0.0"
  }
}

部署

部署函数的方法如下:

gcloud run deploy nodejs-run-function \
      --source . \
      --function helloWorld \
      --base-image nodejs22 \
      --region $REGION \
      --timeout 600 \
      --no-allow-unauthenticated

此命令使用 buildpack 将函数源代码转换为可用于生产环境的容器映像。

请注意以下事项:

  • --source 标志用于指示 Cloud Run 将函数构建为基于可运行容器的服务
  • --function 标志(新)用于将新服务的入口点设置为您要调用的函数签名
  • --base-image 标志(新)用于指定函数的基础映像环境,例如 nodejs22python312go123java21dotnet8ruby33php83。如需详细了解基础映像以及每个映像中包含的软件包,请参阅运行时基础映像
  • (可选)--timeout 标志可让函数在响应 HTTP 请求时使用更长的超时时间。在此示例中,使用 600 秒来演示 10 分钟的响应时间。
  • (可选)--no-allow-unauthenticated,用于防止函数被公开调用

测试

使用以下命令测试函数:

# get the Service URL
SERVICE_URL="$(gcloud run services describe nodejs-run-function --region $REGION --format 'value(status.url)')"

# invoke the service
curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET $SERVICE_URL

您应该会看到消息 HTTP with Node.js in Cloud Run functions! 作为响应。

4. Pub/Sub 函数

对于第二个函数,我们将创建一个由发布到特定主题的 Pub/Sub 消息触发的 Python 函数。

设置 Pub/Sub 身份验证令牌

如果您在 2021 年 4 月 8 日当天或之前启用了 Pub/Sub 服务账号,请将 iam.serviceAccountTokenCreator 角色授予 Pub/Sub 服务账号:

PROJECT_NUMBER=$(gcloud projects list --filter="project_id:$PROJECT_ID" --format='value(project_number)')

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member  serviceAccount:service-$PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \
  --role roles/iam.serviceAccountTokenCreator

创建

创建要用于示例的 Pub/Sub 主题:

TOPIC=cloud-run-functions-pubsub-topic
gcloud pubsub topics create $TOPIC

为应用创建一个文件夹,然后打开该文件夹:

mkdir ../hello-pubsub
cd ../hello-pubsub

创建一个 main.py 文件,用于记录包含 CloudEvent ID 的消息:

import functions_framework

@functions_framework.cloud_event
def hello_pubsub(cloud_event):
   print('Pub/Sub with Python in Cloud Run functions! Id: ' + cloud_event['id'])

创建一个包含以下内容的 requirements.txt 文件,以指定依赖项:

functions-framework==3.*

部署

部署函数的方法如下:

gcloud run deploy python-pubsub-function \
       --source . \
       --function hello_pubsub \
       --base-image python313 \
       --region $REGION \
       --no-allow-unauthenticated

检索要用于服务账号身份的项目编号。

PROJECT_NUMBER=$(gcloud projects list --filter="project_id:$PROJECT_ID" --format='value(project_number)')

创建触发器

gcloud eventarc triggers create python-pubsub-function-trigger  \
    --location=$REGION \
    --destination-run-service=python-pubsub-function  \
    --destination-run-region=$REGION \
    --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" \
    --transport-topic=projects/$PROJECT_ID/topics/$TOPIC \
    --service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com

测试

向该主题发送消息以测试函数:

gcloud pubsub topics publish $TOPIC --message="Hello World"

您应该会在日志中看到已接收到的 CloudEvent:

gcloud run services logs read python-pubsub-function --region $REGION --limit=10

5. Cloud Storage 函数

对于下一个函数,我们将创建一个 Node.js 函数来响应来自 Cloud Storage 存储分区的事件。

设置

如需使用 Cloud Storage 函数,请将 pubsub.publisher IAM 角色授予 Cloud Storage 服务账号:

SERVICE_ACCOUNT=$(gsutil kms serviceaccount -p $PROJECT_NUMBER)

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member serviceAccount:$SERVICE_ACCOUNT \
  --role roles/pubsub.publisher

创建

为应用创建一个文件夹,然后打开该文件夹:

mkdir ../hello-storage
cd ../hello-storage

创建一个仅响应 Cloud Storage 事件的 index.js 文件:

const functions = require('@google-cloud/functions-framework');

functions.cloudEvent('helloStorage', (cloudevent) => {
  console.log('Cloud Storage event with Node.js in Cloud Run functions!');
  console.log(cloudevent);
});

创建一个 package.json 文件来指定依赖项:

{
  "name": "nodejs-crf-cloud-storage",
  "version": "0.0.1",
  "main": "index.js",
  "dependencies": {
    "@google-cloud/functions-framework": "^2.0.0"
  }
}

部署

首先,创建一个 Cloud Storage 存储分区(或使用您已有的现有存储分区):

export BUCKET_NAME="gcf-storage-$PROJECT_ID"
​​export BUCKET="gs://gcf-storage-$PROJECT_ID"
gsutil mb -l $REGION $BUCKET

部署函数的方法如下:

gcloud run deploy nodejs-crf-cloud-storage \
 --source . \
 --base-image nodejs22 \
 --function helloStorage \
 --region $REGION \
 --no-allow-unauthenticated

函数部署完毕后,您可以在 Cloud 控制台的 Cloud Run 部分下看到该函数。

现在,创建 Eventarc 触发器。

BUCKET_REGION=$REGION

gcloud eventarc triggers create nodejs-crf-cloud-storage-trigger \
  --location=$BUCKET_REGION \
  --destination-run-service=nodejs-crf-cloud-storage \
  --destination-run-region=$REGION \
  --event-filters="type=google.cloud.storage.object.v1.finalized" \
  --event-filters="bucket=$BUCKET_NAME" \
  --service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com

测试

通过将文件上传到存储分区来测试函数:

echo "Hello World" > random.txt
gsutil cp random.txt $BUCKET/random.txt

您应该会在日志中看到已接收到的 CloudEvent:

gcloud run services logs read nodejs-crf-cloud-storage --region $REGION --limit=10

6. 流量分配

Cloud Run functions 支持函数的多个修订版本,可在不同的修订版本之间拆分流量,还可将函数回滚到先前版本。

在此步骤中,您将部署一个函数的 2 个修订版本,然后在它们之间按 50-50 的比例拆分流量。

创建

为应用创建一个文件夹,然后打开该文件夹:

mkdir ../traffic-splitting
cd ../traffic-splitting

创建一个 main.py 文件,并在其中添加一个 Python 函数,用于读取颜色环境变量,并以相应背景颜色的 Hello World 进行响应:

import os

color = os.environ.get('COLOR')

def hello_world(request):
    return f'<body style="background-color:{color}"><h1>Hello World!</h1></body>'

创建一个包含以下内容的 requirements.txt 文件,以指定依赖项:

functions-framework==3.*

部署

部署背景为橙色的函数的第一个修订版本:

COLOR=orange
gcloud run deploy hello-world-colors \
 --source . \
 --base-image python313 \
 --function hello_world \
 --region $REGION \
 --allow-unauthenticated \
 --update-env-vars COLOR=$COLOR

此时,如果您通过在浏览器中查看 HTTP 触发器(上述部署命令的 URI 输出)来测试函数,则应该会看到背景为橙色的 Hello World

36ca0c5f39cc89cf.png

部署背景为黄色的第二个修订版本:

COLOR=yellow
gcloud run deploy hello-world-colors \
 --source . \
 --base-image python313 \
 --function hello_world \
 --region $REGION \
 --allow-unauthenticated \
 --update-env-vars COLOR=$COLOR

由于这是最新修订版,因此如果您测试该函数,应该会看到背景为黄色的 Hello World

391286a08ad3cdde.png

按 50-50 的比例分配流量

如需在橙色和黄色修订版本之间分配流量,您需要查找 Cloud Run 服务的修订版本 ID。以下是用于查看修订 ID 的命令:

gcloud run revisions list --service hello-world-colors \
  --region $REGION --format 'value(REVISION)'

输出应类似如下所示:

hello-world-colors-00001-man
hello-world-colors-00002-wok

现在,按如下方式在两个修订版本之间拆分流量(请根据您的修订版本名称更新 X-XXX):

gcloud run services update-traffic hello-world-colors \
  --region $REGION \
  --to-revisions hello-world-colors-0000X-XXX=50,hello-world-colors-0000X-XXX=50

测试

访问函数的公共网址,以测试该函数。您应该会有一半的时间看到橙色修订版本,另一半时间看到黄色修订版本:

36ca0c5f39cc89cf.png 391286a08ad3cdde.png

如需了解详情,请参阅回滚、逐步发布和流量迁移

7. 实例数下限

在 Cloud Run 函数中,您可以指定要保持备用状态并且准备处理请求的函数实例数下限。这对于限制冷启动的次数非常有用。

在此步骤中,您将部署一个初始化缓慢的函数。您会观察到冷启动问题。然后,您将最小实例值设置为 1 来部署该函数,以消除冷启动。

创建

为应用创建一个文件夹,并打开该文件夹:

mkdir ../min-instances
cd ../min-instances

创建 main.go 文件,此 Go 服务有一个 init 函数,该函数会休眠 10 秒以模拟长时间初始化。它还包含一个用于响应 HTTP 调用的 HelloWorld 函数:

package p

import (
        "fmt"
        "net/http"
        "time"
)

func init() {
        time.Sleep(10 * time.Second)
}

func HelloWorld(w http.ResponseWriter, r *http.Request) {
        fmt.Fprint(w, "Slow HTTP Go in Cloud Run functions!")
}

部署

使用默认的最小实例值 0 部署函数的第一个修订版本:

gcloud run deploy go-slow-function \
 --source . \
 --base-image go123 \
 --function HelloWorld \
 --region $REGION \
 --no-allow-unauthenticated

使用以下命令测试函数:

# get the Service URL
SERVICE_URL="$(gcloud run services describe go-slow-function --region $REGION --format 'value(status.url)')"

# invoke the service
curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET $SERVICE_URL

您会发现第一次调用会出现 10 秒的延迟(冷启动),然后看到消息。后续调用应立即返回。

设置实例数下限

如需消除首次请求时的冷启动,请将 --min-instances 标志设置为 1,然后重新部署函数,如下所示:

gcloud run deploy go-slow-function \
 --source . \
 --base-image go123 \
 --function HelloWorld \
 --region $REGION \
 --no-allow-unauthenticated \
 --min-instances 1

测试

再次测试该函数:

curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET $SERVICE_URL

您应该不会再在第一个请求中看到 10 秒的延迟。由于实例数下限,首次调用(在很长一段时间没有调用后)的冷启动问题已消失!

如需了解详情,请参阅使用实例数下限

8. 恭喜!

恭喜您完成此 Codelab!

所学内容

  • Cloud Run functions 概览以及如何使用自动基础映像更新。
  • 如何编写响应 HTTP 调用的函数。
  • 如何编写响应 Pub/Sub 消息的函数。
  • 如何编写响应 Cloud Storage 事件的函数。
  • 如何在两个修订版本之间拆分流量。
  • 如何通过实例数下限来避免冷启动。