開始使用 Cloud Run 函式

開始使用 Cloud Run 函式

程式碼研究室簡介

subject上次更新時間:5月 7, 2025
account_circle作者:Mete Atamel

1. 簡介

總覽

Cloud Run 函式是 Google Cloud 的函式即服務 (FaaS) 產品,由 Cloud RunEventarc 提供技術支援,可讓您進一步控管效能和擴充性,並進一步控管函式執行階段和來自 90 多個事件來源的觸發事件。

本程式碼研究室將逐步說明如何建立 Cloud Run 函式,以便回應 HTTP 呼叫,並由 Pub/Sub 訊息和 Cloud Audit Logs 觸發。

本程式碼研究室也使用自動更新基本映像檔功能,藉此為函式部署作業指定基本映像檔,--base-image自動更新 Cloud Run 的基本映像檔,可讓 Google 自動為基本映像檔的作業系統和語言執行階段元件提供安全性修補程式。您不必重新建構或重新部署服務,即可更新基礎映像檔。詳情請參閱自動更新基本映像檔

如果您想使用自動基礎映像檔更新功能,可以從本程式碼研究室的範例中移除 --base-image 標記。

課程內容

  • 概略說明 Cloud Run 函式,以及如何使用自動基礎映像檔更新功能。
  • 如何編寫可回應 HTTP 呼叫的函式。
  • 如何編寫回應 Pub/Sub 訊息的函式。
  • 如何編寫可回應 Cloud Storage 事件的函式。
  • 如何在兩個修訂版本之間拆分流量。
  • 如何透過最少的執行個體消除冷啟動。

2. 設定和需求

建立根資料夾

為所有範例建立根目錄。

mkdir crf-codelab
cd crf-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 函式

針對第一個函式,我們將建立一個已驗證的 Node.js 函式,用於回應 HTTP 要求。我們也將使用 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

這個指令會使用 Buildpacks,將函式原始碼轉換為可立即用於實際工作環境的容器映像檔。

請注意下列事項:

  • --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 函式

針對第二個函式,我們將建立 Python 函式,由發布至特定主題的 Pub/Sub 訊息觸發。

設定 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 函式支援多個函式修訂版本,可在不同修訂版本之間拆分流量,並將函式復原至先前的版本。

在這個步驟中,您將部署 2 個函式修訂版本,然後將流量以 50/50 的比例拆分給這 2 個版本。

建立

建立應用程式資料夾並前往該資料夾:

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 秒,模擬長時間初始化。它也包含 HelloWorld 函式,可回應 HTTP 呼叫:

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!")
}

部署

部署函式的第一個修訂版本,其中預設的最小例項值為零:

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. 恭喜!

恭喜您完成程式碼研究室!

涵蓋內容

  • 概略說明 Cloud Run 函式,以及如何使用自動基礎映像檔更新功能。
  • 如何編寫可回應 HTTP 呼叫的函式。
  • 如何編寫回應 Pub/Sub 訊息的函式。
  • 如何編寫可回應 Cloud Storage 事件的函式。
  • 如何在兩個修訂版本之間拆分流量。
  • 如何透過最少的執行個體消除冷啟動。