🍕 Preparando nuestra Cocina en Google Cloud
¡Bienvenido/a al taller! Durante las próximas 3 horas recorreremos la evolución de cómo llevar aplicaciones a producción: desde levantar una máquina virtual tradicional hasta usar contenedores, Kubernetes, plataformas serverless e Inteligencia Artificial. Todo desde el navegador, sin instalar nada en tu ordenador y sin necesitar tarjeta bancaria gracias a los créditos del taller.
Paso 0.1 — Reclamar tus 5$ de créditos gratuitos para el taller
- Accede a la URL de créditos promocionales: https://g.dev/credits/promo-c4c90cfc43cdbefa
- Inicia sesión con una cuenta personal de Gmail (
@gmail.com).- ¿No tienes una cuenta personal de Gmail (solo tienes correo corporativo o universitario)? Créate una cuenta gratuita de Gmail ahora en un minuto para poder reclamar los créditos sin bloqueos de organización, o bien utiliza tu propia cuenta de facturación personal si ya dispones de una.
- Pulsa para reclamar los créditos y acepta las condiciones si se solicitan. Al terminar, Google habrá creado automáticamente en tu usuario una nueva cuenta de facturación con 5 créditos (5$) disponibles.
@gmail.com personal para evitar confusiones en el siguiente paso.
Paso 0.2 — Crear un Proyecto nuevo en la Consola de Google Cloud
En Google Cloud todos los recursos que creamos viven siempre dentro de un Proyecto. Vamos a crear uno limpio para este taller:
- Entra en https://console.cloud.google.com y comprueba en el avatar de arriba a la derecha que estás con la misma cuenta personal de Gmail con la que reclamaste los créditos. (Si es tu primera vez en la consola, acepta los Términos del Servicio).
- Arriba a la izquierda (justo a la derecha del logo Google Cloud), haz clic en el selector de proyectos (puede poner "Selecciona un proyecto" o "My First Project").
- En la esquina superior derecha de la ventana emergente que se abre, haz clic en "Proyecto nuevo" (New Project).
- Rellena el formulario:
- Nombre del proyecto: Escribe por ejemplo
taller-pizzeria-cloud. - Cuenta de facturación (Billing account): Si aparece este selector, elige la cuenta de créditos promocionales recién creada (suele llamarse Google Cloud Platform Trial Billing Account).
- Ubicación: Déjalo en Sin organización.
- Nombre del proyecto: Escribe por ejemplo
- Haz clic en el botón azul "Crear" (Create), espera unos segundos a que se complete la notificación arriba a la derecha y pulsa "Seleccionar proyecto" (Select Project) para que tu nuevo proyecto aparezca activo arriba a la izquierda.
Paso 0.3 — Verificar que el proyecto está asociado a la cuenta de facturación de 5$
Antes de lanzar máquinas o contenedores, comprobemos que nuestro proyecto nuevo está conectado a la cuenta de facturación de los créditos gratuitos:
- Con tu proyecto
taller-pizzeria-cloudseleccionado arriba a la izquierda, abre el menú principal (icono☰arriba a la izquierda) y haz clic en Facturación (Billing). - Comprueba cuál de estas dos pantallas te aparece:
✅ Caso A: Ya aparece el panel de Resumen
Si ves directamente las gráficas de costes en 0,00 y en la columna derecha el bloque de Créditos promocionales (5$) activo, ¡tu proyecto ya está perfectamente vinculado!
🔗 Caso B: Dice "Este proyecto no tiene cuenta de facturación"
Haz clic en "Vincular una cuenta de facturación" (Link a billing account), selecciona en el desplegable la cuenta creada al canjear tus créditos (Google Cloud Platform Trial Billing Account) y pulsa "Establecer cuenta".
Paso 0.4 — Abrir Cloud Shell, confirmar facturación y encender los servicios
- En la barra superior derecha de la consola de Google Cloud, pulsa el icono de Activar Cloud Shell (
>_). Se abrirá una terminal en la parte inferior; si aparece el botón azul Autorizar, púlsalo. - Pulsa 📋 Copiar aquí abajo, pega el bloque en tu terminal de Cloud Shell y pulsa Enter:
export PROJECT_ID=$(gcloud config get-value project) echo "🍕 Proyecto activo en Cloud Shell: $PROJECT_ID" echo "💳 Comprobando que la cuenta de facturación de 5$ está vinculada (debe salir True):" gcloud billing projects describe "$PROJECT_ID" --format="table(projectId, billingAccountName, billingEnabled)" gcloud config set compute/region europe-west1 gcloud config set compute/zone europe-west1-b gcloud services enable \ compute.googleapis.com \ container.googleapis.com \ run.googleapis.com \ cloudfunctions.googleapis.com \ cloudbuild.googleapis.com \ artifactregistry.googleapis.com echo "✅ ¡Facturación verificada y servicios activados! Cocina lista."
BILLING_ENABLED: True. Si apareciera vacío o en False, revisa el desplegable de proyectos arriba a la izquierda o abre la ayuda de aquí abajo.
❓ ¿Cloud Shell no carga o no aparece tu proyecto seleccionado?
- Si Cloud Shell se queda cargando: Asegúrate de no estar en ventana de Incógnito (o habilita cookies de terceros en
cloud.google.com). - Si
PROJECT_IDsalió vacío: Selecciona tu proyecto en la parte superior de la consola o ejecutagcloud projects listy luegogcloud config set project ID_DE_TU_PROYECTOy vuelve a lanzar el bloque anterior.
🖥️ Compute Engine: "Amasando y horneando en casa"
Empezamos por la opción más cercana al hierro: crear una Máquina Virtual Linux desde cero, entrar dentro por SSH para instalar un servidor web a mano y configurar el Firewall para permitir visitas.
Paso 1.1 — Crear nuestra máquina virtual pizzeria-vm
gcloud compute instances create pizzeria-vm \ --zone=europe-west1-b \ --machine-type=e2-micro \ --image-family=debian-12 \ --image-project=debian-cloud \ --tags=http-server
Paso 1.2 — Entrar por SSH e instalar el servidor web Nginx
Ejecuta este comando para conectarte a tu máquina, instalar Nginx y crear nuestra página web. (Si te pregunta Do you want to continue (Y/n)? escribe Y y pulsa Enter; si pide passphrase pulsa Enter dos veces dejándola vacía):
gcloud compute ssh pizzeria-vm --zone=europe-west1-b --command='
sudo apt-get update -y && sudo apt-get install -y nginx
sudo tee /var/www/html/index.html > /dev/null <<EOF
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Trattoria Cloud - Máquina Virtual</title>
<style>
body { font-family: sans-serif; background: #fff8f5; padding: 2rem; display: flex; justify-content: center; }
.card { max-width: 650px; background: white; padding: 2rem; border-radius: 16px; box-shadow: 0 8px 24px rgba(0,0,0,0.08); border-top: 8px solid #ea4335; }
.meta { background: #f1f3f4; padding: 1rem; border-radius: 10px; font-family: monospace; margin: 1rem 0; }
</style>
</head>
<body>
<div class="card">
<h1>🍕 Trattoria Cloud (Compute Engine)</h1>
<p>¡Tu servidor web Nginx está funcionando dentro de tu Máquina Virtual!</p>
<div class="meta">
<strong>Máquina (Hostname):</strong> $(hostname)<br>
<strong>Modo Pizza:</strong> Amasando y horneando en casa
</div>
<p>⚠️ <strong>El reto:</strong> Si esta máquina se cae a las 3:00 AM o entran 10.000 clientes a la vez, nos toca mantenerlo a nosotros.</p>
</div>
</body>
</html>
EOF
sudo systemctl restart nginx
'
Paso 1.3 — Abrir la regla de Firewall (Puerto 80) y visitar la web
gcloud compute firewall-rules create permitir-http-pizzeria \ --allow=tcp:80 \ --target-tags=http-server \ --description="Abre el puerto 80 para nuestra web en Compute Engine" IP_VM=$(gcloud compute instances describe pizzeria-vm --zone=europe-west1-b --format='get(networkInterfaces[0].accessConfigs[0].natIP)') echo "🎉 Abre este enlace en tu navegador -> http://$IP_VM"
❓ ¿Al abrir la IP no carga la página?
http:// (sin la s del final), ya que en esta máquina virtual solo hemos abierto el puerto 80 sin configurar certificados SSL. Haz clic directamente en el enlace que imprimió el comando anterior en la terminal.Paso 1.4 — Borrar la máquina virtual para cuidar nuestro crédito
gcloud compute instances delete pizzeria-vm --zone=europe-west1-b --quiet
🐳☸️ Contenedores y Kubernetes (GKE)
Vamos a empaquetar una aplicación web en un Contenedor Docker y desplegarla en un clúster real de Kubernetes (GKE) con 3 réplicas trabajando en paralelo, balanceo de carga y autocuración automática.
Paso 2.0 — 🔥 Crear el clúster de GKE (Lánzalo antes de la explicación teórica)
Aprovisionar un clúster de Kubernetes tarda unos 4–5 minutos. Ejecuta este comando ahora mismo y atiende a la explicación mientras Google Cloud prepara tus nodos:
gcloud container clusters create pizzeria-cluster \ --zone=europe-west1-b \ --num-nodes=2 \ --machine-type=e2-small \ --disk-type=pd-standard \ --disk-size=20
Paso 2.1 — Crear nuestra aplicación y su Dockerfile
Cuando el comando anterior haya finalizado, crea la aplicación web. Esta app muestra el identificador y color del contenedor/Pod que responde cada petición:
mkdir -p ~/taller-cloud/lab2-gke && cd ~/taller-cloud/lab2-gke
cat << 'EOF' > requirements.txt
Flask==3.1.0
gunicorn==23.0.0
EOF
cat << 'EOF' > app.py
import os, socket, datetime
from flask import Flask, render_template_string
app = Flask(__name__)
CONTAINER_ID = socket.gethostname()
DEPLOY_MODE = os.environ.get("MODO_DESPLIEGUE", "Contenedor Docker")
PALETTE = ["#1a73e8", "#ea4335", "#34a853", "#9334e6", "#e8710a", "#00897b"]
POD_COLOR = PALETTE[sum(ord(c) for c in CONTAINER_ID) % len(PALETTE)]
HTML = """
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Trattoria Cloud</title>
<style>
body { font-family: system-ui, sans-serif; background: #f8f9fa; padding: 2rem; display: flex; justify-content: center; }
.box { max-width: 680px; width: 100%; background: white; border-radius: 18px; padding: 2rem; box-shadow: 0 12px 30px rgba(0,0,0,0.08); border-top: 10px solid {{ color }}; }
.badge { background: {{ color }}20; color: {{ color }}; padding: 0.4rem 0.9rem; border-radius: 999px; font-weight: 700; font-size: 0.85rem; }
.pod { background: #202124; color: white; padding: 1.2rem; border-radius: 12px; margin: 1.5rem 0; display: flex; justify-content: space-between; align-items: center; }
.pod-id { font-family: monospace; font-size: 1.3rem; color: #8ab4f8; font-weight: bold; }
.btn { display: inline-block; background: {{ color }}; color: white; text-decoration: none; padding: 0.7rem 1.3rem; border-radius: 8px; font-weight: 600; }
</style>
</head>
<body>
<div class="box">
<span class="badge">🚀 {{ mode }}</span>
<h1>🍕 Trattoria Cloud</h1>
<p>Especialidad: <strong>Pizza con Sobrasada y Queso de Mahón</strong></p>
<div class="pod">
<div>
<div style="font-size:0.8rem; color:#9aa0a6;">ATENDIDO POR EL CONTENEDOR / POD:</div>
<div style="font-size:0.85rem; color:#dadce0;">Recarga la página para ver qué réplica te atiende</div>
</div>
<div class="pod-id">{{ cid }}</div>
</div>
<p><small>Hora del servidor: {{ now }} UTC</small></p>
<a class="btn" href="/">🔄 Pedir otra pizza (Recargar)</a>
</div>
</body>
</html>
"""
@app.route("/")
def index():
return render_template_string(HTML, cid=CONTAINER_ID, mode=DEPLOY_MODE, color=POD_COLOR, now=datetime.datetime.utcnow().strftime("%H:%M:%S"))
if __name__ == "__main__":
app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
EOF
cat << 'EOF' > Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
ENV PORT=8080
EXPOSE 8080
CMD ["gunicorn", "--bind", "0.0.0.0:8080", "--workers", "2", "app:app"]
EOF
echo "✅ Archivos listos"
Paso 2.2 — Construir la imagen y guardarla en Artifact Registry
export PROJECT_ID=$(gcloud config get-value project) gcloud artifacts repositories create pizzeria-repo \ --repository-format=docker \ --location=europe-west1 \ --description="Repositorio de contenedores del taller" || true gcloud builds submit \ --tag europe-west1-docker.pkg.dev/$PROJECT_ID/pizzeria-repo/pizzeria-web:v1 .
Paso 2.3 — Desplegar en Kubernetes, escalar a 3 réplicas y exponer al mundo
export PROJECT_ID=$(gcloud config get-value project) kubectl get nodes kubectl create deployment pizzeria-web \ --image=europe-west1-docker.pkg.dev/$PROJECT_ID/pizzeria-repo/pizzeria-web:v1 kubectl set env deployment/pizzeria-web MODO_DESPLIEGUE="Google Kubernetes Engine (GKE)" kubectl scale deployment pizzeria-web --replicas=3 kubectl expose deployment pizzeria-web \ --type=LoadBalancer \ --port=80 \ --target-port=8080
Paso 2.4 — Ver la IP Pública y probar la Autocuración (Self-Healing)
Consulta tus 3 Pods y la dirección EXTERNAL-IP del balanceador:
kubectl get pods kubectl get service pizzeria-web
❓ ¿En EXTERNAL-IP aparece <pending>?
kubectl get service pizzeria-web hasta que aparezca la IP numérica. Ábrela con http://TU_EXTERNAL_IP y pulsa varias veces "Recargar".Ahora destruye uno de los Pods a propósito y comprueba cómo Kubernetes levanta uno nuevo al instante para mantener siempre 3 réplicas:
POD_A_BORRAR=$(kubectl get pods -o jsonpath='{.items[0].metadata.name}')
echo "💥 Eliminando el Pod: $POD_A_BORRAR"
kubectl delete pod $POD_A_BORRAR
kubectl get pods
Paso 2.5 — Eliminar el clúster GKE (¡Importante!)
gcloud container clusters delete pizzeria-cluster --zone=europe-west1-b --quiet
⚡ Cloud Run y Cloud Run Functions: "Pidiendo a domicilio"
¿Y si pudieras desplegar exactamente ese mismo contenedor sin crear clústeres, con HTTPS incluido y pagando 0,00 $ cuando no hay visitas? Vamos a probar Cloud Run y Cloud Run Functions.
Paso 3.1 — Desplegar nuestro contenedor en Cloud Run con un solo comando
export PROJECT_ID=$(gcloud config get-value project) gcloud run deploy pizzeria-serverless \ --image=europe-west1-docker.pkg.dev/$PROJECT_ID/pizzeria-repo/pizzeria-web:v1 \ --region=europe-west1 \ --allow-unauthenticated \ --port=8080 \ --set-env-vars="MODO_DESPLIEGUE=Cloud Run (Serverless - Escalado a 0)"
https://pizzeria-serverless-...run.app). Haz clic en ella para abrir tu aplicación con HTTPS automático.
Paso 3.2 — Desplegar una Cloud Run Function (sin servidor ni Dockerfile)
Cuando solo necesitas ejecutar una pequeña función ante una petición o evento, ni siquiera hace falta un servidor completo:
mkdir -p ~/taller-cloud/lab3-functions && cd ~/taller-cloud/lab3-functions
cat << 'EOF' > requirements.txt
functions-framework==3.*
EOF
cat << 'EOF' > main.py
import math
import functions_framework
@functions_framework.http
def calcular_pizzas(request):
amigos = int(request.args.get("amigos", 6))
hambre = request.args.get("hambre", "normal").lower()
porciones = {"poca": 2, "normal": 3, "mucha": 5}.get(hambre, 3)
total_porciones = amigos * porciones
pizzas = math.ceil(total_porciones / 8)
return f"""
<html><body style="font-family:sans-serif; padding:2rem; background:#f0fdf4;">
<div style="max-width:520px; margin:auto; background:white; padding:2rem; border-radius:16px; border-top:8px solid #16a34a; box-shadow:0 8px 20px rgba(0,0,0,0.06);">
<span style="background:#dcfce7; color:#15803d; padding:4px 10px; border-radius:99px; font-weight:bold; font-size:0.8rem;">⚡ CLOUD RUN FUNCTION</span>
<h1>🍕 Calculadora Serverless de Pizzas</h1>
<p>Para <b>{amigos} amigos</b> con hambre <b>{hambre}</b>:</p>
<h2 style="color:#16a34a; font-size:2.2rem;">¡Pedid {pizzas} pizzas! ({total_porciones} porciones)</h2>
<hr>
<p>Prueba a cambiar los parámetros:</p>
<a href="?amigos=4&hambre=poca">4 amigos (poca hambre)</a> ·
<a href="?amigos=10&hambre=normal">10 amigos (hambre normal)</a> ·
<a href="?amigos=18&hambre=mucha">18 amigos (mucha hambre)</a>
</div>
</body></html>
"""
EOF
gcloud functions deploy calculadora-pizzas \
--gen2 \
--runtime=python312 \
--region=europe-west1 \
--source=. \
--entry-point=calcular_pizzas \
--trigger-http \
--allow-unauthenticated
Al terminar, abre la URL (uri) que aparece en el resultado y prueba los enlaces con distinto número de amigos.
🤖🚀 De unas líneas generadas con IA a una URL pública en Cloud Run
En este reto final crearás tu propia aplicación web apoyándote en Gemini, la probarás en el Editor Visual de Cloud Shell y la dejarás publicada en Internet con Cloud Run sin escribir ningún Dockerfile.
Paso 4.1 — Preparar la carpeta y abrir main.py en el Editor de Cloud Shell
mkdir -p ~/taller-cloud/lab4-mi-app-ia && cd ~/taller-cloud/lab4-mi-app-ia
cat << 'EOF' > requirements.txt
Flask==3.1.0
gunicorn==23.0.0
EOF
cat << 'EOF' > Procfile
web: gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app
EOF
cat << 'EOF' > main.py
import os
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "<h1>¡Listo para pegar aquí el código generado con Gemini!</h1>"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
EOF
cloudshell edit main.py
main.py listo para editar.
Paso 4.2 — Pedir a Gemini que genere nuestra aplicación web
Abre gemini.google.com (o aistudio.google.com), copia este prompt, escribe tu propia idea entre los corchetes y envíalo:
Actúa como un desarrollador experto en Python y Google Cloud Run.
Quiero crear una aplicación web interactiva sobre: [ESCRIBE AQUÍ TU IDEA: por ejemplo, un votador en vivo de pizzas donde cualquiera pueda añadir su pizza favorita y votar las de los demás / un quiz interactivo con puntuación / una calculadora para dividir los gastos de un viaje entre amigos].
Por favor, genera el código cumpliendo ESTRICTAMENTE estas reglas técnicas para que funcione a la primera en Cloud Run:
1. Todo el código (backend en Flask + HTML, CSS moderno y JavaScript dentro de render_template_string) debe ir en UN ÚNICO archivo llamado `main.py`.
2. Usa únicamente la librería estándar de Python y `Flask` (guarda los datos en memoria en una lista o diccionario global de Python, sin bases de datos externas).
3. El diseño visual debe ser muy atractivo, moderno, con tarjetas, emojis y en español.
4. Al final del archivo, incluye obligatoriamente este bloque exacto para arrancar en el puerto que exige Cloud Run:
if __name__ == "__main__":
import os
port = int(os.environ.get("PORT", 8080))
app.run(host="0.0.0.0", port=port)
5. Devuélveme únicamente el código completo de `main.py` listo para copiar y pegar.
Paso 4.3 — Probar tu aplicación antes de publicar
- Copia el código Python generado por Gemini, selecciona todo el contenido de
main.pyen el editor de Cloud Shell (Ctrl+A/Cmd+A), bórralo y pega tu nuevo código. - En la terminal inferior, arráncalo en modo prueba:
cd ~/taller-cloud/lab4-mi-app-ia python3 main.py
Haz clic en el icono de Vista previa web (Web Preview) arriba a la derecha de Cloud Shell y elige Vista previa en el puerto 8080. Cuando termines de verla, pulsa Ctrl+C en la terminal.
❓ ¿Te ha dado algún error de sintaxis el código de la IA o quieres probar una plantilla ya lista?
```python al principio o al final de main.py. Si quieres cargar directamente una app completa de Votación de Pizzas en Vivo para desplegarla ya, copia y ejecuta este bloque en la terminal:
cd ~/taller-cloud/lab4-mi-app-ia
cat << 'EOF' > main.py
import os
from flask import Flask, request, redirect, url_for, render_template_string
app = Flask(__name__)
PIZZAS = [
{"id": 1, "nombre": "Mallorquina (Sobrasada y Queso de Mahón)", "autor": "Laura", "votos": 5},
{"id": 2, "nombre": "Diavola al Horno de Leña", "autor": "Andreu", "votos": 4},
{"id": 3, "nombre": "Cuatro Quesos Serverless", "autor": "Cloud Team", "votos": 3},
]
HTML = """<!DOCTYPE html><html lang="es"><head><meta charset="UTF-8"><title>PizzaParty Live</title>
<style>body{font-family:sans-serif;background:#1e1b4b;padding:2rem;display:flex;justify-content:center;}
.card{max-width:640px;width:100%;background:white;padding:2rem;border-radius:18px;}
.item{display:flex;justify-content:space-between;align-items:center;background:#f8fafc;padding:1rem;border-radius:12px;margin:0.6rem 0;border:1px solid #e2e8f0;}
button{background:#4f46e5;color:white;border:none;padding:0.6rem 1rem;border-radius:8px;font-weight:bold;cursor:pointer;}
input{padding:0.6rem;border:1px solid #cbd5e1;border-radius:8px;margin-right:0.4rem;}</style></head>
<body><div class="card"><h1>🍕 Votación de Pizzas en Vivo</h1>
{% for p in pizzas %}<div class="item"><div><b>{{p.nombre}}</b><br><small>Por {{p.autor}}</small></div>
<form method="POST" action="/votar/{{p.id}}"><button>👍 {{p.votos}}</button></form></div>{% endfor %}
<hr><form method="POST" action="/proponer"><input name="nombre" placeholder="Tu pizza favorita" required>
<input name="autor" placeholder="Tu nombre" required><button type="submit">➕ Añadir</button></form></div></body></html>"""
@app.route("/")
def home():
return render_template_string(HTML, pizzas=sorted(PIZZAS, key=lambda x: x["votos"], reverse=True))
@app.route("/votar/<int:pid>", methods=["POST"])
def votar(pid):
for p in PIZZAS:
if p["id"] == pid: p["votos"] += 1
return redirect(url_for("home"))
@app.route("/proponer", methods=["POST"])
def proponer():
PIZZAS.append({"id": len(PIZZAS)+1, "nombre": request.form.get("nombre","Pizza"), "autor": request.form.get("autor","Anónimo"), "votos": 1})
return redirect(url_for("home"))
if __name__ == "__main__":
app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
EOF
Paso 4.4 — ¡Publicar en Cloud Run con URL abierta para todos!
Ejecuta este comando para empaquetar tu código automáticamente con Buildpacks y desplegarlo en producción (si te pregunta si deseas crear un repositorio para código fuente, escribe Y y pulsa Enter):
cd ~/taller-cloud/lab4-mi-app-ia gcloud run deploy mi-app-ia \ --source . \ --region=europe-west1 \ --allow-unauthenticated
https://mi-app-ia-...run.app) desde tu móvil o compártela con el resto del taller.
🧹 Limpieza Final de Recursos (Opcional)
Los servicios desplegados en Cloud Run y Cloud Run Functions escalan automáticamente a 0 instancias cuando nadie los visita, por lo que puedes mantener tu URL activa para enseñársela a quien quieras casi sin coste.
Borrar todos los recursos restantes cuando ya no los necesites
Si quieres dejar tu proyecto de Google Cloud completamente limpio al acabar el día, ejecuta:
gcloud run services delete pizzeria-serverless --region=europe-west1 --quiet gcloud run services delete mi-app-ia --region=europe-west1 --quiet gcloud functions delete calculadora-pizzas --gen2 --region=europe-west1 --quiet gcloud artifacts repositories delete pizzeria-repo --location=europe-west1 --quiet gcloud compute firewall-rules delete permitir-http-pizzeria --quiet