Encontrar e corrigir problemas de aplicativos com o Gemini Cloud Assist

1. Introdução

O Gemini Cloud Assist é um agente completo que oferece suporte às cargas de trabalho do Google Cloud. Ele é seu parceiro para projetar novos aplicativos ou atualizar os atuais, implantar e executar cargas de trabalho no Google Cloud, solucionar problemas e otimizar custos e desempenho.

O Gemini Cloud Assist melhora sua capacidade de responder a erros inesperados e inatividade.

O que você vai aprender

  1. Implantação: como implantar um back-end e um banco de dados básicos no Google Cloud.
  2. Depuração: como o Gemini Cloud Assist automatiza a investigação e a análise da causa raiz de problemas de nuvem e de código.
  3. Correção: como o Gemini Cloud Assist ajuda a identificar correções com base na causa raiz.

2. Configurar o projeto

Conta do Google

Se você ainda não tiver uma Conta do Google pessoal, crie uma Conta do Google.

Use uma conta pessoal em vez de uma conta escolar ou do trabalho.

Fazer login no console do Google Cloud

Faça login no console do Google Cloud usando uma Conta do Google pessoal.

Ativar faturamento

Configurar uma conta de faturamento pessoal

Se você configurou o faturamento usando créditos do Google Cloud, pule esta etapa.

Para configurar uma conta de faturamento pessoal, acesse este link para ativar o faturamento no console do Cloud.

Algumas observações:

  • A conclusão deste laboratório custa menos de US $1 em recursos do Cloud.
  • Siga as etapas no final deste laboratório para excluir recursos e evitar mais cobranças.
  • Novos usuários podem aproveitar a avaliação sem custos de US$300.

Criar um projeto (opcional)

Se você não tiver um projeto atual que gostaria de usar para este laboratório, crie um novo projeto aqui.

3. Abrir editor do Cloud Shell

  1. Clique neste link para navegar diretamente até o editor do Cloud Shell.
  2. Se for solicitado a autorizar a qualquer momento, clique em Autorizar para continuar.Clique para autorizar o Cloud Shell
  3. Se o terminal não aparecer na parte de baixo da tela, abra-o:
    • Clique em Visualizar.
    • Clique em TerminalAbrir um novo terminal no editor do Cloud Shell
  4. No terminal, defina o projeto com este comando:
    gcloud config set project [PROJECT_ID]
    
    • Exemplo:
      gcloud config set project lab-project-id-example
      
    • Se você não se lembrar do ID do projeto, liste todos os IDs com:
      gcloud projects list
      
      Definir o ID do projeto no terminal do Editor do Cloud Shell
  5. Você vai receber esta mensagem:
    Updated property [core/project].
    

4. Ativar APIs

Ative as APIs a seguir para que os componentes do aplicativo sejam implantados e para usar o Google Cloud Assist:

No terminal, ative as 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. Preparar o projeto

Você vai criar o aplicativo e a implantação básicos para testar o Cloud Assist.

Criar o diretório

  1. Abra o editor do Cloud Shell ou o ambiente de desenvolvedor de sua preferência.
  2. Crie uma pasta:
    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. No terminal, execute o comando a seguir para abrir um espaço de trabalho do editor do Cloud Shell:
cloudshell open-workspace ~/gemini-cloud-assist-debug

Criar os arquivos

Agora você vai criar os arquivos iniciais necessários para o aplicativo.

  1. Crie o Dockerfile executando o comando a seguir no terminal. Esse arquivo processa a criação do contêiner do aplicativo.
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. Crie o arquivo main.py executando o comando a seguir no terminal. Esse arquivo contém o aplicativo escrito em 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. Crie o arquivo requirements.txt executando o comando a seguir no terminal. Esse arquivo processa os requisitos do pacote 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. Crie o arquivo main.tf executando o comando a seguir no terminal. Esse arquivo processa os recursos do Google Cloud a serem criados.
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. Crie o arquivo variables.tf executando o comando a seguir no terminal. Esse arquivo processa as variáveis do Terraform para os recursos do 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. Crie o arquivo setup_via_tf.sh executando o comando a seguir no terminal. Esse arquivo processa os requisitos do pacote 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. Execute o comando a seguir para tornar o script de shell executável:
chmod +x ~/gemini-cloud-assist-debug/setup_via_tf.sh
  1. Crie um arquivo .env que contenha o ID do projeto na nuvem do Google Cloud para implantação. Atualize o campo YOUR_PROJECT_ID:
cat <<EOF > ~/gemini-cloud-assist-debug/.env
PROJECT_ID=YOUR_PROJECT_ID
USE_PUBLIC_IP=true
EOF

6. Implantar o aplicativo

O código do aplicativo e os recursos do Google Cloud estão prontos para implantação. Isso pode levar até 15 minutos.

Execute o seguinte comando no terminal:

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

Enquanto os componentes são implantados, navegue pelos arquivos no editor do Cloud Shell para saber mais.

7. Criar e depurar um erro

Agora, vamos acionar um erro no aplicativo. Abra o Cloud Run no painel à esquerda. Em seguida, clique no serviço auth-issue-demo.

  1. Na parte de cima da página Detalhes do serviço , há um URL. Copie o URL e abra uma nova guia do navegador. Cole o URL e adicione /connect a ele. O URL será parecido com este:

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

  1. Acesse o URL. Pode levar alguns segundos para que a instância do Cloud Run seja iniciada. Isso resultará em um erro.
  2. Volte para a página de detalhes do serviço Cloud Run. Clique em Observabilidade e em Registros. Você vai encontrar os registros do contêiner, incluindo um erro. Se o registro de erros ainda não estiver disponível, aguarde alguns segundos e atualize a página usando o ícone no canto superior direito.
  3. Clique no registro de erros para ler mais. Clique no ícone de investigação na linha do registro principal. Em seguida, clique em Investigar registro.

O painel de chat do Cloud Assist será aberto. A investigação leva de 2 a 3 minutos para ser concluída.

Depois que a investigação for concluída, você poderá ler os resultados e as recomendações. Há uma recomendação para adicionar a concessão adequada à conta de serviço para que o Cloud Run acesse a instância do AlloyDB.

8. Corrigir o erro

Corrija o erro de permissão da conta de serviço.

  1. Acesse o Cloud IAM.
  2. Clique no botão Conceder acesso. No painel principal, comece digitando auth-demo e aguarde a exibição da conta de serviço.
  3. Em seguida, adicione o papel AlloyDB Client à conta de serviço e clique em Salvar.

Isso leva até um minuto para ser propagado.

Depois de esperar, volte e atualize o aplicativo. Agora você vai receber uma mensagem de sucesso do banco de dados do AlloyDB.

9. Parabéns

Parabéns! Você concluiu esta introdução às investigações do Cloud e ao processo de depuração das permissões de um aplicativo no Google Cloud.

A seguir