Trouver et résoudre les problèmes d'application avec Gemini Cloud Assist

1. Introduction

Gemini Cloud Assist est un agent complet qui prend en charge vos charges de travail Google Cloud. Il vous aide à concevoir de nouvelles applications ou à mettre à jour celles existantes, à déployer et à exécuter des charges de travail dans Google Cloud, à résoudre les problèmes liés aux charges de travail et à les optimiser en termes de coûts et de performances.

Gemini Cloud Assist vous permet de mieux répondre aux erreurs inattendues et aux temps d'arrêt.

Points abordés

  1. Déploiement : comment déployer un backend et une base de données de base sur Google Cloud.
  2. Débogage : comment Gemini Cloud Assist automatise l'investigation et l'analyse des causes profondes des problèmes liés au cloud et au code.
  3. Correction : comment Gemini Cloud Assist aide à identifier les correctifs en fonction de la cause profonde.

2. Configuration du projet

Compte Google

Si vous ne possédez pas encore de compte Google personnel, vous devez en créer un.

Utilisez un compte personnel au lieu d'un compte professionnel ou scolaire.

Se connecter à la console Google Cloud

Connectez-vous à la console Google Cloud à l'aide d'un compte Google personnel.

Activer la facturation

Configurer un compte de facturation personnel

Si vous configurez la facturation à l'aide de crédits Google Cloud, vous pouvez ignorer cette étape.

Pour configurer un compte de facturation personnel, accédez à cette page pour activer la facturation dans la console Cloud.

Quelques remarques :

  • Cet atelier ne devrait pas vous coûter plus de 1 $en ressources cloud.
  • Vous pouvez suivre les étapes à la fin de cet atelier pour supprimer des ressources et éviter d'autres frais.
  • Les nouveaux utilisateurs peuvent bénéficier de l'essai sans frais de 300$.

Créer un projet (facultatif)

Si vous ne disposez pas d'un projet que vous souhaitez utiliser pour cet atelier, créez-en un ici.

3. Ouvrir l'éditeur Cloud Shell

  1. Cliquez sur ce lien pour accéder directement à l'éditeur Cloud Shell.
  2. Si vous êtes invité à autoriser une action à un moment donné, cliquez sur Autoriser pour continuer.Cliquez pour autoriser Cloud Shell.
  3. Si le terminal ne s'affiche pas en bas de l'écran, ouvrez-le :
    • Cliquez sur Afficher.
    • Cliquez sur TerminalOuvrir un nouveau terminal dans l'éditeur Cloud Shell
  4. Dans le terminal, définissez votre projet à l'aide de la commande suivante :
    gcloud config set project [PROJECT_ID]
    
    • Exemple :
      gcloud config set project lab-project-id-example
      
    • Si vous ne vous souvenez pas de votre ID de projet, vous pouvez répertorier tous vos ID de projet à l'aide de la commande suivante :
      gcloud projects list
      
      Définir l'ID du projet dans le terminal de l'éditeur Cloud Shell
  5. Le message suivant doit s'afficher :
    Updated property [core/project].
    

4. Activer les API

Activez les API suivantes pour déployer les composants de l'application et utiliser Google Cloud Assist :

Dans le terminal, activez les API :

```bash
gcloud services enable \
  container.googleapis.com \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com \
  alloydb.googleapis.com \
  run.googleapis.com
```
<br>
When the command finishes, you should see an output like the following: 
<br>

```console
Operation "operations/acf.p2-176675280136-b03ab5e4-3483-4ebf-9655-43dc3b345c63" finished successfully.
```

5. Préparer le projet

Vous allez créer l'application et le déploiement de base afin de tester Cloud Assist.

Créer le répertoire

  1. Ouvrez l'éditeur Cloud Shell ou l'environnement de développement de votre choix.
  2. Créez un dossier :
    mkdir -p ~/gemini-cloud-assist-debug
    mkdir -p ~/gemini-cloud-assist-debug/auth_issue_demo
    mkdir -p ~/gemini-cloud-assist-debug/terraform
    cd ~/gemini-cloud-assist-debug
    
  3. Dans le terminal, exécutez la commande suivante pour ouvrir un espace de travail de l'éditeur Cloud Shell :
cloudshell open-workspace ~/gemini-cloud-assist-debug

Créer les fichiers

Vous allez maintenant créer les fichiers de démarrage nécessaires pour l'application.

  1. Créez le fichier Dockerfile en exécutant la commande suivante dans le terminal. Ce fichier gère la création du conteneur d'application.
cat <<EOF > ~/gemini-cloud-assist-debug/auth_issue_demo/Dockerfile
FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY main.py .

CMD ["gunicorn", "--bind", "0.0.0.0:8080", "main:app"]
EOF
  1. Créez le fichier main.py en exécutant la commande suivante dans le terminal. Ce fichier contient l'application écrite en Python.
cat <<EOF > ~/gemini-cloud-assist-debug/auth_issue_demo/main.py
import os
import logging
from flask import Flask
from google.cloud.alloydb.connector import Connector
import sqlalchemy

app = Flask(__name__)

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Configuration from Environment Variables
# The fully qualified instance URI: projects/<PROJECT>/locations/<REGION>/clusters/<CLUSTER>/instances/<INSTANCE>
ALLOYDB_URI = os.environ.get("ALLOYDB_URI") 
DB_USER = os.environ.get("DB_USER", "auth-debug")
DB_PASS = os.environ.get("DB_PASS", "debug-auth")
DB_NAME = os.environ.get("DB_NAME", "postgres")
USE_PUBLIC_IP = os.environ.get("USE_PUBLIC_IP", "false").lower() == "true"

# Initialize Connector lazily
_connector = None

def get_connector():
    global _connector
    if _connector is None:
        _connector = Connector()
    return _connector

def getconn():
    connector = get_connector()
    ip_type = "PUBLIC" if USE_PUBLIC_IP else "PRIVATE"
    
    conn = connector.connect(
        ALLOYDB_URI,
        "pg8000",
        user=DB_USER,
        password=DB_PASS,
        db=DB_NAME,
        ip_type=ip_type
    )
    return conn

@app.route("/")
def index():
    return "AlloyDB Auth Demo. /connect to test.", 200

@app.route("/connect")
def connect_db():
    if not ALLOYDB_URI:
        return "FAILURE: ALLOYDB_URI env var is not set.", 500

    try:
        logger.info(f"Attempting connection to {ALLOYDB_URI} with user {DB_USER}...")
        
        # Create connection pool
        pool = sqlalchemy.create_engine(
            "postgresql+pg8000://",
            creator=getconn,
        )
        
        with pool.connect() as db_conn:
            # Simple query to validate connection
            result = db_conn.execute(sqlalchemy.text("SELECT NOW()")).fetchone()
            timestamp = result[0]
            
        msg = f"SUCCESS: Connected to AlloyDB! DB Time: {timestamp}"
        logger.info(msg)
        return msg, 200

    except Exception as e:
        logger.exception("Connection failed")
        # Return the error to the caller to visualize the auth failure
        return f"FAILURE: Connection Error.\nDetails: {str(e)}", 500

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
EOF
  1. Créez le fichier requirements.txt en exécutant la commande suivante dans le terminal. Ce fichier gère les exigences des packages Python.
cat <<EOF > ~/gemini-cloud-assist-debug/auth_issue_demo/requirements.txt
flask==3.1.3
gunicorn==25.3.0
google-cloud-alloydb-connector[pg8000]==1.12.1
sqlalchemy==2.0.49
EOF
  1. Créez le fichier main.tf en exécutant la commande suivante dans le terminal. Ce fichier gère les ressources Google Cloud à créer.
cat <<EOF > ~/gemini-cloud-assist-debug/terraform/main.tf
provider "google" {
  project = var.project_id
  region  = var.region
}

# Enable APIs
locals {
  apis = [
    "alloydb.googleapis.com",
    "run.googleapis.com",
    "artifactregistry.googleapis.com",
    "compute.googleapis.com",
    "geminicloudassist.googleapis.com",
    "monitoring.googleapis.com",
    "cloudasset.googleapis.com",
    "cloudbuild.googleapis.com",
    "recommender.googleapis.com",
    "appoptimize.googleapis.com"
  ]
}

resource "random_password" "db_pass" {
  count            = var.db_password == null ? 1 : 0
  length           = 16
  special          = true
  override_special = "!#$%&*()-_=+[]{}<>:?"
}

locals {
  db_password = var.db_password != null ? var.db_password : random_password.db_pass[0].result
}

resource "google_project_service" "apis" {
  for_each           = toset(local.apis)
  service            = each.value
  disable_on_destroy = false
}

# Service Account
resource "google_service_account" "auth_demo_sa" {
  account_id   = var.service_account_name
  display_name = "Auth Demo SA"
}

# AlloyDB Cluster
resource "google_alloydb_cluster" "rma_cluster" {
  cluster_id = var.cluster_id
  location   = var.region

  # Initial password, managed via variable or generated randomly
  initial_user {
    password = local.db_password
  }

  # Use default network as in the manual setup
  network_config {
    network = "projects/${var.project_id}/global/networks/default"
  }

  depends_on = [google_project_service.apis["alloydb.googleapis.com"]]
}

# AlloyDB Instance
resource "google_alloydb_instance" "rma_instance_1" {
  cluster       = google_alloydb_cluster.rma_cluster.name
  instance_id   = var.instance_id
  instance_type = "PRIMARY"

  machine_config {
    cpu_count = 2
  }

  network_config {
    enable_public_ip = true
  }

  depends_on = [google_alloydb_cluster.rma_cluster]
}

# Cloud Run Service
resource "google_cloud_run_service" "auth_issue_demo" {
  name     = var.cloud_run_service_name
  location = var.region

  template {
    spec {
      containers {
        image = var.cloud_run_image
        env {
          name  = "ALLOYDB_URI"
          value = "projects/${var.project_id}/locations/${var.region}/clusters/${var.cluster_id}/instances/${var.instance_id}"
        }
        env {
          name  = "DB_USER"
          value = "postgres"
        }
        env {
          name  = "DB_PASS"
          value = local.db_password
        }
        env {
          name  = "USE_PUBLIC_IP"
          value = "true"
        }
      }
      service_account_name = google_service_account.auth_demo_sa.email
    }
  }

  traffic {
    percent         = 100
    latest_revision = true
  }

  depends_on = [google_project_service.apis["run.googleapis.com"], google_alloydb_instance.rma_instance_1]
}

# Allow unauthenticated access to Cloud Run service (matching --allow-unauthenticated)
resource "google_cloud_run_service_iam_member" "public_access" {
  location = google_cloud_run_service.auth_issue_demo.location
  project  = google_cloud_run_service.auth_issue_demo.project
  service  = google_cloud_run_service.auth_issue_demo.name
  role     = "roles/run.invoker"
  member   = "allUsers"
}
EOF
  1. Créez le fichier variables.tf en exécutant la commande suivante dans le terminal. Ce fichier gère les variables Terraform pour les ressources Google Cloud.
cat <<EOF > ~/gemini-cloud-assist-debug/terraform/variables.tf
variable "project_id" {
  description = "The ID of the Google Cloud project."
  type        = string
}

variable "region" {
  description = "The region to deploy resources in."
  type        = string
  default     = "us-central1"
}

variable "cluster_id" {
  description = "The ID of the AlloyDB cluster."
  type        = string
  default     = "rma-cluster"
}

variable "instance_id" {
  description = "The ID of the AlloyDB instance."
  type        = string
  default     = "rma-instance-1"
}

variable "service_account_name" {
  description = "The name of the service account."
  type        = string
  default     = "auth-demo-sa"
}

variable "cloud_run_service_name" {
  description = "The name of the Cloud Run service."
  type        = string
  default     = "auth-issue-demo"
}

variable "cloud_run_image" {
  description = "The container image for the Cloud Run service."
  type        = string
}

variable "db_password" {
  description = "The database password. If not provided, a random one will be generated."
  type        = string
  sensitive   = true
  default     = null
}
EOF
  1. Créez le fichier setup_via_tf.sh en exécutant la commande suivante dans le terminal. Ce fichier gère les exigences des packages Python.
cat <<EOF > ~/gemini-cloud-assist-debug/setup_via_tf.sh
#!/bin/bash
set -e

# Get script directory and change to project root
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "$SCRIPT_DIR"

# Load configuration from .env
if [ -f .env ]; then
    set -a
    source .env
    set +a
else
    echo "ERROR: .env file not found. Please create one with PROJECT_ID."
    exit 1
fi

if [ -z "$PROJECT_ID" ]; then
    echo "ERROR: PROJECT_ID is not set in .env file."
    exit 1
fi

REGION="us-central1"
CLUSTER_ID="rma-cluster"
INSTANCE_ID="rma-instance-1"
SA_NAME="auth-demo-sa"
SERVICE_NAME="auth-issue-demo"

echo "--- Terraform Setup for Auth Demo ---"
echo "Using Project: $PROJECT_ID"

# Get current Cloud Run image
echo "Fetching current Cloud Run image..."
IMAGE=$(gcloud run services describe $SERVICE_NAME --region=$REGION --project=$PROJECT_ID --format="value(spec.template.spec.containers[0].image)" 2>/dev/null || true)

if [ -z "$IMAGE" ]; then
    echo "WARNING: Could not find existing Cloud Run service image."
    echo "Using a placeholder image (gcr.io/cloudrun/hello) for initial Terraform apply."
    IMAGE="gcr.io/cloudrun/hello"
fi

echo "Found Image: $IMAGE"

cd terraform

# Initialize Terraform
echo "Initializing Terraform..."
terraform init

echo "Formatting Terraform files..."
terraform fmt

echo "Validating Terraform configuration..."
terraform validate

echo "------------------------------------------------"
echo "Applying changes..."
echo "------------------------------------------------"

terraform apply -var="project_id=$PROJECT_ID" -var="cloud_run_image=$IMAGE" -auto-approve

echo "------------------------------------------------"
echo "Building and deploying updated Cloud Run service..."
echo "------------------------------------------------"

gcloud run deploy $SERVICE_NAME \
  --source ../auth_issue_demo \
  --region $REGION \
  --project $PROJECT_ID \
  --service-account $SA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
  --quiet
EOF
  1. Exécutez la commande suivante pour rendre le script shell exécutable :
chmod +x ~/gemini-cloud-assist-debug/setup_via_tf.sh
  1. Créez un fichier .env contenant votre ID de projet Google Cloud pour le déploiement. Mettez à jour le champ YOUR_PROJECT_ID :
cat <<EOF > ~/gemini-cloud-assist-debug/.env
PROJECT_ID=YOUR_PROJECT_ID
USE_PUBLIC_IP=true
EOF

6. Déployer l'application

Le code de l'application et les ressources Google Cloud sont prêts à être déployés. Cette opération peut prendre jusqu'à 15 minutes.

Exécutez la commande suivante à partir du terminal :

cd ~/gemini-cloud-assist-debug
./setup_via_tf.sh

Pendant le déploiement des composants, parcourez les fichiers dans l'éditeur Cloud Shell pour en savoir plus.

7. Créer et déboguer une erreur

Nous allons maintenant déclencher une erreur à partir de l'application. Ouvrez Cloud Run dans le volet de gauche. Cliquez ensuite sur le service auth-issue-demo.

  1. En haut de la page Informations sur le service , une URL s'affiche. Copiez l'URL et ouvrez un nouvel onglet de navigateur. Collez l'URL et ajoutez-y /connect. Votre URL doit ressembler à ceci :

https://auth-issue-demo-.us-central1.run.app/connect

  1. Accédez à l'URL. Le démarrage de l'instance Cloud Run peut prendre quelques secondes. Vous obtiendrez un message d'erreur.
  2. Revenez à la page Informations sur le service de Cloud Run. Cliquez sur Observabilité, puis sur Journaux. Les journaux du conteneur, y compris une erreur, s'affichent. Si le journal d'erreurs n'est pas encore disponible, patientez quelques secondes et actualisez la page à l'aide de l'icône en haut à droite.
  3. Cliquez sur le journal d'erreurs pour en savoir plus. Cliquez sur l'icône d'investigation dans la ligne du journal principal. Cliquez ensuite sur Investigate Log (Examiner le journal).

Le volet de chat Cloud Assist s'ouvre. L'investigation prend deux à trois minutes.

Une fois l'investigation terminée, vous pouvez lire les résultats et les recommandations. Une recommandation consiste à ajouter l'autorisation appropriée au compte de service pour que Cloud Run puisse accéder à l'instance AlloyDB.

8. Corriger l'erreur

Corrigez l'erreur d'autorisation du compte de service.

  1. Accédez à Cloud IAM.
  2. Cliquez sur le bouton Accorder l'accès. Dans le volet principal, commencez par saisir auth-demo, puis attendez que le compte de service s'affiche.
  3. Ensuite, ajoutez le rôle AlloyDB Client au compte de service, puis cliquez sur Enregistrer.

La propagation prend jusqu'à une minute.

Une fois que vous avez attendu, revenez en arrière et actualisez l'application. Un message de réussite s'affiche désormais dans la base de données AlloyDB.

9. Félicitations

Félicitations ! Vous avez terminé cette introduction aux investigations Cloud et au processus de débogage des autorisations d'une application sur Google Cloud.

Étape suivante