Encuentra y corrige problemas de la aplicación con Gemini Cloud Assist

1. Introducción

Gemini Cloud Assist es un agente con todas las funciones que admite tus cargas de trabajo de Google Cloud. El agente es tu socio para diseñar aplicaciones nuevas o actualizar las existentes, implementar y ejecutar cargas de trabajo en Google Cloud, solucionar problemas relacionados con las cargas de trabajo y optimizarlas en función del costo y el rendimiento.

Gemini Cloud Assist mejora tu capacidad de responder a errores inesperados y tiempos de inactividad.

Qué aprenderás

  1. Implementación: Cómo implementar una base de datos y un backend básicos en Google Cloud
  2. Depuración: Cómo Gemini Cloud Assist automatiza la investigación y el análisis de causa raíz de problemas de código y de la nube
  3. Corrección: Cómo Gemini Cloud Assist ayuda a identificar correcciones según la causa raíz

2. Configura el proyecto

Cuenta de Google

Si aún no tienes una Cuenta de Google personal, debes crear una.

Usa una cuenta personal en lugar de una cuenta de trabajo o institución educativa.

Accede a la consola de Google Cloud

Accede a la consola de Google Cloud con una Cuenta de Google personal.

Habilitar facturación

Configura una cuenta de facturación personal

Si configuraste la facturación con créditos de Google Cloud, puedes omitir este paso.

Para configurar una cuenta de facturación personal, ve aquí para habilitar la facturación en la consola de Cloud.

Algunas notas:

  • Completar este lab debería costar menos de USD 1 en recursos de Cloud.
  • Puedes seguir los pasos al final de este lab para borrar recursos y evitar cargos adicionales.
  • Los usuarios nuevos pueden acceder a la prueba gratuita de USD 300.

Crear un proyecto (opcional)

Si no tienes un proyecto actual que quieras usar para este lab, crea uno nuevo aquí.

3. Abre el editor de Cloud Shell

  1. Haz clic en este vínculo para navegar directamente al editor de Cloud Shell.
  2. Si se te solicita autorización en algún momento, haz clic en Autorizar para continuar.Haz clic para autorizar Cloud Shell
  3. Si la terminal no aparece en la parte inferior de la pantalla, ábrela:
    • Haz clic en Ver.
    • Haz clic en Terminal.Abre una terminal nueva en el editor de Cloud Shell
  4. En la terminal, configura tu proyecto con este comando:
    gcloud config set project [PROJECT_ID]
    
    • Ejemplo:
      gcloud config set project lab-project-id-example
      
    • Si no recuerdas el ID de tu proyecto, puedes enumerar todos tus IDs de proyecto con el siguiente comando:
      gcloud projects list
      
      Establece el ID del proyecto en la terminal del editor de Cloud Shell
  5. Deberías ver el siguiente mensaje:
    Updated property [core/project].
    

4. Habilita las APIs

Habilita las siguientes APIs para implementar los componentes de la aplicación y usar Google Cloud Assist:

En la terminal, habilita las APIs:

```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. Prepara el proyecto

Crearás la aplicación y la implementación básicas para probar Cloud Assist.

Crea el directorio

  1. Abre el editor de Cloud Shell o el entorno de desarrollo que prefieras.
  2. Crea una carpeta nueva:
    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. En la terminal, ejecuta el siguiente comando para abrir un espacio de trabajo del Editor de Cloud Shell:
cloudshell open-workspace ~/gemini-cloud-assist-debug

Crea los archivos

Ahora crearás los archivos de inicio necesarios para la aplicación.

  1. Para crear el Dockerfile, ejecuta el siguiente comando en la terminal. Este archivo controla la creación del contenedor de la aplicación.
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. Crea el archivo main.py ejecutando lo siguiente en la terminal. Este archivo contiene la aplicación escrita 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. Crea el archivo requirements.txt ejecutando lo siguiente en la terminal. Este archivo controla los requisitos del paquete de 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. Crea el archivo main.tf ejecutando lo siguiente en la terminal. Este archivo controla los recursos de Google Cloud que se crearán.
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. Crea el archivo variables.tf ejecutando lo siguiente en la terminal. Este archivo controla las variables de Terraform para los recursos de 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. Crea el archivo setup_via_tf.sh ejecutando lo siguiente en la terminal. Este archivo controla los requisitos del paquete de 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. Ejecuta el siguiente comando para hacer que la secuencia de comandos de shell sea ejecutable:
chmod +x ~/gemini-cloud-assist-debug/setup_via_tf.sh
  1. Crea un archivo .env que contenga el ID de tu proyecto de Google Cloud para la implementación. Actualiza el campo YOUR_PROJECT_ID:
cat <<EOF > ~/gemini-cloud-assist-debug/.env
PROJECT_ID=YOUR_PROJECT_ID
USE_PUBLIC_IP=true
EOF

6. Implementa la aplicación

El código de la aplicación y los recursos de Google Cloud están listos para la implementación. Esta acción puede llevar hasta 15 minutos.

Ejecuta el siguiente comando desde la terminal:

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

Mientras se implementan los componentes, explora los archivos en el editor de Cloud Shell para obtener más información.

7. Crea y depura un error

Ahora, activaremos un error desde la aplicación. Abre Cloud Run en el panel izquierdo. Luego, haz clic en el servicio auth-issue-demo.

  1. En la parte superior de la página Detalles del servicio, hay una URL. Copia la URL y abre una nueva pestaña del navegador. Pega la URL y agrégale /connect. La URL se verá de la siguiente manera:

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

  1. Ve a la URL. La instancia de Cloud Run puede tardar unos segundos en iniciarse. Recibirás un mensaje de error.
  2. Regresa a la página de detalles del servicio de Cloud Run. Haz clic en Observabilidad y, luego, en Registros. Verás los registros del contenedor, incluido un error. Si el registro de errores aún no está disponible, espera unos segundos y actualiza la página con el ícono que se encuentra en la esquina superior derecha.
  3. Haz clic en el registro de errores para obtener más información. Haz clic en el ícono de investigación en la línea del registro principal. Luego, haz clic en Investigate Log.

Se abrirá el panel de chat de Cloud Assist. La investigación tarda de 2 a 3 minutos en completarse.

Una vez que se complete la investigación, podrás leer los resultados y las recomendaciones. Se recomienda agregar el permiso adecuado a la cuenta de servicio para que Cloud Run acceda a la instancia de AlloyDB.

8. Cómo corregir el error

Corrige el error de permiso de la cuenta de servicio.

  1. Ve a Cloud IAM.
  2. Haz clic en el botón Otorgar acceso. En el panel principal, comienza a escribir auth-demo y espera a que se muestre la cuenta de servicio.
  3. A continuación, agrega el rol AlloyDB Client a la cuenta de servicio y, luego, haz clic en Guardar.

Este proceso tarda hasta un minuto en propagarse.

Una vez que hayas esperado, regresa y actualiza la aplicación. Ahora verás un mensaje de éxito de la base de datos de AlloyDB.

9. Felicitaciones

¡Felicitaciones! Completaste correctamente esta introducción a Cloud Investigations y el proceso de depuración de los permisos de una aplicación en Google Cloud.

Próximos pasos