Logo GCP con Eduardo

GCP con Eduardo

Migración de Apache Spark a Cloud Dataproc en Google Cloud | Guía Arquitectónica
✦ Guía Técnica & Arquitectura

Migración de Apache Spark a Cloud Dataproc en Google Cloud

Cómo eliminar la sobrecarga de mantenimiento de clústeres on-premise, desacoplar almacenamiento de cómputo y optimizar costes de procesamiento masivo en batch y streaming.

Lo que aprenderás en esta guía

Desacoplamiento total de HDFS/disco local hacia Google Cloud Storage.
Aprovisionamiento declarativo de clústeres Dataproc con Terraform.
Migración y ejecución de pipelines Spark tanto en Batch como en Streaming.
Patrones FinOps para reducir hasta un 35% el coste computacional.
Google Cloud Platform Cloud Dataproc Cloud Storage (GCS) Apache Spark 3.x Scala / PySpark Terraform (IaC) FinOps Architecture

El dilema de la infraestructura Spark on-premise

Mantener clústeres de Apache Spark tradicionales autogestionados (ya sea en hardware físico on-premise, máquinas virtuales o contenedores Docker en servidores dedicados) suele convertirse en una trampa operativa para los equipos de ingeniería de datos.

El acoplamiento entre disco y cómputo fuerza a sobredimensionar máquinas completas solo porque el volumen de datos crece, aun cuando la CPU permanece ociosa la mayor parte del tiempo. La gestión constante de parches del sistema operativo, el mantenimiento de los demonios Master/Worker, el rebalanceo de discos HDFS y la resolución de caídas imprevistas por falta de almacenamiento pueden consumir hasta el 40% del tiempo semanal de un equipo.

Matriz de Decisión Arquitectónica

A la hora de procesar cargas de Big Data distribuidas, la elección del modelo de infraestructura condiciona directamente el SLA, el tiempo de mantenimiento y el TCO (Total Cost of Ownership):

Criterio Arquitectónico Spark Standalone / On-Premise Google Cloud Dataproc (GCP) Dataproc Serverless
Almacenamiento Acoplado a disco local / HDFS Desacoplado en Cloud Storage (GCS) Totalmente desacoplado (GCS / BigQuery)
Gestión del Clúster Manual (parches, YARN/Master, OS) Gestionado por GCP (aprovisionamiento rápido) Cero infraestructura (NoOps)
Modelo de Escalado Estático o autoscaling complejo Autoscaling dinámico + Preemptibles Escalado elástico automático por tarea
Estrategia de Costes CapEx alto o servidores fijos 24/7 Clústeres efímeros + Facturación por segundo Pago estrictamente por cómputo consumido
Caso de Uso Óptimo Entornos legacy con restricciones regulatorias Migraciones directas con control fino de tuning Pipelines de analítica pura sin gestión de VMs

⚠ Antipatrón Crítico de Producción: Habilitación de APIs y Clústeres Permanentes

Uno de los errores más comunes al migrar hacia Dataproc es conservar la mentalidad on-premise y dejar clústeres encendidos 24/7 para jobs que solo corren durante 20 minutos al día. El verdadero salto de eficiencia consiste en transformar la arquitectura a clústeres efímeros (crear clúster → ejecutar job → destruir clúster) respaldados por buckets de Google Cloud Storage.

Asimismo, asegúrate de activar la dataproc.googleapis.com vía IaC o CLI antes de lanzar tu pipeline para evitar fallos de despliegue en entornos automatizados de CI/CD.

Aprovisionamiento de Infraestructura con Terraform

Para garantizar la reproducibilidad entre entornos (Dev, Staging, Prod), la infraestructura debe declararse mediante Terraform. A continuación se presenta una configuración de producción que crea el bucket de almacenamiento persistente y el clúster gestionado de Dataproc:

# main.tf - Despliegue de Bucket y Clúster Dataproc
provider "google" {
  project = var.project_id
  region  = "europe-southwest1" # Madrid
}

# Bucket de almacenamiento desacoplado para datos y artefactos JAR
resource "google_storage_bucket" "dataproc_bucket" {
  name          = "${var.project_id}-dataproc-storage"
  location      = "EU"
  force_destroy = false

  uniform_bucket_level_access = true
}

# Clúster gestionado de Cloud Dataproc
resource "google_dataproc_cluster" "spark_cluster" {
  name   = "spark-cluster-prod"
  region = "europe-southwest1"

  cluster_config {
    staging_bucket = google_storage_bucket.dataproc_bucket.name

    master_config {
      num_instances = 1
      machine_type  = "n2-standard-2"
      disk_config {
        boot_disk_type    = "pd-standard"
        boot_disk_size_gb = 50
      }
    }

    worker_config {
      num_instances = 2
      machine_type  = "n2-standard-2"
      disk_config {
        boot_disk_type    = "pd-standard"
        boot_disk_size_gb = 50
      }
    }

    # FinOps: Nodos preemptibles/spot para procesado masivo tolerante a fallos
    preemptible_worker_config {
      num_instances = 2
    }

    software_config {
      image_version = "2.1-debian11"
    }
  }
}

Migración y Ejecución de Cargas de Trabajo

Una vez desacoplados los artefactos y datasets hacia Cloud Storage, los jobs ya no dependen de los nodos locales. Dataproc permite orquestar ejecuciones batch y streaming mediante el comando unificado gcloud dataproc jobs submit.

1. Despliegue de un Trabajo Batch (Agregación de Ventas)

El script compilado lee desde GCS, computa agregaciones distribuidas y escribe la salida en formato Parquet en otra ruta del bucket:

# Copiar artefactos y datos a Cloud Storage
gcloud storage cp ./target/scala-2.12/spark-batch-job.jar gs://${PROJECT_ID}-dataproc-storage/code/
gcloud storage cp ./data/batch/sales.csv gs://${PROJECT_ID}-dataproc-storage/data/batch/

# Enviar el Job Batch a Dataproc
gcloud dataproc jobs submit spark \
    --cluster=spark-cluster-prod \
    --region=europe-southwest1 \
    --class=BatchSalesAggregator \
    --jars=gs://${PROJECT_ID}-dataproc-storage/code/spark-batch-job.jar \
    -- gs://${PROJECT_ID}-dataproc-storage/data/batch/sales.csv \
       gs://${PROJECT_ID}-dataproc-storage/data/batch/output/

2. Despliegue de un Trabajo Streaming

Para streaming estructurado, Dataproc procesa micro-batches leyendo flujos continuos desde GCS o Pub/Sub, manteniendo los checkpoints en el bucket para garantizar tolerancia a fallos:

# Enviar el Job de Spark Structured Streaming a Dataproc
gcloud dataproc jobs submit spark \
    --cluster=spark-cluster-prod \
    --region=europe-southwest1 \
    --class=StreamActionCounter \
    --jars=gs://${PROJECT_ID}-dataproc-storage/code/spark-streaming-job.jar \
    -- gs://${PROJECT_ID}-dataproc-storage/data/stream/ \
       gs://${PROJECT_ID}-dataproc-storage/data/stream/output/ \
       gs://${PROJECT_ID}-dataproc-storage/data/stream/checkpoint/

Framework de Implementación Paso a Paso

  1. Auditoría y desacoplamiento de storage: Identifica los accesos a discos locales o HDFS en tus aplicaciones Spark y sustituye las rutas por URIs gs://bucket_name/....
  2. Empaquetado de artefactos: Compila tu código Scala/Java en un fat JAR o prepara tus scripts PySpark asegurándote de no incrustar credenciales duras; Dataproc asume los permisos de la Service Account asignada.
  3. Aprovisionamiento con Terraform: Define la infraestructura como código especificando tipo de máquina, auto-scaling y políticas de eliminación programada.
  4. Pruebas de paridad funcional (Batch y Streaming): Ejecuta los jobs en Dataproc validando que los tiempos de ejecución y las particiones generadas en GCS coincidan con el resultado esperado.
  5. Estrategia FinOps & Automatización: Introduce auto-scaling policies, workers preemptibles y migra hacia workflows orquestados con Cloud Composer o Cloud Workflows para destruir el clúster al finalizar.

Preguntas Frecuentes (FAQ)

¿Por qué separar almacenamiento y cómputo al migrar Apache Spark a Google Cloud?
En arquitecturas on-premise tradicionales con HDFS, los discos de almacenamiento están físicamente ligados a los nodos de cómputo. Al mover los datos a Cloud Storage (GCS), el almacenamiento se vuelve independiente, duradero y de coste marginal, permitiendo apagar o destruir los clústeres de cómputo sin riesgo de pérdida de datos.
¿Cómo se gestionan las dependencias JAR y los datos en Cloud Dataproc?
Tanto los archivos JAR compilados como los archivos de datos se cargan en Cloud Storage. El conector Cloud Storage de Dataproc permite que Spark consuma y escriba directamente sobre el bucket con protocolo nativo gs://, eliminando la necesidad de copiar archivos manualmente a cada nodo.
¿Cómo optimizar costes (FinOps) en clústeres de Spark en Dataproc?
Las mejores prácticas FinOps incluyen: 1) Diseñar clústeres efímeros que existan solo durante la ejecución del job, 2) Utilizar instancias secundarias de tipo Spot/Preemptible para cargas de procesamiento masivo tolerantes a fallos, y 3) Ajustar correctamente el tamaño de las máquinas al perfil de memoria y núcleos del driver y los ejecutores.

Sobre el Autor: Eduardo Martínez Agrelo

AI & Data Architect

Especialista en diseño de arquitecturas de datos en la nube, modernización de pipelines de analítica a gran escala y optimización de costes en Google Cloud Platform. Asesoro a organizaciones en la transición hacia infraestructuras modernas de datos, IA y gobierno empresarial.