Raspberry one serving

Деплоим на Raspberry, или пилим бэкенды для поделок. Часть 1: сервер в локальной сети.

Время от времени в практике возникали ситуации, когда я мечтательно задумывался о том, что неплохо было бы запилить веб-сервер в качестве бэкенда для каких-то своих несложных проектов. Ну, чтобы был hostname, как положено, и чтобы снаружи можно было отдать ему какие-то данные и получить какие-то данные, может быть прикрутить API-шечку, а может и вообще — хостить там свой уютный бложик.

В воображении сразу вырисовывались какие-то стойки с blade-ами, аренда виртуалки на Digital Ocean, или, на худой конец, круглосуточно гудящий компьютер под столом.

А ведь хочется чего-то тихого, изящного, бесшумного, и желательно бесплатного…

Стоп! Но ведь все уже изобретено до нас!

Сегодня я хочу рассказать про то, как можно за копейки, обладая минимальным количеством знаний, запилить машину, которая обеспечит 90% ваших (ну, моих — точно) потребностей в бэкенде.
Рассказ будет нести характер записей для самого себя — чтобы не забыть что делать, повторяя это в следующий раз, например)

Кому интересно — го под кат (кстати, обратите внимание, как бутербродом напаяны чипы на плате).

Итак, как вы уже догадались, речь пойдет о Raspberry Pi.
Фффи — скажет кто-то из вас — она ведь ниче не может!
Я тоже так думал, но в спецификации на новую Raspberry Pi-2 написано, что в ней 4 ядра по 1Ghz каждое, и гиг оперативки на борту. Норм? Конечно норм!

О конкретных применениях этого решения поговорим наверное в следующих статьях, но, скажу вам, пока я всем доволен.

И вот погуглил я цены и характеристики, и заказал Raspberry B — 2 за 2500 рублей с Aliexpress (уже после скачка курса).
Плюс microSD-карта (обязательно тип 10!) на 8 гигабайт — 600 рублей.
И блок питания c разъемом USB-micro — зарядное устройство для мобильных гаджетов в ближайшей Евросети — еще 500 рублей за самый дорогой.
Итого: 3600 рублей за железки.

Вот так выглядит вторая версия (которая, к слову, пришла в красивой коробочке вместе с корпусом, и парой медных радиаторов: на процессор и ethernet-контроллер).

А пока шла Raspberry 2, товарищ на работе подогнал первую версию — в которой всего лишь одно ядро на 700 Mhz, и 512 Mb RAM, и сейчас работает именно она, а 2-ая версия ждет своего часа для освещения в следующей статье.

Что будем делать

Итак, давайте договоримся, что мы получим под завершение этой статьи.
Сервер на linux, к которому можно подключиться по SSH, удобную и привычную (для меня) CLI на борту, окружение для старта серверов, написанных на Node.js (и Coffee script туда же). И, конечно же, возможность разворачивать и поднимать несколько сервисов а одной машине.

Исходные данные

Железо, на котором я работаю — MacBook Pro, Mac OS X 10.10, почти всё (или даже вообще всё) будем делать из терминала, у меня это iTerm и oh-my-zsh в качестве shell.

Сама плата в примере — Raspberry первой версии, но для второй, думаю, никак отличий не будет.

Raspberry setup

1. Качаем Raspbian здесь: www.raspberrypi.org/downloads/raspbian/
На момент написания там 2 дистрибутива, основанные на разных сборках Debian. Я скачал посвежее: RASPBIAN JESSIE.

2. Пихаем sd-карту в комп, пишем:

Находим свою карту (например, /dev/disk4)

3. Отмонтируем карту (здесь и далее пример на /dev/disk4, хотя у вас номер может отличаться):

4. Идем в папку со скачанным zip-архивом с образом OS. У меня был в Downloads.

5. Копируем образ на карту (название файла с образом актуально на момент написания статьи, потом может отличаться, естессно):

6. Вставляем карточку в слот. Подключаем питание и сеть напрямую к компу (ну или через роутер, хотя я напрямую подключал). Ждем, пока загрузится плата — лампочки помигают-помигают, и станут мигать менее интенсивно.

7. В Raspbian уже почти все предварительно настроено, и даже поднят zeroconf, поэтому наша плата доступна. Попингуем raspberrypy.local — и удостоверимся, что пакетики побежали.

8. Заходим на плату:

Вводим пароль для супер-пользователя на вашей машине, на вопрос системы о внесении неизвестного хоста в список известных — говорим yes, вводим дефолтный пароль для пользователя pi на плате: raspberry.

9. Конфигурируем распберри, не мудрствуя лукаво, встроенной утилитой. Эту команду мы выполняем уже не на локальной машине, а на raspberry по ssh, здесь и далее буду писать [email protected]`hostname`$, когда мы должны запустить команду на будущем сервере:

1. Expand file system (надо, чтобы плата умела работать со всей sd-карточкой)
2. Change password (два раза вводим новый пароль)
8. Advanced Options -> hostname (вводим новый hostnamr — у меня это ratm, и дальше примеры будут с этим именем)
8. Advanced Options -> Finish (да, хотим перезагрузить)

10. Reboot. Просто ждём, пока система перезагрузится.

Здесь последует небольшое лирическое отступление.

В нашей локальной сети DHCP довольно умен и выдает не только IP, но и домен.
Поэтому, когда я подключил плату не напрямую к компу, а к локальной сети на работе, искать плату нужно уже не по: raspberry.local (мы же сменили hostname), но и не по ratm.local (ибо DHCP умен и выдал нам чуть другой хостнейм) — пинговать мне уже нужно было по адресу ratm.domen.local, у вас нового домена может не появиться, если роутер не умеет в такой DHCP.

11. Далее убеждаемся что все хорошо (естественно, это мы выполняем на локальной машине):

12. Снова заходим на плату, но уже на на другой hostname:

Написать простейший сервер очень легко на Node.js — кто не знает, это такой фреймфорк для JavaScript, который позволяет запускать JS не только внутри браузера, где вообще ему и место, но и снаружи браузера.
JS, конечно, довольно неказист, но когда нужно быстро написать простенький сервачок для своих целей — это то что нужно)

Поднимаем окружение для ноды

13. На всякий случай подтягиваем новые зависимости для менеджера пакетов.

14. Устанавливаем ноду.

15. Устанавливаем менеджер пакетов для ноды — без него мы не сможем подтягивать нужные фреймворки для приложений на node.js. Если кто знает про yotta для mbed, то она как раз сделана по образу и подобию npm)

16. Проверим что все ок.

Делаем красиво — Oh-My-Zsh

Я очень люблю, когда командная строка помогает работать, и выглядит привычно.
Поэтому стараюсь там где можно использовать Oh-My-Zsh. Шаг необязательный, но это очень удобный инструмент с автокомплитом, отображением веток репозиториев, сразу предзабитыми алиасами и вообще очень удобная вещь, так что рекомендую не проходить мимо. Есть, конечно, и минусы, но скорее всего вы с ними не столкнетесь, а вот удовольствия от работы получите — факт.

17. Шаг супер-стандартный — качаем zsh

18. На всякий случай удостоверяемся, что git у вас уже есть.

19. Подтягиваем oh-my-zsh.

20. Меняем текущий shell нв zsh.

21. Перезагружаем систему.

22. Ждем и заходим снова на raspberry по ssh уже традиционным способом.
Видим, что shell стал минималистичен, красив, и вообще няшка. Вот как на картинке:

НО!
Лично у меня точно такой же shell локально на машине, и чтобы однозначно понимать, где мы находимся — локально или на удаленной машине, сделаем небольшой модик — будем отображать в приглашении строчку [[email protected]] и уже потом приглашение.

Делаем следующие шаги.

23. Устанавливаем vim (это текстовый редактор, тоже шаг не обязательный — если вам удобно работать в другом редакторе — ваш выбор).

24. Идем модифицировать наш шелл.

25. Чтобы корректно вести себя, создадим новую ветку для изменений.

26. Открываем файл, описывающий дефолтный вид командной строки:

27. Заменяем полностью строчку PROMPT на эту:

Если вы никогда не работали с vim’ом, у вас возможно немного сломается мозг, потому что сделать нужно в окне редактора вот что:
— нажать i (при это внизу появится надпись, означающая, что вы в режиме редактирования: — INSERT —).
— стереть строчку со старым PROMPT.
— просто вставить (CMD+V) новую строчку на место старой.
— выйти из редактора с записью: для этого нажать ESC, потом `:` (двоеточие — появится двоеточие), написать wq — значит выйти с записью, и нажать ENTER — все просто)

28. Закоммитать изменения на всякий случай:
Коммит месседж может быть любым)

29. Перезагружить систему, зайти в неё, и удостовериться, что теперь наше приглашение содержит надпись [[email protected]]. Ура!

У меня это выглядит вот так (с замазанными участками выглядит не так красиво, но все равно примерно понятно — сверху картинки приглашение командной строки моей локальной машины, ниже, когда мы зашли на raspberry — уже её приглашение, которое спутать с локальным довольно сложно):

Чуть не забыл! Алиас для ноды.

30. Нода запускается командой nodejs, а хотелось бы запускать ее командой node. Создадим нужный симлинк:

В принципе, теперь мы можем спокойно запускать сервера, написанные на node.js просто командой:

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

Для этого есть несколько способов.
Один из них — сконфигурять и использовать Linux Service, в Raspbian это, например, System V.
Но мы пока что пойдем другим — поставим специальный пакет для node.js, который называется forever, и позволяет, к тому же, например, рестартовать сервер поле его падения. Это удобная функция)

31. Устанавливаем forever:

Может потребоваться время. У меня — около 10 минут.

Если forever не встал или не заработал, то возможно поможет пересобрать ноду — это очень просто, но у меня заняло целый день (то есть не у меня, а у Raspberry Pi, 1-ой её версии).
Если вам также не повезло, то делается это вот так:

Запускаем сервер фоновым процессом!

32. И вот, наконец то, ради чего весь сыр-бор. Запускаем наш ненаглядный сервер работать в фоне.

Или для coffee-script:

Помотреть список крутящихся сервисов:

Там же можно найти и название файла, куда пишутся логи.

Где server — это имя сервиса.

Собственно, это пока всё.
Мы подняли в локальной сети машину, со своим hostname, подняли на ней окружение для сервера, и научились стартовать серверы на node.js (и на coffee-script). При этом стОит она копейки, жрёт мало электричества и не гудит.

А в следующей статье, я попробую описать, как вытащить вашу пишечку наружу — прямо в интернет, прикрутить к белому айпишнику выбранный hostname, да ещё так, чтобы она не стала жертвой какого-нибудь ботнета + поднимем какой-нибудь http-сервер со страничкой и простейшим API.

Кому тема интересна, пишите в комментариях вопросы, постараюсь на них ответить.
У кого есть замечания — тоже не молчите)

Источник

Маленькие «малинки» в крупном дата-центре

В мае у нас появились новые серверы на базе Raspberry Pi 4. И ребята из Selectel Community (это такой неформальный телеграм-чат компании) часто спрашивали, как нам вообще удалось интегрировать их в систему автоматической сдачи. Спустя время мы окинули сделанное ретроспективным взором и готовы подробно ответить на этот вопрос.

Тема использования «малинок» в промышленных масштабах не нова — в сети можно найти множество публикаций на тему сборки вычислительных кластеров. Вначале они представляли собой самодельные фермы, где самым интересным была возможность добавить побольше плат или приспособить водяную систему охлаждения. Но с ростом интереса начали появляться уже готовые кронштейны для монтирования «малинок» в стандартную 19” стойку. Даже были попытки создать blade-варианты.

Но, несмотря на весь оптимизм в медиасфере, вопрос, удастся ли вообще интегрировать «малинки» в дата-центры Selectel, оставался открытым.

Общие требования к размещению в дата-центре

Чтобы понять, что же могло помешать, рассмотрим основные отличия «малинок» от «стандартных» серверов. Под «стандартными» подразумеваются серверы линейки Chipcore на базе десктопного железа.

Чтобы разместить сервер в дата-центре, он должен удовлетворять следующим требованиям:

  • Поддержка сетевых интерфейсов. Самое очевидное требование. Сервер должен быть доступен клиенту по «белому» IP-адресу. Обеспечивается Gigabit Ethernet портом.
  • Размещение в стойке. На время тестов мы использовали распечатанные на 3D-принтере салазки. На 1 монтажный юнит приходится 12 «малинок».
  • Удаленное управление питанием. По умолчанию питание происходит через предназначенный для этого порт USB Type-C, что дает только ручное управление.
    Но через 40-пиновый разъем можно подключить модуль PoE HAT. В таком случае управлять питанием удаленно можно через коммутатор, включая или отключая питание на порту.
  • Независимость от локальных дисковых устройств. Аренда выделенных серверов предполагает полный доступ клиента к железу. Более того, диски могут быть заменены по требованию. В этом случае они должны быть полностью очищены и не содержать дополнительных данных, а развертывание сервера не должно на них опираться.
  • Загрузка по сети (PXE). Самый непонятный и вызывающий вопросы пункт. Мы знали, что «малинки» поддерживают загрузку по PXE, но, как в действительности это работает, оставалось неизвестным.

На последнем пункте остановимся подробнее. Нужно учитывать, что Raspberry Pi относится к железу для встраиваемых систем. А на них процесс инициализации и загрузки системы заметно отличается от привычного.

Процесс загрузки «обычного» сервера

Для сравнения, вкратце рассмотрим, как происходит загрузка на «обычном» сервере.

  1. BIOS/UEFI. Система стартует с BIOS/UEFI, который инициализирует железо и передает управление первому устройству в списке загрузки. По умолчанию это первый диск в системе, но для загрузки по PXE первым выбирается нужный сетевой интерфейс. Важно, что BIOS/UEFI дает нам интерфейс для изменения этого списка и может его сохранять.
  2. NIC. После того, как сетевой интерфейс получил управление, он посылает в сеть широковещательный запрос DHCP, получает в ответе настройки TFTP (tftp-server-name и boot-file-name) и по ним загружает файл, которому передается управление.
  3. iPXE. В нашем случае мы возвращаем кастомизированный iPXE-загрузчик, который через параметр chain запрашивает iPXE-скрипт и получает сценарий загрузки сервера.
  4. Автоустановка / автозагрузка. В зависимости от выбора дистрибутива на базе шаблона генерируется уникальный сценарий (прежде всего данные подключения) автоустановки для конкретного сервера. После завершения автоустановки сценарий загрузки меняется, и iPXE в следующий раз получит другой шаблон загрузки. Загрузка через сетевой интерфейс позволяет нам гибко управлять загрузкой сервера, меняя только ответ сервера, с которого iPXE ожидает ответ.

Процесс загрузки «малинки»

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

  1. EEPROM. Старт «малинки» начинается с запуска прошивки из энергонезависимой микросхемы EEPROM. В сценарии она по умолчанию ищет файлы на /boot разделе SD-карты, необходимые для инициализации компонентов. В этом смысле ее можно сравнить с BIOS без графического интерфейса. Для изменения настроек и сценария загрузки (BOOT_ORDER) нужно полностью обновить файл загрузчика с применением опций из текстового файла и заново записать его в микросхему.
  2. Директория загрузки (/boot). По умолчанию загрузчик из EEPROM обращается к первому разделу SD-карты, где располагаются необходимые файлы для дальнейшей загрузки. Прежде всего это файл прошивки (firmware) для GPU, DTB-файлы (описание дерева устройств) и образ ядра kernel.img, из которого загружается операционная система. В установленной и загруженной системе этот раздел монтируется в /boot. Изменение опции BOOT_ORDER по сути меняет только устройство, с которого загрузчик ожидает получить файлы, но не их список.

Да, процесс сильно отличается. И это вызывает много вопросов о его интеграции в существующую схему. Но будем разбираться последовательно.

Обновление EEPROM

Для обновления EEPROM нам нужна предустановленная система с утилитой vcgencmd. Получить ее мы можем, загрузив образ Raspberry Pi OS и раскатав его напрямую на SD-карту.

Возвращаем SD-карту обратно в «малинку» и загружаемся с нее в операционную систему. Для входа по умолчанию используются логин и пароль pi / raspberry.

Здесь можно посмотреть текущие опции прошивки EEPROM:

Генерируем из файла прошивки файл конфигурации:

В файле bootconf.txt необходимо изменить значение BOOT_ORDER для изменения порядка загрузки. Поскольку нас интересует загрузка по сети, сначала указываем загрузку по сети (2), затем — с SD-карты (1), и делать это нужно в цикле (f). Также можно указать максимальное количество попыток загрузки по сети:

После подготовки bootconf.txt нужно применить настройки из него к файлу прошивки:

В конце записываем новый файл прошивки с нужными нам опциями в EEPROM:

Мы в Selectel любим одноплатники, так что собрали для вас еще подборку интересных статей на эту тему:

Загрузка «малинки» в PXE

После перезагрузки мы видим на экране монитора, что сервер начинает грузиться по сети. Одноплатник успешно получает адрес у DHCP-сервера и начинает запрашивать файлы с TFTP-сервера. Ошибка загрузки! Ведь мы еще не подготовили замену /boot директории на TFTP-сервере.

Для этого достаточно скопировать содержимое из директории /boot в установленной Raspberry Pi OS на удаленный TFTP-сервер. Например:

После такой подготовки «малинка» успешно начнет загрузку по сети, получит по TFTP-протоколу запрошенные файлы и загрузится в уже установленную систему.

Остановитесь для оценки происходящего: используя логи TFTP-сервера, внимательно просмотрите список файлов, которые «малинка» запрашивает по сети. Для лучшего понимания будем сверяться с документацией, поясняя только для минимально необходимого набора файлов.

По первой строке можно заметить, что файлы начинают запрашиваться с префиксом, соответствующим серийному номеру платы. Если такая директория отсутствует, все остальные файлы запрашиваются из корня.

start4.elf и fixup4.dat — блоб и линкер, необходимые для инициализации видеоядра, так как GPU инициализируется еще до CPU.

сonfig.txt — файл с пользовательскими параметрами, влияющими на поведение прошивки EEPROM и инициализацию железа. Если проводить аналогию между eeprom и bios, в файле хранятся все настройки, измененные пользователем через графическое меню. Активные значения можно посмотреть через утилиту vcgencmd.

bcm2711-rpi-4-b.dtb — базовый файл, описывающий дерево устройств (device tree binary) на плате. Вообще тема DTB-файлов (и DTBO из папки overlays/) достойна отдельной статьи. В нашем контексте ограничимся, что это дерево впоследствии передается ядру Linux.

kernel8.img и cmdline.txt — ядро Linux, с которого начинается загрузка операционной системы. Через файл cmdline.txt передаются дополнительные параметры ядра.

В нашем случае, когда мы скопировали директорию /boot из установленной ОС, мы скопировали и файл cmdline.txt. Если просмотреть его содержимое, становится понятно почему, загружаясь по сети, мы попадали в установленную на SD-карту операционную систему.

Опция root, которая указывает на корневую файловую систему, ведет на второй раздел SD-карты с ранее установленной Raspberry Pi OS.

Итоги и дальнейшие планы

Мы разобрались, как именно происходит загрузка по сети у Raspberry Pi 4. Осталось придумать, что в описанной схеме заменит загрузчик iPXE, через который мы управляем загрузкой сервера.

Стоп. А так ли нужно искать замену iPXE? Может, каким-то образом загрузить «малинку» сразу в iPXE?

Получилось ли у нас реализовать задуманное, я расскажу в следующей статье. А пока подписывайтесь на наш блог, чтобы не пропустить продолжение.

Источник

Adblock
detector