為了支持我們加速開發者在 Google Cloud 上的旅程的使命,我們建立了 Dev Signal:一個多代理系統,旨在透過自動化從發現到建立專家的路徑,將原始的社群訊號轉化為可靠的技術指導。

在本系列的前三部分中,我們透過建立其核心能力和本地驗證流程,奠定了必要的基礎:

第一部分中,我們透過模型上下文協議 (MCP) 對智能體的功能進行標準化,並將其連接到 Reddit 以發現趨勢,連接到 Google Cloud Docs 以提供技術基礎。在第二部分中,我們建立了一個多智能體架構,並整合了 Vertex AI 記憶庫,使系統能夠學習並持久化使用者在不同對話中的偏好。在第三部分中,我們使用專用測試執行器在本地驗證了完整的端到端生命週期,以確保研究、內容建立和基於雲端的記憶檢索完美同步。

如果您想直接查看程式碼,可以從這裡克隆儲存庫。

部署至 Cloud Run 及生產環境路徑

為了幫助您從本地原型過渡到生產服務,最後一部分將重點介紹如何使用Agent Starter Pack提供的基礎部署模式建立代理程式的生產骨幹網路。我們將實現雲端監控、資料完整性和長期狀態管理所需的關鍵結構元件。您將學習如何實作生產就緒部署所需的應用程式伺服器和輔助工具,然後再使用 Terraform 配置安全、可重複的基礎架構。

Dockerfile 用於打包代理程式的程式碼及其特定相依性(例如 Reddit MCP 工具所需的 Node.js),而 Terraform 則用於建立代理程式執行的平台。 Terraform 可自動建立 Artifact Registry、最小權限服務帳戶以及 Secret Manager 集成,以確保 API 金鑰的安全。

在本部分結束時,您將擁有一個部署在 Google Cloud Run 上的標準化應用程式框架,以及一個透過持續評估、CI/CD 和進階可觀測性來完善您的原型的路線圖。

生產實用程式和伺服器:建置系統主體

在本節中,您將實現雲端監控和長期狀態管理所需的結構元件。

  • 應用伺服器:初始化 FastAPI 伺服器並建立與 Vertex AI 記憶體庫的重要連線。

  • 實現遙測:啟用「代理追蹤」以了解內部推理過程。

應用程式伺服器

fast_api_app.py檔案是代理程式的關鍵入口點,它將核心邏輯轉換為生產環境的 FastAPI 伺服器,該伺服器充當系統的「主體」。部署到 Cloud Run 時,此伺服器至關重要,因為它提供必要的 Web 介面來監聽傳入的 HTTP 請求,並將它們分發給代理程式進行處理。除了提供基本服務之外,它最重要的作用是透過定義MEMORY_URI來建立與 Vertex AI 記憶體庫的連接,這使得 ADK 框架能夠在不同的生產會話之間持久化和檢索使用者偏好設定。此外,應用程式伺服器也會初始化生產級遙測功能,用於即時監控。

返回dev_signal_agent folder.

cd ..

將以下程式碼貼到dev_signal_agent/fast_api_app.py中:

import os
from fastapi import FastAPI
from google.adk.cli.fast_api import get_fast_api_app
from google.cloud import logging as cloud_logging
from vertexai import agent_engines
from dev_signal_agent.app_utils.env import init_environment

# --- Initialization & Secure Secret Retrieval ---
# We now unpack the SECRETS dictionary returned by our updated env.py
PROJECT_ID, MODEL_LOC, SERVICE_LOC, SECRETS = init_environment()
logger = cloud_logging.Client().logger(__name__)

# Access sensitive credentials from the SECRETS dictionary
# These keys stay in memory and are NOT injected into os.environ
REDDIT_CLIENT_ID = SECRETS.get("REDDIT_CLIENT_ID")
REDDIT_CLIENT_SECRET = SECRETS.get("REDDIT_CLIENT_SECRET")
REDDIT_USER_AGENT = SECRETS.get("REDDIT_USER_AGENT")
DK_API_KEY = SECRETS.get("DK_API_KEY")

# --- Configuration & Sessions ---
AGENT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Non-sensitive configuration uses environment variables
BUCKET = os.environ.get("AI_ASSETS_BUCKET")
USE_IN_MEMORY = os.environ.get("USE_IN_MEMORY_SESSION", "").lower() in ("true", "1")

# --- MEMORY BANK CONNECTION ---
def _get_memory_bank_uri():
    if USE_IN_MEMORY: return None, None
    # We use 'dev_signal_agent' as the display name for the Vertex AI memory bank
    name = os.environ.get("AGENT_ENGINE_MEMORY_BANK_NAME", "dev_signal_agent")
    existing = list(agent_engines.list(filter=f"display_name={name}"))
    ae = existing[0] if existing else agent_engines.create(display_name=name)
    uri = f"agentengine://{ae.resource_name}"
    print(f"DEBUG: Connecting to Memory Bank: {uri} (display_name={name})")
    return uri, uri

SESSION_URI, MEMORY_URI = _get_memory_bank_uri()

# --- Initialize FastAPI with ADK ---
app: FastAPI = get_fast_api_app(
    agents_dir=AGENT_DIR,
    web=True,
    artifact_service_uri=f"gs://{BUCKET}" if BUCKET else None,
    allow_origins=os.getenv("ALLOW_ORIGINS", "").split(",") if os.getenv("ALLOW_ORIGINS") else None,
    session_service_uri=SESSION_URI,
    memory_service_uri=MEMORY_URI, # <--- Connects the Memory Bank
    otel_to_cloud=True, # <--- Enables production telemetry
)

if __name__ == "__main__":
    import uvicorn
    # Standard Cloud Run port is 8080
    uvicorn.run(app, host="0.0.0.0", port=8080)

實施遙測

在生產環境中,了解代理人的推理過程至關重要。我們透過在應用程式伺服器中設定 `otel_to_cloud=True標誌,利用 Google ADK 的內建可觀測性功能。這個參數即可自動處理大部分偵測工作,並將「代理追蹤」直接匯出到 Google Cloud 控制台。這些追蹤以「可視化瀑布圖」的形式展現代理的運作過程,包括代理的思考過程、LLM 呼叫和 MCP 工具呼叫。

監測與針對性評估

必須了解的是,生產環境追蹤會進行抽樣,以平衡性能和成本。由於 Cloud Run 僅捕獲部分請求,因此並非每個使用者互動都會被記錄下來。

  • 系統追蹤(監控):用於分析「整體」行為,例如辨識延遲瓶頸或系統逾時。

  • 推理追蹤(評估):高品質的評估需要有針對性的追蹤捕獲。這意味著要專門針對某個測試案例呼叫代理,以便對特定請求進行全面且詳細的評估。

查看軌跡

若要查看追蹤記錄,請導覽至 Google Cloud 控制台中的追蹤資源管理器,並篩選您的服務(例如dev-signal )。點擊特定的追蹤 ID 會開啟甘特圖,您可以從中區分認知推理失敗(錯誤決策)和物理系統問題(超時)。

追蹤資源管理器視圖

如需了解進階配置,請參閱以下文件:

基礎架構即程式碼:設定安全的雲端資源

我們利用了代理入門包中以安全為先的設計理念所提供的基礎設施即程式碼模式。該入門包建立了專業平台,可在數秒內自動建立最小權限服務帳戶並實現強大的金鑰管理。

使用 Terraform 可確保您的整個 Google Cloud 環境(從 IAM 角色到 Secret Manager 版本)都以可重複、安全的程式碼定義。我們將基礎架構分解為以下邏輯區塊:

  • 資源和變數:定義代理程式使用的特定專案、區域和敏感 API 金鑰。

  • 核心基礎架構:啟用必要的 API 並配置私有工件註冊表來託管代理程式的容器鏡像。

  • 身分與存取管理 (IAM) :設定嚴格遵循最小權限原則的專用服務帳戶,以確保您的系統保持安全。

  • 金鑰管理:將 API 憑證安全地匯入 Google Secret Manager,以實現受保護的執行時間存取。

  • Cloud Run 配置:定義最終部署的容器環境、資源限制和自動金鑰注入。

若要開始配置,請返回專案根資料夾(dev-signal)並建立必要的部署目錄:

cd ..
mkdir deployment
cd deployment
mkdir terraform
cd terraform

Terraform 資源與變數

variables.tf檔案定義了部署的可設定參數,可讓您在不更改底層邏輯的情況下自訂基礎架構。它包含project_id 、部署region (預設為us-central1 )以及 Cloud Run 執行個體的service_name變數。此外,它還定義了一個secrets映射,用於將敏感的 API 憑證(例如 Reddit 和開發者知識庫金鑰)安全地導入 Google Secret Manager 以供執行時間存取。這種模組化方法確保您的生產環境在不同專案中保持可重現性、安全性和適應性。

將以下程式碼貼到deployment/terraform/variables.tf中:

variable "project_id" {
  description = "The Google Cloud Project ID"
  type        = string
}
variable "region" {
  description = "The Google Cloud region to deploy to"
  type        = string
  default     = "us-central1"
}
variable "service_name" {
  description = "The name of the Cloud Run service"
  type        = string
  default     = "dev-signal"
}
variable "secrets" {
  description = "A map of secret names and their values (e.g., REDDIT_CLIENT_ID, DK_API_KEY)"
  type        = map(string)
  default     = {}
}
variable "ai_assets_bucket" {
  description = "The GCS bucket for storing AI assets"
  type        = string
}

核心基礎架構邏輯

我們將基礎設施劃分為邏輯模組。以下是每個模組的功能:

1. 啟用 API :確保專案已啟動必要的服務(例如 Cloud Run、Vertex AI 等)。我們使用disable_on_destroy = false來防止 Terraform 檔案被銷毀時意外遺失資料。

將以下程式碼貼到deployment/terraform/main.tf中:

resource "google_project_service" "services" {
  project = var.project_id
  for_each = toset([
    "run.googleapis.com",
    "artifactregistry.googleapis.com",
    "cloudbuild.googleapis.com",
    "aiplatform.googleapis.com",
    "secretmanager.googleapis.com",
    "logging.googleapis.com"
  ])
  service            = each.key
  disable_on_destroy = false
}

2. Artifact Registry :建立一個私有的 Docker 映像倉庫來儲存我們代理程式的容器映像。

resource "google_artifact_registry_repository" "repo" {
  location      = var.region
  project       = var.project_id
  repository_id = "dev-signal-repo"
  description   = "Docker repository for Dev Signal Agent"
  format        = "DOCKER"
  depends_on    = [google_project_service.services]
}

3. 服務帳號和身分與存取管理 (IAM):遵循最小權限原則- 這是至關重要的安全步驟。根據最小權限原則,我們避免使用預設的運算服務帳號,而是配置一個專用的使用者管理服務帳號 ( dev-signal-sa )。透過將其指定為 Cloud Run 服務身份,我們可以僅授予其必要的最低權限,具體包括roles/aiplatform.userroles/logging.logWriterroles/storage.objectAdmin 。這種細粒度的存取控制確保代理程式擁有與 Vertex AI 和 Cloud Storage 互動所需的精確權限,而不會過度授予對其他敏感雲端資源的存取權限,從而顯著降低帳號被盜用的潛在影響。了解更多安全使用服務帳號的最佳實務

resource "google_service_account" "agent_sa" {
  project      = var.project_id
  account_id   = "${var.service_name}-sa"
  display_name = "Dev Signal Agent Service Account"
}

4. 金鑰管理:此功能可安全地管理您的 API 金鑰。它會在 Google Secret Manager 中建立金鑰,並授予代理程式的服務帳號在執行時存取這些金鑰的權限。

resource "google_secret_manager_secret" "agent_secrets" {
  project  = var.project_id
  for_each = toset(keys(var.secrets))
  secret_id = each.key
  replication {
    auto {}
  }
  depends_on = [google_project_service.services]
}
resource "google_secret_manager_secret_version" "agent_secrets_version" {
  for_each    = toset(keys(var.secrets))
  secret      = google_secret_manager_secret.agent_secrets[each.key].id
  secret_data = var.secrets[each.key]
}
resource "google_secret_manager_secret_iam_member" "secret_accessor" {
  project  = var.project_id
  for_each = toset(keys(var.secrets))
  secret_id = google_secret_manager_secret.agent_secrets[each.key].id
  role      = "roles/secretmanager.secretAccessor"
  member    = "serviceAccount:${google_service_account.agent_sa.email}"
}

5. 雲端執行配置:

安全最佳實務:為了滿足生產環境的安全標準,我們的main.tf授予服務帳戶secretmanager.secretAccessor角色。然後,我們的 Python 應用程式使用Secret Manager SDK在執行時將這些憑證直接載入到本機記憶體中,確保它們永遠不會觸及容器的環境配置。

# 6. Cloud Run Service Deployment
resource "google_cloud_run_v2_service" "default" {
  project  = var.project_id
  name     = var.service_name
  location = var.region
  ingress  = "INGRESS_TRAFFIC_ALL"

  template {
    service_account = google_service_account.agent_sa.email

    containers {
      image = "us-docker.pkg.dev/cloudrun/container/hello" # Placeholder until first build

      env {
        name  = "GOOGLE_CLOUD_PROJECT"
        value = var.project_id
      }
      env {
        name  = "GOOGLE_CLOUD_LOCATION"
        value = "global"
      }
      env {
        name  = "GOOGLE_GENAI_USE_VERTEXAI"
        value = "True"
      }
      env {
        name  = "AI_ASSETS_BUCKET"
        value = var.ai_assets_bucket
      }

      resources {
        limits = {
          cpu    = "1"
          memory = "2Gi"
        }
      }
    }
  }

  traffic {
    type    = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST"
    percent = 100
  }

提供基礎設施

在部署程式碼之前,我們需要設定我們剛剛定義的 Google Cloud 基礎架構。

初始化 Terraform :此操作會下載必要的提供者外掛程式。請在deployment/terraform資料夾中執行此命令:

terraform init

建立變數檔案

將此程式碼貼到deployment/terraform/terraform.tfvars中,並使用您的專案詳細資料和金鑰進行更新。

project_id       = "your-project-id"
region           = "us-central1"
service_name     = "dev-signal"
ai_assets_bucket = "your-bucket-name"
secrets = {
  REDDIT_CLIENT_ID     = "your_client_id"
  REDDIT_CLIENT_SECRET = "your_client_secret"
  REDDIT_USER_AGENT    = "your_user_agent"
  DK_API_KEY           = "your_dk_api_key"
}

計劃配置:這允許您在應用更改之前對其進行預覽。請在deployment/terraform資料夾中執行以下命令:

terraform plan -out=plan.tfplan

應用設定:審核並確認方案符合預期後,執行以下命令:

terraform apply plan.tfplan

部署:容器化和雲端建置管道

在建造過程的最後階段,我們將代理的「身體」和「大腦」打包到一個可移植的、可用於生產環境的容器中。這確保了從 Python 邏輯到 Reddit MCP 工具所需的 Node.js 環境的每個元件都與其所有依賴項打包在一起。

我們使用Dockerfile定義此環境,並使用Makefile編排部署管線。當您觸發部署時, Google Cloud Build會讀取您的本機原始碼,根據 Dockerfile 建立容器映像,並將其儲存在 Terraform 先前建立的私人 Artifact Registry 中。最後,管線會自動更新您的 Cloud Run 服務,使其使用此新鏡像來處理流量,從而完成從本機程式碼到安全執行的雲端工作負載的部署過程。

將此程式碼貼到dev-signal/Dockerfile中:

FROM python:3.12-slim

# Install Node.js and npm for MCP tools (like reddit-mcp)
RUN apt-get update && apt-get install -y \
    curl \
    && curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
    && apt-get install -y nodejs \
    && npm install -g reddit-mcp \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

RUN pip install --no-cache-dir uv==0.8.13

WORKDIR /code

COPY ./pyproject.toml ./README.md ./uv.lock* ./
COPY ./dev_signal_agent ./dev_signal_agent

RUN uv sync --frozen

EXPOSE 8080

CMD ["uv", "run", "uvicorn", "dev_signal_agent.fast_api_app:app", "--host", "0.0.0.0", "--port", "8080"]

Makefile 檔案可自動執行建置和部署操作。

將此程式碼貼到dev-signal/Makefile中:

PROJECT_ID ?= $(shell gcloud config get-value project)
REGION     ?= us-central1
IMAGE_REPO ?= dev-signal-repo
IMAGE := $(REGION)-docker.pkg.dev/$(PROJECT_ID)/$(IMAGE_REPO)/agent:latest

# Deploy via Cloud Build & Container
docker-deploy:
    @echo "? Building and deploying to $(PROJECT_ID) via Cloud Build..."
    gcloud builds submit --tag $(IMAGE) --project $(PROJECT_ID) .
    gcloud run services update dev-signal \
        --image $(IMAGE) \
        --region $(REGION) \
        --project $(PROJECT_ID) \
        --labels dev-tutorial=dev-signal-agent

部署應用程式

現在基礎設施已經準備就緒,我們可以建置和部署應用程式程式碼了。

在專案根目錄下執行以下命令:

make docker-deploy

執行這段程式碼會發生什麼事?

  1. 建置:Google Cloud Build 會取得您的本機程式碼和Dockerfile ,建立容器映像,並將其儲存在 Artifact Registry 中。

  2. 部署:它將 Terraform 中定義的 Cloud Run 服務更新為使用此新映像。

部署完成後,您應該會收到類似這樣的訊息:

Service [dev-signal] revision [dev-signal...] has been deployed and is serving 100 percent of traffic.

Service URL: https://dev-signal-...-.us-central1.run.app

驗證:存取和測試已部署的代理

由於生產服務預設是私有的,本節介紹如何授予權限並安全地存取代理程式。

管理 IAM 權限:向授權使用者授予必要的run.invoker角色。

透過 Cloud Run 代理程式進行安全存取:使用gcloud代理程式與您的即時服務互動。

授予使用者權限

在呼叫此服務之前,您必須為您的 Google 帳號授予此特定服務的roles/run.invoker角色。執行以下命令:

gcloud run services add-iam-policy-binding dev-signal \
  --member="user:$(gcloud config get-value account)" \
  --role="roles/run.invoker" \
  --region=us-central1 \
  --project=$(gcloud config get-value project)

啟動代理

現在,您可以透過代理伺服器安全地存取您的私人服務:

gcloud run services proxy dev-signal \
  --region us-central1 \
  --project $(gcloud config get-value project)

造訪http://localhost:8080即可與已部署的代理程式進行聊天!請參閱本系列文章的第三部分,以了解可能的測試場景。

概括

恭喜!您已成功建置Dev Signal

我們報導的內容包括:

  1. 工具(MCP) :您使用模型上下文協定將您的代理連接到RedditGoogle Docs本機映像產生器

  2. 架構:您實作了一個根協調器來管理專門的代理(掃描器、專家、繪圖器)。

  3. 記憶體:您整合了Vertex AI 記憶體庫,使您的代理程式能夠在會話之間保持長期持久性。

  4. 生產環境:您使用Terraform將整個堆疊部署到Google Cloud Run,以實現安全、可重複的基礎架構。

現在,您已經具備在 Google Cloud 上建立複雜、有狀態 AI 應用的堅實基礎。


原文出處:https://dev.to/googleai/deploying-a-multi-agent-system-with-terraform-and-cloud-run-2a9c


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝12   💬4   ❤️1
464
🥈
alicec
📝1   ❤️2
87
#4
我愛JS
💬1  
3
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
📢 贊助商廣告 · 我要刊登