🎯 El Desafío de Gestionar Infraestructura Cloud
Imagina que necesitas desplegar tu sistema RAG en GCP:
- ✅ VM para Qdrant (Compute Engine)
- ✅ API en Cloud Run (FastAPI)
- ✅ Batch Job (Cloud Run Job para procesamiento)
- ✅ Storage (Google Cloud Storage)
- ✅ Secrets (Secret Manager para .env y JWT keys)
El problema: ¿Cómo creas, actualizas y gestionas toda esta infraestructura de forma reproducible, versionada y colaborativa?
Opciones para Gestionar Infraestructura
Método | Pros | Contras | Reproducibilidad |
---|---|---|---|
Console UI (manual) | Fácil, visual | Propenso a errores, no versionado | ❌ Ninguna |
gcloud CLI scripts | Automatizado | Scripts frágiles, difícil rollback | ⚠️ Limitada |
Cloud Formation | IaC nativo AWS | Solo AWS | ✅ Alta (AWS only) |
Pulumi | Multiple lenguajes | Requiere runtime | ✅ Alta |
Terraform | Declarativo, multi-cloud | Learning curve | ✅✅ Muy Alta |
Nuestra elección: Terraform
📊 La Magnitud del Problema
Requisitos de Infraestructura
Para el proyecto Lus Laboris necesitamos:
-
🗄️ Google Cloud Storage
- Bucket para datos procesados
- Bucket para Terraform state (remoto)
-
🖥️ Compute Engine VM
- VM para Qdrant (vector database)
- Ubuntu 22.04 LTS
- Firewall rules (ports 6333, 6334, 22)
- SPOT instance (cost optimization)
-
🚀 Cloud Run Service
- FastAPI container
- Secrets montados de Secret Manager
- Auto-scaling (0-10 instances)
- 2 CPU, 2Gi RAM
-
⏰ Cloud Run Job
- Batch processing (scheduled)
- Cron schedule
- Logs y notificaciones
-
🔐 Secret Manager
-
.env
file (all API config) - JWT public key
- IAM permissions
-
Desafíos Sin IaC
Sin Terraform:
Developer 1 crea VM via Console → Settings no documentados
Developer 2 necesita replicar → "¿Qué settings usaste?"
Developer 1: "Hmm... creo que era e2-medium con 20GB..."
Developer 2: "¿Y el firewall?"
Developer 1: "Olvidé... tendrás que experimentar"
Disaster Recovery: "La VM se borró, ¿cómo la recreo?"
Team: 🤷 "No hay backup de la configuración"
Con Terraform:
git clone repo
terraform apply
✅ Toda la infraestructura recreada en 5 minutos
✅ Configuración exacta versionada en Git
✅ Documentación viva en código
✅ Rollback a cualquier versión anterior
💡 La Solución: Terraform Infrastructure as Code
¿Qué es Terraform?
Terraform (por HashiCorp) es una herramienta de Infrastructure as Code (IaC) que permite:
- 📝 Definir infraestructura en archivos declarativos (HCL)
- 📊 Planear cambios antes de aplicarlos
- 🚀 Aplicar cambios de forma idempotente
- 🗑️ Destruir infraestructura limpiamente
- 🔄 Versionado en Git como código
Principios de Terraform
- Declarativo: Describes el estado deseado, no los pasos
- Idempotente: Ejecutar N veces = mismo resultado
- Plan-Apply: Preview de cambios antes de ejecutar
- State Management: Trackea estado actual vs deseado
- Modular: Componentes reutilizables
🏗️ Arquitectura de Terraform en el Proyecto
Estructura de Carpetas
terraform/
├── main.tf # Orquestación de módulos
├── variables.tf # Definición de variables
├── terraform.tfvars # Valores de variables
├── providers.tf # Configuración de GCP provider
├── tf_menu.sh # Script interactivo para ops comunes
├── README.md # Documentación
│
└── modules/ # Módulos reutilizables
├── gcs/ # Google Cloud Storage
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
│
├── compute_engine/ # VM para Qdrant
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
│
├── cloud_run_service/ # FastAPI en Cloud Run
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
│
├── cloud_run_job/ # Batch processing
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
│
└── secret_manager/ # Secrets management
├── main.tf
├── variables.tf
└── outputs.tf
Principio de diseño: Un módulo = un recurso lógico reutilizable
🚀 Implementación Paso a Paso
1. Configuración de Providers
Archivo terraform/providers.tf
:
# Provider de Google Cloud Platform
provider "google" {
project = var.project_id
region = var.region
}
# Backend para almacenar state remoto en GCS
terraform {
required_version = ">= 1.0"
required_providers {
google = {
source = "hashicorp/google"
version = "~> 6.0"
}
}
# Remote state backend
backend "gcs" {
bucket = "py-labor-law-rag-terraform-state"
prefix = "terraform/state"
}
}
Características:
- ✅ Remote state: State almacenado en GCS (no local)
- ✅ Versión fijada:
~> 6.0
= 6.x.x (semver) - ✅ State locking: GCS provee locking automático
- ✅ Team collaboration: Múltiples devs comparten state
2. Definición de Variables
Archivo terraform/variables.tf
:
# Basic GCP Configuration
variable "project_id" {
description = "GCP Project ID"
type = string
}
variable "region" {
description = "GCP Region"
type = string
default = "us-central1"
}
variable "project_number" {
description = "GCP Project Number (for service accounts)"
type = string
}
# Google Cloud Storage
variable "bucket_name" {
description = "Name for the GCS bucket"
type = string
}
# Compute Engine (Qdrant VM)
variable "qdrant_vm_name" {
description = "Name for the Qdrant VM"
type = string
default = "qdrant-vm"
}
variable "qdrant_vm_machine_type" {
description = "Machine type for Qdrant VM"
type = string
default = "e2-medium"
}
variable "qdrant_vm_zone" {
description = "Zone for Qdrant VM"
type = string
default = "us-central1-a"
}
variable "qdrant_vm_disk_size" {
description = "Boot disk size in GB"
type = number
default = 20
}
# Cloud Run Service (API)
variable "api_service_name" {
description = "Name of the Cloud Run service"
type = string
default = "lus-laboris-api"
}
variable "api_image" {
description = "Docker image for the API"
type = string
}
variable "api_container_port" {
description = "Container port for the API"
type = number
default = 8000
}
variable "api_cpu" {
description = "Number of CPUs for the API"
type = string
default = "2"
}
variable "api_memory" {
description = "Memory for the API (e.g., 2Gi)"
type = string
default = "2Gi"
}
variable "api_min_instance_count" {
description = "Minimum number of instances"
type = number
default = 0 # Scale to zero for cost savings
}
variable "api_max_instance_count" {
description = "Maximum number of instances"
type = number
default = 10
}
variable "api_timeout" {
description = "Request timeout"
type = string
default = "300s"
}
# Secret Manager
variable "api_env_secret_id" {
description = "Secret ID for .env file"
type = string
}
variable "jwt_public_key_secret_id" {
description = "Secret ID for JWT public key"
type = string
}
# Cloud Run Job (Batch)
variable "job_name" {
description = "Name of the Cloud Run Job"
type = string
}
variable "image" {
description = "Docker image for the job"
type = string
}
variable "args" {
description = "Arguments for the job"
type = list(string)
default = []
}
variable "schedule" {
description = "Cron schedule for the job"
type = string
default = "0 2 * * *" # 2 AM daily
}
variable "notify_email" {
description = "Email for job notifications"
type = string
}
3. Módulo: Compute Engine (VM para Qdrant)
Archivo terraform/modules/compute_engine/main.tf
:
# VM Instance para Qdrant
resource "google_compute_instance" "qdrant_vm" {
name = var.vm_name
machine_type = var.machine_type
zone = var.zone
boot_disk {
initialize_params {
image = "ubuntu-os-cloud/ubuntu-2204-lts"
size = var.disk_size # GB
}
}
network_interface {
network = "default"
access_config {
# Ephemeral public IP
# Para IP estática, especificar: nat_ip = google_compute_address.static.address
}
}
tags = ["qdrant-server", "http-server", "https-server"]
# SPOT instance para optimización de costos
scheduling {
preemptible = true # Puede ser interrumpida
automatic_restart = false # No reiniciar automáticamente
provisioning_model = "SPOT" # Pricing model
}
# Metadata para startup script (opcional)
metadata = {
ssh-keys = "user:ssh-rsa AAAAB3..." # Si necesitas SSH
}
}
# Firewall rule para Qdrant
resource "google_compute_firewall" "qdrant_firewall" {
name = "${var.vm_name}-firewall"
network = "default"
allow {
protocol = "tcp"
ports = ["6333", "6334", "22"] # HTTP, gRPC, SSH
}
source_ranges = ["0.0.0.0/0"] # ⚠️ En producción, restringir a IPs específicas
target_tags = ["qdrant-server"]
}
Archivo terraform/modules/compute_engine/outputs.tf
:
output "vm_name" {
description = "Name of the VM instance"
value = google_compute_instance.qdrant_vm.name
}
output "vm_external_ip" {
description = "External IP of the VM"
value = google_compute_instance.qdrant_vm.network_interface[0].access_config[0].nat_ip
}
output "vm_internal_ip" {
description = "Internal IP of the VM"
value = google_compute_instance.qdrant_vm.network_interface[0].network_ip
}
output "vm_zone" {
description = "Zone where the VM is deployed"
value = google_compute_instance.qdrant_vm.zone
}
Características del módulo:
- ✅ SPOT instance: Hasta 80% más barato que VM normal
- ✅ Ubuntu 22.04 LTS: OS estable y actualizado
- ✅ Firewall automático: Ports correctos abiertos
- ✅ Outputs: IP externa/interna para configuración posterior
4. Módulo: Cloud Run Service (FastAPI)
Archivo terraform/modules/cloud_run_service/main.tf
:
# Cloud Run Service para FastAPI
resource "google_cloud_run_v2_service" "api_service" {
name = var.service_name
location = var.region
project = var.project_id
# Permitir destrucción sin intervención manual
deletion_protection = false
template {
containers {
image = var.image # Docker image from Docker Hub
ports {
container_port = var.container_port # 8000
}
# Variables de entorno
env {
name = "API_HOST"
value = "0.0.0.0"
}
env {
name = "API_PORT"
value = tostring(var.container_port)
}
env {
name = "API_RELOAD"
value = "false"
}
env {
name = "API_JWT_PUBLIC_KEY_PATH"
value = "/app/secrets/jwt/public_key.pem"
}
env {
name = "API_ENV_FILE_PATH"
value = "/app/secrets/env/.env"
}
# Montar secrets desde Secret Manager
volume_mounts {
name = "env-secret"
mount_path = "/app/secrets/env"
}
volume_mounts {
name = "jwt-secret"
mount_path = "/app/secrets/jwt"
}
# Recursos
resources {
limits = {
cpu = var.cpu # "2"
memory = var.memory # "2Gi"
}
}
# Liveness probe
liveness_probe {
http_get {
path = "/api/health"
port = var.container_port
}
initial_delay_seconds = 5
period_seconds = 10
timeout_seconds = 5
failure_threshold = 3
}
}
# Volúmenes para secrets
volumes {
name = "env-secret"
secret {
secret = var.env_secret_name
default_mode = 0444 # Read-only
items {
path = ".env"
version = "latest"
}
}
}
volumes {
name = "jwt-secret"
secret {
secret = var.jwt_secret_name
default_mode = 0444 # Read-only
items {
path = "public_key.pem"
version = "latest"
}
}
}
# Auto-scaling
scaling {
min_instance_count = var.min_instance_count # 0 para scale-to-zero
max_instance_count = var.max_instance_count # 10
}
# Timeout
timeout = var.timeout # "300s"
# Service account
service_account = "${var.project_id}@appspot.gserviceaccount.com"
}
# Traffic routing (100% a última revisión)
traffic {
percent = 100
type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST"
}
}
# IAM policy para permitir acceso público
resource "google_cloud_run_service_iam_policy" "api_service_policy" {
location = google_cloud_run_v2_service.api_service.location
project = google_cloud_run_v2_service.api_service.project
service = google_cloud_run_v2_service.api_service.name
policy_data = data.google_iam_policy.api_service_policy.policy_data
}
data "google_iam_policy" "api_service_policy" {
binding {
role = "roles/run.invoker"
members = [
"allUsers", # Acceso público
]
}
}
Características:
- ✅ Scale to zero: Min instances = 0 (ahorro de costos)
- ✅ Secrets management: Montados desde Secret Manager
- ✅ Health checks: Liveness probe en
/api/health
- ✅ Auto-scaling: 0-10 instances según carga
- ✅ No CPU throttling: Performance consistente
5. Módulo: Secret Manager
Archivo terraform/modules/secret_manager/main.tf
:
# Secret para .env file
resource "google_secret_manager_secret" "api_env_file" {
secret_id = var.api_env_secret_id
replication {
auto {}
}
}
# Secret para JWT public key
resource "google_secret_manager_secret" "jwt_public_key" {
secret_id = var.jwt_public_key_secret_id
replication {
auto {}
}
}
# IAM permissions para que Cloud Run acceda a secrets
resource "google_secret_manager_secret_iam_member" "api_env_access" {
secret_id = google_secret_manager_secret.api_env_file.id
role = "roles/secretmanager.secretAccessor"
member = "serviceAccount:${var.cloud_run_service_account}@appspot.gserviceaccount.com"
}
resource "google_secret_manager_secret_iam_member" "jwt_key_access" {
secret_id = google_secret_manager_secret.jwt_public_key.id
role = "roles/secretmanager.secretAccessor"
member = "serviceAccount:${var.cloud_run_service_account}@appspot.gserviceaccount.com"
}
Nota: Los secrets se crean vacíos. El contenido se agrega via GitHub Actions workflow o gcloud CLI.
6. Main File (Orquestación)
Archivo terraform/main.tf
:
# Google Cloud Storage
module "gcs" {
source = "./modules/gcs"
project_id = var.project_id
region = var.region
bucket_name = var.bucket_name
}
# Compute Engine VM (Qdrant)
module "compute_engine" {
source = "./modules/compute_engine"
vm_name = var.qdrant_vm_name
machine_type = var.qdrant_vm_machine_type
zone = var.qdrant_vm_zone
disk_size = var.qdrant_vm_disk_size
}
# Secret Manager (MUST be created BEFORE Cloud Run)
module "secret_manager" {
source = "./modules/secret_manager"
project_id = var.project_id
cloud_run_service_account = var.project_number
api_env_secret_id = var.api_env_secret_id
jwt_public_key_secret_id = var.jwt_public_key_secret_id
}
# Cloud Run Service (API)
module "cloud_run_service" {
source = "./modules/cloud_run_service"
project_id = var.project_id
region = var.region
service_name = var.api_service_name
image = var.api_image
container_port = var.api_container_port
cpu = var.api_cpu
memory = var.api_memory
min_instance_count = var.api_min_instance_count
max_instance_count = var.api_max_instance_count
timeout = var.api_timeout
env_secret_name = module.secret_manager.env_secret_name
jwt_secret_name = module.secret_manager.jwt_secret_name
depends_on = [module.secret_manager]
}
# Cloud Run Job (Batch Processing)
module "cloud_run_job" {
source = "./modules/cloud_run_job"
project_id = var.project_id
region = var.region
job_name = var.job_name
image = var.image
args = var.args
schedule = var.schedule
notify_email = var.notify_email
}
# Outputs
output "qdrant_vm_external_ip" {
description = "External IP for Qdrant VM"
value = module.compute_engine.vm_external_ip
}
output "api_service_url" {
description = "URL of the deployed API"
value = module.cloud_run_service.service_url
}
output "bucket_name" {
description = "Name of the GCS bucket"
value = module.gcs.bucket_name
}
🔄 Workflow de Uso
1. Inicialización
# Navegar a directorio terraform
cd terraform
# Configurar credenciales
export GOOGLE_APPLICATION_CREDENTIALS="../.gcpcredentials/service-account.json"
# Inicializar Terraform (descargar providers, configurar backend)
terraform init
Output:
Initializing the backend...
Initializing modules...
Initializing provider plugins...
- Finding hashicorp/google versions matching "~> 6.0"...
- Installing hashicorp/google v6.8.0...
Terraform has been successfully initialized!
2. Plan (Preview de Cambios)
# Ver qué cambios se aplicarán
terraform plan
Output:
Terraform will perform the following actions:
# module.compute_engine.google_compute_firewall.qdrant_firewall will be created
+ resource "google_compute_firewall" "qdrant_firewall" {
+ name = "qdrant-vm-firewall"
+ network = "default"
+ ports = ["6333", "6334", "22"]
}
# module.compute_engine.google_compute_instance.qdrant_vm will be created
+ resource "google_compute_instance" "qdrant_vm" {
+ name = "qdrant-vm"
+ machine_type = "e2-medium"
+ zone = "us-central1-a"
}
# module.cloud_run_service.google_cloud_run_v2_service.api_service will be created
+ resource "google_cloud_run_v2_service" "api_service" {
+ name = "lus-laboris-api"
+ location = "us-central1"
}
Plan: 15 to add, 0 to change, 0 to destroy.
3. Apply (Ejecutar Cambios)
# Aplicar cambios
terraform apply
# O sin confirmación (CI/CD):
terraform apply -auto-approve
Output:
module.secret_manager.google_secret_manager_secret.api_env_file: Creating...
module.secret_manager.google_secret_manager_secret.jwt_public_key: Creating...
module.compute_engine.google_compute_firewall.qdrant_firewall: Creating...
module.gcs.google_storage_bucket.bucket: Creating...
module.compute_engine.google_compute_instance.qdrant_vm: Creating...
...
Apply complete! Resources: 15 added, 0 changed, 0 destroyed.
Outputs:
api_service_url = "https://lus-laboris-api-abc123-uc.a.run.app"
bucket_name = "my-data-bucket"
qdrant_vm_external_ip = "34.123.45.67"
4. Verificación
# Ver outputs
terraform output
# Output específico
terraform output api_service_url
# Health check de la API
curl $(terraform output -raw api_service_url)/api/health
5. Destroy (Eliminar Infraestructura)
# Eliminar TODA la infraestructura
terraform destroy
# Con auto-approve (cuidado!)
terraform destroy -auto-approve
🎯 Script Interactivo: tf_menu.sh
Para facilitar operaciones comunes, el proyecto incluye tf_menu.sh
:
#!/bin/bash
# Menu interactivo para Terraform operations
echo "=========================================="
echo " Terraform Operations Menu"
echo "=========================================="
echo ""
echo "1) Initialize Terraform"
echo "2) Plan (preview changes)"
echo "3) Apply (execute changes)"
echo "4) Destroy (delete infrastructure)"
echo "5) Show current state"
echo "6) Show outputs"
echo "7) Validate configuration"
echo "8) Format files"
echo "9) Exit"
echo ""
read -p "Select an option [1-9]: " option
case $option in
1)
echo "Initializing Terraform..."
terraform init
;;
2)
echo "Planning changes..."
terraform plan
;;
3)
echo "Applying changes..."
terraform apply
;;
4)
echo "WARNING: This will destroy ALL infrastructure!"
read -p "Are you sure? (yes/no): " confirm
if [ "$confirm" = "yes" ]; then
terraform destroy
fi
;;
5)
echo "Current state:"
terraform show
;;
6)
echo "Outputs:"
terraform output
;;
7)
echo "Validating configuration..."
terraform validate
;;
8)
echo "Formatting files..."
terraform fmt -recursive
;;
9)
echo "Exiting..."
exit 0
;;
*)
echo "Invalid option"
;;
esac
Uso:
cd terraform
chmod +x tf_menu.sh
./tf_menu.sh
🔄 Integración con CI/CD (GitHub Actions)
Archivo .github/workflows/terraform-apply-on-tf-change.yml
:
name: Terraform Apply on TF Change
on:
push:
paths:
- 'terraform/**/*.tf'
- 'terraform/**/*.tfvars'
jobs:
terraform:
runs-on: ubuntu-latest
env:
GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GSA_KEY }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.9.0
- name: Terraform Init
working-directory: ./terraform
run: terraform init
- name: Terraform Validate
working-directory: ./terraform
run: terraform validate
- name: Terraform Plan
working-directory: ./terraform
run: terraform plan -out=tfplan
- name: Terraform Apply
working-directory: ./terraform
run: terraform apply -auto-approve tfplan
- name: Show Outputs
working-directory: ./terraform
run: terraform output
Ventajas:
- ✅ Auto-apply: Cambios en
.tf
files → auto-deploy - ✅ Validation: Validate antes de apply
- ✅ Plan saved: Plan guardado para apply exacto
- ✅ Outputs visible: Ver resultados en logs
🎯 Casos de Uso Reales
Para Replicar Ambiente:
"Necesito crear un ambiente de staging idéntico a producción"
Solución:
# Crear workspace para staging
terraform workspace new staging
# Aplicar con variables de staging
terraform apply -var-file="staging.tfvars"
# Resultado: Infraestructura idéntica en minutos
Para Disaster Recovery:
"La VM de Qdrant se eliminó accidentalmente"
Solución:
# Ver estado actual
terraform state list
# Recrear solo la VM
terraform apply -target=module.compute_engine
# Resultado: VM recreada con configuración exacta
Para Actualizar Recursos:
"Necesito aumentar RAM de la API de 2Gi a 4Gi"
Solución:
// terraform/terraform.tfvars
api_memory = "4Gi" // Era "2Gi"
terraform apply
# Resultado: Cloud Run actualizado con zero downtime
Para Múltiples Ambientes:
"Quiero dev, staging, y prod con diferentes specs"
Solución:
# Crear workspaces
terraform workspace new dev
terraform workspace new staging
terraform workspace new prod
# Usar variables por workspace
terraform workspace select dev
terraform apply -var="api_cpu=1" -var="api_memory=1Gi"
terraform workspace select prod
terraform apply -var="api_cpu=4" -var="api_memory=8Gi"
🚀 El Impacto Transformador
Antes de Terraform:
- 🖱️ Manual deployment: Click en console por 30-60 minutos
- 📝 Documentación: Notas dispersas, desactualizadas
- 🐛 Errores: "Olvidé abrir el puerto 6334"
- 🔄 Replicación: Imposible crear ambiente idéntico
- 💥 Disaster recovery: Días para recrear infraestructura
Después de Terraform:
- ⚡ Auto deployment:
terraform apply
= 5-10 minutos - 📝 Documentación viva: El código ES la documentación
- ✅ Sin errores: Configuración probada y versionada
- 🔄 Replicación perfecta:
terraform apply
en cualquier ambiente - 💥 Disaster recovery: Minutos para recrear todo
Métricas de Mejora:
Aspecto | Sin IaC | Con Terraform | Mejora |
---|---|---|---|
Tiempo de setup | 30-60 min | 5-10 min | -80% |
Errores de config | Frecuentes | Raros | -90% |
Reproducibilidad | Imposible | Perfecta | +100% |
Versionado | No | Sí (Git) | N/A |
Rollback | Manual |
git revert + apply |
N/A |
Team collaboration | Caos | Sincronizado | N/A |
💡 Lecciones Aprendidas
1. Remote State es Obligatorio
Nunca uses state local para proyectos reales. GCS backend permite colaboración y previene conflictos.
2. Módulos = Reutilización
Un módulo bien diseñado se puede usar en múltiples proyectos con mínimos ajustes.
3. Variables con Defaults Sensatos
Defaults buenos = menos config required = menos errores.
4. Outputs son Documentación
Outputs muestran información crítica (IPs, URLs) que necesitas después del deploy.
5. depends_on para Orden
Algunos recursos deben crearse en orden (Secret Manager → Cloud Run). Usa depends_on
explícitamente.
6. SPOT Instances = 80% Ahorro
Para workloads tolerantes a interrupciones (como Qdrant con persistencia), SPOT instances son oro.
🎯 El Propósito Más Grande
Terraform no es solo "automatización" - es infraestructura como producto. Al tratar infraestructura como código:
- 📝 Versionado: Cada cambio en Git con diff, blame, history
- 👥 Colaboración: Pull requests para cambios de infraestructura
- 🔍 Review: Code review de infraestructura antes de aplicar
-
🔄 Rollback:
git revert
+terraform apply
= rollback instant - 📚 Documentación: El código no miente, siempre está actualizado
- 🧪 Testing: Ambientes efímeros para testing
- 🚀 Velocity: De idea a producción en minutos, no horas
Estamos construyendo infraestructura con la misma calidad, rigor y velocidad que el código de aplicación.
🔗 Recursos y Enlaces
Repositorio del Proyecto
- GitHub: lus-laboris-py
Documentación Técnica
-
Terraform Main:
terraform/main.tf
-
Compute Engine Module:
terraform/modules/compute_engine/
-
Cloud Run Module:
terraform/modules/cloud_run_service/
-
Terraform README:
terraform/README.md
Recursos Externos
- Terraform Docs: terraform.io/docs
- GCP Provider: registry.terraform.io/providers/hashicorp/google
- Terraform Best Practices: terraform-best-practices.com
- HashiCorp Learn: learn.hashicorp.com/terraform
Próximo Post: LLPY-12 - Docker y Containerización
En el siguiente post exploraremos cómo containerizar la aplicación con Docker, multi-stage builds, optimización de imágenes, Docker Compose para desarrollo local, y publicación en Docker Hub.
Top comments (0)