--- title: "Cómo instalar Apache Spark en Ubuntu 24.04 (standalone)" description: "Instala Apache Spark 4 en Ubuntu 24.04 con Java 21, arranca un clúster standalone con master y worker gestionados por systemd y ejecuta tu primer job PySpark." category: "Ingeniería de Datos" language: es source: https://cubepath.com/es/docs/ingeniería-de-datos/instalacion-de-apache-spark-en-linux updated: 2026-09-25 --- # Cómo instalar Apache Spark en Ubuntu 24.04 (standalone) Apache Spark es un motor de procesamiento distribuido que ejecuta trabajos de datos en memoria y ofrece APIs para Python (PySpark), SQL, Scala y Java. En este tutorial instalarás Spark 4.2 en Ubuntu 24.04, lo configurarás como clúster standalone de un nodo (un master y un worker gestionados por systemd) y enviarás trabajos con `spark-submit` y PySpark. El mismo esquema sirve después para añadir más workers. ## Requisitos previos Para seguir esta guía necesitas: - Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con al menos 2 vCPU y 4 GB de RAM. - Un usuario no root con privilegios `sudo`. - Acceso SSH desde tu equipo, que usarás también para abrir un túnel hacia las interfaces web de Spark. Spark 4.2 funciona con Java 17, 21 o 25 y con Python 3.10 o superior. Ubuntu 24.04 trae OpenJDK 21 y Python 3.12, así que ambos requisitos se cubren con paquetes del sistema. ## Paso 1: Instalar Java Spark se ejecuta sobre la JVM, por lo que necesitas un runtime de Java. Instala OpenJDK 21 sin componentes gráficos: ```bash sudo apt update sudo apt install -y openjdk-21-jre-headless ``` Comprueba la versión instalada: ```bash java -version ``` ```output openjdk version "21.0.8" 2025-07-15 OpenJDK Runtime Environment (build 21.0.8+9-Ubuntu-0ubuntu124.04.1) OpenJDK 64-Bit Server VM (build 21.0.8+9-Ubuntu-0ubuntu124.04.1, mixed mode, sharing) ``` Python 3 ya viene instalado en Ubuntu 24.04 y es el intérprete que usará PySpark. Puedes confirmarlo con `python3 --version`. ## Paso 2: Descargar y verificar Spark Spark se distribuye como un archivo precompilado. Descarga la versión 4.2.0 empaquetada para Hadoop 3 desde el CDN de Apache: ```bash cd /tmp wget https://dlcdn.apache.org/spark/spark-4.2.0/spark-4.2.0-bin-hadoop3.tgz wget https://downloads.apache.org/spark/spark-4.2.0/spark-4.2.0-bin-hadoop3.tgz.sha512 ``` > Nota: el CDN solo conserva las versiones más recientes. Si la descarga devuelve un error 404, consulta la versión actual en https://spark.apache.org/downloads.html o descarga la misma versión desde `https://archive.apache.org/dist/spark/`. Comprueba que el archivo no está corrupto comparándolo con la suma SHA-512 publicada: ```bash sha512sum -c spark-4.2.0-bin-hadoop3.tgz.sha512 ``` ```output spark-4.2.0-bin-hadoop3.tgz: OK ``` ## Paso 3: Instalar Spark en /opt/spark Crea un usuario de sistema sin privilegios que ejecutará los procesos del clúster: ```bash sudo useradd --system --home-dir /opt/spark --shell /usr/sbin/nologin spark ``` Extrae el archivo en `/opt` y crea un enlace simbólico `/opt/spark`. Así, al actualizar a otra versión solo tendrás que cambiar el enlace: ```bash sudo tar -xzf spark-4.2.0-bin-hadoop3.tgz -C /opt sudo ln -s /opt/spark-4.2.0-bin-hadoop3 /opt/spark sudo mkdir -p /opt/spark/logs /opt/spark/work sudo chown -R spark:spark /opt/spark-4.2.0-bin-hadoop3 ``` Añade los binarios de Spark al `PATH` de todos los usuarios con un archivo en `/etc/profile.d`: ```bash sudo nano /etc/profile.d/spark.sh ``` ```bash export SPARK_HOME=/opt/spark export PATH="$PATH:$SPARK_HOME/bin" ``` Carga el archivo en la sesión actual y comprueba que `spark-submit` responde: ```bash source /etc/profile.d/spark.sh spark-submit --version ``` ```output Welcome to ____ __ / __/__ ___ _____/ /__ _\ \/ _ \/ _ `/ __/ '_/ /___/ .__/\_,_/_/ /_/\_\ version 4.2.0 /_/ Using Scala version 2.13.16, OpenJDK 64-Bit Server VM, 21.0.8 ``` ## Paso 4: Configurar el clúster standalone El modo standalone es el gestor de clúster que incluye Spark: un proceso master reparte los recursos y uno o varios workers ejecutan los executors. No necesita Hadoop ni YARN. Spark lee sus variables de entorno de `conf/spark-env.sh`. Crea el archivo: ```bash sudo nano /opt/spark/conf/spark-env.sh ``` ```bash # Direccion en la que escuchan el master, el worker y sus interfaces web SPARK_LOCAL_IP=127.0.0.1 SPARK_MASTER_HOST=127.0.0.1 # Recursos que este worker ofrece a los executors SPARK_WORKER_CORES=2 SPARK_WORKER_MEMORY=2g SPARK_LOG_DIR=/opt/spark/logs SPARK_WORKER_DIR=/opt/spark/work ``` Con `SPARK_LOCAL_IP=127.0.0.1` todos los puertos (7077 del master, 8080 y 8081 de las interfaces web, 4040 de cada aplicación) quedan ligados a localhost. Las interfaces web de Spark no tienen autenticación por defecto, así que no deben quedar expuestas a Internet. Ajusta `SPARK_WORKER_CORES` y `SPARK_WORKER_MEMORY` a tu servidor, dejando al menos 1 GB para el sistema operativo. Define ahora los valores por defecto de los trabajos en `spark-defaults.conf`, para no tener que indicar el master en cada `spark-submit`: ```bash sudo nano /opt/spark/conf/spark-defaults.conf ``` ```text spark.master spark://127.0.0.1:7077 spark.driver.memory 1g spark.executor.memory 1g ``` Ajusta el propietario de los archivos nuevos: ```bash sudo chown spark:spark /opt/spark/conf/spark-env.sh /opt/spark/conf/spark-defaults.conf ``` ## Paso 5: Crear servicios systemd para el master y el worker Los scripts `start-master.sh` y `start-worker.sh` lanzan los procesos en segundo plano por defecto. Con la variable `SPARK_NO_DAEMONIZE` se ejecutan en primer plano, que es lo que systemd necesita para supervisarlos y enviar su salida al journal. Crea la unidad del master: ```bash sudo nano /etc/systemd/system/spark-master.service ``` ```ini [Unit] Description=Apache Spark master After=network-online.target Wants=network-online.target [Service] User=spark Group=spark Environment=SPARK_NO_DAEMONIZE=true ExecStart=/opt/spark/sbin/start-master.sh Restart=on-failure [Install] WantedBy=multi-user.target ``` Crea la unidad del worker, que se registra en el master local: ```bash sudo nano /etc/systemd/system/spark-worker.service ``` ```ini [Unit] Description=Apache Spark worker After=spark-master.service Requires=spark-master.service [Service] User=spark Group=spark Environment=SPARK_NO_DAEMONIZE=true ExecStart=/opt/spark/sbin/start-worker.sh spark://127.0.0.1:7077 Restart=on-failure [Install] WantedBy=multi-user.target ``` Recarga systemd y arranca los dos servicios: ```bash sudo systemctl daemon-reload sudo systemctl enable --now spark-master spark-worker ``` Comprueba que el worker se ha registrado en el master: ```bash sudo journalctl -u spark-master --no-pager | grep -i "registering worker" ``` ```output ... INFO Master: Registering worker 127.0.0.1:39417 with 2 cores, 2.0 GiB RAM ``` También puedes ver los puertos en escucha con `sudo ss -tlnp | grep java`: deberían aparecer 7077, 8080 y 8081 en `127.0.0.1`. ## Paso 6: Acceder a la interfaz web del master Como la interfaz solo escucha en localhost, ábrela a través de un túnel SSH. Ejecuta este comando en **tu equipo local**, sustituyendo `your_user` y `your_server_ip`: ```bash ssh -L 8080:127.0.0.1:8080 your_user@your_server_ip ``` Con la sesión abierta, visita `http://localhost:8080` en el navegador. Verás el estado del master como `ALIVE`, un worker activo con 2 cores y 2 GiB de memoria, y la lista de aplicaciones en ejecución y completadas. ## Paso 7: Ejecutar un trabajo de ejemplo La distribución incluye ejemplos listos para usar. Envía al clúster el cálculo de pi escrito en Python, repartido en 10 particiones: ```bash spark-submit /opt/spark/examples/src/main/python/pi.py 10 2>/dev/null ``` ```output Pi is roughly 3.141120 ``` Se ha redirigido stderr a `/dev/null` solo para ocultar los logs de Spark. Si recargas la interfaz web, la aplicación `PythonPi` aparecerá en **Completed Applications**, lo que confirma que el trabajo se ejecutó en el worker y no en modo local. ## Paso 8: Escribir tu propio trabajo PySpark Crea un script que cuente las palabras más frecuentes del `README.md` incluido con Spark, usando la API de DataFrames: ```bash nano ~/conteo_palabras.py ``` ```python from pyspark.sql import SparkSession from pyspark.sql.functions import col, explode, lower, split spark = SparkSession.builder.appName("ConteoPalabras").getOrCreate() texto = spark.read.text("/opt/spark/README.md") palabras = ( texto.select(explode(split(lower(col("value")), r"\W+")).alias("palabra")) .filter(col("palabra") != "") ) conteo = palabras.groupBy("palabra").count().orderBy(col("count").desc()) conteo.show(5) spark.stop() ``` No hace falta indicar el master en el código: `spark-submit` lo toma de `spark-defaults.conf`. Ejecuta el script: ```bash spark-submit ~/conteo_palabras.py 2>/dev/null ``` ```output +-------+-----+ |palabra|count| +-------+-----+ | the| 25| | spark| 18| | to| 17| | for| 12| | and| 10| +-------+-----+ only showing top 5 rows ``` Las cifras exactas dependen de la versión del README. Para trabajar de forma interactiva, ejecuta `pyspark`: abre una consola de Python con la variable `spark` ya creada y conectada al clúster. > Nota: en un clúster con varios nodos, los ficheros que lees con `spark.read` deben existir en la misma ruta en todos los workers o estar en un almacenamiento compartido (S3, HDFS, NFS). En un solo nodo no hay diferencia. ## Añadir más workers Para crecer a varios servidores, repite los pasos 1 a 3 en cada nodo nuevo y usa la red privada entre ellos: - En el master, cambia `SPARK_LOCAL_IP` y `SPARK_MASTER_HOST` a su IP privada y actualiza `spark.master` en `spark-defaults.conf`. - En cada worker, pon su propia IP privada en `SPARK_LOCAL_IP` y apunta el `ExecStart` de `spark-worker.service` a `spark://ip_privada_master:7077`. - Permite el tráfico entre nodos solo desde la subred privada, por ejemplo `sudo ufw allow from 10.0.0.0/24`. Los executors abren puertos dinámicos hacia el driver, por lo que filtrar únicamente el 7077 no es suficiente. ## Solución de problemas **El worker no aparece en el master.** Revisa `sudo journalctl -u spark-worker -n 50`. Si ves errores de conexión a `7077`, comprueba que la URL del `ExecStart` coincide exactamente con `SPARK_MASTER_HOST`: el master rechaza conexiones dirigidas a un nombre distinto del que anuncia. **El trabajo se queda en espera con "Initial job has not accepted any resources".** El worker no tiene memoria o cores suficientes para lo que pide la aplicación. Reduce `spark.executor.memory` o aumenta `SPARK_WORKER_MEMORY` y reinicia el worker con `sudo systemctl restart spark-worker`. **`spark-submit: command not found`.** El `PATH` se carga al iniciar sesión. Cierra y abre la sesión SSH, o ejecuta `source /etc/profile.d/spark.sh`. **`java.lang.OutOfMemoryError` en el driver.** Evita `collect()` sobre conjuntos grandes y sube `spark.driver.memory` en `spark-defaults.conf`. ## Conclusión Tienes Apache Spark 4.2 funcionando en Ubuntu 24.04 como clúster standalone, con el master y el worker supervisados por systemd, las interfaces web protegidas tras un túnel SSH y trabajos PySpark ejecutándose en el worker. Como siguientes pasos puedes activar el servidor de historial (`spark.eventLog.enabled` y `start-history-server.sh`) para conservar la interfaz de las aplicaciones terminadas, añadir workers en otros nodos por la red privada o leer datos en Parquet desde un almacenamiento S3 compatible.