為第 2 代函式設定直接虛擬私有雲輸出流量

透過直接虛擬私有雲輸出,您可以將 Cloud Run 函式 (第 2 代) 的流量直接轉送至虛擬私有雲網路。

限制

事前準備

  • 啟用 Cloud Functions API。
  • 安裝 Google Cloud CLI,然後執行 gcloud init 初始化。
  • gcloud 元件更新至 545.0.0 以上版本:

    gcloud components update
    

  • 如果專案中沒有虛擬私有雲網路,請建立一個

  • 選用:如果函式需要使用內部 IP 位址存取 Google API 和服務,請在用於直接虛擬私有雲端輸出流量的子網路上啟用私人 Google 存取權。

設定 IAM 權限

如要授權直接 VPC 輸出,請要求管理員將 Cloud Run 叫用者 (roles/run.invoker) 角色授予函式的服務帳戶。

請使用下列其中一種方法,確保 Cloud Run 可以存取虛擬私有雲網路:

  • Cloud Run 服務代理程式角色:根據預設,Cloud Run 服務代理程式具有Cloud Run 服務代理程式角色 (roles/run.serviceAgent),其中包含必要權限。

  • 自訂權限:如要更精細地控管,請在專案中授予 Cloud Run 服務代理程式下列額外權限:

    • compute.networks.get
    • compute.subnetworks.get
    • 專案或特定子網路的 compute.subnetworks.use 權限
    • compute.addresses.get
    • compute.addresses.list
    • compute.addresses.create (僅適用於使用外部 IPv6 的雙重堆疊子網路)
    • compute.addresses.delete (僅限使用外部 IPv6 的雙重堆疊子網路)
    • compute.addresses.createInternal
    • compute.addresses.deleteInternal
    • compute.regionOperations.get
  • Compute Network User 角色:如果您未使用預設的 Cloud Run Service Agent 角色或自訂權限,請在 Cloud Run Service Agent 服務帳戶中,授予Compute Network User 角色 (roles/compute.networkUser)。具有外部 IPv6 的子網路也需要 Compute Public IP Admin 角色 (roles/compute.publicIpAdmin)

    舉例來說,如要授予 Compute 網路使用者角色,請執行下列指令:

    gcloud projects add-iam-policy-binding PROJECT_ID \
    --member "serviceAccount:service-PROJECT_NUMBER@serverless-robot-prod.iam.gserviceaccount.com" \
    --role "roles/compute.networkUser"

    更改下列內容:

    • PROJECT_ID:專案 ID。
    • PROJECT_NUMBER:您部署 Cloud Run 函式的專案編號。

設定直接虛擬私有雲輸出

為新函式或現有第 2 代函式設定直接虛擬私有雲輸出流量。

gcloud

  1. 如要在部署函式時設定直接虛擬私有雲輸出,請使用 gcloud beta functions deploy 指令,並搭配網路設定的標記。

    gcloud beta functions deploy FUNCTION_NAME \
        --source . \
        --runtime RUNTIME \
        --trigger-http \
        --region REGION \
        --network=NETWORK \
        --subnet=SUBNET \
        --network-tags=NETWORK_TAG_NAMES \
        --direct-vpc-egress=EGRESS_SETTING
    

    更改下列內容:

    • FUNCTION_NAME:函式名稱。
    • RUNTIME:函式的執行階段,例如 nodejs20
    • REGION:部署函式的區域。
    • 選用:NETWORK,這是您虛擬私有雲網路的名稱。指定虛擬私有雲網路或子網路,或同時指定兩者。如果您只指定網路,子網路會使用與網路相同的名稱。
    • 選用:SUBNET,並將其替換為子網路名稱。指定虛擬私有雲網路或子網路,或兩者皆指定。如果您只指定網路,子網路會使用與網路相同的名稱。您可以在同一個子網路上部署或執行多個函式。
    • 選用:NETWORK_TAG_NAMES,並以半形逗號分隔要與函式建立關聯的網路標記名稱。每個函式可以有不同的網路標記,例如 network-tag-2
    • EGRESS_SETTING,並提供輸出設定值
      • all:預設值。透過虛擬私有雲網路傳送所有輸出流量。
      • private-ranges-only:只透過虛擬私有雲網路將流量傳送至內部位址。
  2. 選用:如要從函式中移除所有 Direct VPC 輸出設定,請使用 --clear-network--clear-network-tags 旗標重新部署函式。

Terraform

如要瞭解如何套用或移除 Terraform 設定,請參閱「基本 Terraform 指令」。

如要設定直接虛擬私有雲輸出流量,請使用 google-beta Terraform 供應商。

以 Cloud Run 函式 (第 2 代) 直接虛擬私有雲輸出範例為起點,更新下列欄位:

  • service_config.network:虛擬私有雲網路的名稱。
  • service_config.subnetwork:虛擬私有雲子網路的名稱。
  • service_config.direct_vpc_egress:要傳送至虛擬私有雲網路的流量。VPC_EGRESS_ALL_TRAFFIC 透過虛擬私有雲網路傳送所有輸出流量。VPC_EGRESS_PRIVATE_RANGES_ONLY 只會將流量傳送至虛擬私有雲網路的私人 IP 位址範圍。

範例:從函式呼叫內部服務

這個範例說明如何建立內部 Cloud Run 服務,然後從使用直接虛擬私有雲輸出流量的 Cloud Run 函式 (第 2 代) 函式呼叫該服務。

建立內部後端服務

  1. 為後端服務建立新目錄,然後切換至該目錄:

    mkdir backend-service
    cd backend-service
    
  2. 建立 package.json 檔案,並加入以下內容:

    {
        "name": "backend-service",
        "version": "1.0.0",
        "description": "",
        "scripts": {
            "start": "node index.js"
        },
        "dependencies": {
            "express": "^4.18.1"
        }
    }
    
  3. 建立 index.js 檔案,並加入以下內容:

    const express = require('express');
    const app = express();
    
    app.get('/', (req, res) => {
        res.send("hello world");
    });
    
    const port = parseInt(process.env.PORT) || 8080;
    app.listen(port, () => {
        console.log(`helloworld: listening on port ${port}`);
    });
    
  4. 將服務部署至 Cloud Run,並使用內部 Ingress:

    gcloud run deploy backend \
        --source . \
        --no-allow-unauthenticated \
        --region=REGION \
        --ingress internal
    

    REGION 替換為您的區域,例如 us-west1

  5. 儲存新服務的網址。下一節會用到這項資訊。

建立及部署函式

  1. 為函式建立新目錄,然後切換至該目錄:

    cd ..
    mkdir dvpc-function
    cd dvpc-function
    
  2. 建立 package.json 檔案,並加入以下內容:

    {
      "name": "sample-http",
      "version": "0.0.1",
      "dependencies": {
        "axios": "0.21.1",
        "@google-cloud/functions-framework": "^3.0.0"
      }
    }
    
  3. 建立 index.js 檔案,並加入以下內容。這段程式碼會向內部後端服務發出經過驗證的要求。

    const axios = require('axios');
    const functions = require('@google-cloud/functions-framework');
    
    const callVPCService = async (req, res) => {
      const backendUrl = process.env.BACKEND_URL;
    
      if (!backendUrl) {
        console.error('BACKEND_URL environment variable not set.');
        res.status(500).send('BACKEND_URL not configured.');
        return;
      }
    
      try {
        const metadataServerURL = 'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=';
        const tokenUrl = metadataServerURL + backendUrl;
    
        const tokenResponse = await axios.get(tokenUrl, {
          headers: {
            'Metadata-Flavor': 'Google',
          },
        });
        const token = tokenResponse.data;
    
        const response = await axios.get(backendUrl, {
          headers: {
            Authorization: `bearer ${token}`,
          },
    });
    
    res.status(200).send(`Response from backend: ${response.data}`);
      } catch (error) {
        console.error(`Error calling backend service: ${error.message}`);
        res.status(500).send(`Error calling backend: ${error.message}`);
      }
    };
    
    functions.http('callVPCService', callVPCService);
    
  4. 部署函式並設定直接虛擬私有雲 egress,將所有流量轉送至預設虛擬私有雲網路:

    gcloud beta functions deploy my-2ndgen-function \
      --source . \
      --runtime nodejs20 \
      --trigger-http \
      --entry-point callVPCService \
      --network=default \
      --subnet=default \
      --direct-vpc-egress=all \
      --region=REGION \
      --allow-unauthenticated \
      --set-env-vars BACKEND_URL=BACKEND_URL
    

    更改下列內容:

    • REGION:部署後端服務的區域。
    • BACKEND_URL:您建立的後端服務網址。
  5. 函式部署完成後,請前往函式網址來叫用函式。函式會呼叫內部後端服務,並傳回其回應。

後續步驟