Integración de Spark y Prometheus para monitorización

Apache Spark es una herramienta que ya hemos abordado anteriormente en distintos artículos de nuestro blog. Y es que, en Damavis, además de usarla en muchos de nuestros proyectos, consideramos a Spark como la navaja suiza en lo que a tratamiento de datos se refiere. Sin embargo, sí hay que aclarar que no es una tecnología perfecta o fácil de utilizar.

Como todo sistema productivo, Spark necesita procesos de monitoreo detallados que permitan garantizar su estabilidad y entender qué está ocurriendo. En este espacio, exploraremos cómo gracias a Prometheus podemos mejorar la observabilidad de los trabajos lanzados en Spark además de analizar las métricas en tiempo real. 

Si todavía no has trabajado con Prometheus, te recomiendo echar un vistazo al post Monitorización con Prometheus y Grafana para conocer la herramienta. Te será muy útil a la hora de comprender los conceptos básicos que se van a utilizar en lo que veremos a continuación.

Monitorización de métricas con Spark

Apache Spark ofrece varias alternativas para la monitorización y observabilidad tanto del sistema como de los procesos que se ejecutan. De manera nativa, en la Spark UI se puede consultar la información básica acerca de la ejecución de jobs, el estado o logs de dichas ejecuciones, etc. También está disponible la API para lanzar consultas específicas acerca del estado de alguna tarea dentro de Spark. Esto resulta muy útil a la hora de integrar sistemas de observabilidad.

En esta ocasión, trataremos únicamente la integración de Prometheus con Spark.

Integración de Spark con Prometheus

La mayoría de sistemas que se integran con Prometheus reservan un espacio dedicado para consultas HTTP llamado /metrics. Sin embargo, y a pesar de su capacidad para desplegar una API capaz de consultar estados y estadísticas de uso, Spark utiliza el sistema de JMX Exporter de Prometheus.

Este agente se acopla a los procesos de Spark y se encarga de transformar las métricas de JMX en un formato que Prometheus pueda entender. De esta forma, el JMX Exporter expone un endpoint http por defecto, /metrics, que Prometheus consultará para recoger las  métricas.

JMX Exporter

La configuración específica que debemos lanzar a la hora de ejecutar nuestro Spark con la capacidad de integración con el JMX Exporter sería:

--conf "spark.driver.extraJavaOptions=-javaagent:/path-to-jmx_prometheus_javaagent.jar=7071:/path-to-driver-config.yml"
--conf "spark.executor.extraJavaOptions=-javaagent:/path-to-jmx_prometheus_javaagent.jar=7072:/path-to-executor-config.yml"

De esta manera, establecemos que al agente que se encargue de levantar un endpoint en el puerto configurado (por defecto 7071 para los drivers y 7072 para los executors), podrá consultar las métricas del mismo en formato Prometheus. 

Así pues, Spark de manera nativa no podrá levantar un /metrics, sino que lo hace a través de la integración con JMX Exporter.

Para comprender qué ocurre por debajo, es necesario conocer en detalle qué es el JMX Exporter y de qué se encarga. Este componente es responsable de extraer las métricas expuestas por una aplicación Java a través del JMX.

Básicamente, JMX son las siglas de Java Management Extension, una tecnología que se encuentra dentro del marco de Java para gestionar y monitorizar aplicaciones Java. Normalmente, se utiliza para exponer información de métricas, configuraciones y otro tipo de información de las operaciones que está realizando Java. Esto permite que se pueda supervisar el estado de la aplicación en tiempo real.

Sin profundizar mucho más sobre JMX, la información relativa a las métricas que se van a exportar es configurada y predefinida de manera nativa por los desarrolladores de Spark. Ellos mismos se encargan de registrar una serie de MBeans (componentes que se encargan de exponer métricas) con datos como rendimiento, estado de los jobs, uso de recursos, etc.

JMX Exporter se configura mediante un archivo yaml, que seleccionará y transformará los MBeans en métricas que Prometheus pueda entender.

Ejemplo de integración de Spark con Prometheus

Los recursos que necesitaremos para llevar a esta integración son los siguientes:

  • Apache Spark
  • JMX Exporter. Se trata de un archivo .jar que se puede descargar desde este repositorio de Git, concretamente, el javaagent.
  • Prometheus. En anteriores posts ya aprendimos cómo lanzarlo. En este caso, utilizaremos Docker.
  • Python y PySpark.

Aplicación PySpark

Para este ejemplo, utilizaremos un código muy sencillo de PySpark que nos permitirá observar cómo se exportan las métricas:

from pyspark.sql import SparkSession
import time

if __name__ == "__main__":
    spark = SparkSession.builder.appName("PrometheusMonitoringExample").getOrCreate()

    df = spark.range(1000)
    df = df.withColumn("square", df["id"] * df["id"])
    df.show()

    time.sleep(60)
    spark.stop()

Esta aplicación simplemente crea un DataFrame y mantiene en ejecución la aplicación durante 60 segundos para poder monitorearla.

Configuración del JMX Exporter

A la hora de configurar el JMX Exporter, necesitamos pasarle un archivo yaml como este:

startDelaySeconds: 0
lowercaseOutputName: true
lowercaseOutputLabelNames: true
rules:
  - pattern: ".*"

Con esta configuración, le indicamos que exponga todas las métricas detectadas y que se normalicen los nombres con letras minúsculas. No obstante, este archivo nos permite afinar mucho más qué y cómo queremos que se exponga.

Ejecución de Spark

En este caso, ejecutaremos el spark-submit sobre nuestro código Python. Sin embargo, hay que aclarar que existen alternativas para configuración de JMX en un cluster Spark.

spark-submit --conf "spark.driver.extraJavaOptions=-javaagent:/home/oscar/spark-prometheus/jmx_prometheus_javaagent-1.1.0.jar=7071:/home/oscar/spark-prometheus/spark-jmx-exporter.yaml" /home/oscar/spark-prometheus/app.py

Configuración de Prometheus

Entramos en la recta final de este tutorial paso a paso. Ahora, únicamente queda la configuración de Prometheus que, en este caso, es muy sencilla.

global:
  scrape_interval: 5s

scrape_configs:
  - job_name: 'spark'
    static_configs:
      - targets: ['localhost:7071']

Una vez configurado, solamente debemos ejecutar Prometheus ya sea en local o en Docker. Si lo haces con Docker, ten en cuenta que hay que utilizar el usuario root y darle permisos a la carpeta donde tenemos el yaml. También habría que cambiar el gateway para que pueda acceder a los puertos del pc anfitrión.

Hasta aquí, ya tenemos integrado Spark con Prometheus. Si consultamos localhost:7071/metrics, encontraremos las variables que se están exportando.

Por ejemplo podemos ver el uso de heap memory con la siguiente query:

jvm_memory_used_bytes{area="heap"}
Captura de pantalla de interfaz gráfica de la integración de Spark con Prometheus con ejemplo de query lanzada para consultar el uso de la heap memory

A continuación, veremos una lista de métricas útiles junto sus queries:

  • jvm_memory_used_bytes{area="heap"}. Muestra los bytes usados de la JVM.
  • jvm_memory_pool_used_bytes{pool="G1 Old Gen"}. Expone cuántos bytes se están utilizando en el pool de memoria G1 Old Gen.
  • jvm_classes_currently_loaded. Indica la cantidad de clases que se están cargando en la JVM, lo que nos da una idea del tamaño de la ejecución.
  • jvm_compilation_time_seconds_total. Tiempo total que la JVM ha dedicado a la compilación.
  • jvm_gc_collection_seconds_sum{gc="G1 Young Generation"}. Es el tiempo Acumulado de Garbage Collection (GC) en G1 Young Generation.
  • jvm_gc_collection_seconds_count{gc="G1 Young Generation"}. Muestra el número de ciclos de Garbage Collection en G1 Young Generation.
  • process_cpu_seconds_total. Indica el uso de CPU del proceso
  • jvm_threads_current. Representa el número actual de hilos en la JVM.

Conclusión

En este post, hemos abordado la integración de integra Spark y Prometheus además de conocer en qué consiste el JMX Exporter y la forma de integrarlo con Spark para exponer el endpoint /metrics. Por último, hemos hecho un ejemplo práctico de ejecución de una aplicación de PySpark y observado algunas métricas dentro de Prometheus.

¡Esperamos que te haya servido el post! Si te ha parecido interesante, te animamos a visitar la categoría Software para ver artículos similares y a compartirlo en redes con tus contactos. ¡Hasta pronto!

Óscar García
Óscar García
Artículos: 36