Skip to content

Infraestructura como Código - Terraform

Este documento describe los procesos de despliegue y gestión de infraestructura de GCP mediante Terraform. Se enfoca en cómo desplegar y operar la infraestructura, no en la arquitectura de los componentes.

Overview

La infraestructura de GCP se gestiona mediante Terraform utilizando módulos reutilizables. Repositorio: solventomx/data/gcp.

Estructura del Repositorio

terraform-gcp-infrastructure/
├── provider.tf              # Configuración de providers
├── versions.tf              # Versiones de providers
├── variables.tf             # Variables comunes
├── variables_dev.tf          # Variables de desarrollo
├── variables_prod.tf        # Variables de producción
├── terraform.tfvars         # Valores de variables
├── tags.tf                  # Tags comunes
├── dataflow.tf              # Recursos de Dataflow
├── pub_sub.tf               # Recursos de Pub/Sub
├── cloud_run.tf             # Recursos de Cloud Run
├── buckets.tf               # Recursos de Cloud Storage
├── cloud_tasks.tf           # Recursos de Cloud Tasks
├── notification.tf          # Notificaciones de GCS
├── vpc.tf                   # Recursos de VPC
└── modules/                 # Módulos reutilizables
    ├── dataflow/            # Módulo de Dataflow
    ├── pubsub/              # Módulo de Pub/Sub
    ├── cloud_run/           # Módulo de Cloud Run
    ├── buckets/             # Módulo de buckets
    ├── cloud_tasks/         # Módulo de Cloud Tasks
    ├── notification/        # Módulo de notificaciones
    └── vpc/                 # Módulo de VPC

Proyectos GCP

La infraestructura se despliega en dos proyectos:

  • solvento-data-dev: Ambiente de desarrollo
  • solvento-data-prod: Ambiente de producción

Módulos Principales

Módulo de Dataflow

Gestiona jobs de Dataflow desde templates desplegados.

Ubicación: modules/dataflow/

Variables: - job_name: Nombre del job de Dataflow - template_gcs_path: Ruta GCS del template - temp_gcs_location: Ubicación GCS para archivos temporales - region: Región donde se ejecuta el job - project_id: ID del proyecto GCP - service_account_email: Service account (opcional) - network: Red (default: "default") - subnetwork: Subred (opcional) - machine_type: Tipo de máquina (default: "n1-standard-2") - max_num_workers: Número máximo de workers (default: 10) - enable_streaming_engine: Habilitar streaming engine (default: false)

Ejemplo de uso:

module "dataflow_prod" {
  source = "./modules/dataflow"

  for_each = var.dataflow_templates_prod

  job_name                = each.value.job_name
  template_gcs_path       = each.value.template_gcs_path
  temp_gcs_location       = each.value.temp_gcs_location
  region                  = var.region_prod
  project_id              = var.project_id_prod
  service_account_email   = try(each.value.service_account_email, null)
  machine_type            = try(each.value.machine_type, null)
  max_num_workers         = try(each.value.max_num_workers, null)
  enable_streaming_engine = try(each.value.enable_streaming_engine, null)
}

Configuración en variables_prod.tf:

dataflow_templates_prod = {
  invoices-webhook-prod = {
    job_name                = "invoices-webhook-prod-20251203-154624"
    template_gcs_path       = "gs://artifacts-bucket-solvento-data-prod/syntage/dataflow_templates/invoices-webhook-prod"
    temp_gcs_location       = "gs://syntage-ingestion/tmp/"
    service_account_email   = "dataflow-sa@solvento-data-prod.iam.gserviceaccount.com"
    machine_type            = "n1-standard-4"
    max_num_workers         = 10
    enable_streaming_engine = true
  }
}

Módulo de Pub/Sub

Gestiona topics y subscriptions de Pub/Sub.

Ubicación: modules/pubsub/

Variables: - topic_name: Nombre del topic - project_id: ID del proyecto - subscriptions: Map de subscriptions con configuración - tags: Tags para recursos

Ejemplo de uso:

module "pubsub_prod" {
  for_each      = var.pubsub_module_prod
  source        = "./modules/pubsub"
  topic_name    = each.value.topic_name
  project_id    = var.project_id_prod
  subscriptions = each.value.subscriptions
  tags          = merge(local.tags_prod, try(each.value.tags, {}))
}

Configuración:

pubsub_module_prod = {
  invoices-webhook-prod = {
    topic_name = "invoices-webhook-prod"
    subscriptions = {
      invoices-webhook-subscription = {
        subscription_name    = "invoices-webhook-subscription"
        ack_deadline_seconds = 60
      }
    }
    tags = {
      project = "data"
      component = "ingestion"
    }
  }
}

Módulo de Cloud Run

Gestiona servicios de Cloud Run.

Ubicación: modules/cloud_run/

Variables principales: - name: Nombre del servicio - location: Región - image: Imagen Docker - port: Puerto (default: 8080) - memory: Memoria (default: "512Mi") - cpu: CPU (default: "1000m") - max_instances: Máximo de instancias - min_instances: Mínimo de instancias - service_account_email: Service account - environment_variables: Variables de entorno - secrets: Secretos

Módulo de Buckets

Gestiona buckets de Cloud Storage.

Ubicación: modules/buckets/

Características: - Configuración de lifecycle rules - Versionado - IAM bindings - Storage classes

Módulo de Cloud Tasks

Gestiona colas de Cloud Tasks.

Ubicación: modules/cloud_tasks/

Variables: - name: Nombre de la cola - location: Región - max_concurrent_dispatches: Máximo de despachos concurrentes - max_dispatches_per_second: Máximo de despachos por segundo - max_attempts: Máximo de intentos

Flujo de Despliegue

1. Desarrollo Local

# Inicializar Terraform
terraform init

# Planificar cambios
terraform plan

# Aplicar cambios (solo en desarrollo)
terraform apply

2. CI/CD Pipeline

  1. Crear branch: Crear una rama para los cambios
  2. Configurar variables: Actualizar terraform.tfvars
  3. Push a branch: git push origin feature/tu-rama
  4. Merge Request: Crear MR hacia main
  5. Merge a main: Al hacer merge, se lanza el pipeline CI/CD
  6. Deploy manual: Ejecutar manualmente la etapa de deploy en el pipeline

3. Despliegue de Templates

  1. Desplegar template: Usar deploy_templates.sh para desplegar template a GCS
  2. Actualizar Terraform: Actualizar variables_prod.tf con nueva ruta del template
  3. Aplicar Terraform: Ejecutar terraform apply para crear/actualizar el job

Integración Templates ↔ Terraform

Flujo Completo

  1. Desarrollo del Template:

    # Modificar template en templates-dataflow/
    cd templates-dataflow/invoices-webhook
    # Editar dataflow_template.py
    

  2. Desplegar Template:

    ./deploy_templates.sh invoices-webhook prod
    # Template desplegado a: gs://artifacts-bucket/.../invoices-webhook-prod-20251215-143022
    

  3. Actualizar Terraform:

    # En variables_prod.tf
    dataflow_templates_prod = {
      invoices-webhook-prod = {
        job_name          = "invoices-webhook-prod-20251215-143022"
        template_gcs_path = "gs://artifacts-bucket/.../invoices-webhook-prod-20251215-143022"
        # ... otras configuraciones
      }
    }
    

  4. Aplicar Terraform:

    terraform plan
    terraform apply
    

Mejores Prácticas

Versionado

  • Templates: Versionado automático con timestamp en GCS
  • Terraform: Usar versiones específicas de providers
  • Jobs: Nombres de jobs incluyen timestamp para trazabilidad

Separación de Ambientes

  • Variables separadas: variables_dev.tf y variables_prod.tf
  • Providers separados: google.dev y google.prod
  • Tags diferenciados: Tags específicos por ambiente

Gestión de Secretos

  • Usar Secret Manager para credenciales
  • No hardcodear secretos en código
  • Referenciar secretos en Cloud Run mediante variables

Tags y Labels

  • Tags consistentes para todos los recursos
  • Tags por proyecto, componente, ambiente
  • Facilita gestión de costos y organización

Referencias