Кластерные приложения на Docker

Кластер Apache Spark на Docker (с интерфейсом JupyterLab)

Создайте собственный кластер Apache Spark в автономном режиме на Docker с помощью интерфейса JupyterLab.

Apache Spark, пожалуй, самый популярный механизм обработки больших данных. Фреймворк с более чем 25 тысячами звезд на GitHub является отличной отправной точкой для изучения параллельных вычислений в распределенных системах с использованием Python, Scala и R.

Для начала вы можете запустить Apache Spark на своем компьютере, используя один из множества доступных доступных дистрибутивов Docker. Jupyter предлагает отличный dockerized Apache Spark с интерфейсом JupyterLab, но пропускает распределенное ядро ​​фреймворка из-за его запуска в одном контейнере. Некоторые проекты GitHub предлагают возможности распределенного кластера, но не имеют интерфейса JupyterLab, что снижает удобство использования, обеспечиваемое IDE.

Я считаю, что комплексная среда для изучения и практики кода Apache Spark должна сохранять свою распределенную природу, обеспечивая при этом отличное взаимодействие с пользователем.

Эта статья полностью посвящена этой вере.

В следующих разделах я покажу вам, как построить собственный кластер. К концу у вас будет полнофункциональный кластер Apache Spark, построенный с помощью Docker и поставляемый с главным узлом Spark, двумя рабочими узлами Spark и интерфейсом JupyterLab. Он также будет включать API Apache Spark Python (PySpark) и смоделированную распределенную файловую систему Hadoop (HDFS).

TL;DR

В этой статье показано, как построить кластер Apache Spark в автономном режиме, используя Docker в качестве уровня инфраструктуры. Поставляется со следующим:

  • Python 3.7 с PySpark 3.0.0 и Java 8;
  • Apache Spark 3.0.0 с одним главным и двумя рабочими узлами;
  • JupyterLab IDE 2.1.5;
  • Имитация HDFS 2.7.

Чтобы создать кластер, нам нужно создать, собрать и скомпоновать образы Docker для узлов JupyterLab и Spark. Вы можете пропустить это руководство, используя готовый дистрибутив, размещенный на моем GitHub.

Обновление № 1. В 2020-08-09 мы выпустили поддержку Spark Scala API через ядро ​​Almond Jupyter Scala. Спасибо, Алмонд, за то, что он классный. ✨

Обновление №2: В 2020–08–19 мы выпустили поддержку Spark R API (SparkR) через ядро ​​IRkernel Jupyter R. Спасибо IRkernel за то, что они классные. ✨

Требования

  • Docker 1.13.0+;
  • Docker Compose 1.10.0+.

Оглавление

  1. Обзор кластера;
  2. Создание изображений;
  3. Построение образов;
  4. Составление кластера;
  5. Создание приложения PySpark.

1. Обзор кластера

Кластер состоит из четырех основных компонентов: IDE JupyterLab, главного узла Spark и двух рабочих узлов Spark. Пользователь подключается к главному узлу и отправляет команды Spark через красивый графический интерфейс, предоставляемый записными книжками Jupyter. Главный узел обрабатывает ввод и распределяет вычислительную нагрузку по рабочим узлам, отправляя результаты обратно в IDE. Компоненты соединены с помощью локальной сети и обмениваются данными друг с другом через общий смонтированный том, имитирующий HDFS.

Как уже упоминалось, нам нужно создать, собрать и скомпоновать образы Docker для узлов JupyterLab и Spark, чтобы создать кластер. Мы будем использовать следующую иерархию образов Docker:

Базовый образ кластера загрузит и установит стандартные программные инструменты (Java, Python и т. Д.) И создаст общий каталог для HDFS. В базовом образе Spark приложение Apache Spark будет загружено и настроено как для главного, так и для рабочего узлов. Главный образ Spark настроит платформу для работы в качестве главного узла. Точно так же рабочий узел Spark настроит приложение Apache Spark для работы в качестве рабочего узла. Наконец, образ JupyterLab будет использовать базовый образ кластера для установки и настройки IDE и PySpark, API Python Apache Spark.

2. Создание изображений

2.1. Базовый образ кластера

В качестве базового образа мы будем использовать дистрибутив Linux для установки Java 8 (или 11), только для Apache Spark. Нам также необходимо установить Python 3 для поддержки PySpark и создать общий том для имитации HDFS.

Для начала выберем ОС Linux. В официальном репозитории Apache Spark на GitHub есть Dockerfile для развертывания Kubernetes, в котором используется небольшой образ Debian со встроенной средой выполнения Java 8 (JRE). Выбирая тот же базовый образ, мы решаем как выбор ОС, так и установку Java. Затем мы получаем последний выпуск Python (в настоящее время 3.7) из официального репозитория пакетов Debian и создаем общий том.

2.2. Базовое изображение Spark

Для базового образа Spark мы получим и настроим Apache Spark в автономном режиме, в его простейшей конфигурации развертывания. В этом режиме мы будем использовать его диспетчер ресурсов для настройки контейнеров для работы в качестве главного или рабочего узла. Напротив, менеджеры ресурсов, такие как Apache YARN, динамически выделяют контейнеры в качестве главных или рабочих узлов в соответствии с рабочей нагрузкой пользователя. Кроме того, мы получим версию Apache Spark с поддержкой Apache Hadoop, позволяющую кластеру моделировать HDFS с использованием общего тома, созданного в базовом образе кластера.

Начнем с загрузки последней версии Apache Spark (в настоящее время 3.0.0) с поддержкой Apache Hadoop из официального репозитория Apache. Затем мы немного поиграем с загруженным пакетом (распаковываем, перемещаем и т. Д.), И мы готовы к этапу установки. Наконец, мы настраиваем четыре переменные Spark, общие как для главного, так и для рабочих узлов:

  1. SPARK_HOME - это установленное расположение Apache Spark, используемое платформой для настройки задач;
  2. SPARK_MASTER_HOST - это имя хоста главного узла, используемое рабочими узлами для подключения;
  3. SPARK_MASTER_PORT - это порт главного узла, используемый рабочими узлами для подключения;
  4. PYSPARK_PYTHON - это установленная папка Python, используемая Apache Spark для поддержки своего Python API.

2.3. Главный образ Spark

Для главного образа Spark мы настроим приложение Apache Spark для работы в качестве главного узла. Мы настроим сетевые порты, чтобы разрешить сетевое соединение с рабочими узлами и открыть главный веб-интерфейс, веб-страницу для мониторинга действий главного узла. В конце мы настроим команду запуска контейнера для запуска узла в качестве главного экземпляра.

Мы начинаем с открытия порта, настроенного в переменной среды SPARK_MASTER_PORT, чтобы рабочие могли подключаться к главному узлу. Затем мы открываем порт SPARK_MASTER_WEBUI_PORT для доступа к главной странице веб-интерфейса. Наконец, мы устанавливаем команду запуска контейнера для запуска встроенного сценария развертывания Spark с мастер-классом в качестве аргумента.

2.4. Образ рабочего Spark

Для рабочего образа Spark мы настроим приложение Apache Spark для работы в качестве рабочего узла. Подобно главному узлу, мы настроим сетевой порт, чтобы открыть рабочий веб-интерфейс, веб-страницу для мониторинга активности рабочего узла и настроить команду запуска контейнера для запуска узла в качестве рабочего экземпляра.

Сначала мы открываем порт SPARK_WORKER_WEBUI_PORT, чтобы разрешить доступ к странице рабочего веб-интерфейса пользователя, как мы это сделали с главным узлом. Затем мы устанавливаем команду запуска контейнера для запуска встроенного сценария развертывания Spark с рабочим классом и основным сетевым адресом в качестве аргументов. Это заставит рабочие узлы подключаться к главному узлу в процессе его запуска.

2.5. Изображение JupyterLab

Для образа JupyterLab мы вернемся немного назад и снова начнем с базового образа кластера. Мы установим и настроим IDE вместе с дистрибутивом Apache Spark, который немного отличается от того, который установлен на узлах Spark.

Мы начинаем с установки pip, диспетчера пакетов Python и инструментов разработки Python, которые позволяют устанавливать пакеты Python во время создания образа и во время выполнения контейнера. Затем возьмем JupyterLab и PySpark из индекса пакетов Python (PyPI). Наконец, мы открываем порт по умолчанию, чтобы разрешить доступ к веб-интерфейсу JupyterLab, и устанавливаем команду запуска контейнера для запуска приложения IDE.

3. Создание образов

Образы Docker готовы, давайте их создадим. Обратите внимание: поскольку мы использовали ключевое слово Docker arg в файлах Docker для указания версий программного обеспечения, мы можем легко изменить версии Apache Spark и JupyterLab по умолчанию для кластера.

4. Составление кластера

Файл компоновки Docker содержит рецепт для нашего кластера. Здесь мы создадим контейнеры узлов JuyterLab и Spark, предоставим их порты для локальной сети и подключим их к смоделированной HDFS.

Начнем с создания тома Docker для смоделированной HDFS. Затем мы создаем по одному контейнеру для каждого компонента кластера. Контейнер jupyterlab предоставляет порт IDE и связывает свой общий каталог рабочей области с томом HDFS. Точно так же контейнер spark-master предоставляет свой порт веб-интерфейса и порт подключения master-worker, а также привязывается к тому HDFS.

Мы завершаем создание двух рабочих контейнеров Spark с именами spark-worker-1 и spark-worker-2. Каждый контейнер предоставляет свой порт веб-интерфейса (сопоставлен с 8081 и 8082 соответственно) и привязывается к тому HDFS. У этих контейнеров есть шаг среды, который определяет их аппаратное распределение:

  • SPARK_WORKER_CORE - количество ядер;
  • SPARK_WORKER_MEMORY - объем оперативной памяти.

По умолчанию мы выбираем одно ядро ​​и 512 МБ ОЗУ для каждого контейнера. Не стесняйтесь играть с распределением оборудования, но обязательно соблюдайте ограничения вашего компьютера, чтобы избежать проблем с памятью. Кроме того, предоставьте приложению Docker достаточно ресурсов для обработки выбранных значений.

Чтобы собрать кластер, запустите файл компоновки Docker:

После завершения проверьте веб-интерфейс компонентов:

5. Создание приложения PySpark

Когда наш кластер запущен и работает, давайте создадим наше первое приложение PySpark.

Откройте IDE JupyterLab и создайте записную книжку Python Jupyter. Создайте приложение PySpark, подключившись к главному узлу Spark с помощью объекта сеанса Spark со следующими параметрами:

  • appName - это имя нашего приложения;
  • master - это главный URL-адрес подключения Spark, тот же самый, который используется рабочими узлами Spark для подключения к главному узлу Spark;
  • config - это общая конфигурация Spark для автономного режима. Здесь мы сопоставляем память исполнителя, то есть рабочий процесс JVM Spark, с выделенной памятью рабочего узла.

Запустите ячейку, и вы сможете увидеть приложение, указанное в разделе Запущенные приложения в главном веб-интерфейсе Spark. Затем мы загружаем набор данных радужки из репозитория UCI в смоделированную HDFS. Наконец, мы читаем и распечатываем данные с помощью PySpark.

Это все, ребята. Надеюсь, я помог вам узнать немного больше о внутреннем устройстве Apache Spark и о том, как работают распределенные приложения. Удачного обучения!