Доступ к пользовательским JAR из Spark-заданий на AWS EMR

Доступ к пользовательским JAR из Spark-заданий на AWS EMR

В рамках обучения разработчиков распределенных Spark-приложений, сегодня рассмотрим, как добавить функции из пользовательских JAR-файлов в кластер AWS EMR. Достоинства и недостатки действия начальной загрузки EMR с переопределением конфигурации Spark, а также расширенное управление зависимостями через spark-submit.

Трудности обращения к пользовательским JAR в Amazon EMR с Apache Spark и Livy

На практике довольно часто случается ситуация, когда требуется отправить собственный JAR с некоторыми дополнительными библиотеками, например, источниками данных для пользовательских форматов в кластер Amazon EMR с Apache Spark и Livy. Считается, что Amazon EMR как мощная облачная платформа больших данных отлично подходит для выполнения распределенных заданий Apache Spark. Однако содержимое JAR недоступно при попытке получить к нему доступ из Livy — REST-API сервиса для взаимодействия с кластером Spark. По сути, Apache Livy – это агент для запросов Spark, который отправляет код в кластер в виде фрагментов скрипта или пакетов. При этом он предоставляет программный RESTfull API для Java, Scala и Python, чтобы удаленное приложение выполняло код внутри Spark без необходимости поддерживать локальный контекст. Подробнее об этом мы писали здесь и здесь.

Например, есть задание для обработки данных и загрузки их в базу данных, которая доступна через коннектор в виде JAR. Необходимо запустить это задание на AWS EMR, поэтому JAR-коннектор должен быть доступен для кластера Spark. Или задание, содержащее зависимость, например, стороннюю библиотеку, упакованную в JAR, которая должна быть доступна при использовании с Livy.

Обеспечить доступ к функциям из пользовательских JAR-файлов в кластере AWS EMR можно одним из следующих способов:

  • действие начальной загрузки EMR с переопределением конфигурации Spark;
  • расширенное управление зависимостями через spark-submit.

Достоинства и недостатки каждого подхода мы рассмотрим далее.

Начальная загрузка EMR

Для решения вышеописанной проблемы можно использовать действие начальной загрузки EMR. Это предполагает отправку JAR-файла на узлы в кластере, чтобы сделать его доступным через переопределение конфигурации Spark. Сперва следует поместить файл JAR-библиотеки, созданной с помощью сборки sbt со всеми необходимыми зависимостями в корзину S3. Затем нужно создать скрипт для копирования JAR на узел кластера, который содержит следующее:

#!/bin/bash

mkdir -p /home/hadoop/mylib

aws s3 cp s3://mybucket/mylib.jar/home/hadoop/mylib

Этот скрипт будет настроен как действие начальной загрузки в EMR, поэтому он будет выполняться на каждом узле после его подготовки.

Наконец, нужно переопределить конфигурации Spark, чтобы включить JAR в путь к классам. Здесь стоит убедиться, что JAR добавлен в задание через свойства spark.driver.extraClassPath и spark.executor.extraClassPath в spark-submit с помощью конфигурации JSON при создании кластера. Конфигурацию JSON помещается в туже корзину AWS S3, где лежат JAR-файл и скрипт для его копирования на узел кластера.

Конфигурации для сред Spark и YARN нужны, чтобы PySpark работал с Python3 в EMR через Livy. По умолчанию AWS EMR сам заполняет два класса extraClassPath множеством библиотек, которые требуются для правильной работы этой облачной платформы. Поэтому приходится запускать кластер без пользовательской библиотеки JAR и извлекать эти настройки из конфигурационного файла spark-defaults.conf, чтобы настроить собственную конфигурацию. Иначе доступ к S3 не будет работать.

Таким образом, при создании кластера на шаге 1 следует сослаться на файл конфигурации JSON, а на шаге 3 – настроить скрипт копирования JAR-файла как пользовательское действие начальной загрузки. Далее можно открыть Jupyterhub кластера, запустить блокнот и работать с добавленными функциями.

Этот подход работает, но имеет несколько недостатков:

  • необходима ручная проверка, что конфигурация driver.extraClassPath и spark.executor.extraClassPath синхронизирована с путями к зависимостям, необходимым для работы EMR с учетом актуальной версии платформы;
  • усложнение процесса создания кластера EMR, т.к. сюда включается действие начальной загрузки и переопределение конфигурации Spark. Из-за ошибки на этих шагах придется заново создавать EMR или копировать JAR на все узлы вручную, а также устанавливать driver.extraClassPath и spark.executor.extraClassPath как часть spark-submit. Также это увеличивает время создания кластера EMR.

Чтобы избежать указанных недостатков, можно использовать альтернативный способ, рассмотренный далее.

Альтернативный подход

Добавить функции из пользовательских JAR-файлов в кластер AWS EMR без действия начальной загрузки и переопределения конфигурации Spark можно с помощью расширенного управления зависимостями через spark-submit — скрипт для распределения заданий независимо от типа диспетчера кластера. Он позволяет запускать код Apache Spark, написанный на Java, Scala или Python.

Spark-submit имеет параметр —jars для отправки JAR-файлов на узлы в кластере и делает их доступными в пути к классам всех исполнителей. При этом JAR-файл приложения вместе со всеми JAR-файлами, включенными в spark-submit с параметром —jars, будут автоматически перенесены в кластер. URL-адреса, указанные после опции —jars, должны быть разделены запятыми. Этот список включен в пути к классам драйвера и исполнителя. Расширение каталога не работает с параметром —jars.

Spark использует следующую схему URL-адресов, позволяющую использовать различные стратегии распространения JAR-файлов:

  • file: — абсолютные пути и URI-адреса file:/ обслуживаются файловым HTTP-сервером драйвера, и каждый исполнитель извлекает файл с HTTP-сервера драйвера;
  • hdfs:, http:, https:, ftp: — эти файлы и JAR-файлы вытягиваются из URI;
  • local: — ожидается, что URI, начинающийся с local:/, будет существовать как локальный файл на каждом рабочем узле. Это означает, что сетевой ввод-вывод не будет выполняться, что отлично подходит для работы с большими файлами, которые передаются каждому рабочему процессу или совместно используются через NFS, GlusterFS и прочие сетевые файловые системы.

Поскольку файлы копируются в рабочий каталог для каждого SparkContext на узлах-исполнителях, в перспективе это может занимать много места на дисках и их придется чистить. В YARN очистка выполняется автоматически, а в автономном режиме Spark автоматическую очистку можно настроить с помощью свойства spark.worker.cleanup.appDataTtl.

Apache Airflow для инженеров данных

Код курса
AIRF
Ближайшая дата курса
1 декабря, 2025
Продолжительность
24 ак.часов
Стоимость обучения
72 000

Пользователи также могут включать любые другие зависимости, указав разделенный запятыми список координат Maven с опцией —packages. Все транзитивные зависимости будут обработаны при использовании этой команды. Дополнительные репозитории или распознаватели в sbt можно добавлять через запятую с помощью флага —repositories. При этом учетные данные для защищенных паролем репозиториев могут быть предоставлены в их URI, например, https://user:password@host/. Поэтому применять подобные команды следует очень осторожно. Эти команды могут использоваться с pyspark, spark-shell и spark-submit для включения пакетов Spark.

Для Python можно использовать эквивалентную опцию —py-files, чтобы распространить библиотеки .egg, .zip и .py по исполнителям.

Поскольку EMR может обращаться к S3 как к файловой системе, через spark-submit можно передать сам путь к корзине в параметре —jars. Например,

spark-submit —deploy-mode cluster —jars s3://my-bucket/my-jars/db-connector.jar …

spark-submit —deploy-mode cluster —jars s3://my-bucket/my-jars/*.jar …

Таким образом, все JAR-файлы с зависимостями будут скопированы в кластер AWS EMR и можно использовать любой JAR из S3, пропустив добавление действия начальной загрузки во время создания кластера. Это позволяет сделать любой JAR в S3 доступным для заданий Spark как часть отправки задания и избежать дополнительных шагов при создании кластера AWS EMR.

Узнайте больше про применение Apache Spark для разработки распределенных ML-приложений и аналитики больших данных на специализированных курсах в нашем лицензированном учебном центре обучения и повышения квалификации для разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data в Москве:

Источники

  1. https://arunvelsriram.dev/adding-custom-jars-to-spark-jobs-on-aws-emr
  2. https://stackoverflow.com/questions/56666457/how-to-add-functions-from-custom-jars-to-emr-cluster/56667997#56667997
  3. https://spark.apache.org/docs/latest/submitting-applications/#advanced-dependency-management