Lección 4 — Guides pas à pas

10-3. Tout déployer avec Terraform

7 min de lectura

Este contenido aún no está traducido. Se muestra la versión original.

Ce guide répond à : comment créer le serveur MCP, l'agent (A2A et/ou Agent Runtime), leurs droits et l'entrée Agent Registry avec Terraform ? Que montre le plan ? Comment ajouter Agent Runtime ou l'app plus tard ?

Même résultat que le script (10-2). Choisissez l'un ou l'autre pour un même projet : les noms de ressources sont les mêmes.

Testé en vrai (14 octobre 2026) sur un projet neuf (second-project), avec l'app (main-project) et Agent Runtime :

  • terraform apply → Apply complete! ;
  • ./scripts/deployer.sh tester : 403 sans jeton, 17 outils sur le vrai classeur, agent A2A et agent Agent Runtime qui répondent avec le vrai Gemini ;
  • relancé, terraform plan → No changes. Your infrastructure matches the configuration.

Deux corrections trouvées pendant ce test réel, faites dans le code :

  • le numéro du projet est maintenant donné (NUM_PROJET), et non plus lu ;
  • une commande à lancer avant Terraform (partie 2.1 bis).

1. Ce que Terraform crée

#RessourceRôle
1google_project_service.apis[…]Les API (Cloud Run, Cloud Build, Artifact Registry, IAM, Logging, Sheets, Drive, Vertex AI, Agent Registry)
2google_service_account.build + 3 rôlesLe compte qui construit les images
2google_service_account.mcpLe compte du serveur MCP : aucun rôle
2google_service_account.agent + 2 rôlesLe compte de l'agent (Gemini, journaux)
3google_artifact_registry_repository.imagesLe dépôt d'images sheets-mcp
3terraform_data.image["mcp_server"], ["agent"]Les images, construites par Cloud Build (gcloud builds submit), étiquetées par l'empreinte du code
4google_cloud_run_v2_service.mcpLe serveur MCP, privé
5google_cloud_run_v2_service.agent[0]L'agent A2A (deploy_agent_cloudrun = true, par défaut)
6google_vertex_ai_reasoning_engine.agent[0]L'agent sur Agent Runtime (deploy_agent_runtime = true)
7google_cloud_run_v2_service_iam_member.mcp[…]Qui peut appeler le serveur MCP : le compte de l'agent, et le compte de l'app (si ge_project_number)
7google_cloud_run_v2_service_iam_member.agent[0]L'app peut appeler l'agent A2A
7google_project_iam_member.ge_runtime[0]L'app peut appeler l'agent Agent Runtime
8google_agent_registry_service.mcp[0]Le serveur et ses 17 outils dans Agent Registry

L'étiquette d'image est l'empreinte du code. Code inchangé : même image, rien à refaire. Si agent/ change, seule l'image de l'agent est reconstruite, et le serveur MCP ne bouge pas.

2. Pas à pas

2.1 La configuration

config/10-mcp.env, avec OAUTH_CLIENT_IDS rempli (client OAuth : 10-5, étape 1). Terraform lit les variables TF_VAR_* calculées par config.sh : il n'y a pas de terraform.tfvars à écrire.

source scripts/config.sh config/10-mcp.env
python3 scripts/gen_toolspec.py         # terraform/toolspec.json (liste des outils pour Agent Registry)

2.1 bis Une commande, une seule fois, avant Terraform

gcloud services enable cloudresourcemanager.googleapis.com serviceusage.googleapis.com --project=$PROJET

Terraform gère les API et les rôles du projet à travers ces deux API. Sur un projet neuf où elles sont inactives, il ne peut même pas les activer lui-même.

Constaté en vrai le 14 octobre 2026, sur un projet neuf, sans cette commande : Error 403: Cloud Resource Manager API has not been used in project … or it is disabled sur chaque API et chaque rôle. ./scripts/deployer.sh preparer l'active aussi. Sur les projets Acme, elle est très probablement déjà active : la commande ne change alors rien.

2.2 Le plan

cd terraform
terraform init
terraform plan

Résultat obtenu (projet de test, sans app, sans Agent Runtime) : Plan: 24 to add, 0 to change, 0 to destroy. Avec la version actuelle, qui active aussi Cloud Resource Manager, comptez une ressource de plus dans chaque cas (25, 27, 29).

Résultat obtenu avec l'app (NUM_APP rempli) et Agent Runtime (TF_VAR_deploy_agent_runtime=true) :

  # google_agent_registry_service.mcp[0] will be created
  # google_artifact_registry_repository.images will be created
  # google_cloud_run_v2_service.agent[0] will be created
  # google_cloud_run_v2_service.mcp will be created
  # google_cloud_run_v2_service_iam_member.agent[0] will be created
  # google_cloud_run_v2_service_iam_member.mcp["serviceAccount:service-<NUM_APP>@gcp-sa-discoveryengine.iam.gserviceaccount.com"] will be created
  # google_cloud_run_v2_service_iam_member.mcp["serviceAccount:sheets-agent-sa@<PROJET>.iam.gserviceaccount.com"] will be created
  # google_project_iam_member.agent["roles/aiplatform.user"] will be created
  # google_project_iam_member.agent["roles/logging.logWriter"] will be created
  # google_project_iam_member.build["roles/artifactregistry.writer"] will be created
  # google_project_iam_member.build["roles/logging.logWriter"] will be created
  # google_project_iam_member.build["roles/storage.objectViewer"] will be created
  # google_project_iam_member.ge_runtime[0] will be created
  # google_project_service.apis["agentregistry.googleapis.com"] will be created
  # … (8 autres API)
  # google_service_account.agent will be created
  # google_service_account.build will be created
  # google_service_account.mcp will be created
  # google_vertex_ai_reasoning_engine.agent[0] will be created
  # terraform_data.image["agent"] will be created
  # terraform_data.image["mcp_server"] will be created
Plan: 28 to add, 0 to change, 0 to destroy.
OptionsPlan obtenu
Sans app, sans Agent Runtime24 to add
Avec app (NUM_APP)26 to add (+2 droits pour l'app)
Avec app et Agent Runtime28 to add (+ l'agent et le droit ②)
OAUTH_CLIENT_IDS videError: Resource precondition failed … oauth_client_ids est vide : le serveur MCP refuserait de démarrer

2.3 Appliquer

terraform apply        # relit le plan, demande « yes » ; 6 à 10 min (15 à 20 avec Agent Runtime)

Attendu :

  • des lignes terraform_data.image["mcp_server"] (local-exec): … SUCCESS ;
  • Apply complete! Resources: 24 added ;
  • puis les sorties :

Résultat obtenu (sorties, projet de test) :

agent_runtime = "projects/second-project-511608/locations/europe-west1/reasoningEngines/2125248224351485952"
agent_url = "https://sheets-agent-872505552973.europe-west1.run.app"
autorisations_attendues = { "a2a" = "acces-sheets", "agent_runtime" = "acces-sheets-runtime" }
carte_a2a = "{\"protocolVersion\": \"0.3\", \"name\": \"sheets_agent\", …}"
domaines_de_sortie_a_autoriser = ["sheets-mcp-872505552973.europe-west1.run.app", "accounts.google.com", "oauth2.googleapis.com"]
ge_service_agent = "service-100000000005@gcp-sa-discoveryengine.iam.gserviceaccount.com"
mcp_url = "https://sheets-mcp-872505552973.europe-west1.run.app/mcp"
SortiePour
mcp_urlLe connecteur « Custom MCP Server » (10-5)
carte_a2aLa carte à coller (Custom agent via A2A), sur une ligne : vient de agent/carte.py
agent_runtimeLe chemin à coller (Custom agent via Agent Runtime)
autorisations_attenduesLes ID d'autorisation que l'agent attend : acces-sheets (A2A) et acces-sheets-runtime
ge_service_agentLe compte de l'app qui a reçu les droits
domaines_de_sortie_a_autoriserPour la politique d'organisation du connecteur natif (10-5, étape 2)
terraform output -raw carte_a2a      # la carte, prête à copier

2.4 Plus tard : ajouter Agent Runtime, ou l'app

Vous voulezVous faitesLe plan doit montrer
Ajouter l'agent Agent Runtimeexport TF_VAR_deploy_agent_runtime=true, plan+ google_vertex_ai_reasoning_engine.agent[0] (+ ge_runtime[0] si l'app est connue). Rien d'autre
Donner les droits à l'appNUM_APP dans le fichier, recharger, plan2 ou 3 droits …iam_member… en plus, 0 à détruire
Accepter un autre client OAuthOAUTH_CLIENT_IDS="a,b", recharger, plangoogle_cloud_run_v2_service.mcp will be updated in-place (nouvelle révision, même adresse)
Nouveau code du serveurModifier mcp_server/main.py, planterraform_data.image["mcp_server"] must be replaced + …service.mcp will be updated in-place
Seulement Sheets (sans Slides)export TF_VAR_produits_mcp='["sheets"]'Pas de …mcp["slides"]
Ajouter Slides à un déploiement Sheets existantproduits_mcp par défaut (["sheets","slides"]), plan…mcp[0] has moved to …mcp["sheets"], puis seulement des créations ["slides"] : rien n'est détruit (testé, 10-13)
Pas d'Agent Registry (bloqué par l'organisation)export TF_VAR_register_in_agent_registry=falseL'entrée du registre n'est pas créée

Lisez toujours la ligne Plan: avant de taper yes. Si un destroy apparaît sans raison, répondez no.

3. Côté app, après apply

Terraform ne crée pas le connecteur natif : Google ne publie pas d'API pour cela. Il ne crée pas non plus l'autorisation OAuth, parce que le secret ne doit pas entrer dans l'état Terraform. Faites ensuite :

  • connecteur : 10-5 ;
  • agent : 10-6. Ou par script : ./scripts/deployer.sh autorisation … puis ajouter-app.

4. Supprimer

terraform destroy       # relit la liste, demande « yes »

L'agent Agent Runtime est supprimé avec ses sessions (deletion_policy = "FORCE"). Les API restent actives (disable_on_destroy = false), pour ne pas casser d'autres usages du projet.

Siguiente