Cerrábamos el módulo 1 con una promesa: dejar de planificar y empezar a construir. Esta lección la cumple. Compute Engine es el servicio de máquinas virtuales de Google Cloud y, aunque hoy existan opciones más modernas —contenedores, PaaS, serverless—, sigue siendo la puerta de entrada natural para una empresa como AlpinaShop, que hoy tiene su catálogo Flask corriendo sobre un servidor físico alquilado y necesita moverlo a la nube sin reescribirlo.
En esta lección aprenderás qué es realmente una VM gestionada y cuándo sigue siendo la elección correcta; cómo se organizan las familias y los tipos de máquina, y cómo evitar pagar de más eligiendo mal; qué imágenes puedes usar y cómo crear las tuyas; los tipos de disco y su rendimiento; cómo crear la instancia alpinashop-web-1 en europe-west1-b desde la consola y desde gcloud, con un startup script que instala la aplicación sola; cómo entrar por SSH de forma segura con OS Login; y, sobre todo, cómo las plantillas de instancia y los grupos de instancias gestionados resuelven el problema real de AlpinaShop: los picos de tráfico de las campañas de otoño.
Contenido
- Qué es una máquina virtual gestionada y cuándo usarla
- Familias y tipos de máquina
- Imágenes públicas y personalizadas
- Discos: tipos, rendimiento e instantáneas
- Crear
alpinashop-web-1desde la consola - Crear la misma VM con
gcloudy un startup script - Acceso por SSH y OS Login
- Cuentas de servicio y ámbitos de acceso
- Plantillas de instancia y grupos gestionados (MIG)
- Autoescalado y reparación automática: los picos de otoño
- VMs Spot: cómputo barato e interrumpible
- Ciclo de vida de una instancia y qué se cobra en cada estado
- Qué es una máquina virtual gestionada y cuándo usarla
Una máquina virtual de Compute Engine es un ordenador completo que se ejecuta sobre la infraestructura de Google: tiene su CPU, su memoria, sus discos, su sistema operativo y su dirección IP. Desde dentro, es indistinguible de un servidor físico. La diferencia está en todo lo que la rodea: se crea en 30 segundos con un comando, se redimensiona apagándola y encendiéndola, se replica cien veces con una plantilla y desaparece cuando la borras.
Que sea gestionada significa que Google se ocupa del hardware, la virtualización, la red física, la refrigeración y el reemplazo de discos averiados. Tú te ocupas del sistema operativo hacia arriba: parches, configuración, aplicación, datos. Es exactamente el reparto IaaS que vimos en la tabla de responsabilidad compartida de la lección 01-05.
Cuándo sigue teniendo sentido una VM en 2026, con tanta alternativa serverless disponible:
- Migración lift-and-shift. Tienes una aplicación que funciona y quieres moverla sin reescribirla. Es el caso de AlpinaShop.
- Necesitas control del sistema operativo. Kernel concreto, módulos, drivers, software con licencia atada a hardware, agentes de seguridad corporativos.
- Procesos de larga duración o siempre activos. Serverless penaliza (o directamente prohíbe) procesos de horas.
- Software que no se contenedoriza bien. Aplicaciones monolíticas antiguas, sistemas con estado en disco local, servidores de licencias.
- Cargas con hardware especial. GPU para inferencia, discos locales de latencia mínima, máquinas de mucha memoria para bases de datos en RAM.
- Coste predecible a alto uso constante. Una VM 24×7 con descuento por uso comprometido puede salir más barata que su equivalente serverless.
Cuándo NO es la elección adecuada: una API HTTP con tráfico intermitente (mejor Cloud Run, 07-02), un trabajo que responde a un evento y dura segundos (Cloud Functions, 06-03) o una aplicación web ya contenedorizada que quieres escalar horizontalmente (GKE, 02-05). En la lección 02-07 pondremos todo esto en una tabla de decisión.
- Familias y tipos de máquina
El tipo de máquina define cuántas CPU virtuales (vCPU) y cuánta memoria tiene la instancia. Google los agrupa en familias, cada una optimizada para un perfil de carga distinto. Elegir bien aquí es la decisión que más impacto tiene en la factura de cómputo.
| Familia | Perfil | vCPU/memoria típicos | Para qué sirve | Ejemplo de tipo |
|---|---|---|---|---|
| E2 | Uso general económico | 2–32 vCPU, ratios flexibles | Servidores web pequeños, entornos de desarrollo, microservicios. La opción por defecto para empezar | e2-medium (2 vCPU, 4 GB) |
| N2 / N2D | Uso general equilibrado | 2–128 vCPU | Cargas de producción generales. N2D usa AMD EPYC y suele salir algo más barata | n2-standard-4 (4 vCPU, 16 GB) |
| N4 / C4 | Generaciones recientes | Amplio | Sustitutos modernos de N2/C2 con mejor relación precio-rendimiento en las regiones donde están disponibles | n4-standard-4 |
| C3 / C3D | Optimizada para cómputo | 4–176 vCPU | CPU intensiva: renderizado, compilación, simulación, servidores de juegos, procesamiento de imágenes | c3-highcpu-8 |
| M3 / M2 / M1 | Optimizada para memoria | Hasta varios TB de RAM | SAP HANA, bases de datos en memoria, análisis de grandes datasets en RAM | m3-ultramem-32 |
| A3 / G2 | Aceleradores | Con GPU (NVIDIA) | Entrenamiento e inferencia de modelos, transcodificación de vídeo | a3-highgpu-8g |
| Personalizada | A medida | Tú eliges vCPU y RAM | Cuando ningún tipo estándar encaja y pagas memoria o CPU que no usas | custom-6-16384 |
Dentro de cada familia hay sufijos que indican el ratio memoria/CPU:
-highcpu: poca memoria por vCPU (≈1 GB). Para procesos de cálculo.-standard: ratio equilibrado (≈4 GB por vCPU). El caso general.-highmem: mucha memoria por vCPU (≈8 GB). Cachés, bases de datos.-ultramem/-megamem: extremos de memoria, solo en familias M.
Tipos personalizados. Si tu aplicación necesita 6 vCPU y 16 GB, ningún tipo estándar te da exactamente eso: n2-standard-8 te daría 8 vCPU y 32 GB, y pagarías el doble de lo que necesitas. La sintaxis de un tipo personalizado es <familia>-custom-<vCPU>-<MiB de memoria>:
# 6 vCPU y 16 GB (16384 MiB) sobre la familia N2
gcloud compute instances create ejemplo-custom \
--machine-type=n2-custom-6-16384 \
--zone=europe-west1-bTen en cuenta las restricciones: el número de vCPU debe ser par (salvo 1), y la memoria por vCPU tiene un mínimo y un máximo por familia. Si te pasas del máximo estándar, se factura como "memoria extendida", más cara.
¿Qué elige AlpinaShop? Su catálogo Flask sirve hoy unas pocas decenas de peticiones por segundo, con picos concentrados en otoño. Empezamos con e2-medium (2 vCPU, 4 GB) en desarrollo y e2-standard-2 en producción, sabiendo que el crecimiento se resolverá horizontalmente (más instancias) y no verticalmente (una instancia más grande). Esta decisión —escalar a lo ancho, no a lo alto— es la que hace posible el autoescalado del apartado 10.
Sobre precios: todos los importes de este curso son órdenes de magnitud para razonar, no tarifas. Los precios varían por región y cambian con el tiempo; consulta siempre la calculadora oficial de Google Cloud y la página de precios de Compute Engine antes de comprometerte.
- Imágenes públicas y personalizadas
Una imagen es la plantilla del disco de arranque: el sistema operativo y el software preinstalado. Google mantiene un catálogo de imágenes públicas, agrupadas en familias de imágenes que siempre apuntan a la versión más reciente.
# Ver las familias de imagenes de Debian disponibles
gcloud compute images list \
--filter="family~debian" \
--format="table(name, family, status)"Las más habituales:
| Familia de imagen | Proyecto | Notas |
|---|---|---|
debian-12 |
debian-cloud |
Ligera, estable, la elección por defecto en GCP |
ubuntu-2404-lts |
ubuntu-os-cloud |
Muy común, mucha documentación de terceros |
rocky-linux-9 |
rocky-linux-cloud |
Compatible con RHEL, sin coste de licencia |
rhel-9 |
rhel-cloud |
Red Hat oficial, con coste de licencia añadido |
cos-stable |
cos-cloud |
Container-Optimized OS: mínima, pensada solo para ejecutar contenedores |
windows-2022 |
windows-cloud |
Windows Server, con licencia facturada por hora |
Usar la familia en lugar del nombre exacto (--image-family=debian-12 en lugar de --image=debian-12-bookworm-v20260101) es una buena práctica: cada VM nueva arranca con la última versión parcheada.
Imágenes personalizadas. Cuando tienes una VM configurada como quieres —dependencias instaladas, agentes, configuración de la empresa— puedes convertirla en imagen y usarla como base de todas las demás. Es la técnica clave para que las instancias nuevas arranquen en segundos en lugar de minutos:
# 1. Detener la instancia para garantizar consistencia del disco
gcloud compute instances stop alpinashop-web-1 --zone=europe-west1-b
# 2. Crear la imagen a partir de su disco de arranque
gcloud compute images create alpinashop-web-base-v1 \
--source-disk=alpinashop-web-1 \
--source-disk-zone=europe-west1-b \
--family=alpinashop-web \
--description="Debian 12 + Python + Flask + dependencias del catalogo"Al asignarle --family=alpinashop-web, las versiones posteriores (-v2, -v3) formarán una familia propia y podrás crear VMs con --image-family=alpinashop-web --image-project=alpinashop-prod, obteniendo siempre la última.
En el módulo 6 verás cómo automatizar la construcción de estas imágenes en un pipeline; por ahora, hacerlo a mano es suficiente para entender el mecanismo.
- Discos: tipos, rendimiento e instantáneas
Toda VM necesita al menos un disco de arranque, y puede tener discos adicionales. La elección del tipo de disco afecta al rendimiento tanto o más que la CPU.
| Tipo | Nombre en gcloud |
Rendimiento | Persistencia | Cuándo usarlo |
|---|---|---|---|---|
| Persistente estándar | pd-standard |
Bajo (HDD) | Sobrevive a la VM | Datos fríos, logs, copias. Casi obsoleto |
| Persistente balanceado | pd-balanced |
Medio-alto (SSD) | Sobrevive a la VM | Opción por defecto. Arranque y datos generales |
| Persistente SSD | pd-ssd |
Alto, IOPS elevadas | Sobrevive a la VM | Bases de datos, cargas con muchas escrituras aleatorias |
| Persistente extremo | pd-extreme |
Muy alto, IOPS aprovisionables | Sobrevive a la VM | Bases de datos críticas de gran tamaño |
| Hyperdisk | hyperdisk-balanced, hyperdisk-extreme, hyperdisk-throughput |
Configurable: IOPS y caudal independientes del tamaño | Sobrevive a la VM | Generación actual en familias modernas (C3, N4, M3); permite ajustar rendimiento sin sobredimensionar el tamaño |
| SSD local | local-ssd |
Máximo, latencia mínima | Se pierde al parar o borrar la VM | Caché, scratch, índices reconstruibles. Nunca datos únicos |
| Disco persistente regional | --region en vez de --zone |
Algo menor que su equivalente zonal | Replicado síncronamente en dos zonas | Cuando necesitas que los datos sobrevivan a la caída de una zona |
Puntos que suelen sorprender a quien viene de un servidor físico:
- En los discos persistentes tradicionales, el rendimiento escala con el tamaño. Un
pd-balancedde 10 GB tiene muy pocas IOPS. Si tu base de datos va lenta, a veces la solución es agrandar el disco aunque no necesites el espacio. Con Hyperdisk esto se rompe: el rendimiento se aprovisiona por separado. - El rendimiento también está limitado por el tipo de máquina. Una VM de 2 vCPU no alcanzará el caudal máximo del disco aunque el disco lo permita.
- Los discos persistentes ya están replicados dentro de su zona. No necesitas RAID por fiabilidad.
- El SSD local es efímero de verdad. Si paras la instancia, el contenido desaparece. Es un error frecuente y caro.
Instantáneas (snapshots) e imágenes de disco. Son dos mecanismos distintos que se confunden a menudo:
| Instantánea | Imagen | |
|---|---|---|
| Propósito | Copia de seguridad puntual | Plantilla para crear VMs nuevas |
| Incremental | Sí (solo bloques cambiados desde la anterior) | No |
| Alcance | Global, se puede restaurar en otra región | Global |
| Uso típico | Recuperación ante desastre, backup diario | Estandarizar el arranque de una flota |
Crear una instantánea y programarlas automáticamente:
# Instantanea puntual del disco de arranque
gcloud compute snapshots create alpinashop-web-1-snap-20260805 \
--source-disk=alpinashop-web-1 \
--source-disk-zone=europe-west1-b \
--storage-location=europe-west1
# Politica de instantaneas diarias a las 03:00 UTC, con 14 dias de retencion
gcloud compute resource-policies create snapshot-schedule alpinashop-diario \
--region=europe-west1 \
--max-retention-days=14 \
--daily-schedule \
--start-time=03:00 \
--on-source-disk-delete=apply-retention-policy
# Asociar la politica al disco
gcloud compute disks add-resource-policies alpinashop-web-1 \
--resource-policies=alpinashop-diario \
--zone=europe-west1-bEste bloque merece detenerse. --max-retention-days=14 significa que las instantáneas más antiguas de 14 días se borran solas, lo que evita que el coste crezca indefinidamente. --on-source-disk-delete=apply-retention-policy indica que, si alguien borra el disco, las instantáneas no se borran inmediatamente sino que siguen su política de retención: es tu red de seguridad ante un borrado accidental. Marta tendrá copias diarias sin escribir un solo cron.
- Crear
alpinashop-web-1 desde la consola
alpinashop-web-1 desde la consolaAntes de automatizar conviene ver el formulario completo una vez, porque enseña qué opciones existen. En la consola: Compute Engine → Instancias de VM → Crear instancia.
Los campos que importan:
- Nombre:
alpinashop-web-1. Minúsculas, guiones, sin acentos. No se puede cambiar después. - Región y zona:
europe-west1/europe-west1-b, la decisión que tomamos en 01-05. - Configuración de la máquina: familia Uso general → serie E2 → tipo
e2-medium. - Disco de arranque: Debian 12,
pd-balanced, 20 GB. - Identidad y acceso a la API: cuenta de servicio y ámbitos (apartado 8).
- Firewall: las casillas "Permitir tráfico HTTP/HTTPS" añaden etiquetas de red y crean reglas de firewall. Las usaremos para probar, pero el diseño correcto de red y firewall es materia de la lección 03-01.
- Opciones avanzadas → Automatización: aquí se pega el startup script.
- Etiquetas (labels):
entorno=dev,equipo=plataforma,centro-coste=tienda,aplicacion=catalogo, siguiendo el esquema que fijamos en 01-04.
Antes de pulsar Crear, usa el enlace "Línea de comandos equivalente" que vimos en 01-03: te devuelve el comando gcloud exacto. Es la mejor forma de aprender la sintaxis y el primer paso hacia la infraestructura como código.
- Crear la misma VM con
gcloud y un startup script
gcloud y un startup scriptUn startup script es un script que la VM ejecuta como root en cada arranque. Es la forma más simple de configuración automática: sin él, tendrías que entrar por SSH y teclear los comandos a mano en cada instancia nueva, lo que hace imposible el autoescalado.
Primero escribimos el script en un fichero aparte (más legible y versionable que meterlo en línea):
cat > ~/startup-catalogo.sh <<'SCRIPT'
#!/bin/bash
set -e
# Instalar dependencias del sistema
apt-get update
apt-get install -y python3-pip python3-venv
# Crear el entorno de la aplicacion
mkdir -p /opt/alpinashop
python3 -m venv /opt/alpinashop/venv
/opt/alpinashop/venv/bin/pip install flask gunicorn
# Aplicacion Flask minima del catalogo
cat > /opt/alpinashop/app.py <<'PYCODE'
from flask import Flask
import socket
app = Flask(__name__)
PRODUCTOS = [
{"sku": "MOC-40", "nombre": "Mochila Trekking 40L", "precio": 89.90},
{"sku": "BOT-GTX", "nombre": "Botas Gore-Tex Alpina", "precio": 149.00},
{"sku": "TDA-2P", "nombre": "Tienda 2 plazas Ultralight", "precio": 219.50},
]
@app.route("/")
def catalogo():
filas = "".join(
f"<li>{p['sku']} - {p['nombre']} - {p['precio']:.2f} EUR</li>"
for p in PRODUCTOS
)
return (
f"<h1>AlpinaShop</h1><ul>{filas}</ul>"
f"<p>Servido por: {socket.gethostname()}</p>"
)
@app.route("/salud")
def salud():
return "ok", 200
PYCODE
# Servicio systemd para que arranque solo y se reinicie si falla
cat > /etc/systemd/system/alpinashop.service <<'UNIT'
[Unit]
Description=Catalogo AlpinaShop
After=network.target
[Service]
WorkingDirectory=/opt/alpinashop
ExecStart=/opt/alpinashop/venv/bin/gunicorn -b 0.0.0.0:80 -w 2 app:app
Restart=always
[Install]
WantedBy=multi-user.target
UNIT
systemctl daemon-reload
systemctl enable --now alpinashop
SCRIPTTres detalles del script que conviene entender:
set -eaborta el script en cuanto un comando falla. Sin esto, unapt-getfallido pasaría desapercibido y acabarías con una VM a medio configurar que parece sana.<<'SCRIPT'con comillas simples impide que bash sustituya las variables al escribir el fichero; queremos que el contenido llegue literal a la VM.- La ruta
/saludexiste para que, más adelante, el grupo de instancias pueda comprobar si la aplicación está viva. Devolver 200 en una ruta ligera es la base de cualquier health check.
Ahora creamos la instancia:
gcloud compute instances create alpinashop-web-1 \
--project=alpinashop-dev \
--zone=europe-west1-b \
--machine-type=e2-medium \
--image-family=debian-12 \
--image-project=debian-cloud \
--boot-disk-size=20GB \
--boot-disk-type=pd-balanced \
--tags=http-server \
--metadata-from-file=startup-script=$HOME/startup-catalogo.sh \
--metadata=enable-oslogin=TRUE \
--labels=entorno=dev,equipo=plataforma,centro-coste=tienda,aplicacion=catalogoFlag por flag:
--image-family+--image-project: siempre la última Debian 12 parcheada.--tags=http-server: etiqueta de red que asocia la VM a la regla de firewall que permite el puerto 80. Las reglas de firewall se estudian en 03-01; aquí basta con saber que sin la etiqueta correcta el tráfico no llega.--metadata-from-file=startup-script=...: la clave de metadatosstartup-scriptes especial, el agente invitado la ejecuta en cada arranque.--metadata=enable-oslogin=TRUE: activa OS Login (apartado 7).--labels: etiquetas de facturación, no de red. No confundas--tagscon--labels: los primeros gobiernan el firewall, las segundas la contabilidad.
Comprobamos que funciona:
# Ver la IP externa asignada
gcloud compute instances describe alpinashop-web-1 \
--zone=europe-west1-b \
--format="value(networkInterfaces[0].accessConfigs[0].natIP)"
# Si aun no existe la regla de firewall, crearla (detalle en 03-01)
gcloud compute firewall-rules create permitir-http \
--allow=tcp:80 \
--target-tags=http-server \
--description="Acceso HTTP temporal para pruebas del catalogo"
# Probar (el startup script tarda 1-2 minutos la primera vez)
IP=$(gcloud compute instances describe alpinashop-web-1 \
--zone=europe-west1-b \
--format="value(networkInterfaces[0].accessConfigs[0].natIP)")
curl -s "http://$IP/"Si no responde, el sitio donde mirar es el log del script:
gcloud compute ssh alpinashop-web-1 --zone=europe-west1-b \
--command="sudo journalctl -u google-startup-scripts.service --no-pager | tail -40"
- Acceso por SSH y OS Login
Hay tres formas de entrar en una VM de Linux:
| Método | Cómo funciona | Ventajas | Inconvenientes |
|---|---|---|---|
| SSH desde el navegador | Botón SSH en la consola; Google genera claves efímeras | Cero configuración, funciona desde cualquier sitio | Requiere que la VM tenga IP pública o IAP configurado |
gcloud compute ssh |
Genera un par de claves en ~/.ssh/google_compute_engine y lo publica |
Cómodo, integrado con tu identidad de gcloud | Depende del CLI instalado |
| Cliente SSH propio | Añades tu clave pública a los metadatos o a OS Login | Compatible con tus herramientas | Gestión manual de claves |
Ejemplos:
# Entrar en la VM
gcloud compute ssh alpinashop-web-1 --zone=europe-west1-b
# Ejecutar un comando sin sesion interactiva
gcloud compute ssh alpinashop-web-1 --zone=europe-west1-b \
--command="systemctl status alpinashop --no-pager"
# Copiar un fichero a la VM
gcloud compute scp ./catalogo.csv alpinashop-web-1:/tmp/ --zone=europe-west1-b
# Entrar sin IP publica, a traves de IAP (tunel seguro)
gcloud compute ssh alpinashop-web-1 --zone=europe-west1-b --tunnel-through-iapPor qué OS Login es lo recomendado. Sin OS Login, las claves SSH se guardan en los metadatos de la instancia o del proyecto. Eso tiene tres problemas serios: cualquiera con permiso para editar metadatos puede añadir su clave y entrar; cuando alguien deja la empresa hay que recorrer las instancias borrando su clave a mano; y no queda un rastro claro de quién entró.
OS Login vincula la cuenta SSH del Linux a la identidad de Google Cloud. Con ello:
- El acceso se concede con roles IAM (
roles/compute.osLoginpara usuario normal,roles/compute.osAdminLoginpara sudo), no manipulando ficheros. - Cuando se desactiva la cuenta de un empleado en Cloud Identity, pierde el acceso a todas las VM inmediatamente.
- Los accesos quedan auditados en Cloud Logging.
- Se puede exigir verificación en dos pasos con
enable-oslogin-2fa=TRUE.
Actívalo a nivel de proyecto para que aplique a todas las instancias, presentes y futuras:
gcloud compute project-info add-metadata \
--metadata=enable-oslogin=TRUE
# Conceder a Dani acceso SSH normal (sin sudo)
gcloud projects add-iam-policy-binding alpinashop-dev \
--member="user:[email protected]" \
--role="roles/compute.osLogin"El detalle de cómo se componen los roles IAM lo veremos en 03-04; aquí basta con retener la idea: el acceso a los servidores se gestiona con identidades, no con ficheros de claves repartidos.
- Cuentas de servicio y ámbitos de acceso
Toda VM se ejecuta como alguien. Ese alguien es una cuenta de servicio: una identidad no humana que la aplicación usa para llamar a otras APIs de Google Cloud. Cuando el catálogo de AlpinaShop suba una imagen a alpinashop-catalogo (lección 02-02), no usará contraseñas: usará la cuenta de servicio de la VM.
Por defecto se asigna la cuenta de servicio predeterminada de Compute Engine, que tiene el rol de Editor sobre todo el proyecto. Es demasiado permisiva: si alguien compromete la aplicación web, obtiene control casi total del proyecto. La práctica correcta es crear una cuenta de servicio dedicada con solo los permisos necesarios:
# Crear una cuenta de servicio propia para el catalogo
gcloud iam service-accounts create sa-catalogo-web \
--display-name="Catalogo web de AlpinaShop"
# Darle solo lo que necesita: leer y escribir objetos en Storage
gcloud projects add-iam-policy-binding alpinashop-dev \
--member="serviceAccount:[email protected]" \
--role="roles/storage.objectAdmin"
# Asignarla a la VM (requiere la VM parada)
gcloud compute instances set-service-account alpinashop-web-1 \
--zone=europe-west1-b \
--service-account="[email protected]" \
--scopes=cloud-platformSobre los ámbitos (scopes): son un mecanismo antiguo que limita qué APIs puede invocar la VM, además de lo que permite IAM. El permiso efectivo es la intersección de ambos. La recomendación actual es usar --scopes=cloud-platform y controlar los permisos reales con roles IAM, que son mucho más granulares. Todo esto se desarrolla en 03-04.
- Plantillas de instancia y grupos gestionados (MIG)
Una sola VM tiene dos problemas: si se cae, el sitio se cae; y si llega un pico de tráfico, no hay a dónde crecer. La solución de Compute Engine son las plantillas de instancia y los grupos de instancias gestionados.
- Plantilla de instancia (instance template): la definición inmutable de cómo es una VM (tipo, imagen, discos, red, metadatos, script). No crea nada por sí sola; es un molde. Como es inmutable, cambiar algo significa crear una plantilla nueva.
- Grupo de instancias gestionado (MIG): un conjunto de VM idénticas creadas a partir de una plantilla, que el sistema mantiene vivas y en el número que le indiques.
graph TD
A[Plantilla de instancia<br/>alpinashop-web-tpl-v1] --> B[MIG alpinashop-web-mig]
B --> C[VM alpinashop-web-mig-a1b2]
B --> D[VM alpinashop-web-mig-c3d4]
B --> E[VM alpinashop-web-mig-e5f6]
F[Comprobacion de estado<br/>GET /salud] --> B
G[Politica de autoescalado<br/>CPU objetivo 60 por ciento] --> B
Creamos la plantilla a partir de todo lo que ya sabemos:
gcloud compute instance-templates create alpinashop-web-tpl-v1 \
--machine-type=e2-medium \
--image-family=debian-12 \
--image-project=debian-cloud \
--boot-disk-size=20GB \
--boot-disk-type=pd-balanced \
--tags=http-server \
--metadata-from-file=startup-script=$HOME/startup-catalogo.sh \
--metadata=enable-oslogin=TRUE \
--service-account="[email protected]" \
--scopes=cloud-platform \
--labels=entorno=prod,equipo=plataforma,centro-coste=tienda,aplicacion=catalogoDefinimos una comprobación de estado y creamos el grupo regional (repartido entre las zonas de europe-west1, para sobrevivir a la caída de una zona, tal como razonamos en 01-05):
# Comprobacion de estado: pide /salud cada 10 s
gcloud compute health-checks create http hc-catalogo \
--port=80 \
--request-path=/salud \
--check-interval=10s \
--timeout=5s \
--healthy-threshold=2 \
--unhealthy-threshold=3
# Grupo gestionado regional con 2 instancias iniciales
gcloud compute instance-groups managed create alpinashop-web-mig \
--template=alpinashop-web-tpl-v1 \
--size=2 \
--region=europe-west1 \
--health-check=hc-catalogo \
--initial-delay=180--initial-delay=180 es importante: le dice al grupo que espere 3 minutos antes de considerar enferma a una instancia recién creada. Sin ese margen, el startup script todavía estaría instalando dependencias, el health check fallaría y el MIG entraría en un bucle de destruir y recrear instancias que nunca llegan a arrancar. Es uno de los errores clásicos.
- Autoescalado y reparación automática: los picos de otoño
Aquí está la respuesta al problema que arrastra AlpinaShop desde la primera lección: en las campañas de otoño el servidor físico se satura y la tienda va lenta justo cuando más vende.
gcloud compute instance-groups managed set-autoscaling alpinashop-web-mig \
--region=europe-west1 \
--min-num-replicas=2 \
--max-num-replicas=10 \
--target-cpu-utilization=0.60 \
--cool-down-period=120Qué hace exactamente:
--min-num-replicas=2: nunca baja de 2 instancias, en zonas distintas. Es el mínimo para que una caída zonal no deje la tienda sin servicio.--max-num-replicas=10: techo de seguridad. Protege la factura ante un pico anómalo o un ataque; sin techo, un bot podría multiplicar tu gasto.--target-cpu-utilization=0.60: el autoescalador añade o quita instancias para mantener la CPU media del grupo cerca del 60 %. Se deja margen porque escalar no es instantáneo: entre que se decide crear una VM y está sirviendo tráfico pasan minutos.--cool-down-period=120: ignora las métricas de los primeros 120 segundos de vida de cada instancia, mientras arranca.
También se puede escalar por peticiones por segundo o por métricas propias de Cloud Monitoring (por ejemplo, la longitud de una cola), lo cual suele funcionar mejor que la CPU para aplicaciones web. Lo veremos en 06-04.
Reparación automática. Con el health check asociado, si una instancia deja de responder en /salud durante tres comprobaciones seguidas, el MIG la borra y crea otra a partir de la plantilla. Es autorreparación real, no un reinicio: la instancia nueva nace limpia.
Esto tiene una consecuencia de diseño que hay que asumir: las instancias del grupo son desechables. Nada importante puede vivir solo en su disco, porque desaparecerán sin avisar. Los datos van a Cloud SQL (02-03), las imágenes a Cloud Storage (02-02) y las sesiones a un almacén compartido (02-06). El servidor deja de ser una mascota y pasa a ser ganado.
Para actualizar la aplicación se crea una plantilla nueva y se lanza una actualización progresiva:
gcloud compute instance-groups managed rolling-action start-update alpinashop-web-mig \
--region=europe-west1 \
--version=template=alpinashop-web-tpl-v2 \
--max-surge=2 \
--max-unavailable=0--max-unavailable=0 combinado con --max-surge=2 significa: crea hasta dos instancias nuevas antes de retirar las viejas, de modo que la capacidad nunca baje. Es un despliegue sin corte de servicio. Si algo va mal, se relanza el comando apuntando de nuevo a -v1.
Lo que falta para que esto sea una arquitectura completa es un balanceador de carga que reparta el tráfico entre las instancias del grupo con una única IP y un certificado TLS. Ese es exactamente el contenido de la lección 03-02, y por eso aquí paramos.
- VMs Spot: cómputo barato e interrumpible
Las VM Spot (evolución de las antiguas preemptibles) usan capacidad sobrante de Google y cuestan del orden de un 60–90 % menos. A cambio, Google puede detenerlas en cualquier momento con solo 30 segundos de aviso.
gcloud compute instances create procesador-imagenes-spot \
--zone=europe-west1-b \
--machine-type=e2-standard-4 \
--provisioning-model=SPOT \
--instance-termination-action=DELETE \
--metadata-from-file=startup-script=$HOME/procesar-lote.sh| Aspecto | VM estándar | VM Spot |
|---|---|---|
| Precio | Tarifa normal | Muy inferior (varía con la demanda) |
| Duración | Indefinida | Puede terminarse en cualquier momento |
| Aviso previo | — | 30 segundos (evento ACPI G2) |
| SLA | Sí | No |
| Uso adecuado | Servicios en producción | Lotes, renderizado, pruebas, CI |
Casos válidos para AlpinaShop: regenerar las miniaturas de los 60 GB de imágenes de producto, recalcular un informe pesado, ejecutar la batería de tests nocturna. Casos inválidos: el servidor web de la tienda o cualquier cosa cuya interrupción se note en un cliente.
Buena práctica: captura la señal de terminación con un shutdown script para guardar el progreso y que el trabajo pueda reanudarse donde lo dejó.
- Ciclo de vida de una instancia y qué se cobra en cada estado
stateDiagram-v2
[*] --> PROVISIONING: crear
PROVISIONING --> STAGING
STAGING --> RUNNING
RUNNING --> STOPPING: stop
STOPPING --> TERMINATED
TERMINATED --> STAGING: start
TERMINATED --> [*]: delete
RUNNING --> SUSPENDING: suspend
SUSPENDING --> SUSPENDED
SUSPENDED --> RUNNING: resume
Esta es la tabla que más dinero ahorra de toda la lección:
| Estado | ¿Se cobra CPU/RAM? | ¿Se cobran los discos? | ¿Se cobra la IP externa? | ¿Se conserva el contenido? |
|---|---|---|---|---|
RUNNING |
Sí | Sí | Sí (si es estática o efímera en uso) | Sí |
TERMINATED (parada) |
No | Sí | Sí si es estática y sin usar | Disco persistente sí; SSD local no |
SUSPENDED |
No (se cobra el almacenamiento de la RAM volcada) | Sí | Igual que parada | Sí, incluida la memoria |
| Borrada | No | Solo si marcaste "conservar disco" | Solo si la IP es estática | Solo lo que hayas conservado |
Lecciones prácticas:
- Parar una VM no elimina su coste. Los discos siguen facturándose. Una VM de desarrollo parada durante meses con un disco de 500 GB sigue costando dinero.
- Las IP externas estáticas reservadas y no utilizadas se cobran, precisamente para desincentivar el acaparamiento. Libera las que no uses.
- Apagar los entornos de desarrollo fuera de horario es la optimización más rentable y sencilla: unas 128 horas semanales apagado sobre 168 es un ahorro directo del 75 % en cómputo. Puede automatizarse con Cloud Scheduler y una función (06-03).
Operaciones habituales:
# Parar y arrancar
gcloud compute instances stop alpinashop-web-1 --zone=europe-west1-b
gcloud compute instances start alpinashop-web-1 --zone=europe-west1-b
# Redimensionar (requiere la instancia parada)
gcloud compute instances set-machine-type alpinashop-web-1 \
--zone=europe-west1-b \
--machine-type=e2-standard-2
# Ampliar el disco (en caliente; luego hay que ampliar el sistema de ficheros)
gcloud compute disks resize alpinashop-web-1 --zone=europe-west1-b --size=50GB
gcloud compute ssh alpinashop-web-1 --zone=europe-west1-b \
--command="sudo resize2fs /dev/sda1"
# Proteger contra borrado accidental
gcloud compute instances update alpinashop-web-1 \
--zone=europe-west1-b --deletion-protection
# Borrar conservando el disco de datos
gcloud compute instances delete alpinashop-web-1 \
--zone=europe-west1-b --keep-disks=dataFíjate en resize2fs: ampliar el disco en Google Cloud no amplía automáticamente el sistema de ficheros dentro del sistema operativo. Es un paso que se olvida constantemente y produce el desconcierto de ver 50 GB en la consola y 20 GB en df -h.
Errores Comunes y Consejos
- Sobredimensionar la primera VM "por si acaso". Es más barato empezar pequeño y crecer: Compute Engine te dirá incluso, en las recomendaciones de la consola, que tu instancia está infrautilizada. La optimización sistemática se aborda en 07-05.
- Confundir
--tagscon--labels. Las tags de red controlan reglas de firewall; los labels son metadatos de facturación y organización. Ponerentorno=prodcomo tag no hace nada útil. - Guardar datos importantes en un SSD local. Se pierden al parar la instancia. Nunca es "solo un momento".
- Depender del disco de una instancia de un MIG. Las instancias de un grupo gestionado son desechables por diseño.
- Olvidar
--initial-delayen el MIG. El grupo mata las instancias mientras arrancan y entra en un bucle infinito de creación y destrucción. - Dejar la cuenta de servicio predeterminada con rol Editor. Es la escalada de privilegios más fácil de explotar si comprometen tu aplicación.
- Repartir claves SSH por metadatos. Usa OS Login desde el principio; retirar accesos después es mucho más difícil.
- Creer que parar una VM la deja a coste cero. Los discos y las IP estáticas siguen contando.
- Consejo: haz que el startup script sea idempotente. Se ejecuta en cada arranque, no solo en el primero.
- Consejo: prueba el startup script en una VM desechable antes de meterlo en una plantilla. Depurarlo dentro de un MIG que se autodestruye es exasperante.
- Consejo: nombra las plantillas con versión (
-v1,-v2). Son inmutables y necesitarás poder volver atrás. - Consejo: activa la protección contra borrado en cualquier instancia de producción que no forme parte de un grupo gestionado.
Ejercicios
Ejercicio 1: elegir tipo de máquina y disco
Para cada escenario de AlpinaShop, indica familia y tipo de máquina, tipo de disco y justificación breve:
- El servidor web del catálogo Flask en producción, con tráfico moderado y crecimiento horizontal previsto.
- Un proceso nocturno que reescala las 60.000 imágenes de producto y tarda unas 3 horas; puede reintentarse si falla.
- Una futura instancia de análisis que carga en memoria un dataset de 400 GB para consultas interactivas.
- Una VM de desarrollo donde Dani prueba cambios unas 6 horas al día.
Ejercicio 2: crear la instancia y verificar el startup script
Partiendo del proyecto alpinashop-dev:
- Crea
alpinashop-web-2eneurope-west1-ccone2-medium, Debian 12, disco balanceado de 20 GB, OS Login activado y los cuatro labels del esquema de AlpinaShop. - Usa un startup script que instale nginx y escriba una página con el nombre de la instancia.
- Crea la regla de firewall necesaria y comprueba con
curlque responde. - Consulta el log del startup script dentro de la instancia.
- Borra la instancia conservando su disco de arranque y explica qué coste sigue generando.
Ejercicio 3: grupo gestionado con autoescalado
Marta quiere estar preparada para la campaña de otoño:
- Crea una plantilla
alpinashop-web-tpl-ejcon el startup script del catálogo. - Crea un MIG regional en
europe-west1con 2 instancias y comprobación de estado sobre/salud. - Configura autoescalado entre 2 y 6 instancias con objetivo de CPU al 65 %.
- Simula una caída: entra en una instancia, para el servicio y observa qué hace el grupo.
- Explica por qué esta arquitectura todavía no es utilizable de cara al público y qué falta.
Soluciones
Solución 1
| Escenario | Máquina | Disco | Justificación |
|---|---|---|---|
| 1. Web del catálogo | e2-standard-2 (o e2-medium) |
pd-balanced 20 GB |
Carga ligera y estable; el crecimiento se resuelve con más instancias en el MIG, no con una máquina mayor |
| 2. Reescalado de imágenes | c3-highcpu-8 o e2-standard-8 en modo Spot |
pd-balanced + local-ssd como scratch |
CPU intensiva, tolerante a interrupción: Spot reduce mucho el coste. El SSD local es válido porque el resultado final va a Cloud Storage |
| 3. Análisis en memoria | m3-ultramem-32 o similar de la familia M |
pd-ssd o Hyperdisk |
Solo las familias de memoria ofrecen esa RAM; el disco rápido acelera la carga inicial |
| 4. VM de desarrollo | e2-medium |
pd-balanced 20 GB |
Barata; lo importante es apagarla fuera de horario, lo que elimina el coste de CPU y RAM |
Solución 2
cat > ~/startup-nginx.sh <<'SCRIPT'
#!/bin/bash
set -e
apt-get update
apt-get install -y nginx
NOMBRE=$(curl -s -H "Metadata-Flavor: Google" \
http://metadata.google.internal/computeMetadata/v1/instance/name)
echo "<h1>AlpinaShop</h1><p>Instancia: $NOMBRE</p>" > /var/www/html/index.html
systemctl enable --now nginx
SCRIPT
gcloud compute instances create alpinashop-web-2 \
--project=alpinashop-dev \
--zone=europe-west1-c \
--machine-type=e2-medium \
--image-family=debian-12 --image-project=debian-cloud \
--boot-disk-size=20GB --boot-disk-type=pd-balanced \
--tags=http-server \
--metadata-from-file=startup-script=$HOME/startup-nginx.sh \
--metadata=enable-oslogin=TRUE \
--labels=entorno=dev,equipo=plataforma,centro-coste=tienda,aplicacion=catalogoObserva cómo el script obtiene el nombre de la instancia del servidor de metadatos (metadata.google.internal), disponible desde dentro de cualquier VM. La cabecera Metadata-Flavor: Google es obligatoria y sirve como protección frente a peticiones fabricadas desde el exterior.
# 3. Firewall y comprobacion
gcloud compute firewall-rules create permitir-http \
--allow=tcp:80 --target-tags=http-server 2>/dev/null || true
IP=$(gcloud compute instances describe alpinashop-web-2 --zone=europe-west1-c \
--format="value(networkInterfaces[0].accessConfigs[0].natIP)")
curl -s "http://$IP/"
# 4. Log del startup script
gcloud compute ssh alpinashop-web-2 --zone=europe-west1-c \
--command="sudo journalctl -u google-startup-scripts.service --no-pager | tail -30"
# 5. Borrar conservando el disco
gcloud compute instances delete alpinashop-web-2 \
--zone=europe-west1-c --keep-disks=bootTras el punto 5 sigues pagando el disco persistente de 20 GB, que queda huérfano en la zona europe-west1-c. Discos huérfanos así son una fuente clásica de gasto invisible: conviene listarlos periódicamente con gcloud compute disks list --filter="-users:*".
Solución 3
# 1. Plantilla
gcloud compute instance-templates create alpinashop-web-tpl-ej \
--machine-type=e2-medium \
--image-family=debian-12 --image-project=debian-cloud \
--boot-disk-type=pd-balanced --boot-disk-size=20GB \
--tags=http-server \
--metadata-from-file=startup-script=$HOME/startup-catalogo.sh \
--metadata=enable-oslogin=TRUE
# 2. Health check y MIG regional
gcloud compute health-checks create http hc-catalogo-ej \
--port=80 --request-path=/salud \
--check-interval=10s --unhealthy-threshold=3
gcloud compute instance-groups managed create alpinashop-web-mig-ej \
--template=alpinashop-web-tpl-ej \
--size=2 --region=europe-west1 \
--health-check=hc-catalogo-ej --initial-delay=180
# 3. Autoescalado
gcloud compute instance-groups managed set-autoscaling alpinashop-web-mig-ej \
--region=europe-west1 \
--min-num-replicas=2 --max-num-replicas=6 \
--target-cpu-utilization=0.65 --cool-down-period=120
# 4. Simular caida
INST=$(gcloud compute instance-groups managed list-instances alpinashop-web-mig-ej \
--region=europe-west1 --format="value(instance)" | head -1 | xargs basename)
ZONA=$(gcloud compute instances list --filter="name=$INST" --format="value(zone)")
gcloud compute ssh "$INST" --zone="$ZONA" --command="sudo systemctl stop alpinashop"
# Observar el estado del grupo
watch -n 10 gcloud compute instance-groups managed list-instances \
alpinashop-web-mig-ej --region=europe-west1En el punto 4 verás que, tras tres comprobaciones fallidas (unos 30 segundos), el estado de la instancia pasa a UNHEALTHY y poco después el grupo la recrea: cambia su nombre y vuelve a HEALTHY una vez el startup script ha terminado. No se ha reiniciado el servicio: se ha reemplazado la máquina entera.
En el punto 5, lo que falta es un balanceador de carga: hoy cada instancia tiene su propia IP efímera, no hay un punto de entrada único, ni HTTPS, ni un nombre de dominio, ni distribución del tráfico. Además, las instancias están directamente expuestas a internet en el puerto 80, algo inaceptable en producción. Todo eso se resuelve en el módulo 3 (03-01 VPC, 03-02 balanceo, 03-07 DNS y TLS).
Recuerda limpiar al terminar:
gcloud compute instance-groups managed delete alpinashop-web-mig-ej --region=europe-west1 --quiet
gcloud compute instance-templates delete alpinashop-web-tpl-ej --quiet
gcloud compute health-checks delete hc-catalogo-ej --quietConclusión
Hemos dado el primer paso real de la migración de AlpinaShop. Sabes qué es una VM gestionada y, más importante, cuándo sigue siendo la respuesta correcta y cuándo no. Conoces las familias de máquinas —E2 para empezar, N2/N4 para producción general, C3 para cómputo, M3 para memoria, y los tipos personalizados cuando nada encaja— y sabes que el sufijo highcpu/standard/highmem gobierna el ratio de memoria. Has visto el catálogo de imágenes públicas, por qué conviene usar familias de imagen en lugar de versiones fijas, y cómo crear tu propia imagen base. Has comparado los tipos de disco y has interiorizado dos ideas críticas: que el rendimiento de un disco persistente clásico depende de su tamaño, y que un SSD local se pierde al parar la máquina. Has programado instantáneas automáticas con retención, la copia de seguridad que Marta nunca había tenido.
Has creado alpinashop-web-1 en europe-west1-b desde la consola y desde gcloud, con un startup script que instala Python, Flask y gunicorn y deja el catálogo sirviendo bajo systemd, incluyendo una ruta /salud que resultó ser la pieza clave del resto de la lección. Has aprendido las tres vías de acceso SSH y por qué OS Login —identidades en lugar de ficheros de claves— es la única opción defendible en una empresa. Has sustituido la cuenta de servicio predeterminada por sa-catalogo-web, con permisos mínimos. Y, sobre todo, has convertido una máquina única en una plantilla y un grupo gestionado regional con autoescalado de 2 a 10 instancias y reparación automática: el mecanismo que hará que la campaña de otoño de AlpinaShop deje de ser un problema. Por el camino has asumido el cambio mental que exige la nube: las instancias son desechables, y por tanto los datos tienen que vivir en otro sitio.
Ese "otro sitio" es justo el tema de la siguiente lección. En 02-02, Cloud Storage, moveremos los 60 GB de imágenes de producto que hoy ocupan el disco local del servidor físico al bucket alpinashop-catalogo: veremos el modelo de objetos y por qué no existen los directorios, elegiremos clase de almacenamiento y ubicación, haremos la transferencia real con gcloud storage rsync, protegeremos el bucket con acceso uniforme y URLs firmadas, automatizaremos el abaratamiento con reglas de ciclo de vida y conectaremos la aplicación Flask a Storage con la biblioteca cliente de Python. Las instancias podrán morir sin llevarse nada por delante.
Curso de Google Cloud Platform (GCP)
Módulo 1: Introducción a Google Cloud Platform
- ¿Qué es Google Cloud Platform?
- Configuración de tu cuenta de GCP
- Descripción general de la consola de GCP
- Proyectos, jerarquía de recursos y facturación
- Regiones, zonas y modelo de responsabilidad compartida
- Cloud Shell y la CLI de gcloud
Módulo 2: Servicios principales de GCP
- Compute Engine: máquinas virtuales en Google Cloud
- Cloud Storage: almacenamiento de objetos
- Cloud SQL: bases de datos relacionales gestionadas
- App Engine: plataforma como servicio
- Google Kubernetes Engine (GKE)
- Bases de datos NoSQL: Firestore, Bigtable y Spanner
- Cómo elegir el servicio de cómputo adecuado
Módulo 3: Redes y seguridad
- Redes VPC
- Balanceo de carga en la nube
- Cloud CDN
- Gestión de identidad y acceso (IAM)
- Cloud Armor
- Secretos y cifrado: Secret Manager y Cloud KMS
- Cloud DNS, certificados TLS y publicación segura de servicios
Módulo 4: Datos y análisis
- BigQuery: el almacén de datos analítico
- Cloud Dataflow: procesamiento de datos por lotes y en streaming
- Cloud Dataproc: Spark y Hadoop gestionados
- Cloud Pub/Sub: mensajería asíncrona
- Cloud Data Fusion: integración de datos sin código
- Orquestación de pipelines con Cloud Composer y Workflows
- Gobierno del dato y cuadros de mando con Dataplex y Looker Studio
Módulo 5: Aprendizaje automático e IA
- Vertex AI: la plataforma de machine learning de GCP
- AutoML: modelos a medida sin escribir código
- TensorFlow en GCP: entrenamiento y servicio de modelos
- API de lenguaje natural
- API de visión
- IA generativa en Vertex AI: modelos Gemini y embeddings
- MLOps: del modelo al producto con Vertex AI Pipelines
Módulo 6: DevOps y monitoreo
- Cloud Build: integración continua en GCP
- Cloud Source Repositories y gestión del código fuente
- Cloud Functions: funciones sin servidor
- Cloud Monitoring (antes Stackdriver): métricas, paneles y alertas
- Cloud Deployment Manager e infraestructura como código nativa
- Cloud Logging y Cloud Trace: logs, trazas y diagnóstico
- Terraform en GCP: infraestructura como código en la práctica
Módulo 7: Temas avanzados de GCP
- Híbrido y multinube con Anthos
- Computación sin servidor con Cloud Run
- Redes avanzadas: VPC compartida, peering y conectividad híbrida
- Mejores prácticas de seguridad
- Gestión y optimización de costos
- Fiabilidad: SLO, alta disponibilidad y recuperación ante desastres
- Gobierno a escala: organización, políticas y auditoría
