Рубрики
Без рубрики

Создание кластера Raspberry Pi Hadoop / Spark

Совет профессионала: если вы только ищете, как настроить Hadoop и Spark для запуска в кластере, запустите ее… Помеченный raspberry pi, showdev, hadoop, java.

Профессиональный совет: если вы только ищете, как настроить Hadoop и Spark для запуска в кластере, начните здесь .

содержание

  1. Мотивация и предпосылки
    • Что такое Apache Hadoop?
    • Сокращение карты и распараллеливание
    • Что такое Apache Spark?
  2. Оборудование
    • О Raspberry Pi
    • Выбор модели Pi
    • Питание через Ethernet (PoE) и сеть
    • Дисковое пространство
    • Стоимость и общие характеристики
    • Установка PoE-шляп
  3. Программное обеспечение
    • Операционная система
    • Сетевой
    • Обеспечение безопасности кластера
  4. Hadoop и Spark
    • Настройка с одним узлом
    • Настройка кластера
  5. Вывод

Мотивация и предпосылки

“Большие данные” уже почти десять лет являются модным словечком в отрасли, хотя разногласия по поводу того, что означает этот термин и что охватывает область аналитики больших данных, были предметом разногласий. Использование инструментов больших данных, таких как Apache Software Foundation Hadoop и Искра (H&S) программное обеспечение было встречено с презрением и хвалить одинаково. Правда в том, что, как и любые другие инструменты, H & S полезны только в том случае, если вы знаете, когда и как их правильно использовать.

Многие компании используют H&S для хранения и анализа данных. Разработчики с такими навыками востребованы, но до недавнего времени было трудно получить необходимый опыт работы с кластерными вычислениями без больших затрат времени и/или денег. Широкая доступность небольших дешевых одноплатных компьютеров, таких как совершенно новый Raspberry Pi 4 (начальная цена 35 долларов США), практически устранила эти препятствия для разработки вашего собственного кластера.

В этом руководстве Я научу вас, как создать сетевой кластер Raspberry Pi . Мы заставим их взаимодействовать друг с другом через сетевой коммутатор, установим HDFS и заставим Spark выполнять задания распределенной обработки через YARN по всему кластеру. Это руководство представляет собой полнофункциональное введение в аппаратное и программное обеспечение, необходимое для настройки кластера H & S, и может масштабироваться (как и H & S!) до любого количества или размера машин.

Что такое Apache Hadoop?

Распределенная файловая система Apache Hadoop (HDFS) – это распределенная (сетевая) файловая система, которая может быть запущена на готовом оборудовании потребительского класса. Запуск на сетевом оборудовании означает, что HDFS является одновременно масштабируемой и экономически эффективной. HDFS разбивает файлы на “блоки” (обычно размером 64 МБ) и хранит несколько копий этих блоков в разных “узлах данных” на одной стойке, разных стойках в одном и том же центре хранения данных или в нескольких центрах хранения данных.

Разделение и хранение данных таким образом имеет ряд преимуществ:

  1. Отказоустойчивость. Резервные копии создаются из каждого блока и хранятся в нескольких физических местах. Это означает, что в случае сбоя диска (как и следовало ожидать при больших объемах аппаратного обеспечения) все блоки на этом узле могут быть получены из других мест. HDFS также может создавать дополнительные копии потерянных блоков, чтобы всегда сохранялось желаемое количество избыточных блоков.

    В более старых версиях Hadoop один NameNode был потенциальной уязвимостью для всей системы. Поскольку NameNode содержит всю информацию о файловой системе и внесенных в нее изменениях, сбой NameNode ставит под угрозу весь кластер. В более новых версиях кластер может иметь несколько NameNodes , устраняя эту единственную точку отказа.

  2. Распараллеливание. Данные, разделенные на блоки, готовы для параллельной обработки с помощью конвейера анализа map-reduce . Файл, разделенный на 100 блоков на 100 машинах с аналогичным питанием, может быть обработан примерно за 1/100 времени, которое потребовалось бы для обработки одного и того же файла на одной машине.

  3. Местоположение данных. Обработка блоков на месте также устраняет необходимость передачи больших файлов данных по сети. Это может значительно снизить требования к пропускной способности сети. Время и вычислительные мощности, которые в противном случае были бы потрачены на копирование файлов из хранилища, вместо этого могут быть использованы для локальной обработки данных: “перемещение вычислений дешевле, чем перемещение данных” .

  4. Большие наборы данных. Поскольку HDFS разбивает файлы на блоки, размер любого отдельного файла ограничен только общим объемом хранилища, доступного по сети. HDFS основана на POSIX, но ослабляет некоторые требования POSIX, чтобы обеспечить быструю потоковую передачу данных , среди прочих преимуществ. HDFS может поддерживать сотни сетевых узлов и десятки миллионов файлов.

HDFS ускоряет обработку данных за счет распределения задержки ввода-вывода (чтения/записи) между всеми дисками в сети. Вместо того, чтобы считывать файл из одного места на одном диске, он считывается одновременно из нескольких точек несколькими машинами. Те же самые машины могут затем работать с одним и тем же файлом параллельно, увеличивая скорость обработки на порядки.

Один момент, который следует отметить для HDFS, заключается в том, что для обеспечения согласованности данных файлы, записанные в HDFS, являются неизменяемыми . Это означает, что для редактирования файла его необходимо загрузить из HDFS в локальную файловую систему, изменить и загрузить обратно в HDFS. Этот рабочий процесс немного отличается от того, к чему привыкло большинство пользователей, но он необходим для доступа к данным с высокой пропускной способностью, предоставляемого HDFS. HDFS не предназначена для замены вашей обычной интерактивной файловой системы. Его следует использовать в качестве хранилища для ваших больших данных, которые не будут регулярно меняться, но которые необходимо обрабатывать быстро и легко. Это файловая система “запись один раз, чтение много раз”.

Вы можете прочитать гораздо больше о мельчайших архитектурных деталях HDFS здесь , если вам интересно.

Сокращение карты и распараллеливание

Распределенный характер данных, хранящихся в HDFS, делает их идеальными для обработки с помощью map-reduce analysis framework. Mapreduce (также “MapReduce”, “Map-Reduce” и т.д.) – это метод программирования, при котором, насколько это возможно, параллельно выполняются распараллеливаемые задачи, за которыми следуют любые непараллеливаемые “узкие места”. Mapreduce – это общая основа для анализа, а не конкретный алгоритм. (Однако в кругах больших данных это иногда синонимично Apache Hadoop MapReduce , который подробно обсуждается ниже.)

Некоторые задачи анализа данных распараллеливаются . Например, если бы мы хотели найти наиболее распространенные буквы среди всех слов в определенной базе данных, мы могли бы сначала подсчитать количество букв в каждом слове. Поскольку частота букв в одном слове не влияет на частоту букв в другом, два слова можно считать отдельно. Если у вас есть 300 слов примерно одинаковой длины и 3 компьютера для их подсчета, вы можете разделить базу данных, предоставив по 100 слов каждой машине. Этот подход примерно в 3 раза быстрее, чем если бы один компьютер подсчитывал все 300 слов. Обратите внимание, что задачи также могут быть распараллелены между ядрами процессора.

Примечание: существуют некоторые накладные расходы, связанные с разделением данных на блоки для параллельного анализа. Таким образом, если эти фрагменты не могут быть обработаны параллельно (если доступно только одно ядро процессора на одной машине), распараллеленная версия алгоритма обычно будет выполняться медленнее , чем ее непараллельный аналог.

Как только каждая машина в приведенном выше примере проанализирует все свои 100 слов, нам нужно обобщить результаты. Это непараллеливаемая задача. Один компьютер должен суммировать все результаты со всех других компьютеров, чтобы результаты можно было проанализировать. Непараллеливаемые задачи являются узкими местами , поскольку дальнейший анализ даже не может быть начат до тех пор, пока они не будут завершены.

Общие распараллеливаемые задачи включают:

  • фильтрация (например: удаление неверных или неполных данных)
  • преобразование (например: форматирование строковых данных, интерпретация строк как числовых)
  • потоковые вычисления (например: сумма, среднее значение, стандартное отклонение и т.д.)
  • привязка (например, частота, гистограммирование)

Общие непараллеливаемые задачи включают:

  • агрегирование (например: сбор частичных результатов в единый глобальный результат)
  • синтаксический анализ текста (например: регулярные выражения, синтаксический анализ)
  • визуализация (например, создание сводных графиков)
  • математическое моделирование (например, линейные регрессии, машинное обучение)

Сортировка данных – это пример алгоритма, который плохо вписывается ни в одну из вышеперечисленных категорий. Хотя весь набор данных обязательно должен быть собран в одном месте для полной глобальной сортировки, сортировка небольших наборов данных, которые сами по себе уже локально отсортированы, намного быстрее и проще, чем сортировка эквивалентного объема несортированных данных. Сортировка данных таким образом, по сути, является одновременно map и уменьшить задачу.

Распараллеливание подходит не для всех задач. Некоторые алгоритмы по своей сути являются последовательными (ака. P-завершить ). К ним относятся задачи с n телами , задача о значении схемы , Метод Ньютона для численной аппроксимации корней полиномиальной функции и хэш-цепочка , которая широко используется в криптографии.

Что такое Apache Spark?

Когда HDFS была впервые выпущена в 2006 году, она была объединена с платформой анализа map-reduce, которая называлась – достаточно креативно – Hadoop MapReduce (обычно просто “MapReduce”). И HDFS, и MapReduce были вдохновлены исследованиями Google и являются аналогами Apache для Google “Файловая система Google” и “MapReduce” , на последний из которых Google получил патент (который подвергся критике).

Hadoop MapReduce – это оригинальная аналитическая платформа для работы с данными, хранящимися в HDFS. MapReduce выполняет конвейеры анализа mapreduce (описанные выше), считывая данные из HDFS перед задачами “map” и записывая результат обратно в HDFS после задачи “reduce”. Такое поведение, в частности, является одной из причин, по которой Apache Spark , широко рассматриваемый как преемник MapReduce, предлагает ускорение в 10-100 раз по сравнению с MapReduce.

Hadoop MapReduce работает с HDFS для обработки “обработки огромных объемов данных (многотерабайтных наборов данных) параллельно на больших кластерах (тысячи узлов) товарного оборудования надежным, отказоустойчивым способом”. [ источник ]

Hadoop против Искровая производительность при логистической регрессии

Spark предлагает по крайней мере четыре основных преимущества по сравнению с MapReduce:

  1. Spark сводит к минимуму ненужный диск Ввод-вывод Spark предлагает несколько улучшений по сравнению с MapReduce, чтобы как можно меньше считывать и записывать на диск. * В то время как MapReduce записывает каждый промежуточный результат на диск , Spark пытается максимально упорядочить результаты, записывая на диск только по требованию пользователя или в конце конвейера анализа. Spark также будет кэшировать данные, которые используются для нескольких операций в памяти, поэтому их не нужно считывать с диска несколько раз. По этим причинам иногда говорят, что Spark имеет “обработку в памяти”. (Однако это немного вводящий в заблуждение термин, поскольку и MapReduce, и Spark обязательно обрабатывают данные в оперативной памяти.)

    * В общем, чтение и запись в кэш процессора на порядок быстрее, чем оперативная память, а оперативная память на несколько порядков быстрее, чем SSD (который все еще быстрее , чем обычный жесткий диск).

  2. Spark предоставляет абстракции для отказоустойчивой обработки. Основной структурой данных, предоставляемой Spark, является Устойчивый распределенный набор данных ( RDD ) :

    • ResilientSpark сохраняет происхождение того, как данный RDD создается из любых “родительских” RDD. Если какой-либо RDD поврежден или утерян, его можно легко воссоздать из его графика происхождения (он же. его логический план выполнения ).
    • Распределенный — RDD может физически существовать в разных частях на нескольких машинах. Spark полностью абстрагируется от распределенного характера файлов, хранящихся в HDFS. Тот же код, который считывает и обрабатывает один файл, хранящийся на одном компьютере, может быть использован для обработки распределенного файла, разбитого на фрагменты и хранящегося во многих разных физических местах.
    • Наборы данныхRDDS могут хранить простые объекты, такие как Строка s и Float s, или более сложные объекты, такие как кортежи, записи, пользовательские Object s и так далее. Эти наборы данных по своей сути являются распараллеливаемыми.

    RDDS – это неизменяемые наборы данных, поэтому они потокобезопасны : они могут обрабатываться параллельно, и программисту не нужно беспокоиться о условиях гонки или других подводных камнях многопоточности. (Логика для того, чтобы сделать файлы, хранящиеся в HDFS, неизменяемыми, аналогична.)

    RDDS лениво оцениваются . Последовательность вычислений, которые необходимо выполнить для построения RDD, не выполняется до тех пор, пока RDD не будет использован – распечатан на терминале, нанесен на график, записан в файл и т.д. Это уменьшает объем ненужной обработки, выполняемой Spark.

  3. У Spark другая модель обработки. Spark использует Ориентированный ациклический граф ( DAG )

    модель обработки, а не простой двухэтапный конвейер с уменьшением карты:

    Диаграмма направленного ациклического графа (DAG) Это означает, что Spark использует целостный взгляд на весь процесс обработки и пытается оптимизировать процесс в глобальном масштабе. В то время как MapReduce будет (1) считывать данные с диска, (2) выполнять операцию “сопоставление”, (3) выполнять операцию “сокращение”, (4) записывать данные на диск, Spark более гибко определяет, что и когда завершается. До тех пор, пока будет достигнут дальнейший прогресс в направлении конечного результата, карты и уменьшает может выполняться параллельно или в разное время для разных фрагментов данных. DAG – это более общая версия конвейера Mapreduce mapreduce – его также можно рассматривать как реализацию в коде идеализированного lineage graph

  4. RDD. Spark устраняет время загрузки JVM. Загружая виртуальную машину Java (JVM) на каждом узле данных при запуске (в отличие от выполнения нового задания), Spark сокращает время, необходимое для загрузки *.jar

Кроме того, Spark имеет встроенную поддержку сложной аналитики, такой как машинное обучение ( MLlib ) и обработка графиков ( GraphX ), и может использоваться в интерактивном режиме в Python, R, Scala, Java и SQL ракушки

Вышеперечисленные функции делают Spark намного быстрее, более отказоустойчивым и более многофункциональным, чем MapReduce. При всех преимуществах Spark по сравнению с MapReduce, по сути единственный раз , когда вы должны предпочесть использовать последний, – это когда у вас есть устаревший код MapReduce для поддержки. Или если вас не волнует время обработки. Или если вы не хотите тратить время на изучение Spark.

Существуют и другие конвейеры распределенного хранения данных/распределенного анализа, но Apache Hadoop и Spark бесплатны, быстры, отказоустойчивы и относительно просты в установке и понимании. Обладая этим основополагающим пониманием H & S, теперь мы можем перейти к созданию нашего собственного кластера Raspberry Pi H &S.

[ вернуться к началу ]

Оборудование

О Raspberry Pi

Фонд Raspberry Pi Foundation разрабатывает и выпускает одноплатные компьютеры с начала 2012 года. Первоначально задуманный как способ вдохновить детей на изучение электроники и программирования , как компьютеры “сделай сам” 1970-х и 80-х годов, популярность Raspberry Pi намного превзошла ожидания создателей Фонда , продажи 12,5 миллионов единиц, чтобы стать третьим по популярности персональным компьютером за всю историю , обогнав Commodore 64, но все еще уступая Apple Macintosh и ПК с Windows. Да, Raspberry Pi использовались для внедрения нового поколения вычислений, но они также используются для домашней автоматизации, производства, робототехники, цифровых камер, и многого другого .

Сравнительная таблица Raspberry Pi (нажмите, чтобы открыть PDF-файл)

Сегодня доступно множество различных моделей Raspberry Pi, и они делятся на четыре семейства: Model A, Model B, Zero и Compute. Семейство Model B – это флагманские полнофункциональные Raspberry Pi. Все модели Bs имеют подключение по Ethernet, которого нет ни в одном другом семействе Pi. Каждая модель B имеет MSRP (рекомендованная производителем розничная цена) в размере 35 долларов США. Все модели Bs имеют одинаковый форм-фактор: 85,6 мм x 56,5 мм x 17,0 мм, вес всего 17 г.

Писи модели B буквально размером с кредитную карту! И примерно такой же “толстый”, как ширина клавиши клавиатуры. Они примерно такого же размера и веса, как колода карт.

Схема Raspberry Pi 3 B+

Существуют также различные версии Raspberry Pi. Версия 1 включала модель B, а также модель B +, в которую были включены два дополнительных порта USB, переключение с SD на microSD и изменение заголовка GPIO (Универсальный ввод/вывод) на плате, что позволило добавить Pi. (Оборудование прикреплено сверху). Шляпы подключаются к выводам GPIO и добавляют дополнительные функции к Pi: позволяют подключать PoE (питание через Ethernet), вентиляторы охлаждения, ЖК-экраны и многое другое.

Версия 1 также включала модели A и A+. Серия A физически меньше, дешевле (20-25 долларов США) и имеет уменьшенные характеристики (только 1 USB-порт, нет Ethernet, меньше оперативной памяти). Pi модели Zero еще более урезаны и еще дешевле (5-10 долларов). Подробную информацию обо всех этих моделях Pi можно увидеть в таблице выше или найти в различных | сравнительных | таблицах онлайн.

Выбор модели Pi

Мы хотим подключить ваш Pis к сети для создания кластера Hadoop, поэтому мы ограничены моделями, оснащенными оборудованием Wi-Fi и/или Ethernet. Из доступных в настоящее время контактов это ограничивает нас Pi 3 Model B, Pi 3 Model B+, Pi 3 Model A+ или Pi Zero Wireless. Все эти Pi имеют подключение к Wi-Fi, но только модели B и B + имеют Ethernet.

Обратите внимание, что Pi версии 4 были выпущены всего несколько недель назад, но они распродаются так быстро, как только магазины могут их приобрести. Если вы можете, я рекомендую использовать Pis версии 4 вместо Pis версии 3. У них более быстрые процессоры и возможность добавить больше оперативной памяти (до 4 ГБ).

Модели Raspberry Pi

Если мы подключим Pis к сети с помощью Wi-Fi, нам понадобится беспроводной маршрутизатор. Нам также нужно будет купить блоки питания для каждого Pi. Я собираюсь построить кластер из восьми Пи. Восемь источников питания будут громоздкими. Мне придется носить с собой все это, плюс несколько розеток, если я захочу кому-нибудь показать свой кластер. Чтобы устранить этот объем, мы можем вместо этого питать их через PoE. Это заботится как о сети, так и о источнике питания для каждого Pi, но это дороже. Этот выбор ограничивает меня только моделью B или моделью B +.

Наконец, чтобы устранить любую возможную задержку в сети с помощью Pis (и поскольку все модели B/B + имеют одинаковую цену) Я собираюсь выбрать Pi 3 Model B +, который имеет самую большую поддержку Ethernet с пропускной способностью (~ 300 Мбит/с). Для моего кластера 8-Pi общая стоимость публикации составляет около 280 долларов США .

Питание через Ethernet (PoE) и сеть

Raspberry Pis Model B+ может питаться от традиционного источника постоянного тока (micro-USB). Они стоят около 8 долларов каждый (итого 64 доллара за мой кластер из 8 Pi) и потребует, чтобы каждый Pi имел доступ к своей собственной электрической розетке. Вы можете купить мультирозетку (“power strip”) онлайн примерно за 9 долларов .

В качестве альтернативы, вывод B + также может питаться через Ethernet с помощью технологии, известной в творческом плане как Power over Ethernet или PoE. Для PoE требуется сетевой коммутатор, поддерживающий PoE; они, как правило, дороже, чем те, которые не поддерживают PoE. 8-портовые сетевые коммутаторы без PoE можно купить всего за 10 долларов на Amazon , а гигабитные (1000 Мбит/с) коммутаторы доступны всего за 15 долларов. 8-портовый сетевой коммутатор с поддержкой PoE на всех портах стоит около 75 долларов США . Для подключения к сети через Ethernet требуется 8 коротких кабелей Ethernet ( около 14 долларов США за 10 упаковок ). Если вы выберете маршрут без PoE, вы также можете подключить свои фотографии к сети с помощью хорошего дешевого беспроводного маршрутизатора ( около 23 долларов США на Amazon).

Таким образом, как минимум, мы рассматриваем $64 + $9 + $10 + $14 = $97 в расходах на сеть и энергоснабжение для проводного кластера (Ethernet) с источниками питания постоянного тока, или $64 + $9 + $23 = 96 долларов США затраты на сеть и поставку для кластера Wi-Fi с источниками питания постоянного тока.

Кластер Raspberry Pi, использующий питание через Ethernet

Кластер, который я создаю, будет использоваться для демонстраций, поэтому он должен быть переносимым. Восемь источников питания плюс несколько розеток – это не идеально, поэтому я выбрал вариант PoE. Это устраняет весь этот дополнительный объем, но за это приходится платить. Для кластера Poet Pi требуется 8 PoE ( около 21 доллара США каждый ), плюс кабели Ethernet (10 за 14 долларов США), плюс 8-портовый сетевой коммутатор с поддержкой PoE (около 75 долларов США). Это означает, что кластер Poet Pi будет стоить не менее 257 долларов США затрат на сеть и электропитание, или более чем в 2,5 раза больше, чем беспроводной кластер.

C4Labs Корпус кластера Cloudlet, содержащий кластер Raspberry Pi

У меня тоже есть еще одно небольшое осложнение. Я купил специальный чехол для переноски у C4 Labs для своего кластера Pi (55 долларов США), поэтому единственным сетевым коммутатором, который я мог заказать у Amazon UK (из-за ограничений по пространству), является TRENDnet V1.1R , стоимостью около 92 долларов. Таким образом, моя общая стоимость подключения к сети и источника питания (плюс этот случай) составляет 329 долларов США .

Обратите внимание, что ни одна из приведенных выше цен не включает доставку. Кроме того, корпус C4Labs поставляется с охлаждающими вентиляторами, которые предназначены для получения питания от контактов GPIO 5V на фотографиях. Поскольку они будут заняты ШЛЯПОЙ Папы римского, я купил несколько USB-разъемов и паяльник таким образом, я могу припаять провода вентилятора охлаждения к разъемам USB. Затем вентиляторы могут получать питание от Pis через USB. Эти две покупки добавили еще около 32 долларов к стоимости кластера.

Дисковое пространство

Raspberry Pi не имеют встроенного места для хранения. Однако они поставляются со слотами microSD, поэтому карты microSD можно использовать для хранения операционной системы и данных для Pi. Карты microSD с высоким рейтингом, как правило, стоят около 17,50 долларов США для моделей емкостью 128 ГБ , хотя большинство из них ограничивают скорость чтения примерно до 80 МБ/s. На момент написания этой статьи самые дешевые SD-карты емкостью 128 ГБ со скоростью чтения до 100 Мбит/с стоили около 21 доллара США каждая или 168 долларов США за весь кластер.

Стоимость и общие характеристики

Таким образом, общая стоимость моего кластера 8-Pi составляет примерно

  • 280 долларов за все восемь Raspberry Pi Model B+
  • 274 доллара за весь блок питания и сетевое оборудование
  • 168 долларов за все карты microSD
  • 55 долларов за хороший чехол для переноски
  • 32 доллара за USB-разъемы и паяльник

… или в общей сложности около 810 долларов. Доставка всего этого в Ирландию обошлась еще примерно в 125 долларов, в результате чего Доставка всего этого в Ирландию обошлась еще примерно в 125 долларов, в результате чего

Выбранные спецификации этого кластера из 8 машин следующие:

  • Процессор: 8 64-разрядных четырехъядерных процессоров ARM Cortex-A53 с частотой 1,4 ГГц
  • Процессор: 8 64-разрядных четырехъядерных процессоров ARM Cortex-A53 с частотой 1,4 ГГц
  • Процессор: 8 64-разрядных четырехъядерных процессоров ARM Cortex-A53 с частотой 1,4 ГГц
  • Хранилище: 8 x 128 ГБ памяти microSD (максимальная скорость чтения 80 МБ/с)
  • Порты: 8 x портов HDMI, 8 x 4 x портов USB 2.0

Не так уж плохо менее чем за 1000 долларов!

Установка PoE-шляп

По большей части Raspberry Pi – это подключи и играй. Но поскольку мы устанавливаем ШЛЯПУ, нам нужно немного поработать с оборудованием. Веб-сайт Raspberry Pi дает инструкции здесь о том, как установить PoE-шляпы поверх Raspberry Pi – это довольно просто:

  1. Найдите 40-контактный разъем GPIO и соседний 4-контактный разъем питания в верхней части Raspberry Pi, а также соответствующие 40-контактный и 4-контактный разъемы на нижней стороне PoE HAT, но пока ничего не соединяйте .

    Когда Поэт перевернут правой стороной вверх, штифты на Пи должны совпадать с прорезями на ШЛЯПЕ:

  2. Найдите распорки и винты, которые прилагались к ШЛЯПЕ поэта. Должно быть не менее 4 прокладок и не менее 8 винтов.

  3. Прикрутите распорки к ШЛЯПКЕ сверху.

  4. На этом этапе, если вы собираете только один Pi, вы прикрепите Pi к ШЛЯПЕ, совместив распорки с отверстиями на Pi и вкрутив распорки с нижней стороны Pi, при этом обязательно аккуратно вставьте контакты Pi GPIO и PoE в GPIO и PoE прорези на ШЛЯПЕ.

    Однако для моего кластера я собираю все Pi в C4 Labs Корпус Cloudlet/Cluster, поэтому Pis необходимо прикрепить к креплениям из оргстекла. Я снимаю защитную бумагу с оргстекла и добавляю металлические прокладки и винты, как показано на следующей фотографии:

    Обязательно используйте более длинные винты, потому что они должны проходить через оргстекло, мимо металлических прокладок, через печатную плату Pi и в прокладки PoE HAT:

    Как только все будет скручено вместе, Pi должен быть надежно прикреплен к креплению из оргстекла:

…вот и все! PoE БЫЛ успешно установлен.

Будьте очень осторожны |

[ вернуться к началу ]

Программное обеспечение

Операционная система

Существуют десятки операционных систем , доступных для Raspberry Pi . Некоторые из наиболее заметных из них включают:

  • Raspbian — ОС на базе Debian, разработанная и поддерживаемая Фондом Raspberry Pi (рекомендуемая Фондом ОС для системы)

  • Windows IoT Core — операционная система Windows для Интернета вещей (IoT) для небольших устройств; выглядит и работает аналогично Windows 10

  • Ядро Ubuntu — Урезанная версия одного из самых популярных дистрибутивов Linux, Ubuntu

  • AndroidСамая популярная операционная система в мире; установлена на более чем 2 миллиардах устройств, в основном на мобильных телефонах

  • RaspBSD — Ответвление дистрибутива программного обеспечения Berkeley (BSD) UNIX для Raspberry Pi; macOS также основана на BSD

  • Хромированная ОС — Операционная система Google на базе браузера

  • RetroPie – ОС для превращения вашего Raspberry Pi в ретро-игровой автомат (игры, защищенные авторским правом, запрещены!)

  • ОС RISC Pi — оптимизированная для Pi версия RISC OS , операционной системы, разработанной специально для чипов с уменьшенным набором команд (RISC), подобных серии AMD, используемой в Raspberry Pi

Как бы ни было интересно установить RetroPie, я думаю, что буду придерживаться Raspbian, поскольку это ОС, рекомендованная Фондом Raspberry Pi, и была специально оптимизирована для высокопроизводительного оборудования Raspberry Pi.

Raspbian НОВИЧКИ Установщик (Новое готовое программное обеспечение) – это самый простой способ установить Raspbian на Raspberry Pi. Просто скачайте его и следуйте инструкциям , указанным на веб-сайте Raspberry Pi. Вам нужно будет отформатировать карту microSD как FAT ( не exFAT !) , извлеките нубов *.zip заархивируйте и скопируйте содержащиеся в нем файлы на вашу недавно отформатированную карту microSD. Затем вставьте карту microSD в Pi; на нижней стороне Pi есть слот, на стороне, противоположной портам USB:

Включите Pi, подключив к нему кабель Ethernet, а другой конец кабеля подключите к сетевому коммутатору с поддержкой PoE. Подключите сетевой коммутатор и включите его. Через секунду или две Pi должен включиться: должен загореться желтый индикатор рядом с портом Ethernet и красный индикатор рядом с картой microSD.

Затем подключите Pi к монитору, используя порт HDMI на стороне, противоположной заголовку GPIO.

Подключите мышь и клавиатуру к Pi через USB и следуйте инструкциям на экране в мастере установки ОС (он должен выглядеть так, как показано на скриншоте ниже).

Установщик NOOBS на Raspberry Pi

После того, как вы успешно установили выбранную вами ОС на один Pi, вы можете просто клонировать карту microSD , чтобы установить ту же ОС на другой Pi. Нет необходимости проходить через мастер установки несколько раз. Позже в этом руководстве я объясню, как легко выполнить определенную команду (включая установку программного обеспечения с помощью apt ) одновременно во всех Pis в кластере, чтобы вам не нужно было повторять одни и те же ручные задачи снова и снова, как обезьяна за пишущей машинкой – вот почему мы есть технология, не так ли?

Сетевой

Настройка статических IP-адресов

Чтобы упростить подключение Pics к сети, я собираюсь установить статические IP-адреса для каждого Pi на сетевом коммутаторе. Я пронумерую Pin-код 1-8 (включительно) в соответствии с их расположением на сетевом коммутаторе и в чехле для переноски. При взгляде на порты на фотографиях (“передняя” часть корпуса) # 1 – это крайний правый Pi, а # 8 – крайний левый Pi.

Чтобы включить определяемые пользователем статические IP-адреса, я редактирую файл /etc/dhcpcd.conf на каждом Pi и раскомментируйте/отредактируйте строки:

interface eth0
static ip_address=192.168.0.10X/24

…где X следует заменить на 1 для числа Пи #1, 2 для Pi # 2 и т.д. После того, как это изменение было внесено в конкретный Pi, я перезагружаю компьютер. Как только это будет сделано для всех восьми контактов, все они должны иметь возможность пинговать друг друга по этим адресам.

Я также установил nmap на Pi # 1, чтобы можно было легко проверить статус всех восьми Pi:

$ sudo nmap –sP 192.168.0.0/24

……покажет статус всех семи других Pis, не включая тот, на котором выполняется команда. ” N hosts up ” показывает, сколько Pis правильно настроено в соответствии с вышеизложенным, подключено в данный момент и включено.

Включение ssh

Чтобы включить ssh на каждом Pi нам нужно следовать этим инструкциям (воспроизведено здесь, чтобы избежать гниения ссылок):

Начиная с выпуска в ноябре 2016 года, Raspbian по умолчанию отключил SSH-сервер. Его можно включить вручную с рабочего стола:

  1. Запустите Конфигурацию Raspberry Pi из Настройки меню
  2. Перейдите к Интерфейсы вкладка
  3. Выберите Включено рядом с тсс
  4. Нажмите OK

В качестве альтернативы в терминале можно использовать raspi-config :

  1. Введите sudo raspi-config в окне терминала
  2. Выберите Параметры сопряжения
  3. Перейдите к SSH и выберите//SSH
  4. Выберите Да
  5. Выберите Хорошо
  6. Выбрать Завершить

В качестве альтернативы используйте systemctl для запуска службы

 $ sudo systemctl enable ssh
 $ sudo systemctl start ssh

При включении SSH на Pi, который может быть подключен к Интернету, вы должны изменить его пароль по умолчанию, чтобы убедиться, что он остается безопасным. Более подробную информацию смотрите на странице Безопасность .

Имена хостов

Изначально все Pi известны как raspberry pi и имеют одного пользователя, пи :

$ hostname
raspberrypi

$ whoami
pi

Это может привести к большой путанице, если мы постоянно перемещаемся туда и обратно между различными контактами в сети. Чтобы упростить это, мы собираемся присвоить каждому Pi имя хоста в зависимости от его положения в корпусе/на сетевом коммутаторе. Pi # 1 будет известен как pi1 , Pi # 2 как pi2 и так далее.

Для этого необходимо отредактировать два файла: /etc/hosts и /etc/имя хоста . В этих файлах должно быть только одно вхождение каждого из raspberry pi , которое является именем хоста по умолчанию. Мы меняем каждый из них на piX где X – соответствующее число 1-8. Наконец, только в /etc/hosts мы также добавляем IP-адреса для всех остальных Pis в конце файла, например:

192.168.0.101 pi1
192.168.0.102 pi2
...
192.168.0.108 pi8

Это должно быть сделано вручную для каждого Pi.

Как только вышеуказанные задачи будут выполнены для соответствующего Pi, мы перезагрузим этот конкретный Pi. Теперь, когда терминал открыт, вместо:

pi@raspberrypi:~ $

… вы должны увидеть

pi@piX:~ $

…где X – индекс этого Pi в кластере. Мы делаем это на каждом Pi и перезагружаем каждый из них после того, как это будет сделано. Отныне в этих инструкциях командная строка будет сокращаться просто до $ . Выводится любой другой код или текст файла.

Упрощение ssh

Для подключения от одного Pi к другому, следуя только приведенным выше инструкциям, потребуется следующая серия команд:

$ ssh pi@192.168.0.10X
pi@192.168.0.10X's password: 

Конечно, это не слишком много для набора текста, но если нам придется делать это очень часто, это может стать громоздким. Чтобы избежать этого, мы можем настроить ssh псевдонимы и пароль без пароля ssh соединения с парами открытых/закрытых ключей.

псевдонимы ssh

Чтобы настроить псевдоним ssh , мы редактируем файл ~/.ssh/config на конкретном Pi и добавляем следующие строки:

Host piX
User pi
Hostname 192.168.0.10X

…замена X на 1-8 для каждого из восьми Pi. Обратите внимание, что это делается на одном Pi, так что одна часть должна содержать восемь фрагментов кода внутри ~/.ssh/config , которые выглядят идентично приведенным выше, за исключением символа X , который должен меняться для каждого Pi в сети. Затем последовательность команд ssh становится просто:

$ ssh piX
pi@192.168.0.10X's password: 

Это можно еще больше упростить, настроив пары открытых/закрытых ключей.

пары открытых/закрытых ключей

На каждом Pi выполните следующую команду:

$ ssh-keygen –t ed25519

Это сгенерирует пару открытых/закрытых ключей в каталоге ~/.ssh/ , которую можно использовать для безопасного ssh без ввода пароля. Один из этих файлов будет называться id_ed25519 , это закрытый ключ . Другой, id_ed25519.pub , является открытым ключом . Для защиты доступа к паре ключей парольная фраза не требуется. Открытый ключ используется для связи с другими Pi, а закрытый ключ никогда не покидает свой хост-компьютер и никогда не должен быть перемещен или скопирован на какое-либо другое устройство.

Каждый открытый ключ необходимо будет объединить с файлом ~/.ssh/authorized_keys на каждом другом Pi. Проще всего сделать это один раз, для одного Pi, а затем просто скопировать authorized_keys файл для других Pis. Давайте предположим, что Pi # 1 будет содержать “главную” запись, которая затем копируется в другие Pi.

На Pi #2 (и #3, #4 и т.д.) Выполните следующую команду:

$ cat ~/.ssh/id_ed25519.pub | ssh pi@192.168.0.101 'cat >> .ssh/authorized_keys'

Это объединяет файл открытого ключа Pi # 2 со списком авторизованных ключей Pi # 1, предоставляя Pi # 2 разрешение на ssh в Pi # 1 без пароля (вместо этого открытый и закрытый ключи используются для проверки соединения). Нам нужно сделать это для каждой машины, объединив каждый файл открытого ключа со списком авторизованных ключей Pi # 1. Мы также должны сделать это для Pi # 1, чтобы, когда мы копируем заполненный файл authorized_keys в другие Pics, все они также имели разрешение на ssh в Pi # 1. Выполните следующую команду на Pi #1:

$ cat .ssh/id_ed25519.pub >> .ssh/authorized_keys

Как только это будет сделано, как и в предыдущем разделе, ssh -инг так же прост, как:

$ ssh pi1

…и это все! Дополнительные псевдонимы могут быть настроены в файле ~/.bashrc , чтобы сократить это еще больше (см. Ниже), хотя это не настроено в нашей системе:

alias p1="ssh pi1" # etc.

реплицируйте конфигурацию

Наконец, чтобы воспроизвести пароль без пароля ssh для всех Pi просто скопируйте два файла, упомянутых выше, из Pi # 1 в каждый другой Pi, используя scp :

$ scp ~/.ssh/authorized_keys piX:~/.ssh/authorized_keys
$ scp ~/.ssh/config piX:~/.ssh/config 

Теперь вы должны иметь возможность ssh входить в любой Pi в кластере с любого другого Pi с помощью всего лишь ssh piX .

Простота использования

Наконец, несколько различных улучшений типа простоты использования для кластера.

получите имя хоста каждого Pi, кроме этого

Чтобы получить имя хоста API, вы можете просто использовать:

$ hostname
pi1

…чтобы получить имя хоста всех других Pis в кластере, определите функцию:

function otherpis {
  grep "pi" /etc/hosts | awk '{print $2}' | grep -v $(hostname)
}

Флаг -v указывает grep на инвертирование выбор. Только строки, которые не совпадают возвращается имя хоста .

…в вашем ~/.bashrc , затем исходный ваш ~/.bashrc файл с:

$ source ~/.bashrc

((Обратите внимание, что всякий раз, когда вы редактируете ~/.bashrc , чтобы эти изменения вступили в силу, вы должны исходный файл или выйти из системы и снова войти в систему.) Затем вы можете вызвать новую функцию в командной строке с помощью:

$ otherpis
pi2
pi3
pi4
...

Обратите внимание, что эта функция зависит от того, что вы перечислили все IP-адреса и имена хостов Pis в файле /etc/hosts .

отправьте одну и ту же команду всем Pis

Чтобы отправить одну и ту же команду каждому Pi, добавьте следующую функцию в ~/.bashrc Pi, с которого вы хотите диктовать команды (я добавляю это в Pi # 1/| ~/.bashrc а затем скопируйте файл ~/.bashrc во все остальные Pis, используя приведенные ниже инструкции):

function clustercmd {
  for pi in $(otherpis); do ssh $pi "$@"; done
  $@
}

Это позволит выполнить заданную команду на каждом другом Pi, а затем на этом Pi:

$ clustercmd date
Tue Apr  9 00:32:41 IST 2019
Tue Apr  9 05:58:07 IST 2019
Tue Apr  9 06:23:51 IST 2019
Tue Apr  9 23:51:00 IST 2019
Tue Apr  9 05:58:57 IST 2019
Tue Apr  9 07:36:13 IST 2019
Mon Apr  8 15:19:32 IST 2019
Wed Apr 10 03:48:11 IST 2019

…выше мы видим, что все наши Pi имеют разное системное время. Давайте это исправим.

синхронизация времени между кластерами

Просто скажите каждому Pi установить пакет htpdate и дата будет обновлена. Вот и все:

$ clustercmd "sudo apt install htpdate -y > /dev/null 2>&1"

$ clustercmd date
Wed Jun 19 16:04:22 IST 2019 
Wed Jun 19 16:04:18 IST 2019 
Wed Jun 19 16:04:19 IST 2019
Wed Jun 19 16:04:20 IST 2019 
Wed Jun 19 16:04:48 IST 2019 
Wed Jun 19 16:04:12 IST 2019 
Wed Jun 19 16:04:49 IST 2019
Wed Jun 19 16:04:25 IST 2019

Обратите внимание, что все даты и время указаны с точностью до минуты. Если мы перезагрузим все Pi, они будут еще более тесно согласованы:

$ clustercmd date
Wed Jun 19 16:09:28 IST 2019 
Wed Jun 19 16:09:27 IST 2019 
Wed Jun 19 16:09:29 IST 2019
Wed Jun 19 16:09:31 IST 2019 
Wed Jun 19 16:09:28 IST 2019 
Wed Jun 19 16:09:30 IST 2019 
Wed Jun 19 16:09:24 IST 2019
Wed Jun 19 16:09:28 IST 2019

Теперь они выровнены с точностью до 10 секунд. Обратите внимание, что выполнение команды по всему кластеру занимает несколько секунд. Чтобы точно синхронизировать все часы с удаленным сервером (уважаемый стандарт, такой как time.nist.gov или google.com ) вы можете сделать:

$ clustercmd sudo htpdate -a -l time.nist.gov

…это займет несколько минут, потому что программа медленно настраивает часы с интервалом < 30 мс таким образом, ни в каких временных метках системных файлов нет “скачков”. Как только эта команда завершится, часы будут синхронизированы (помните, что для связи по сети требуется секунда или две, поэтому они все еще “выключены” на две или три секунды):

$ clustercmd date
Wed Jun 19 16:36:46 IST 2019 
Wed Jun 19 16:36:47 IST 2019 
Wed Jun 19 16:36:47 IST 2019
Wed Jun 19 16:36:48 IST 2019 
Wed Jun 19 16:36:49 IST 2019 
Wed Jun 19 16:36:49 IST 2019 
Wed Jun 19 16:36:49 IST 2019
Wed Jun 19 16:36:49 IST 2019

перезагрузите кластер

Я добавляю следующую функцию в свой ~/.bashrc на Pi # 1:

function clusterreboot {
  clustercmd sudo shutdown -r now
}

Эта функция позволяет легко перезагрузить весь кластер. Другой позволяет мне закрыть весь кластер без перезагрузки:

function clustershutdown {
  clustercmd sudo shutdown now
}

отправьте один и тот же файл всем Pis

Чтобы скопировать файл из одного Pi во все остальные, давайте добавим функцию с именем clusters cp (cluster secure copy) в ~/.bashrc файл любого конкретного Pi:

function clusterscp {
  for pi in $(otherpis); do
    cat $1 | ssh $pi "sudo tee $1" > /dev/null 2>&1
  done
}

Затем мы можем скопировать все простые в использовании функции, которые мы определили в ~/.bashrc , на любой другой Pi в кластере:

$ source ~/.bashrc && clusterscp ~/.bashrc

Обеспечение безопасности кластера

Возможно, вы создаете кластер Hadoop только для развлечения, но я создаю его, чтобы провести некоторый анализ данных для работы. Поскольку в моем кластере будут храниться конфиденциальные данные, безопасность кластера имеет первостепенное значение.

Мы многое можем сделать для защиты компьютера от несанкционированного доступа. Самая простая (и наиболее эффективная) вещь, которую можно сделать (после настройки без пароля ssh следуя инструкциям в приведенном выше разделе “Упрощение ssh “), необходимо отключить аутентификацию на основе пароля. Это означает, что пользователи могут войти в систему только в том случае, если у них есть открытый ключ, соответствующий одному из закрытых ключей на одном из Pis. Хотя (теоретически) возможно взломать эти ключи, ed25519 – самый безопасный алгоритм пары открытых/закрытых ключей на сегодняшний день и, скорее всего, не будет разрушен в обозримом будущем.

Отключить аутентификацию на основе пароля и вход в систему root

Чтобы отключить аутентификацию на основе пароля, мы редактируем файл /etc/ssh/sshd_config . Есть 6 вариантов, которые мы хотим изменить, в частности. Найдите следующие ключи в этом файле и измените их так, чтобы они соответствовали приведенным ниже примерам. Убедитесь, что ни одна из приведенных ниже строк не начинается с ‘ # ‘, это закомментирует строку, чтобы она игнорировалась системой.

PermitRootLogin no
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no
X11Forwarding no
PrintMotd no

Приведенные выше команды, соответственно: предотвратят попытки хакеров войти в систему как root (поэтому им нужно будет знать, что имя пользователя – pi ); запретить аутентификацию на основе пароля (поэтому им понадобится соответствующий открытый ключ ed25519 для конкретного закрытого ключа на данном Pi); отключить пересылку X11 (GUI) между/из/в Pis (все должно выполняться из командной строки); и отключить “сообщение дня” (MOTD), которое иногда может включите компрометирующую информацию. Отредактируйте /etc/ssh/sshd_config и внесите вышеуказанные изменения в конкретный Pi, затем скопируйте эти изменения во все остальные Pi с помощью…

ПРЕДУПРЕЖДЕНИЕ: БУДЬТЕ ПРЕДЕЛЬНО ОСТОРОЖНЫ ПРИ ВЫПОЛНЕНИИ СЛЕДУЮЩИХ ДЕЙСТВИЙ. Если вы сделаете опечатку в sshd_config , , затем перезапустите службу ssh на Pi, она выдаст ошибку, и вы больше не сможете ssh

$ clusterscp /etc/ssh/sshd_config

…и перезапустите службу ssh (перезагрузите конфигурацию) во всех Pis с:

$ clustercmd sudo service ssh restart

Чтобы полностью удалить MOTD, удалите файл /etc/motd :

$ clustercmd sudo rm /etc/motd

Отслеживать активность ssh с помощью fail2ban

Еще одна важная вещь, которую мы можем сделать для мониторинга и защиты целостности кластера, – это установить программу с именем fail2ban . fail2ban “регистрирует и временно блокирует IP-адреса [s] на основе возможной вредоносной активности”. Чтобы установить эту программу на каждую машину в кластере, выполните команду:

$ clustercmd sudo apt install fail2ban –y

Затем скопируйте файл конфигурации на один Pi:

$ cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

…и отредактируйте строки внутри jail.local рядом с местом, начинающимся с [sshd] . Обратите внимание, что [sshd] появляется в верхней части файла в блоке с комментариями – игнорируйте это. [sshd] появляется в верхней части файла в блоке с комментариями – игнорируйте это.

[sshd]
enabled = true
port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s

[sshd] появляется в верхней части файла в блоке с комментариями – игнорируйте это.

$ clusterscp /etc/fail2ban/jail.local

[sshd] появляется в верхней части файла в блоке с комментариями – игнорируйте это.

$ clustercmd sudo service fail2ban restart

[ вернуться к началу ]

Hadoop и Spark

Настройка с одним узлом

Хадуп

Apache Hadoop v2.7+ для запуска требуется Java 7+ . Когда я устанавливал Raspbian на свой Pis, я использовал НОВИЧКИ v3.0.1 (2019-04-08). Это устанавливает Raspbian, а также Java 1.8.0_65 (Java 8 от Hotspot aka. Оракул). Таким образом, у всех Pi по умолчанию установлена приемлемая версия Java. Далее мы можем загрузить и установить Hadoop.

Я начну с создания одноузловой настройки на главном узле (Pi # 1), затем я использую рабочие узлы для создания многоузлового кластера. На Pi #1 получите Hadoop с помощью команд:

$ cd && wget https://bit.ly/2wa3Hty

(Это сокращенная ссылка на hadoop-3.2.0.tar.gz )

$ sudo tar -xvf 2wa3Hty -C /opt/
$ rm 2wa3Hty && cd /opt
$ sudo mv hadoop-3.2.0 hadoop

Затем обязательно измените разрешения для этого каталога:

$ sudo chown pi:pi -R /opt/hadoop

Наконец, добавьте этот каталог в $PATH , отредактировав ~/.bashrc и помещаем следующие строки в конец файла:

export JAVA_HOME=$(readlink –f /usr/bin/java | sed "s:bin/java::")
export HADOOP_HOME=/opt/hadoop
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

…и редактировать /opt/hadoop/etc/hadoop/hadoop-env.sh чтобы добавить следующую строку:

export JAVA_HOME=$(readlink –f /usr/bin/java | sed "s:bin/java::") 

Вы можете убедиться, что Hadoop установлен правильно, проверив версию:

$ cd && hadoop version | grep Hadoop
Hadoop 3.2.0

Искра

Мы загрузим Spark аналогично тому, как мы загрузили Hadoop выше:

$ cd && wget https://bit.ly/2HK6nTW

(Это сокращенная ссылка на spark-2.4.3-bin-hadoop2.7.tgz )

$ sudo tar –xvf 2HK6nTW –C /opt/
$ rm 2HK6nTW && cd /opt
$ sudo mv spark-2.4.3-bin-hadoop2.7 spark

Затем обязательно измените разрешения для этого каталога:

$ sudo chown pi:pi -R /opt/spark

Наконец, добавьте этот каталог в свой $PATH , отредактировав ~/.bashrc и помещаем следующие строки в конец файла:

export SPARK_HOME=/opt/spark
export PATH=$PATH:$SPARK_HOME/bin

Вы можете убедиться, что Spark установлен правильно, проверив версию:

$ cd && spark-shell --version
... version 2.4.3 ... Using Scala version 2.11.12 ...

HDFS

Чтобы запустить и запустить распределенную файловую систему Hadoop (HDFS), нам необходимо изменить некоторые конфигурационные файлы. Все эти файлы находятся в /opt/hadoop/etc/hadoop . Первый – это core-site.xml . Отредактируйте его итак, это выглядит следующим образом:


  
    fs.defaultFS
    hdfs://pi1:9000
  

Следующий – это hdfs-site.xml , который должен выглядеть следующим образом:


  
    dfs.datanode.data.dir
    file:///opt/hadoop_tmp/hdfs/datanode
  
  
    dfs.namenode.name.dir
    file:///opt/hadoop_tmp/hdfs/namenode
  
  
    dfs.replication
    1
  
 

…это настраивает, где хранится информация о DataNode и NameNode, а также устанавливает репликацию (количество раз, когда блок копируется по кластеру) равным 1 (мы изменим это позже). Убедитесь, что вы также создаете эти каталоги с помощью команд:

$ sudo mkdir -p /opt/hadoop_tmp/hdfs/datanode
$ sudo mkdir -p /opt/hadoop_tmp/hdfs/namenode

…и настройте владельца этих каталогов:

$ sudo chown pi:pi -R /opt/hadoop_tmp

Следующий файл – mapred-site.xml , который должен выглядеть следующим образом:


  
    mapreduce.framework.name
    yarn
  

…и, наконец, yarn-site.xml , который должен выглядеть следующим образом:


  
    yarn.nodemanager.aux-services
    mapreduce_shuffle
  
  
    yarn.nodemanager.auxservices.mapreduce.shuffle.class  
    org.apache.hadoop.mapred.ShuffleHandler
  
 

Как только эти четыре файла будут отредактированы, мы сможем отформатировать HDFS ( ВНИМАНИЕ: НЕ ДЕЛАЙТЕ ЭТОГО, ЕСЛИ У ВАС УЖЕ ЕСТЬ ДАННЫЕ В HDFS! ОН БУДЕТ ПОТЕРЯН! ):

$ hdfs namenode -format -force

…затем мы загружаем HDFS с помощью следующих двух команд:

$ start-dfs.sh
$ start-yarn.sh

…и проверьте, что он работает, создав временный каталог:

$ hadoop fs -mkdir /tmp

$ hadoop fs -ls /
Found 1 items
drwzr-xr-x   - pi supergroup          0 2019-04-09 16:51 /tmp

…или выполнив команду jps :

$ jps
2736 NameNode
2850 DataNode
3430 NodeManager
3318 ResourceManager
3020 SecondaryNameNode
3935 Jps

Это показывает, что HDFS запущена и работает, по крайней мере, на Pi # 1. Чтобы проверить, что Spark и Hadoop работают вместе, мы можем сделать:

$ hadoop fs -put $SPARK_HOME/README.md /

$ spark-shell

…это откроет оболочку Spark с подсказкой scala> :

scala> val textFile = sc.textFile("hdfs://pi1:9000/README.md")
...

scala> textFile.first()
res0: String = # Apache Spark

Скрыть предупреждение execstack

При выполнении приведенных выше команд Hadoop вы можете получить предупреждение типа…

” Вы загрузили библиотеку… что могло бы отключить защиту стека.”

…причина, по которой это происходит на нашем Raspberry Pi, заключается в несоответствии между 32-разрядной средой выполнения, для которой были созданы двоичные файлы Hadoop, и 64-разрядной версией Raspbian, которую мы запускаем. Чтобы игнорировать эти предупреждения, измените строку

# export HADOOP_OPTS="-Djava.net.preferIPv4Stack=true"

…в /opt/hadoop/etc/hadoop/hadoop-env.sh к

export HADOOP_OPTS="-XX:-PrintWarnings –Djava.net.preferIPv4Stack=true"

Это позволит скрыть предупреждения в будущем. (В качестве альтернативы вы также можете загрузить исходный код Hadoop и создать его с нуля.)

Скрыть предупреждение NativeCodeLoader

Еще одно предупреждение, которое вы можете увидеть, заключается в том, что until. NativeCodeLoader – это ” Не удается загрузить [библиотеку] native-hadoop для вашей платформы “. Это предупреждение не может быть легко устранено. Это связано с тем, что Hadoop скомпилирован для 32-разрядных архитектур, а версия Raspbian, которая у нас есть, 64-разрядная. Мы могли бы перекомпилировать библиотеку с нуля на 64-разрядной машине, но я бы предпочел просто не видеть предупреждение. Для этого мы можем добавить следующие строки в нижнюю часть вашего файла ~/.bashrc :

export HADOOP_HOME_WARN_SUPPRESS=1
export HADOOP_ROOT_LOGGER="WARN,DRFA" 

Это предотвратит печать этих предупреждений NativeCodeLoader .

Настройка кластера

На этом этапе у вас должен быть кластер с одним узлом, и этот единственный узел действует как главный, так и рабочий узел. Чтобы настроить рабочие узлы (и распределить вычисления по всему кластеру), мы должны выполнить следующие шаги…

Создайте каталоги

Создайте необходимые каталоги на всех других Pis, используя:

$ clustercmd sudo mkdir -p /opt/hadoop_tmp/hdfs
$ clustercmd sudo chown pi:pi –R /opt/hadoop_tmp
$ clustercmd sudo mkdir -p /opt/hadoop
$ clustercmd sudo chown pi:pi /opt/hadoop

Скопируйте конфигурацию

Скопируйте файлы в/opt/hadoop друг в друга, используя:

$ for pi in $(otherpis); do rsync –avxP $HADOOP_HOME $pi:/opt; done

Это займет довольно много времени, так что иди перекуси.

Когда вы вернетесь, убедитесь, что файлы скопированы правильно, запросив версию Hadoop на каждом узле с помощью следующей команды:

$ clustercmd hadoop version | grep Hadoop
Hadoop 3.2.0
Hadoop 3.2.0
Hadoop 3.2.0
...

Настройка Hadoop в кластере

Трудно найти хорошее руководство по установке Hadoop в сетевом кластере машин. Эта ссылка указывает на ту, по которой я следовал, в основном без происшествий. Чтобы запустить HDFS во всем кластере, нам нужно изменить файлы конфигурации, которые мы отредактировали ранее. Все эти файлы находятся в /opt/hadoop/etc/hadoop . Первый – это core-site.xml . Отредактируйте его итак, это выглядит следующим образом:


  
    fs.default.name
    hdfs://pi1:9000
  

Следующий – это hdfs-site.xml , который должен выглядеть следующим образом:


  
    dfs.datanode.data.dir
    /opt/hadoop_tmp/hdfs/datanode
  
  
    dfs.namenode.name.dir
    /opt/hadoop_tmp/hdfs/namenode
  
  
    dfs.replication
    4
  
 

Следующий файл – mapred-site.xml , который должен выглядеть следующим образом:


  
    mapreduce.framework.name
    yarn
  
  
    yarn.app.mapreduce.am.resource.mb
    256
  
  
    mapreduce.map.memory.mb
    128
  
  
    mapreduce.reduce.memory.mb
    128
  
 

…и, наконец, yarn-site.xml , который должен выглядеть следующим образом:


  
    yarn.acl.enable
    0
  
  
    yarn.resourcemanager.hostname
    pi1
  
  
    yarn.nodemanager.aux-services
    mapreduce_shuffle
  
  
    yarn.nodemanager.auxservices.mapreduce.shuffle.class  
    org.apache.hadoop.mapred.ShuffleHandler
  
  
    yarn.nodemanager.resource.memory-mb
    900
  
  
    yarn.scheduler.maximum-allocation-mb
    900
  
  
    yarn.scheduler.minimum-allocation-mb
    64
  
  
    yarn.nodemanager.vmem-check-enabled
    false
  

Внесите эти изменения в эти файлы, затем удалите все старые файлы со всех Pis. Я предполагаю, что вы пошагово прорабатываете этот учебник и еще не добавили никаких больших, важных данных в одноузловый Pi кластер №1. Вы можете очистить все фотографии с помощью:

$ clustercmd rm –rf /opt/hadoop_tmp/hdfs/datanode/*
$ clustercmd rm –rf /opt/hadoop_tmp/hdfs/namenode/*

Если вы этого не сделаете , у вас могут возникнуть ошибки, связанные с тем, что P не распознает друг друга. Если вы не можете запустить узлы данных (Pi # 2-# 8) или установить связь с NameNode (Pi # 1), решением может быть очистка файлов выше (это было для меня).

Далее нам нужно создать два файла в $HADOOP_HOME/etc/hadoop/ , которые сообщают Hadoop, какие узлы следует использовать в качестве рабочих узлов, а какой Pi должен быть главным узлом (NameNode). Создайте файл с именем master в вышеупомянутом каталоге и добавьте только одну строку:

pi1

Затем создайте файл с именем workers ( НЕ slaves , как это было в предыдущих версиях Hadoop) в том же каталоге и добавьте все остальные Pi:

pi2
pi3
pi4
...

Затем вам нужно будет снова отредактировать /etc/hosts . На любом Pi удалите строку, которая выглядит как

127.0.0.1 PiX

…где X – индекс этого конкретного числа Пи. Затем скопируйте этот файл во все остальные Pis с помощью:

$ clusterscp /etc/hosts

Мы можем сделать это сейчас, потому что этот файл больше не зависит от Pi. Наконец, перезагрузите кластер, чтобы эти изменения вступили в силу. Когда все Pi перезагрузятся, на Pi #1 выполните команду:

ВНИМАНИЕ: НЕ ДЕЛАЙТЕ ЭТОГО, ЕСЛИ У ВАС УЖЕ ЕСТЬ ДАННЫЕ В HDFS! ОН БУДЕТ ПОТЕРЯН!

$ hdfs namenode -format -force

…затем мы загружаем HDFS с помощью следующих двух команд:

$ start-dfs.sh && start-yarn.sh

Мы можем протестировать кластер, поместив файлы в HDFS из любого Pi (используя hadoop fs -put ) и убедитесь, что они отображаются на других Pis (используя hadoop fs - л.с. ). Вы также можете проверить, что кластер запущен и запущен, открыв веб-браузер и перейдя по ссылке http://pi1:9870 . Этот веб-интерфейс предоставляет вам проводник файлов, а также информацию о работоспособности кластера.

Веб-интерфейс Hadoop, работающий на порту 9870.

Веб-интерфейс Hadoop, показывающий статистику DataNode.

Файловый браузер в веб-интерфейсе Hadoop.

Настройка Spark в кластере

Spark будет нормально работать на одной машине, поэтому мы можем обмануть себя, думая, что используем всю мощь кластера Hadoop, когда на самом деле это не так. Часть конфигурации, которую мы выполнили выше, была предназначена для Hadoop YARN (еще один переговорщик ресурсов). Это “средство согласования ресурсов” для HDFS, которое управляет перемещением и анализом файлов по кластеру. Чтобы Spark мог взаимодействовать с YARN, нам нужно настроить еще две переменные среды в Pi #1/| ~/.bashrc . Ранее мы определили

export SPARK_HOME=/opt/spark
export PATH=$PATH:$SPARK_HOME/bin

…в ~/.bashrc . Непосредственно под этим мы теперь добавим еще две переменные среды:

export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
export LD_LIBRARY_PATH=$HADOOP_HOME/lib/native:$LD_LIBRARY_PATH

$HADOOP_CONF_DIR – это каталог, содержащий все *-site.xml конфигурационные файлы, которые мы отредактировали выше. Далее мы создаем конфигурационный файл Spark:

$ cd $SPARK_HOME/conf
$ sudo mv spark-defaults.conf.template spark-defaults.conf

…и мы добавляем следующие строки в конец этого файла:

spark.master            yarn
spark.driver.memory     465m
spark.yarn.am.memory    356m
spark.executor.memory   465m
spark.executor.cores    4

Значение этих значений объясняется по адресу эта ссылка . Но обратите внимание, что приведенное выше очень специфично для конкретной машины . Приведенная выше конфигурация отлично работает для меня с Raspberry Pi 3 Model B +, но она может не сработать для вас (или быть оптимальной) для менее или более мощной машины. Spark также устанавливает жесткие нижние границы того, сколько памяти может быть выделено. Там, где вы видите 465m выше, это минимальное настраиваемое значение для этой записи – любое меньшее значение, и Spark откажется запускаться.

Raspberry Pi 3 Model B+ использует от 9 до 25% своей оперативной памяти на холостом ходу. Поскольку у них в общей сложности 926 МБ оперативной памяти, Hadoop и Spark будут иметь доступ не более чем к 840 МБ оперативной памяти на Pi.

Как только все это будет настроено, перезагрузите кластер. Обратите внимание, что при перезагрузке вам НЕ следует повторно форматировать именной код HDFS. Вместо этого просто остановите и перезапустите службу HDFS с помощью:

$ stop-dfs.sh && stop-yarn.sh

$ start-dfs.sh && start-yarn.sh

Теперь вы можете отправить задание в Spark из командной строки:

pi@pi1:~ $ spark-submit --deploy-mode client --class org.apache.spark.examples.SparkPi $SPARK_HOME/examples/jars/spark-examples_2.11-2.4.3.jar 7
OpenJDK Client VM warning: You have loaded library /opt/hadoop/lib/native/libhadoop.so.1.0.0 which might have disabled stack guard. The VM will try to fix the stack guard now.
It's highly recommended that you fix the library with 'execstack -c ', or link it with '-z noexecstack'.
2019-07-08 14:01:24,408 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
2019-07-08 14:01:25,514 INFO spark.SparkContext: Running Spark version 2.4.3
2019-07-08 14:01:25,684 INFO spark.SparkContext: Submitted application: Spark Pi
2019-07-08 14:01:25,980 INFO spark.SecurityManager: Changing view acls to: pi
2019-07-08 14:01:25,980 INFO spark.SecurityManager: Changing modify acls to: pi
2019-07-08 14:01:25,981 INFO spark.SecurityManager: Changing view acls groups to: 
2019-07-08 14:01:25,981 INFO spark.SecurityManager: Changing modify acls groups to: 
2019-07-08 14:01:25,982 INFO spark.SecurityManager: SecurityManager: authentication disabled; ui acls disabled; users  with view permissions: Set(pi); groups with view permissions: Set(); users  with modify permissions: Set(pi); groups with modify permissions: Set()
2019-07-08 14:01:27,360 INFO util.Utils: Successfully started service 'sparkDriver' on port 46027.
2019-07-08 14:01:27,491 INFO spark.SparkEnv: Registering MapOutputTracker
2019-07-08 14:01:27,583 INFO spark.SparkEnv: Registering BlockManagerMaster
2019-07-08 14:01:27,594 INFO storage.BlockManagerMasterEndpoint: Using org.apache.spark.storage.DefaultTopologyMapper for getting topology information
2019-07-08 14:01:27,596 INFO storage.BlockManagerMasterEndpoint: BlockManagerMasterEndpoint up
2019-07-08 14:01:27,644 INFO storage.DiskBlockManager: Created local directory at /tmp/blockmgr-e5479834-d1e4-48fa-9f5c-cbeb65531c31
2019-07-08 14:01:27,763 INFO memory.MemoryStore: MemoryStore started with capacity 90.3 MB
2019-07-08 14:01:28,062 INFO spark.SparkEnv: Registering OutputCommitCoordinator
2019-07-08 14:01:28,556 INFO util.log: Logging initialized @10419ms
2019-07-08 14:01:28,830 INFO server.Server: jetty-9.3.z-SNAPSHOT, build timestamp: unknown, git hash: unknown
2019-07-08 14:01:28,903 INFO server.Server: Started @10770ms
2019-07-08 14:01:28,997 INFO server.AbstractConnector: Started ServerConnector@89f072{HTTP/1.1,[http/1.1]}{0.0.0.0:4040}
2019-07-08 14:01:28,997 INFO util.Utils: Successfully started service 'SparkUI' on port 4040.
2019-07-08 14:01:29,135 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@1b325b3{/jobs,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,137 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@b72664{/jobs/json,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,140 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@34b7b8{/jobs/job,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,144 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@1e8821f{/jobs/job/json,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,147 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@b31700{/stages,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,150 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@165e559{/stages/json,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,153 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@1ae47a0{/stages/stage,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,158 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@5a54d{/stages/stage/json,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,161 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@1ef722a{/stages/pool,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,165 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@1d9b663{/stages/pool/json,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,168 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@14894fc{/storage,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,179 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@567255{/storage/json,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,186 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@362c57{/storage/rdd,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,191 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@4ee95c{/storage/rdd/json,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,195 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@1c4715d{/environment,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,200 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@a360ea{/environment/json,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,204 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@148bb7d{/executors,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,209 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@27ba81{/executors/json,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,214 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@336c81{/executors/threadDump,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,217 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@156f2dd{/executors/threadDump/json,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,260 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@1e52059{/static,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,265 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@159e366{/,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,283 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@1dc9128{/api,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,288 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@c4944a{/jobs/job/kill,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,292 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@772895{/stages/stage/kill,null,AVAILABLE,@Spark}
2019-07-08 14:01:29,304 INFO ui.SparkUI: Bound SparkUI to 0.0.0.0, and started at http://pi1:4040
2019-07-08 14:01:29,452 INFO spark.SparkContext: Added JAR file:/opt/spark/examples/jars/spark-examples_2.11-2.4.3.jar at spark://pi1:46027/jars/spark-examples_2.11-2.4.3.jar with timestamp 1562590889451
2019-07-08 14:01:33,070 INFO client.RMProxy: Connecting to ResourceManager at pi1/192.168.0.101:8032
2019-07-08 14:01:33,840 INFO yarn.Client: Requesting a new application from cluster with 7 NodeManagers
2019-07-08 14:01:34,082 INFO yarn.Client: Verifying our application has not requested more than the maximum memory capability of the cluster (900 MB per container)
2019-07-08 14:01:34,086 INFO yarn.Client: Will allocate AM container, with 740 MB memory including 384 MB overhead
2019-07-08 14:01:34,089 INFO yarn.Client: Setting up container launch context for our AM
2019-07-08 14:01:34,101 INFO yarn.Client: Setting up the launch environment for our AM container
2019-07-08 14:01:34,164 INFO yarn.Client: Preparing resources for our AM container
2019-07-08 14:01:35,577 WARN yarn.Client: Neither spark.yarn.jars nor spark.yarn.archive is set, falling back to uploading libraries under SPARK_HOME.
2019-07-08 14:02:51,027 INFO yarn.Client: Uploading resource file:/tmp/spark-ca0b9022-2ba9-45ff-8d63-50545ef98e55/__spark_libs__7928629488171799934.zip -> hdfs://pi1:9000/user/pi/.sparkStaging/application_1562589758436_0002/__spark_libs__7928629488171799934.zip
2019-07-08 14:04:09,654 INFO yarn.Client: Uploading resource file:/tmp/spark-ca0b9022-2ba9-45ff-8d63-50545ef98e55/__spark_conf__4579290782490197871.zip -> hdfs://pi1:9000/user/pi/.sparkStaging/application_1562589758436_0002/__spark_conf__.zip
2019-07-08 14:04:13,226 INFO spark.SecurityManager: Changing view acls to: pi
2019-07-08 14:04:13,227 INFO spark.SecurityManager: Changing modify acls to: pi
2019-07-08 14:04:13,227 INFO spark.SecurityManager: Changing view acls groups to: 
2019-07-08 14:04:13,228 INFO spark.SecurityManager: Changing modify acls groups to: 
2019-07-08 14:04:13,228 INFO spark.SecurityManager: SecurityManager: authentication disabled; ui acls disabled; users  with view permissions: Set(pi); groups with view permissions: Set(); users  with modify permissions: Set(pi); groups with modify permissions: Set()
2019-07-08 14:04:20,235 INFO yarn.Client: Submitting application application_1562589758436_0002 to ResourceManager
2019-07-08 14:04:20,558 INFO impl.YarnClientImpl: Submitted application application_1562589758436_0002
2019-07-08 14:04:20,577 INFO cluster.SchedulerExtensionServices: Starting Yarn extension services with app application_1562589758436_0002 and attemptId None
2019-07-08 14:04:21,625 INFO yarn.Client: Application report for application_1562589758436_0002 (state: ACCEPTED)
2019-07-08 14:04:21,680 INFO yarn.Client: 
     client token: N/A
     diagnostics: [Mon Jul 08 14:04:20 +0100 2019] Scheduler has assigned a container for AM, waiting for AM container to be launched
     ApplicationMaster host: N/A
     ApplicationMaster RPC port: -1
     queue: default
     start time: 1562591060331
     final status: UNDEFINED
     tracking URL: http://pi1:8088/proxy/application_1562589758436_0002/
     user: pi
2019-07-08 14:04:22,696 INFO yarn.Client: Application report for application_1562589758436_0002 (state: ACCEPTED)
2019-07-08 14:04:23,711 INFO yarn.Client: Application report for application_1562589758436_0002 (state: ACCEPTED)
2019-07-08 14:04:24,725 INFO yarn.Client: Application report for application_1562589758436_0002 (state: ACCEPTED)
...
2019-07-08 14:05:45,863 INFO yarn.Client: Application report for application_1562589758436_0002 (state: ACCEPTED)
2019-07-08 14:05:46,875 INFO yarn.Client: Application report for application_1562589758436_0002 (state: ACCEPTED)
2019-07-08 14:05:47,883 INFO yarn.Client: Application report for application_1562589758436_0002 (state: RUNNING)
2019-07-08 14:05:47,884 INFO yarn.Client: 
     client token: N/A
     diagnostics: N/A
     ApplicationMaster host: 192.168.0.103
     ApplicationMaster RPC port: -1
     queue: default
     start time: 1562591060331
     final status: UNDEFINED
     tracking URL: http://pi1:8088/proxy/application_1562589758436_0002/
     user: pi
2019-07-08 14:05:47,891 INFO cluster.YarnClientSchedulerBackend: Application application_1562589758436_0002 has started running.
2019-07-08 14:05:47,937 INFO util.Utils: Successfully started service 'org.apache.spark.network.netty.NettyBlockTransferService' on port 46437.
2019-07-08 14:05:47,941 INFO netty.NettyBlockTransferService: Server created on pi1:46437
2019-07-08 14:05:47,955 INFO storage.BlockManager: Using org.apache.spark.storage.RandomBlockReplicationPolicy for block replication policy
2019-07-08 14:05:48,178 INFO storage.BlockManagerMaster: Registering BlockManager BlockManagerId(driver, pi1, 46437, None)
2019-07-08 14:05:48,214 INFO storage.BlockManagerMasterEndpoint: Registering block manager pi1:46437 with 90.3 MB RAM, BlockManagerId(driver, pi1, 46437, None)
2019-07-08 14:05:48,265 INFO storage.BlockManagerMaster: Registered BlockManager BlockManagerId(driver, pi1, 46437, None)
2019-07-08 14:05:48,269 INFO storage.BlockManager: Initialized BlockManager: BlockManagerId(driver, pi1, 46437, None)
2019-07-08 14:05:49,426 INFO cluster.YarnClientSchedulerBackend: Add WebUI Filter. org.apache.hadoop.yarn.server.webproxy.amfilter.AmIpFilter, Map(PROXY_HOSTS -> pi1, PROXY_URI_BASES -> http://pi1:8088/proxy/application_1562589758436_0002), /proxy/application_1562589758436_0002
2019-07-08 14:05:49,441 INFO ui.JettyUtils: Adding filter org.apache.hadoop.yarn.server.webproxy.amfilter.AmIpFilter to /jobs, /jobs/json, /jobs/job, /jobs/job/json, /stages, /stages/json, /stages/stage, /stages/stage/json, /stages/pool, /stages/pool/json, /storage, /storage/json, /storage/rdd, /storage/rdd/json, /environment, /environment/json, /executors, /executors/json, /executors/threadDump, /executors/threadDump/json, /static, /, /api, /jobs/job/kill, /stages/stage/kill.
2019-07-08 14:05:49,816 INFO ui.JettyUtils: Adding filter org.apache.hadoop.yarn.server.webproxy.amfilter.AmIpFilter to /metrics/json.
2019-07-08 14:05:49,829 INFO handler.ContextHandler: Started o.s.j.s.ServletContextHandler@136bd1{/metrics/json,null,AVAILABLE,@Spark}
2019-07-08 14:05:49,935 INFO cluster.YarnClientSchedulerBackend: SchedulerBackend is ready for scheduling beginning after waiting maxRegisteredResourcesWaitingTime: 30000(ms)
2019-07-08 14:05:50,076 INFO cluster.YarnSchedulerBackend$YarnSchedulerEndpoint: ApplicationMaster registered as NettyRpcEndpointRef(spark-client://YarnAM)
2019-07-08 14:05:52,074 INFO spark.SparkContext: Starting job: reduce at SparkPi.scala:38
2019-07-08 14:05:52,479 INFO scheduler.DAGScheduler: Got job 0 (reduce at SparkPi.scala:38) with 7 output partitions
2019-07-08 14:05:52,481 INFO scheduler.DAGScheduler: Final stage: ResultStage 0 (reduce at SparkPi.scala:38)
2019-07-08 14:05:52,485 INFO scheduler.DAGScheduler: Parents of final stage: List()
2019-07-08 14:05:52,492 INFO scheduler.DAGScheduler: Missing parents: List()
2019-07-08 14:05:52,596 INFO scheduler.DAGScheduler: Submitting ResultStage 0 (MapPartitionsRDD[1] at map at SparkPi.scala:34), which has no missing parents
2019-07-08 14:05:53,314 WARN util.SizeEstimator: Failed to check whether UseCompressedOops is set; assuming yes
2019-07-08 14:05:53,404 INFO memory.MemoryStore: Block broadcast_0 stored as values in memory (estimated size 1936.0 B, free 90.3 MB)
2019-07-08 14:05:53,607 INFO memory.MemoryStore: Block broadcast_0_piece0 stored as bytes in memory (estimated size 1256.0 B, free 90.3 MB)
2019-07-08 14:05:53,625 INFO storage.BlockManagerInfo: Added broadcast_0_piece0 in memory on pi1:46437 (size: 1256.0 B, free: 90.3 MB)
2019-07-08 14:05:53,639 INFO spark.SparkContext: Created broadcast 0 from broadcast at DAGScheduler.scala:1161
2019-07-08 14:05:53,793 INFO scheduler.DAGScheduler: Submitting 7 missing tasks from ResultStage 0 (MapPartitionsRDD[1] at map at SparkPi.scala:34) (first 15 tasks are for partitions Vector(0, 1, 2, 3, 4, 5, 6))
2019-07-08 14:05:53,801 INFO cluster.YarnScheduler: Adding task set 0.0 with 7 tasks
2019-07-08 14:06:08,910 WARN cluster.YarnScheduler: Initial job has not accepted any resources; check your cluster UI to ensure that workers are registered and have sufficient resources
2019-07-08 14:06:23,907 WARN cluster.YarnScheduler: Initial job has not accepted any resources; check your cluster UI to ensure that workers are registered and have sufficient resources
2019-07-08 14:06:38,907 WARN cluster.YarnScheduler: Initial job has not accepted any resources; check your cluster UI to ensure that workers are registered and have sufficient resources
2019-07-08 14:06:47,677 INFO cluster.YarnSchedulerBackend$YarnDriverEndpoint: Registered executor NettyRpcEndpointRef(spark-client://Executor) (192.168.0.106:44936) with ID 1
2019-07-08 14:06:48,266 INFO storage.BlockManagerMasterEndpoint: Registering block manager pi6:39443 with 90.3 MB RAM, BlockManagerId(1, pi6, 39443, None)
2019-07-08 14:06:48,361 INFO scheduler.TaskSetManager: Starting task 0.0 in stage 0.0 (TID 0, pi6, executor 1, partition 0, PROCESS_LOCAL, 7877 bytes)
2019-07-08 14:06:48,371 INFO scheduler.TaskSetManager: Starting task 1.0 in stage 0.0 (TID 1, pi6, executor 1, partition 1, PROCESS_LOCAL, 7877 bytes)
2019-07-08 14:06:48,375 INFO scheduler.TaskSetManager: Starting task 2.0 in stage 0.0 (TID 2, pi6, executor 1, partition 2, PROCESS_LOCAL, 7877 bytes)
2019-07-08 14:06:48,379 INFO scheduler.TaskSetManager: Starting task 3.0 in stage 0.0 (TID 3, pi6, executor 1, partition 3, PROCESS_LOCAL, 7877 bytes)
2019-07-08 14:06:50,877 INFO storage.BlockManagerInfo: Added broadcast_0_piece0 in memory on pi6:39443 (size: 1256.0 B, free: 90.3 MB)
2019-07-08 14:06:52,001 INFO scheduler.TaskSetManager: Starting task 4.0 in stage 0.0 (TID 4, pi6, executor 1, partition 4, PROCESS_LOCAL, 7877 bytes)
2019-07-08 14:06:52,024 INFO scheduler.TaskSetManager: Starting task 5.0 in stage 0.0 (TID 5, pi6, executor 1, partition 5, PROCESS_LOCAL, 7877 bytes)
2019-07-08 14:06:52,039 INFO scheduler.TaskSetManager: Starting task 6.0 in stage 0.0 (TID 6, pi6, executor 1, partition 6, PROCESS_LOCAL, 7877 bytes)
2019-07-08 14:06:52,115 INFO scheduler.TaskSetManager: Finished task 2.0 in stage 0.0 (TID 2) in 3733 ms on pi6 (executor 1) (1/7)
2019-07-08 14:06:52,143 INFO scheduler.TaskSetManager: Finished task 0.0 in stage 0.0 (TID 0) in 3891 ms on pi6 (executor 1) (2/7)
2019-07-08 14:06:52,144 INFO scheduler.TaskSetManager: Finished task 1.0 in stage 0.0 (TID 1) in 3776 ms on pi6 (executor 1) (3/7)
2019-07-08 14:06:52,156 INFO scheduler.TaskSetManager: Finished task 3.0 in stage 0.0 (TID 3) in 3780 ms on pi6 (executor 1) (4/7)
2019-07-08 14:06:52,217 INFO scheduler.TaskSetManager: Finished task 4.0 in stage 0.0 (TID 4) in 222 ms on pi6 (executor 1) (5/7)
2019-07-08 14:06:52,249 INFO scheduler.TaskSetManager: Finished task 6.0 in stage 0.0 (TID 6) in 215 ms on pi6 (executor 1) (6/7)
2019-07-08 14:06:52,262 INFO scheduler.TaskSetManager: Finished task 5.0 in stage 0.0 (TID 5) in 247 ms on pi6 (executor 1) (7/7)
2019-07-08 14:06:52,270 INFO cluster.YarnScheduler: Removed TaskSet 0.0, whose tasks have all completed, from pool 
2019-07-08 14:06:52,288 INFO scheduler.DAGScheduler: ResultStage 0 (reduce at SparkPi.scala:38) finished in 59.521 s
2019-07-08 14:06:52,323 INFO scheduler.DAGScheduler: Job 0 finished: reduce at SparkPi.scala:38, took 60.246659 s
Pi is roughly 3.1389587699411
2019-07-08 14:06:52,419 INFO server.AbstractConnector: Stopped Spark@89f072{HTTP/1.1,[http/1.1]}{0.0.0.0:4040}
2019-07-08 14:06:52,432 INFO ui.SparkUI: Stopped Spark web UI at http://pi1:4040
2019-07-08 14:06:52,473 INFO cluster.YarnClientSchedulerBackend: Interrupting monitor thread
2019-07-08 14:06:52,602 INFO cluster.YarnClientSchedulerBackend: Shutting down all executors
2019-07-08 14:06:52,605 INFO cluster.YarnSchedulerBackend$YarnDriverEndpoint: Asking each executor to shut down
2019-07-08 14:06:52,640 INFO cluster.SchedulerExtensionServices: Stopping SchedulerExtensionServices
(serviceOption=None,
 services=List(),
 started=false)
2019-07-08 14:06:52,649 INFO cluster.YarnClientSchedulerBackend: Stopped
2019-07-08 14:06:52,692 INFO spark.MapOutputTrackerMasterEndpoint: MapOutputTrackerMasterEndpoint stopped!
2019-07-08 14:06:52,766 INFO memory.MemoryStore: MemoryStore cleared
2019-07-08 14:06:52,769 INFO storage.BlockManager: BlockManager stopped
2019-07-08 14:06:52,825 INFO storage.BlockManagerMaster: BlockManagerMaster stopped
2019-07-08 14:06:52,851 INFO scheduler.OutputCommitCoordinator$OutputCommitCoordinatorEndpoint: OutputCommitCoordinator stopped!
2019-07-08 14:06:52,902 INFO spark.SparkContext: Successfully stopped SparkContext
2019-07-08 14:06:52,927 INFO util.ShutdownHookManager: Shutdown hook called
2019-07-08 14:06:52,935 INFO util.ShutdownHookManager: Deleting directory /tmp/spark-1d1b5b79-679d-4ffe-b8aa-7e84e6be10f2
2019-07-08 14:06:52,957 INFO util.ShutdownHookManager: Deleting directory /tmp/spark-ca0b9022-2ba9-45ff-8d63-50545ef98e55

Если вы просеете выходные данные приведенной выше команды, вы увидите, что следующий результат:

took 60.246659 s
Pi is roughly 3.1389587699411

Самое последнее, что я хотел бы вам посоветовать, это добавить stop-dfs.sh и stop-yarn.sh к вашему clusterreboot и

function clusterreboot {
  stop-yarn.sh && stop-dfs.sh && \
  clustercmd sudo shutdown -r now
}
function clustershutdown {
  stop-yarn.sh && stop-dfs.sh && \
  clustercmd sudo shutdown now
}

[ вернуться к началу ]

Вывод

Так вот оно что! Надеюсь, это руководство было вам полезно, независимо от того, настраиваете ли вы Raspberry Pi, создаете свой собственный кластер Hadoop и Spark или просто хотите узнать о некоторых технологиях больших данных. Пожалуйста, дайте мне знать, если вы обнаружите какие-либо проблемы с приведенным выше руководством; Я был бы рад внести в него изменения или сделать его более понятным.

Если вы хотите получить дополнительную информацию о командах, которые вы можете запускать в HDFS, или как отправить задание в Spark , пожалуйста, перейдите по этим ссылкам. Спасибо, что дожили до конца!

Если вам нравится подобный контент, обязательно подписывайтесь на меня в Twitter и здесь, на Dev. В . Я пишу о Java, Hadoop и Spark, R и многом другом.

[ вернуться к началу ]

Оригинал: “https://dev.to/awwsmm/building-a-raspberry-pi-hadoop-spark-cluster-8b2”