Cómo CREAR una Máquina Virtual en GCP con Terraform
Compute Engine + Startup Script
Crear una VM en Google Cloud manualmente es sencillo. Diseñarla de forma reproducible, automatizable y preparada para integrarse en un flujo IaC es otra historia. En esta guía de nivel Senior / Architect construiremos una instancia de Google Compute Engine con Terraform, inyectaremos un startup script Bash para instalar y levantar Apache y expondremos el servicio mediante una IP pública efímera.
Lo que aprenderás
1. ¿Qué estamos construyendo realmente?
El objetivo no es simplemente ejecutar un recurso google_compute_instance. El patrón completo combina infraestructura, configuración del sistema operativo y exposición de red.
Terraform será responsable del estado deseado de la infraestructura. Compute Engine proporciona la máquina virtual y su ciclo de vida. El startup script actúa como mecanismo de bootstrap para instalar Apache y publicar una página inicial.
Terraform
Declara y mantiene recursos cloud de forma reproducible.
- VM
- Firewall
- Red y NIC
- IP externa efímera
Compute Engine
Ejecuta la carga de trabajo sobre una máquina virtual gestionada por GCP.
- Disco de arranque
- Imagen Debian
- Tipo de máquina
- Red VPC
Startup Script
Automatiza la configuración inicial del sistema operativo.
- Actualización de paquetes
- Instalación de Apache
- Creación del index.html
- Arranque del servicio
2. Matriz de decisión arquitectónica
Antes de implementar, conviene distinguir entre una VM efímera para laboratorio, una VM con IP estática para un servicio controlado y una plataforma gestionada para cargas web de producción.
| Patrón | Latencia | Consistencia / Control | Coste | Operación | Cuándo usarlo |
|---|---|---|---|---|---|
| VM + IP efímera | Baja | Alto | Bajo | Manual / IaC | Labs, demos, prototipos y workloads simples |
| VM + IP estática | Baja | Muy alto | Medio | IaC | Servicios que necesitan endpoint estable |
| Managed Instance Group | Baja | Alto | Medio / Alto | Automatizada | Escalabilidad horizontal y autorrecuperación |
| Cloud Run | Baja / Variable | Gestionado | Optimizado para demanda | Muy baja | Aplicaciones HTTP containerizadas y stateless |
| GKE | Baja | Muy alto | Alto | Alta | Plataformas Kubernetes y workloads complejos |
3. Antipatrones y errores críticos
El código Terraform puede ser válido y aun así producir una arquitectura operativamente deficiente. Los principales problemas aparecen cuando se confunden bootstrap, configuración permanente y ciclo de vida de la infraestructura.
⚠ Antipatrón #1: tratar una IP efímera como una IP permanente
Una IP externa efímera no debe utilizarse como identificador estable de un servicio. Si la instancia se destruye y se recrea, la dirección puede cambiar.
Solución: si un consumidor externo necesita un endpoint estable, reserva y gestiona explícitamente una dirección IP estática o utiliza una capa de entrada apropiada, como un balanceador.
⚠ Antipatrón #2: abrir SSH o HTTP a todo Internet sin necesidad
Una regla de firewall con 0.0.0.0/0 implica exposición global. Para una demo HTTP es razonable abrir TCP/80, pero no se debe trasladar automáticamente el mismo patrón a SSH o servicios administrativos.
Solución: minimizar puertos, restringir rangos CIDR cuando sea posible y utilizar mecanismos de acceso administrativo adecuados.
⚠ Antipatrón #3: instalar software crítico indefinidamente mediante startup script
El startup script es excelente para bootstrap, pero no siempre es la mejor solución para configuración compleja o repetitiva.
Solución: para entornos más maduros, considera imágenes inmutables, pipelines de creación de imágenes, instance templates y mecanismos de configuración especializados. El principio clave es separar la creación de infraestructura del proceso de configuración cuando la complejidad lo justifique.
⚠ Antipatrón #4: olvidar FinOps
Una VM que funciona perfectamente también puede ser una mala decisión económica. Mantener una instancia encendida 24/7 para una prueba puntual genera coste sin aportar valor.
Solución: utilizar tamaños adecuados, etiquetado, presupuestos, políticas de apagado y destrucción automatizada de recursos temporales.
4. Implementación práctica con Terraform
La implementación siguiente utiliza tres piezas principales: proveedor de Google Cloud, regla de firewall HTTP y una instancia de Compute Engine. La IP pública se obtiene mediante un bloque access_config {} sin reservar una dirección estática.
terraform {
required_version = ">= 1.6.0"
required_providers {
google = {
source = "hashicorp/google"
version = ">= 6.0, < 7.0"
}
}
}
provider "google" {
project = var.project_id
region = var.region
zone = var.zone
}
variable "project_id" {
description = "ID del proyecto de Google Cloud"
type = string
}
variable "region" {
description = "Región donde se desplegarán los recursos"
type = string
default = "europe-southwest1"
}
variable "zone" {
description = "Zona de Compute Engine"
type = string
default = "europe-southwest1-b"
}
# -----------------------------------------------------------------------------
# Firewall: permite tráfico HTTP hacia las instancias que tengan la etiqueta
# "web-server".
# -----------------------------------------------------------------------------
resource "google_compute_firewall" "allow_http" {
name = "allow-http-web-server"
network = "default"
direction = "INGRESS"
source_ranges = [
"0.0.0.0/0"
]
allow {
protocol = "tcp"
ports = [
"80"
]
}
target_tags = [
"web-server"
]
}
# -----------------------------------------------------------------------------
# Máquina virtual de Compute Engine.
# -----------------------------------------------------------------------------
resource "google_compute_instance" "web_server" {
name = "terraform-apache-vm"
machine_type = "e2-micro"
zone = var.zone
tags = [
"web-server"
]
boot_disk {
initialize_params {
image = "debian-cloud/debian-12"
size = 10
type = "pd-balanced"
}
}
network_interface {
network = "default"
# Al no especificar una dirección reservada, GCP asigna
# una IP externa efímera a la instancia.
access_config {}
}
# ---------------------------------------------------------------------------
# Startup script:
# 1. Actualiza índices de paquetes.
# 2. Instala Apache.
# 3. Crea una página HTML.
# 4. Habilita e inicia Apache.
# ---------------------------------------------------------------------------
metadata = {
startup-script = <<-EOT
#!/bin/bash
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y apache2
cat > /var/www/html/index.html <<'HTML'
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Terraform + Compute Engine</title>
</head>
<body>
<h1>Servidor desplegado con Terraform</h1>
<p>Apache fue instalado mediante un startup script de Compute Engine.</p>
</body>
</html>
HTML
systemctl enable apache2
systemctl restart apache2
EOT
}
}
output "web_server_name" {
description = "Nombre de la instancia"
value = google_compute_instance.web_server.name
}
output "web_server_public_ip" {
description = "IP pública efímera asignada a la VM"
value = google_compute_instance.web_server.network_interface[0].access_config[0].nat_ip
}
output "web_server_url" {
description = "URL HTTP del servidor Apache"
value = "http://${google_compute_instance.web_server.network_interface[0].access_config[0].nat_ip}"
}
5. Flujo de despliegue
El ciclo completo sigue el modelo clásico de Infrastructure as Code: declarar, inicializar, validar, planificar, aplicar y verificar.
# 1. Inicializar el proveedor
terraform init
# 2. Validar sintaxis y configuración
terraform validate
# 3. Revisar el plan de ejecución
terraform plan \
-var="project_id=TU_PROJECT_ID"
# 4. Crear la infraestructura
terraform apply \
-var="project_id=TU_PROJECT_ID"
# 5. Obtener la IP pública
terraform output web_server_public_ip
# 6. Obtener la URL generada
terraform output web_server_url
Después de obtener la URL, el flujo esperado es: Internet → IP pública efímera → regla de firewall TCP/80 → NIC de Compute Engine → Apache → index.html.
6. Patrones de diseño y mejores prácticas
El ejemplo es intencionadamente pequeño, pero los principios arquitectónicos utilizados son los mismos que aparecen en plataformas empresariales más grandes.
01 · Infraestructura declarativa
Terraform debe describir el estado deseado y no convertirse en una colección de comandos imperativos difíciles de reproducir.
02 · Bootstrap controlado
El startup script debe mantenerse pequeño, observable e idempotente. Cuanto más compleja sea la configuración, más valor aporta una imagen inmutable.
03 · Menor privilegio
Las reglas de red deben permitir exclusivamente los puertos y orígenes necesarios para el caso de uso.
04 · Outputs explícitos
Exponer la IP y la URL como outputs permite integrar Terraform con pipelines, scripts de validación y procesos posteriores.
05 · Separación de entornos
Los valores de proyecto, región y zona deben externalizarse mediante variables, workspaces o estructuras de módulos apropiadas.
06 · Evolución hacia producción
Para alta disponibilidad, el siguiente paso no es simplemente crear más VMs: se necesita un patrón de distribución, health checks, escalado y observabilidad.
7. ¿Qué cambiaría para producción?
Una VM individual es adecuada para aprender Compute Engine y Terraform, pero presenta un único punto de fallo. En un entorno empresarial, la arquitectura debería evolucionar hacia un modelo con separación clara entre aplicación, red, identidad, observabilidad y ciclo de vida.
Regla de Architect:
No escales una solución porque técnicamente puedes hacerlo. Escala cuando exista un requisito explícito de disponibilidad, capacidad, latencia, aislamiento o gobernanza que lo justifique.
8. Checklist de implementación empresarial
Utiliza este framework antes de considerar completado un despliegue de VM mediante Terraform.
Definir el objetivo
Determina si necesitas una VM temporal, un servidor persistente, una plataforma escalable o simplemente un entorno de laboratorio.
Diseñar la red
Define VPC, subredes, reglas de firewall, puertos expuestos y necesidad real de IP externa.
Elegir la imagen
Selecciona una imagen de sistema operativo compatible con el workload y establece una estrategia de actualización.
Implementar Terraform
Versiona el código, fija versiones de proveedores cuando corresponda, utiliza variables y revisa siempre el plan antes de aplicar.
Diseñar el bootstrap
Mantén el startup script pequeño, robusto y verificable. Utiliza set -euo pipefail para reducir fallos silenciosos.
Validar conectividad
Comprueba que Apache esté escuchando, que la regla de firewall sea correcta y que la IP publicada responda por HTTP.
Aplicar FinOps
Revisa tamaño de máquina, almacenamiento, duración del entorno y estrategia de destrucción de recursos temporales.
Preparar evolución
Si aparecen requisitos de alta disponibilidad o escalabilidad, migra hacia un patrón de Instance Template + Managed Instance Group o hacia un servicio gestionado más adecuado.
9. Preguntas frecuentes sobre Terraform y Compute Engine
¿Cómo crear una VM en GCP con Terraform?
El patrón básico utiliza el recurso google_compute_instance. Debes definir la zona, tipo de máquina, disco de arranque, interfaz de red y, si necesitas acceso externo, un bloque access_config {}. La configuración queda así declarada y puede reproducirse mediante terraform plan y terraform apply.
¿Cómo ejecutar un startup script Bash en Compute Engine mediante Terraform?
El script puede inyectarse mediante el atributo metadata utilizando la clave startup-script. Compute Engine utiliza ese metadata para ejecutar el bootstrap durante el proceso de arranque de la instancia.
¿La IP pública creada mediante access_config es permanente?
No debe considerarse permanente. En este ejemplo se utiliza una IP externa efímera porque no se está declarando una dirección estática reservada. Si una aplicación necesita una dirección estable, la IP debe gestionarse explícitamente como un recurso persistente y desacoplarse del ciclo de vida de una VM individual.
Conclusión
Crear una VM en GCP con Terraform es un ejercicio pequeño que permite entender varios conceptos fundamentales de arquitectura cloud: Infrastructure as Code, configuración de máquinas, bootstrap, networking, firewall, direccionamiento externo y ciclo de vida de recursos.
El patrón Terraform → Compute Engine → Startup Script → Apache → IP efímera es perfecto para laboratorios, demostraciones y primeros despliegues. La clave a nivel Architect está en saber cuándo dejar de utilizarlo tal cual y evolucionar hacia imágenes inmutables, instance templates, managed instance groups, balanceadores o servicios gestionados.
La infraestructura correcta no es la más compleja: es la que satisface los requisitos de disponibilidad, seguridad, rendimiento y coste con el menor nivel de complejidad operacional razonable.
