使用 Terraform 预配代理

您可以使用 Terraform 以声明方式预配和管理 Agent Runtime 实例。使用 Terraform 部署代理时,您可以使用官方 Google Cloud Terraform 提供程序(GA 提供程序Beta 提供程序)管理 google_vertex_ai_reasoning_engine 资源

本页上的说明对应于 使用 Agent Runtime 部署容器化代理 Codelab 中介绍的示例容器化代理实现。

前提条件

在使用 Terraform 部署代理之前,请确保您已完成以下设置:

  1. 安装 Terraform(版本 1.5.0 或更高版本),并查看 HashiCorp Terraform 注册表中有关 google_vertex_ai_reasoning_engine 资源(正式版提供程序Beta 版提供程序)的官方文档。
  2. 设置 Google Cloud 环境,并启用 Vertex AI API (aiplatform.googleapis.com)、Artifact Registry API (artifactregistry.googleapis.com) 和 Cloud Build API (cloudbuild.googleapis.com)。
  3. 使用 Google Cloud 凭据对本地环境进行身份验证:

    gcloud auth application-default login
  4. 为了使应用代码与基础设施管理分开,请将代理工作区整理为专用应用目录和 Terraform 目录:

    weather-agent-byoc/
    ├── main.py                # Python ADK agent entrypoint
    ├── requirements.txt       # Python dependencies
    ├── Dockerfile             # Container build definition
    └── terraform/             # Terraform configuration directory
        ├── main.tf            # Agent Runtime resources and specifications
        ├── variables.tf       # Project, region, and container variables
        └── outputs.tf         # Resource name outputs
    
    • 应用文件main.pyrequirements.txtDockerfile):包含代理逻辑、Web 框架封装容器(例如 FastAPI 或 ADK 应用)、Python 依赖项和容器构建说明。

    • Terraform 目录 (terraform/):包含用于配置资源的所有 Terraform 配置文件:

      • variables.tf:声明输入变量,例如 project_idlocationrepository_nameimage_tag
      • main.tf:声明提供方设置、局部变量、IAM 角色绑定和 google_vertex_ai_reasoning_engine 资源规范。
      • outputs.tf:在部署后导出已配置的资源属性,例如 Agent Runtime ID 和完整资源名称。
  5. 根据执行部署的人员授予相应的 IAM 角色:

    • 执行 terraform apply 和本地 build 命令的人工开发者或 CI/CD 服务账号。

    • 系统管理的 Agent Runtime Service Agent (service-<var>PROJECT_NUMBER</var>@gcp-sa-aiplatform-re.iam.gserviceaccount.com)。

准备部署

Terraform 支持以下 Agent Runtime 部署路径:

  • 从预构建的容器映像进行部署:预先构建容器映像并将其推送到 Artifact Registry ({region}-docker.pkg.dev/...),然后使用 container_spec 部署该映像。如果您需要完全控制容器构建流程、自定义基础映像或降低部署延迟时间,请使用此方法。
  • 从源文件或 Dockerfile 部署:直接从本地源文件或 Dockerfile 部署代理。Agent Runtime 会自动构建和预配容器映像,无需手动管理映像。
  • 使用 Python 软件包规范进行部署:使用在 Cloud Storage 中暂存的 (package_spec) 进行部署。Agent Runtime 会自动构建和预配容器映像,无需手动管理映像。

从预构建的容器映像进行部署

如果您预先构建容器映像并将其推送到 Artifact Registry(例如,为了包含自定义系统库、优化冷启动性能或强制执行组织映像构建控制),则可以使用 container_spec 进行部署。如需详细了解映像要求,请参阅从容器映像进行部署

容器映像必须存储在 Artifact Registry ({LOCATION}-docker.pkg.dev/{PROJECT_ID}/{REPOSITORY}/{IMAGE}:{TAG}) 中,侦听端口 8080(或 container_spec 中指定的自定义端口),并符合运行时合同

  1. 在本地构建容器映像并将其推送到 Artifact Registry 代码库:

    # 1. Authenticate Docker with your Artifact Registry region
    gcloud auth configure-docker us-central1-docker.pkg.dev
    # 2. Build the container image from your application root directory
    cd weather-agent-byoc
    docker build -t us-central1-docker.pkg.dev/PROJECT_ID/agents-repo/weather-agent-image:latest .
    # 3. Push the container image to Artifact Registry
    docker push us-central1-docker.pkg.dev/PROJECT_ID/agents-repo/weather-agent-image:latest
  2. 配置预构建的容器映像以进行 Terraform 部署。以下配置演示了如何通过在 terraform/ 目录中创建 variables.tfmain.tfoutputs.tf 文件来部署托管在 Artifact Registry 中的预构建容器映像:

    输入变量 (terraform/variables.tf)

    variable "project_id" {
      type        = string
      description = "The Google Cloud Project ID"
    }
    
    variable "project_number" {
      type        = string
      description = "The Google Cloud Project Number"
    }
    
    variable "location" {
      type        = string
      default     = "us-central1"
      description = "The region to deploy Agent Runtime"
    }
    
    variable "repository_name" {
      type        = string
      default     = "agents-repo"
      description = "The Artifact Registry repository name"
    }
    
    variable "image_tag" {
      type        = string
      default     = "latest"
      description = "The tag of the container image to deploy"
    }
    

    资源规范 (terraform/main.tf)

    terraform {
      required_providers {
        google = {
          source  = "hashicorp/google"
          version = ">= 5.28.0"
        }
      }
    }
    
    provider "google" {
      project = var.project_id
      region  = var.location
    }
    
    locals {
      class_methods = [
        { "name" = "get_session", "api_mode" = "" },
        { "name" = "list_sessions", "api_mode" = "" },
        { "name" = "create_session", "api_mode" = "" },
        { "name" = "delete_session", "api_mode" = "" },
        { "name" = "async_get_session", "api_mode" = "async" },
        { "name" = "async_list_sessions", "api_mode" = "async" },
        { "name" = "async_create_session", "api_mode" = "async" },
        { "name" = "async_delete_session", "api_mode" = "async" },
        { "name" = "async_add_session_to_memory", "api_mode" = "async" },
        { "name" = "async_search_memory", "api_mode" = "async" },
        { "name" = "stream_query", "api_mode" = "stream" },
        { "name" = "async_stream_query", "api_mode" = "async_stream" },
        { "name" = "streaming_agent_run_with_events", "api_mode" = "async_stream" }
      ]
    }
    
    # Grant Artifact Registry Reader permission to the Agent Runtime Service Agent
    resource "google_project_iam_member" "re_service_agent_ar_reader" {
      project = var.project_id
      role    = "roles/artifactregistry.reader"
      member  = "serviceAccount:service-${var.project_number}@gcp-sa-aiplatform-re.iam.gserviceaccount.com"
    }
    
    # Define the Agent Runtime resource with BYOC container configuration
    resource "google_vertex_ai_reasoning_engine" "byoc_weather_agent" {
      display_name = "byoc_weather_agent_tf"
      description  = "BYOC weather agent deployed using Terraform"
      project      = var.project_id
      location     = var.location
    
      spec {
        agent_framework = "google-adk"
    
        container_spec {
          image_uri = "${var.location}-docker.pkg.dev/${var.project_id}/${var.repository_name}/weather-agent-image:${var.image_tag}"
        }
    
        class_methods = jsonencode(local.class_methods)
      }
    
      # Ensure service agent permission exists before provisioning to prevent IMAGE_PULL_BACKOFF
      depends_on = [google_project_iam_member.re_service_agent_ar_reader]
    }
    

    资源输出 (terraform/outputs.tf)

    output "reasoning_engine_id" {
      value       = google_vertex_ai_reasoning_engine.byoc_weather_agent.id
      description = "The ID of the deployed Agent Runtime instance"
    }
    
    output "reasoning_engine_resource_name" {
      value       = google_vertex_ai_reasoning_engine.byoc_weather_agent.name
      description = "The resource name of the deployed Agent Runtime instance"
    }
    

从 Dockerfile 或源代码库部署

从 Dockerfile 进行部署时,请在 source_code_spec 中指定您的源归档,并设置一个空的 image_spec {} 块,以指示 Agent Runtime 使用您的 Dockerfile 构建容器映像。根据 Dockerfile 构建的容器必须遵守运行时合同

如需详细了解部署的工作方式,请参阅从 Dockerfile 部署从源文件部署

  1. 将应用代码 (main.py)、Python 依赖项清单 (requirements.txt) 和容器 build 说明 (Dockerfile) 压缩到 gzip 压缩的 tar 文件归档中。

  2. 从应用根目录运行以下命令(示例使用根目录 weather-agent-byoc/ 和 tar 文件归档 weather_agent_source.tar.gz):

    cd weather-agent-byoc
    tar -czvf terraform/weather_agent_source.tar.gz main.py requirements.txt Dockerfile
  3. terraform/ 目录中创建 variables.tfmain.tfoutputs.tf 文件:

    输入变量 (terraform/variables.tf)
    variable "project_id" {
      type        = string
      description = "The Google Cloud Project ID"
    }
    
    variable "location" {
      type        = string
      default     = "us-central1"
      description = "The region to deploy Agent Runtime"
    }
    

    资源规范 (terraform/main.tf)

    terraform {
      required_providers {
        google = {
          source  = "hashicorp/google"
          version = ">= 5.28.0"
        }
      }
    }
    
    provider "google" {
      project = var.project_id
      region  = var.location
    }
    
    resource "google_vertex_ai_reasoning_engine" "dockerfile_agent" {
      display_name = "dockerfile_weather_agent_tf"
      description  = "BYOC weather agent deployed using Dockerfile"
      project      = var.project_id
      location     = var.location
    
      spec {
        agent_framework = "google-adk"
    
        source_code_spec {
          inline_source {
            source_archive = filebase64("weather_agent_source.tar.gz")
          }
    
          # Empty image_spec instructs the runtime to build using the Dockerfile
          image_spec {}
        }
    
        class_methods = jsonencode([
          { "name" = "get_session", "api_mode" = "" },
          { "name" = "list_sessions", "api_mode" = "" },
          { "name" = "create_session", "api_mode" = "" },
          { "name" = "delete_session", "api_mode" = "" },
          { "name" = "async_get_session", "api_mode" = "async" },
          { "name" = "async_list_sessions", "api_mode" = "async" },
          { "name" = "async_create_session", "api_mode" = "async" },
          { "name" = "async_delete_session", "api_mode" = "async" },
          { "name" = "async_add_session_to_memory", "api_mode" = "async" },
          { "name" = "async_search_memory", "api_mode" = "async" },
          { "name" = "stream_query", "api_mode" = "stream" },
          { "name" = "async_stream_query", "api_mode" = "async_stream" },
          { "name" = "streaming_agent_run_with_events", "api_mode" = "async_stream" }
        ])
      }
    }
    

    资源输出 (terraform/outputs.tf)

    output "dockerfile_agent_id" {
      value       = google_vertex_ai_reasoning_engine.dockerfile_agent.id
      description = "Resource ID of the deployed Dockerfile agent"
    }
    

使用 Python 软件包规范进行部署

如果您的代理是使用 Python SDK 对象或序列化应用(例如 ADK、LangChain 或自定义 Python 代理)构建的,则可以在 Cloud Storage 存储桶中暂存序列化代理 (.pkl) 和依赖项配置 (requirements.txt),并使用 package_spec 引用它们。

如需详细了解部署的工作原理,请参阅从 Python 对象进行部署

  1. 运行以下 Python 脚本,以序列化您的代理并将部署制品暂存到 Cloud Storage 中:

    import cloudpickle
    from google.adk.agents import Agent
    from google.cloud import storage
    from vertexai.agent_engines import AdkApp
    PROJECT_ID = "PROJECT_ID"
    BUCKET_NAME = "BUCKET_NAME"
    GCS_DIR = "agents/weather_agent"
    
    # 1. Define agent logic
    root_agent = Agent(
        model="gemini-3.1-flash-lite",
        name="weather_agent",
        description="Agent deployed using Terraform package_spec.",
    )
    local_app = AdkApp(agent=root_agent)
    
    # 2. Upload pickle to Cloud Storage
    storage_client = storage.Client(project=PROJECT_ID)
    bucket = storage_client.bucket(BUCKET_NAME)
    
    pkl_blob = bucket.blob(f"{GCS_DIR}/agent.pkl")
    with pkl_blob.open("wb") as f:
        cloudpickle.dump(local_app, f)
    
    # 3. Upload requirements.txt
    requirements_content = """google-cloud-aiplatform[agent_engines,adk]>=1.144
    cloudpickle==3.0.0
    """
    req_blob = bucket.blob(f"{GCS_DIR}/requirements.txt")
    req_blob.upload_from_string(requirements_content)
    
    print(f"Artifacts uploaded to gs://{BUCKET_NAME}/{GCS_DIR}/")
    
  2. terraform/ 目录中创建 variables.tfmain.tfoutputs.tf 文件,引用已暂存的 Cloud Storage URI:

    输入变量 (terraform/variables.tf)
    variable "project_id" {
      type        = string
      description = "The Google Cloud Project ID"
    }
    
    variable "location" {
      type        = string
      default     = "us-central1"
      description = "The region to deploy Agent Runtime"
    }
    
    variable "bucket_name" {
      type        = string
      description = "Cloud Storage bucket name containing agent artifacts"
    }
    
    资源规范 (terraform/main.tf)
    terraform {
      required_providers {
        google = {
          source  = "hashicorp/google"
          version = ">= 5.28.0"
        }
      }
    }
    
    provider "google" {
      project = var.project_id
      region  = var.location
    }
    
    resource "google_vertex_ai_reasoning_engine" "package_agent" {
      display_name = "weather_agent_package_tf"
      description  = "Agent Runtime instance deployed using package_spec"
      project      = var.project_id
      location     = var.location
    
      spec {
        agent_framework = "google-adk"
        package_spec {
          python_version        = "3.11"
          pickle_object_gcs_uri = "gs://${var.bucket_name}/agents/weather_agent/agent.pkl"
          requirements_gcs_uri  = "gs://${var.bucket_name}/agents/weather_agent/requirements.txt"
        }
      }
    }
    
    资源输出 (terraform/outputs.tf)
    output "package_agent_id" {
      value       = google_vertex_ai_reasoning_engine.package_agent.id
      description = "Resource ID of the deployed package agent"
    }
    

配置环境变量和 Secret

在部署之前,您可以将自定义运行时服务账号附加到代理,并传递环境变量 (env) 或 Secret Manager 引用 (secret_env)。

以下示例配置了环境变量(LOCATIONMODELMODEL_REGION),并通过 terraform/main.tf 文件将 API 密钥从 Secret Manager 安全地传递到运行时服务账号:

# 1. Dedicated Runtime Service Account
resource "google_service_account" "agent_runtime_sa" {
  account_id   = "agent-runtime-sa"
  display_name = "Agent Runtime Identity"
  project      = var.project_id
}

# 2. Secret Manager Secret for Agent Credentials
resource "google_secret_manager_secret" "api_key_secret" {
  secret_id = "agent-api-key"
  project   = var.project_id

  replication {
    auto {}
  }
}

resource "google_secret_manager_secret_version" "api_key_version" {
  secret      = google_secret_manager_secret.api_key_secret.id
  secret_data = var.api_key_value
}

# Grant Secret Accessor role to Runtime Service Account
resource "google_secret_manager_secret_iam_member" "secret_accessor" {
  secret_id = google_secret_manager_secret.api_key_secret.id
  role      = "roles/secretmanager.secretAccessor"
  member    = "serviceAccount:${google_service_account.agent_runtime_sa.email}"
}

# Grant Artifact Registry Reader permission to the Agent Runtime Service Agent
resource "google_project_iam_member" "re_service_agent_ar_reader" {
  project = var.project_id
  role    = "roles/artifactregistry.reader"
  member  = "serviceAccount:service-${var.project_number}@gcp-sa-aiplatform-re.iam.gserviceaccount.com"
}

# 3. Agent Runtime Resource with Environment Variables and Secret References
resource "google_vertex_ai_reasoning_engine" "advanced_weather_agent" {
  display_name = "byoc_weather_agent_advanced_tf"
  description  = "BYOC weather agent with custom service account and secrets"
  project      = var.project_id
  location     = var.location

  spec {
    agent_framework = "google-adk"
    service_account = google_service_account.agent_runtime_sa.email

    container_spec {
      image_uri = "${var.location}-docker.pkg.dev/${var.project_id}/${var.repository_name}/weather-agent-image:${var.image_tag}"
    }

    deployment_spec {
      env {
        name  = "LOCATION"
        value = var.location
      }
      env {
        name  = "MODEL"
        value = "gemini-3.1-flash-lite"
      }
      env {
        name  = "MODEL_REGION"
        value = "global"
      }

      secret_env {
        name = "API_KEY"
        secret_ref {
          secret  = google_secret_manager_secret.api_key_secret.secret_id
          version = "latest"
        }
      }
    }

    class_methods = jsonencode([
      { "name" = "get_session", "api_mode" = "" },
      { "name" = "create_session", "api_mode" = "" },
      { "name" = "stream_query", "api_mode" = "stream" },
      { "name" = "async_stream_query", "api_mode" = "async_stream" }
    ])
  }

  depends_on = [
    google_secret_manager_secret_iam_member.secret_accessor,
    google_project_iam_member.re_service_agent_ar_reader
  ]
}

执行和生命周期

执行标准 Terraform 生命周期,以规划、部署、调用和销毁代理资源。

应用 Terraform 配置

通过应用 Terraform 配置来部署代理:

  1. 切换到您的 Terraform 目录(例如 cd weather-agent-byoc/terraform):

    cd weather-agent-byoc/terraform
  2. 初始化工作目录:

    terraform init
  3. 预览部署计划:

    terraform plan -var="project_id=PROJECT_ID" -var="project_number=PROJECT_NUMBER"
  4. 应用配置以预配代理:

    terraform apply -var="project_id=PROJECT_ID" -var="project_number=PROJECT_NUMBER"

向已部署的智能体发出查询请求

在 Terraform 预配 google_vertex_ai_reasoning_engine 资源后,向 :streamQuery?alt=sse 端点发送 HTTP POST 请求,以使用服务器发送的事件 (SSE) 实时流式传输响应事件:

LOCATION="LOCATION"
PROJECT_ID="PROJECT_ID"
REASONING_ENGINE_ID="REASONING_ENGINE_ID"
curl -X POST \
  -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  -H "Content-Type: application/json; charset=utf-8" \
  -d '{
    "class_method": "async_stream_query",
    "input": {
      "user_id": "terraform_test_user",
      "message": "What is the temperature in Seattle?"
    }
  }' \
  "https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${LOCATION}/reasoningEngines/${REASONING_ENGINE_ID}:streamQuery?alt=sse"
  • OAuth 访问令牌Authorization: Bearer $(gcloud auth print-access-token) 使用本地 Google Cloud 凭据生成短期有效的 OAuth 2.0 访问令牌。
  • JSON input 封装容器:请求正文需要包含 input 对象的 JSON 载荷。调用显式类方法(例如 async_stream_query)时,请在 "input" 旁边添加 "class_method" 参数。
  • 响应载荷:响应以 data: { ... } 服务器发送的事件 (SSE) 块的形式持续传送。

销毁代理资源

如需清理资源并避免产生意外的结算费用,请切换到 terraform/ 目录(例如 cd weather-agent-byoc/terraform),然后运行 terraform destroy

cd weather-agent-byoc/terraform
terraform destroy -var="project_id=PROJECT_ID" -var="project_number=PROJECT_NUMBER"

后续步骤