iT邦幫忙

2026 iThome 鐵人賽

DAY 14
0
Build on Google AI

將考國際證照的應用程式變成開源系列 第 23

使用 API 閘道部署和保護無伺服器 API:挑戰實驗室

  • 分享至 

  • xImage
  •  

使用 API 閘道部署和保護無伺服器 API:挑戰實驗室
Deploy and Secure Serverless APIs with API Gateway: Challenge Lab

https://www.skills.google/games/7399/labs/45439

整個流程整理成一份「學習筆記」。包含完整的 CLI 指令,還加入了每個步驟背後的架構意義與除錯小提醒。


📝 學習筆記:使用 API Gateway 部署與保護 Serverless API

🏗️ 架構總覽

本實作的資料流與架構如下:
[用戶端 (Client)] ➡️ [API Gateway] ➡️ [Cloud Run Function (後端邏輯)] ➡️ [Pub/Sub (事件驅動/訊息發布)]


步驟 0:事前準備 (設定環境變數)

說明: 在雲端環境操作時,將常用的專案 ID、編號與區域設為環境變數,可以大幅減少手動輸入錯誤並提升指令的重複使用性。

# 取得當前專案的 Project ID 和 Project Number
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")

# 設定本次 Lab 的預設 Region
export REGION="us-east1"

# 確保啟用本架構所需的所有 Google Cloud APIs
gcloud services enable \
  apigateway.googleapis.com \
  servicemanagement.googleapis.com \
  servicecontrol.googleapis.com \
  run.googleapis.com \
  cloudfunctions.googleapis.com


步驟 1:建立基礎 Cloud Run Function (Task 1)

說明: 建立一個 Node.js 22 的後端函式。這是我們整個架構的運算核心。

💡 避坑提示: Node.js 函式需要 @google-cloud/functions-framework 才能正確啟動,務必在 package.jsondependencies 中宣告,否則會發生 Container Healthcheck 失敗的錯誤。

# 建立並進入工作目錄
mkdir ~/my_api_backend && cd ~/my_api_backend

# 1. 建立 package.json (宣告必要套件)
cat <<EOF > package.json
{
  "name": "gcfunction",
  "version": "1.0.0",
  "main": "index.js",
  "dependencies": {
    "@google-cloud/functions-framework": "^3.0.0"
  }
}
EOF

# 2. 建立 index.js (撰寫回傳 Hello World 的基礎邏輯)
cat <<EOF > index.js
const functions = require('@google-cloud/functions-framework');
functions.http('helloHttp', (req, res) => {
  res.status(200).send("Hello World!");
});
EOF

# 3. 部署 Cloud Run Function (2nd gen)
# 參數說明:允許未經驗證的呼叫 (--allow-unauthenticated),由 HTTP 觸發 (--trigger-http)
gcloud functions deploy gcfunction \
  --gen2 \
  --region=$REGION \
  --runtime=nodejs22 \
  --source=. \
  --entry-point=helloHttp \
  --trigger-http \
  --allow-unauthenticated

# 4. 提取部署後的真實 Function URL (供下一步 API Gateway 使用)
export FUNCTION_URL=$(gcloud functions describe gcfunction --gen2 --region=$REGION --format="value(serviceConfig.uri)")
echo "後端 Function URL 為: $FUNCTION_URL"


步驟 2:建立 API Gateway 作為代理 (Task 2)

說明: 我們不希望用戶端直接呼叫 Function URL,而是透過 API Gateway 來統一管理、路由與保護 API。這裡需要撰寫一份 OpenAPI (Swagger) 規格書來定義路由。

cd ~

# 1. 建立 OpenAPI 規格檔 (openapispec.yaml)
# 注意 x-google-backend.address 這裡會自動代入剛才取得的 $FUNCTION_URL
cat <<EOF > openapispec.yaml
swagger: '2.0'
info:
  title: gcfunction API
  description: Sample API on API Gateway with a Google Cloud Run functions backend
  version: 1.0.0
schemes:
  - https
produces:
  - application/json
x-google-backend:
  address: $FUNCTION_URL
paths:
  /gcfunction:
    get:
      summary: gcfunction
      operationId: gcfunction
      responses:
        '200':
          description: A successful response
          schema:
            type: string
EOF

# 2. 建立 API 實體 (定義這是一個 API 服務)
gcloud api-gateway apis create gcfunction-api \
  --display-name="gcfunction API" \
  --project=$PROJECT_ID

# 3. 建立 API Config (將 OpenAPI 規格書與服務帳戶綁定)
gcloud api-gateway api-configs create gcfunction-api \
  --api=gcfunction-api \
  --openapi-spec=openapispec.yaml \
  --project=$PROJECT_ID \
  --backend-auth-service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com

# 4. 部署 API Gateway (將 Config 實例化到特定 Region,此步驟需耗時數分鐘)
gcloud api-gateway gateways create gcfunction-api \
  --api=gcfunction-api \
  --api-config=gcfunction-api \
  --location=$REGION \
  --project=$PROJECT_ID


步驟 3:整合 Pub/Sub 與端對端測試 (Task 3)

說明: 在實際業務場景中,API 被呼叫後通常會觸發其他非同步事件。這裡我們將 Function 升級,讓它在收到請求時,推送一筆訊息到 Pub/Sub Topic。

# 1. 建立 Pub/Sub Topic (訊息主題) 與預設的 Subscription (訂閱者)
gcloud pubsub topics create demo-topic
gcloud pubsub subscriptions create demo-topic-sub --topic=demo-topic

# 回到後端程式碼目錄
cd ~/my_api_backend

# 2. 更新 package.json (加入 Pub/Sub SDK 依賴)
cat <<EOF > package.json
{
  "dependencies": {
    "@google-cloud/functions-framework": "^3.0.0",
    "@google-cloud/pubsub": "^3.4.1"
  }
}
EOF

# 3. 更新 index.js (加入推送訊息到 demo-topic 的邏輯)
cat <<EOF > index.js
const {PubSub} = require('@google-cloud/pubsub');
const pubsub = new PubSub();
const topic = pubsub.topic('demo-topic');
const functions = require('@google-cloud/functions-framework');

exports.helloHttp = functions.http('helloHttp', (req, res) => {
  // 發送訊息到 Pub/Sub
  topic.publishMessage({data: Buffer.from('Hello from Cloud Run functions!')});
  res.status(200).send("Message sent to Topic demo-topic!");
});
EOF

# 4. 重新部署 Cloud Run Function (套用新程式碼)
gcloud functions deploy gcfunction \
  --gen2 \
  --region=$REGION \
  --runtime=nodejs22 \
  --source=. \
  --entry-point=helloHttp \
  --trigger-http \
  --allow-unauthenticated

# ==========================================
# 🎯 最終測試與驗證
# ==========================================

# 取得 API Gateway 的公開網址
export GATEWAY_URL=$(gcloud api-gateway gateways describe gcfunction-api --location=$REGION --format="value(defaultHostname)")
echo "API Gateway URL 為: https://$GATEWAY_URL/gcfunction"

# 透過 API Gateway 觸發整個資料流
curl -s https://$GATEWAY_URL/gcfunction

# (進階驗證) 去 Pub/Sub 檢查是否真的有收到剛才推送的訊息
gcloud pubsub subscriptions pull demo-topic-sub --auto-ack

將這份筆記存下來,未來如果需要架設一套「API 閘道 + 無伺服器運算 + 非同步事件傳遞」的系統,只要照著這個骨架稍作修改!


上一篇
發布/訂閱:快速啟動 - 控制台
下一篇
IAM 自訂角色
系列文
將考國際證照的應用程式變成開源27
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言