Instalación de Apache Spark en Linux
Apache Spark es el motor de procesamiento de datos distribuido más utilizado en el ecosistema big data, capaz de procesar petabytes de datos con una velocidad hasta 100 veces superior a Hadoop MapReduce gracias al procesamiento en memoria. Con soporte para PySpark (Python), Spark SQL, Spark Streaming y MLlib, Spark se despliega desde un único servidor de desarrollo hasta clusters distribuidos en producción. Esta guía cubre la instalación completa de Apache Spark en Linux.
Requisitos Previos
- Ubuntu 20.04+, Debian 11+, CentOS 8+ o Rocky Linux 8+
- Java 11 o 17 (requerido)
- Python 3.8+ (para PySpark)
- Mínimo 4 GB de RAM por nodo (8 GB recomendados)
- Almacenamiento rápido (SSD) para datos temporales y shuffle
- Acceso SSH sin contraseña entre nodos del cluster (para modo cluster)
- Puertos 7077 (master), 8080 (web UI), 4040 (aplicación) abiertos
Instalación de Java y Scala
Spark requiere Java. Instalar OpenJDK 11:
# Ubuntu/Debian
sudo apt update
sudo apt install -y openjdk-11-jdk openjdk-11-jre
# CentOS/Rocky Linux
sudo dnf install -y java-11-openjdk java-11-openjdk-devel
# Verificar la instalación
java -version
# Debe mostrar: openjdk version "11.x.x"
# Configurar JAVA_HOME
echo 'export JAVA_HOME=$(dirname $(dirname $(readlink $(readlink $(which javac)))))' | sudo tee -a /etc/environment
source /etc/environment
echo $JAVA_HOME
# Instalar Scala (opcional, para desarrollo con Scala)
sudo apt install -y scala # Ubuntu/Debian
# sudo dnf install -y scala # CentOS/Rocky
scala -version
Instalación de Apache Spark
# Descargar Apache Spark (versión con Hadoop precompilado)
SPARK_VERSION="3.5.1"
HADOOP_VERSION="3"
wget "https://downloads.apache.org/spark/spark-${SPARK_VERSION}/spark-${SPARK_VERSION}-bin-hadoop${HADOOP_VERSION}.tgz"
# Verificar la integridad (opcional pero recomendado)
wget "https://downloads.apache.org/spark/spark-${SPARK_VERSION}/spark-${SPARK_VERSION}-bin-hadoop${HADOOP_VERSION}.tgz.sha512"
sha512sum -c spark-${SPARK_VERSION}-bin-hadoop${HADOOP_VERSION}.tgz.sha512
# Extraer e instalar
sudo tar -xzf spark-${SPARK_VERSION}-bin-hadoop${HADOOP_VERSION}.tgz -C /opt/
sudo ln -s /opt/spark-${SPARK_VERSION}-bin-hadoop${HADOOP_VERSION} /opt/spark
# Crear usuario dedicado para Spark
sudo useradd -r -s /bin/bash -d /opt/spark spark
sudo chown -R spark:spark /opt/spark-${SPARK_VERSION}-bin-hadoop${HADOOP_VERSION}
# Configurar variables de entorno
sudo tee /etc/profile.d/spark.sh << 'EOF'
export SPARK_HOME=/opt/spark
export PATH=$PATH:$SPARK_HOME/bin:$SPARK_HOME/sbin
export PYSPARK_PYTHON=python3
EOF
source /etc/profile.d/spark.sh
# Verificar la instalación
spark-submit --version
# Debe mostrar: Welcome to Spark version 3.5.x
Configuración del Cluster Standalone
Spark tiene un modo standalone que no requiere Hadoop o YARN:
# Crear el archivo de configuración de Spark
cd /opt/spark/conf
# Copiar la plantilla de configuración
sudo cp spark-env.sh.template spark-env.sh
sudo nano spark-env.sh
Configuración para el nodo Master:
# /opt/spark/conf/spark-env.sh
# IP del nodo Master de Spark
export SPARK_MASTER_HOST=IP-DEL-MASTER
# Puerto del Master
export SPARK_MASTER_PORT=7077
# Puerto de la interfaz web del Master
export SPARK_MASTER_WEBUI_PORT=8080
# Memoria RAM asignada a los Workers (en megabytes)
export SPARK_WORKER_MEMORY=4g
# Número de núcleos de CPU por Worker
export SPARK_WORKER_CORES=4
# Directorio de logs
export SPARK_LOG_DIR=/opt/spark/logs
# Directorio de trabajo (shuffle data)
export SPARK_WORKER_DIR=/opt/spark/work
# Java
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
Configurar los nodos Worker (en el archivo workers):
# /opt/spark/conf/workers
# Agregar las IPs o hostnames de los workers (uno por línea)
localhost # Para un cluster de un solo nodo
# worker1.cluster.local
# worker2.cluster.local
# worker3.cluster.local
Configuración de rendimiento (spark-defaults.conf):
sudo cp /opt/spark/conf/spark-defaults.conf.template /opt/spark/conf/spark-defaults.conf
sudo tee /opt/spark/conf/spark-defaults.conf << 'EOF'
# Configuración por defecto para todos los jobs de Spark
# URL del Master (para modo standalone)
spark.master spark://IP-DEL-MASTER:7077
# Memoria por defecto para el driver
spark.driver.memory 2g
# Memoria por defecto para los executors
spark.executor.memory 4g
# Núcleos por executor
spark.executor.cores 2
# Tamaño máximo de las particiones durante el shuffle
spark.sql.shuffle.partitions 200
# Directorio temporal (preferiblemente en SSD)
spark.local.dir /tmp/spark-temp
# Habilitar compresión de datos durante el shuffle
spark.shuffle.compress true
spark.rdd.compress true
# Serialización más eficiente
spark.serializer org.apache.spark.serializer.KryoSerializer
# Historial de jobs (para la UI de historial)
spark.eventLog.enabled true
spark.eventLog.dir /opt/spark/history-logs
spark.history.fs.logDirectory /opt/spark/history-logs
EOF
sudo mkdir -p /opt/spark/{logs,work,history-logs}
sudo chown -R spark:spark /opt/spark/logs /opt/spark/work /opt/spark/history-logs
Iniciar el cluster:
# Iniciar el Master
sudo -u spark /opt/spark/sbin/start-master.sh
# Iniciar los Workers
sudo -u spark /opt/spark/sbin/start-worker.sh spark://IP-DEL-MASTER:7077
# Para iniciar el cluster completo (master + todos los workers en conf/workers)
sudo -u spark /opt/spark/sbin/start-all.sh
# Verificar que el Master está funcionando
sudo -u spark /opt/spark/sbin/spark-daemon.sh status org.apache.spark.deploy.master.Master 1
# Acceder a la UI del Master:
# http://TU-SERVIDOR:8080
Crear servicios systemd para inicio automático:
# Servicio para el Master de Spark
sudo tee /etc/systemd/system/spark-master.service << 'EOF'
[Unit]
Description=Apache Spark Master
After=network.target
[Service]
Type=forking
User=spark
Group=spark
ExecStart=/opt/spark/sbin/start-master.sh
ExecStop=/opt/spark/sbin/stop-master.sh
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
# Servicio para el Worker de Spark
sudo tee /etc/systemd/system/spark-worker.service << 'EOF'
[Unit]
Description=Apache Spark Worker
After=spark-master.service
[Service]
Type=forking
User=spark
Group=spark
ExecStart=/opt/spark/sbin/start-worker.sh spark://localhost:7077
ExecStop=/opt/spark/sbin/stop-worker.sh
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now spark-master spark-worker
Configuración de PySpark
# Instalar PySpark via pip (versión que coincida con Spark instalado)
pip3 install pyspark==3.5.1
# O usar el PySpark incluido con Spark
export PYSPARK_PYTHON=python3
pyspark --master spark://IP-DEL-MASTER:7077
# Ejemplo de sesión PySpark interactiva
# Script de prueba PySpark: contar palabras
from pyspark.sql import SparkSession
# Crear la sesión de Spark
spark = SparkSession.builder \
.appName("ConteoPalabras") \
.master("spark://IP-DEL-MASTER:7077") \
.config("spark.executor.memory", "2g") \
.getOrCreate()
# Leer un archivo de texto
texto = spark.read.text("/opt/spark/README.md")
# Contar palabras
from pyspark.sql.functions import explode, split, lower, col
palabras = texto.select(
explode(split(lower(col("value")), r"\W+")).alias("palabra")
).filter(col("palabra") != "")
conteo = palabras.groupBy("palabra").count().orderBy("count", ascending=False)
# Mostrar las 10 palabras más frecuentes
conteo.show(10)
# Guardar resultado en formato Parquet
conteo.write.mode("overwrite").parquet("/tmp/conteo-palabras")
spark.stop()
Envío y Ejecución de Jobs
# Enviar un job al cluster standalone
spark-submit \
--master spark://IP-DEL-MASTER:7077 \
--executor-memory 2g \
--executor-cores 2 \
--num-executors 4 \
/ruta/al/script.py
# Enviar con archivos Python adicionales
spark-submit \
--master spark://IP-DEL-MASTER:7077 \
--py-files dependencias.zip \
--packages org.apache.spark:spark-sql-kafka-0-10_2.12:3.5.1 \
mi_job.py --fecha 2024-01-01
# Enviar un JAR de Scala/Java
spark-submit \
--class com.ejemplo.MiAplicacion \
--master spark://IP-DEL-MASTER:7077 \
mi-aplicacion-1.0.jar
Spark SQL
# Usar Spark SQL para consultas sobre DataFrames
from pyspark.sql import SparkSession
spark = SparkSession.builder \
.appName("SparkSQL") \
.master("local[*]") \
.getOrCreate()
# Cargar datos CSV como DataFrame
df_ventas = spark.read.csv(
"/datos/ventas.csv",
header=True,
inferSchema=True
)
# Registrar como tabla temporal SQL
df_ventas.createOrReplaceTempView("ventas")
# Ejecutar SQL sobre el DataFrame
resultado = spark.sql("""
SELECT
year(fecha) AS año,
month(fecha) AS mes,
categoria,
SUM(importe) AS total_ventas,
COUNT(*) AS num_ventas
FROM ventas
WHERE fecha >= '2023-01-01'
GROUP BY año, mes, categoria
ORDER BY año, mes, total_ventas DESC
""")
resultado.show(20)
# Guardar como tabla Parquet particionada
resultado.write \
.partitionBy("año", "mes") \
.mode("overwrite") \
.parquet("/datos/ventas-agregadas")
spark.stop()
Gestión de Recursos
# Ver el uso de recursos del cluster
# Interfaz web del Master: http://TU-SERVIDOR:8080
# Limitar recursos por aplicación
spark-submit \
--master spark://IP-DEL-MASTER:7077 \
--total-executor-cores 8 \ # Máximo de cores en todo el cluster
--executor-memory 4g \
mi_job.py
# Configurar la gestión de recursos dinámicos (workers se escalan según carga)
# En spark-defaults.conf:
# spark.dynamicAllocation.enabled=true
# spark.dynamicAllocation.minExecutors=1
# spark.dynamicAllocation.maxExecutors=20
# spark.shuffle.service.enabled=true
Monitorización con la UI de Spark
# Spark expone interfaces web para monitorización:
# - Master UI: http://TU-SERVIDOR:8080 (cluster overview)
# - Worker UI: http://TU-SERVIDOR:8081 (estado del worker)
# - App UI: http://TU-SERVIDOR:4040 (job en ejecución actual)
# - History UI: http://TU-SERVIDOR:18080 (historial de jobs)
# Iniciar el servidor de historial de Spark
sudo -u spark /opt/spark/sbin/start-history-server.sh
# O como servicio systemd
sudo tee /etc/systemd/system/spark-history.service << 'EOF'
[Unit]
Description=Apache Spark History Server
After=network.target
[Service]
Type=forking
User=spark
Group=spark
ExecStart=/opt/spark/sbin/start-history-server.sh
ExecStop=/opt/spark/sbin/stop-history-server.sh
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable --now spark-history
Solución de Problemas
El Master no inicia:
# Ver logs del Master
cat /opt/spark/logs/spark-spark-org.apache.spark.deploy.master.Master-1-*.out
# Verificar que el puerto 7077 no está en uso
sudo ss -tlnp | grep 7077
# Verificar la variable JAVA_HOME
echo $JAVA_HOME
java -version
Los Workers no se conectan al Master:
# Verificar conectividad desde el Worker al Master
nc -zv IP-DEL-MASTER 7077
# Ver logs del Worker
cat /opt/spark/logs/spark-spark-org.apache.spark.deploy.worker.Worker-*.out
# Verificar que el hostname del Master se resuelve
nslookup IP-DEL-MASTER
Jobs muy lentos o errores de memoria:
# Aumentar la memoria del executor
spark-submit --executor-memory 8g mi_job.py
# Ver el desglose de tiempo en la UI de la aplicación (puerto 4040)
# Stages > Task Time Breakdown
# Aumentar el número de particiones para reducir el tamaño de cada partición
# En el código PySpark:
# df = df.repartition(500)
# spark.conf.set("spark.sql.shuffle.partitions", "500")
Conclusión
Apache Spark es la plataforma de procesamiento distribuido más versátil del ecosistema big data, con soporte nativo para Python, Scala y Java. Su capacidad para escalar desde un laptop hasta clusters de cientos de nodos, combinada con Spark SQL, MLlib y Structured Streaming, lo convierte en la herramienta imprescindible para cualquier equipo de ingeniería de datos que necesite procesar grandes volúmenes de información de forma eficiente en sus servidores Linux.


