הקצאת סוכנים באמצעות Terraform

אתם יכולים להשתמש ב-Terraform כדי להקצות ולנהל מופעים של Agent Runtime באופן הצהרתי. כשפורסים סוכנים באמצעות Terraform, מנהלים את המשאב google_vertex_ai_reasoning_engine באמצעות ספק Terraform הרשמי ( Google Cloud ספק GA או ספק בטא).

ההוראות בדף הזה מתאימות להטמעה לדוגמה של סוכן מבוסס-קונטיינר שמתוארת ב-Codelab בנושא פריסת סוכן מבוסס-קונטיינר באמצעות Agent Runtime.

דרישות מוקדמות

לפני שמשתמשים ב-Terraform כדי לפרוס סוכן, צריך לוודא שהשלמתם את ההגדרה הבאה:

  1. מתקינים את Terraform (גרסה 1.5.0 ואילך) ומעיינים במסמכי התיעוד הרשמיים של מאגר Terraform של HashiCorp בנושא המשאב google_vertex_ai_reasoning_engine (ספק GA וספק בטא).
  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.py,‏ requirements.txt,‏ Dockerfile): מכילים את הלוגיקה של הסוכן, את העטיפה של מסגרת האינטרנט (כמו FastAPI או ADK App), את התלות ב-Python ואת הוראות הבנייה של הקונטיינר.

    • ספריית Terraform (terraform/): מכילה את כל קובצי התצורה של Terraform שמשמשים להקצאת משאבים:

      • ‫variables.tf: הצהרה על משתני קלט כמו project_id,‏ location,‏ repository_name ו-image_tag.
      • ‫main.tf: הצהרה על הגדרות ספק, משתנים מקומיים, קישורי תפקידי IAM ומפרטי משאבים של google_vertex_ai_reasoning_engine.
      • outputs.tf: מייצא מאפיינים של משאבים שהוקצו, כמו מזהה Agent Runtime ושם המשאב המלא, אחרי הפריסה.
  5. נותנים את התפקידים המתאימים ב-IAM בהתאם למי שמבצע את הפריסה:

    • חשבון שירות של מפתח אנושי או של CI/CD שמריץ את הפקודות terraform apply ופקודות build מקומיות.

    • סוכן שירות של Agent Runtime שמנוהל על ידי המערכת (service-<var>PROJECT_NUMBER</var>@gcp-sa-aiplatform-re.iam.gserviceaccount.com).

הכנה לפריסה

‫Terraform תומך בנתיבי הפריסה הבאים של Agent Runtime:

  • פריסה מקובץ אימג' של קונטיינר שנבנה מראש: יוצרים מראש קובץ אימג' של קונטיינר, מעבירים אותו בדחיפה ל-Artifact Registry ‏ ({region}-docker.pkg.dev/...) ופורסים אותו באמצעות container_spec. כדאי להשתמש בשיטה הזו אם אתם רוצים שליטה מלאה בתהליך build של הקונטיינר, בתמונות בסיס מותאמות אישית או בזמן אחזור קצר יותר של הפריסה.
  • פריסה מקובצי מקור או מקובץ Dockerfile: פריסת הסוכן ישירות מקובצי מקור מקומיים או מקובץ Dockerfile. ‫Agent Runtime יוצר ומקצה את קובץ אימג' של קונטיינר באופן אוטומטי, בלי צורך בניהול ידני של האימג'.
  • פריסה באמצעות מפרטים של חבילות Python פריסה באמצעות (package_spec) שמוצג ב-Cloud Storage. ‫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. ההגדרה הבאה מדגימה פריסה של קובץ אימג' של קונטיינר שנבנה מראש ומתארח ב-Artifact Registry, על ידי יצירת הקבצים variables.tf, main.tf ו-outputs.tf בספרייה terraform/:

    משתני קלט (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
      region       = 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 או ממאגר קוד מקור

כשפורסים מקובץ Docker, צריך לציין את ארכיון המקור ב-source_code_spec ולהגדיר בלוק image_spec {} ריק כדי להנחות את Agent Runtime ליצור את קובץ האימג' של הקונטיינר באמצעות קובץ Docker. הקונטיינר שנבנה מקובץ ה-Dockerfile חייב לעמוד בדרישות של הסכם זמן הריצה.

לפרטים נוספים על אופן הפריסה, אפשר לעיין במאמרים פריסה מקובץ Docker או פריסה מקובצי מקור.

  1. דוחסים את קוד האפליקציה (main.py), את מניפסט התלות של Python (requirements.txt) ואת הוראות הבנייה של הקונטיינר (Dockerfile) לארכיון מסוג gzipped 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. יוצרים את הקבצים variables.tf, main.tf ו-outputs.tf בספרייה terraform/:

    משתני קלט (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
      region       = 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 או אפליקציות pickled (כמו ADK,‏ LangChain או סוכני Python בהתאמה אישית), אתם יכולים להכין את הסוכן הסדרתי (.pkl) ואת הגדרת התלות (requirements.txt) בקטגוריה של Cloud Storage ולהפנות אליהם באמצעות 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. יוצרים את הקבצים variables.tf, main.tf ו-outputs.tf בספרייה terraform/ עם הפניות ל-URI של Cloud Storage שהועלו:

    משתני קלט (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
      region       = 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"
    }
    

הגדרת משתני סביבה וסודות

לפני הפריסה, אפשר לצרף לחשבון של הסוכן חשבון שירות של סביבת זמן ריצה בהתאמה אישית ולהעביר משתני סביבה (env) או הפניות ל-Secret Manager (secret_env).

בדוגמה הבאה מוגדרים משתני סביבה (LOCATION, ‏MODEL, ‏MODEL_REGION) ומפתח API מועבר בצורה מאובטחת מ-Secret Manager לחשבון השירות של זמן הריצה דרך הקובץ terraform/main.tf:

# 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
  ]
}

הגדרת Agent Gateway

כדי לנתב תעבורת נתונים בין Agent Runtime לבין ממשקי API או לקוחות חיצוניים דרך Agent Gateway, צריך להגדיר את הבלוק agent_gateway_config בתוך deployment_spec באמצעות פלאגין שמתממשק עם שירותים חיצוניים google-beta.

דוגמאות מלאות לפריסה ופרטים על הפרמטרים של ניתוב מסוג Agent-to-Anywhere (יציאה) ו-Client-to-Agent (כניסה) מופיעים במאמר ניתוב תנועה בזמן ריצה דרך Agent Gateway.

ביצוע ומחזור חיים

מריצים את מחזור החיים הרגיל של 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, שולחים בקשת HTTP POST לנקודת הקצה :streamQuery?alt=sse כדי להזרים אירועי תגובה בזמן אמת באמצעות Server-Sent Events ‏ (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 Access Token: Authorization: Bearer $(gcloud auth print-access-token) יוצר אסימון גישה מסוג OAuth 2.0 עם תוקף קצר באמצעות פרטי הכניסה המקומיים שלכם. Google Cloud
  • מעטפת JSON input: תוכן הבקשה צריך להיות מטען ייעודי (payload) של JSON שמכיל אובייקט input. כשקוראים לשיטות של מחלקה מפורשת (כמו async_stream_query), צריך לכלול את הפרמטר "class_method" לצד "input".
  • מטען ייעודי של תשובה: התשובות מועברות באופן רציף כנתונים של 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"

המאמרים הבאים