Привет, Хабр! Меня зовут Лев Евсеенко, я работаю системным администратором в Selectel, сопровождаю сервисы наших выделенных серверов. В декабре мы пополнили линейку конфигом Ampere Altra Max M128-30 (3 ГГц, 128 ядер) с ARM-процессором внутри.
Перед введением в «эксплуатацию» нужно было разобраться с сетевой загрузкой, модифицировать служебный дистрибутив, адаптировать существующие процессы автоустановки ПО под новую архитектуру. В тексте расскажу, с какими проблемами мы столкнулись и какие решения нашли.
Вы можете подробнее почитать о том, зачем мы добавили ARM-серверы в линейку, а еще посмотреть на результаты бенчмарков тестовой платформы на Ampere Altra Q80-30 в классной статье от моего коллеги.
Если коротко, они хорошо показывают себя в многопоточных задачах и при этом намного энергоэффективнее процессоров от AMD и Intel. Основные задачи, которые решали клиенты во время тестов Ampere Altra, — работа с СУБД, запуск высоконагруженных веб-сервисов, разработка мобильных приложений и embedded-разработка.
На первый взгляд, новые серверы мало чем отличаются от решений на архитектуре x86_64. Тем не менее, для их полноценной поддержки нужно было решить несколько проблем:
- разобраться с сетевой загрузкой,
- модифицировать служебный дистрибутив,
- адаптировать существующие процессы автоустановки ОС под новую архитектуру.
Сетевая загрузка, или часть, в которой все идет по плану
Это была самая простая часть процесса, где все работало именно так, как ожидалось.
Автоматизируем сборку и деплой PXE-клиента
Мы используем модифицированный iPXE (небольшие изменения во время сборки, чтобы DHCP-сервер мог опознать PXE-клиент), который уже поддерживает arm64. Единственной проблемой стала сборка бинарного файла для arm64 на x86_64 GitLab-worker с помощью кросс-компиляции. Для сборки используется стандартный Docker-контейнер linux/amd64 ubuntu:20.04, Dockerfile:
FROM ubuntu:20.04
LABEL name="ipxe-builder-aarch64" \
description="Image to build ipxe binary files" \
version="1.0.1"
# Install all necessary packages for compiling the iPXE binary files
RUN apt update && apt install -y git gcc gcc-aarch64-linux-gnu make curl
Сборка выполняется из мастера iPXE GitHub следующей командой:
make CROSS=aarch64-linux-gnu- ARCH=arm64 bin-aarch64-efi/ipxe.efi EMBED=universal.ipxe
, где universal.ipxe — встраиваемый скрипт, который обрабатывает проблемы с сетью и работает со ссылками на загрузочные скрипты, которые генерирует наш бэкенд. На выходе получаем готовый arm64-binary, который деплоится на наши TFTP-серверы.
Убеждаемся, что DHCP-сервер отдаст ссылку на нужную сборку iPXE, в зависимости от архитектуры
Мы определяем архитектуру и/или режим загрузки (Legacy/UEFI) сервера с помощью опции 60 DHCP — Vendor class identifier:
DHCP DISCOVER от ARM64-EFI сервера.
DHCP DISCOVER от x86_64-EFI сервера.
Смотрим на часть PXE Client:Arch:00011, значения соответствуют RFC4578:
0 | Standard PC BIOS |
---|---|
6 | 32-bit x86 EFI |
7 | 64-bit x86 EFI |
9 | 64-bit x86 EFI (obsolete) |
10 | 32-bit ARM EFI |
11 | 64-bit ARM EFI |
В зависимости от этого значения DHCP-сервер возвращает имя необходимого файла в DHCP Option 67 — Bootfile name.
После iPXE проходит по одноразовой ссылке и получает сгенерированный загрузочный скрипт. В зависимости от содержимого скрипта сервер либо загружается с диска, либо запускает переустановку ОС, либо загружается в дистрибутив для восстановления.
Arch Linux для ARM, или грустный рассказ о неверных эстимейтах
Поскольку мы сдаем выделенные серверы в аренду и стараемся делать это очень быстро, мы автоматизируем многие процессы. Например, запуск операций зачистки дисков при завершении аренды сервера, проведение промежуточных тестов при завершении аренды и приемочных тестов после сборки сервера. Для всего этого мы используем кастомную сборку Arch Linux — внутри компании мы называем этот дистрибутив rescue. Помимо прочего, он используется для диагностики серверов и аварийных работ с ними.
Нам нужно было состыковать Arch Linux с ARM-процессором. Изначально никаких подводных камней не ожидалось: есть проект Arch Linux for ARM, на GitHub есть проект archiso-aarch64 – mkarchiso, адаптированный под aarch64. Казалось бы, собираем все вместе, заменяем архитектуру в существующих пайплайнах по сборке и деплою образа — готово. Мы оценили задачу примерно в 2 недели. Именно в этот момент все пошло не так.
Разумеется, такая потрясающая подготовка не могла не выйти боком: мы столкнулись сразу с пачкой проблем.
Проблема со сборкой артефактов для загрузки сервера в режиме UEFI
Разработчик archiso-aarch64 просто продублировал большинство классов, поменяв значения переменных на необходимые для архитектуры aarch64. Нам пришлось немного модифицировать сборочные скрипты archiso-aarch64. Модификация только одна: был изменен класс, который используется при сборке образа под legacy-режим загрузки. Дело в том, что тестируемые нами серверы с процессорами ARM работают только в UEFI, но при этом в оригинальных скриптах артефакты загрузки (vmlinuz и initramfs) собираются только в legacy-части скриптов.
В итоге в часть, ответственную за сборку UEFI-артефактов, был импортирован класс, ответственный за упаковку ядра и initramfs. В строку 622 мы добавили:
_run_once _make_boot_on_iso9660
Это позволило нам получить необходимые артефакты для сетевой загрузки.
Не поддерживалась кросс-архитектурная сборка образа
При сборке образа используется chroot, который ломается во время «добавления» пакетов «внутрь» образа.
Тут мы решили попробовать проект archboot, который обещал поддержку кросс-архитектурной сборки, но процесс интеграции наших инструментов сильно затягивался. Кроме того, в образе слишком много лишнего — например, графическая оболочка, доступ через VNC, огромная куча хуков mkinitcpio, с которой было решительно некогда разбираться. Из-за этого вернулись к использованию archiso-aarch64.
Мы пробовали собирать образ в эмулированной через QEMU виртуальной машине, но процесс занимал больше часа. Проблему со сборкой решили заведением GitLab-runners на Raspberry Pi 4. Наши раннеры для сборки x86-образа запущены на хостах облачной платформы Selectel, в то время как раннеры для этого проекта запускаются на физических RPi4, которые находятся в служебной стойке в одном из наших дата-центров.
Ранее мы писали, как внедряли серверы на «малинках» в дата-центры. Подробно описали каждый этап. Все тексты — в одной подборке.
В качестве executor в GitLab-runner используется Docker. Это сильно отличается от сборки x86-образа, где используется libvirt и QEMU. Дело в том, что последняя работает пока крайне медленно в режиме эмуляции aarch64, да и использование более простого в настройке исполнителя приветствуется. Dockerfile:
FROM agners/archlinuxarm-arm64v8
WORKDIR /archlinux
RUN mkdir -p /archlinux/rootfs
COPY pacstrap-docker /archlinux/
RUN ./pacstrap-docker /archlinux/rootfs \
bash sed gzip pacman
# Remove current pacman database, likely outdated very soon
RUN rm rootfs/var/lib/pacman/sync/*
FROM scratch
COPY --from=0 /archlinux/rootfs/ /
COPY rootfs/ /
ENV LANG=en_US.UTF-8
RUN locale-gen
RUN pacman-key --init
# Currently command crashes. Use key below for package sign
#RUN pacman-key --populate archlinuxarm
RUN pacman-key --recv-keys 68B3537F39A313B3E574D06777193F152BDBE6A6 && pacman-key --lsign-key 68B3537F39A313B3E574D06777193F152BDBE6A6
# Original image outdated, upgrade needed
RUN pacman -Syyu --noconfirm
# mkarchiso dependencies
RUN pacman -Sy --noconfirm arch-install-scripts awk dosfstools e2fsprogs erofs-utils findutils gzip libarchive libisoburn mtools openssl sed squashfs-tools
CMD ["/usr/bin/bash"]
Сборка выполняется стандартной командой ./mkarchiso -v -o $OUTDIR -w $WORKDIR -m $MODE $PROFILE
Недостаток готовых бинарных пакетов в репозиториях
Наш служебный образ достаточно сильно кастомизирован: начиная от вшитых ключей авторизации моих коллег — системных инженеров и сотрудников техподдержки, заканчивая кастомными загрузочными хуками по настройке сети и собственными скриптами и утилитами.
Первым делом нам пришлось сильно переработать список пакетов для установки в дистрибутив. Огромное количество ПО просто не существует в репозиториях, да и сам репозиторий Arch Linux, хоть и поддерживается некоторыми мейнтейнерами, — является скорее неофициальным.
Достаточно много пакетов — stress-ng, утилиты для прошивки материнских плат, SSD и NIC — мы собираем сами. Некоторые из них поставляются в виде бинарных файлов только под архитектуру x86_64. Из-за этого нам пришлось переписать скрипт автотестов, а также временно отказаться от некоторых используемых фич для архитектуры arm64. Например, автоматической прошивки материнских плат и периферии, а также автоматической настройки BMC.
Коротко об автотестах при передаче сервера клиенту
После сборки платформы, а также при передаче сервера новому клиенту мы проводим ряд автотестов.
После сборки сервера он должен пройти тест комплектующих. Проверяем, что CPU, RAM, GPU и блочные устройства корректно определяются, их характеристики соответствуют заявленным. Также проверяем SMART-параметры блочных устройств и убеждаемся, что их скорость чтения соответствует классу устройства. Для проверки SMART используем самописную утилиту на Python в сочетании с базой данных граничных значений. Выход за пределы значений вызывает автоматический вывод сервера из эксплуатации и его передачу на диагностику.
Дальше стресс-тест. В течение двух часов нагружаем CPU, RAM, GPU и смотрим, чтобы не было ошибок и троттлинга. Для стресс-тестов мы используем утилиту stress-ng.
Завершают цикл приемочные тесты (перед передачей сервера новому клиенту). Здесь также проверяем комплектацию сервера и SMART-параметры дисков.
Еще немного граблей, на которые мы наступили
Отсутствие логов
Эта проблема сильно осложнила дебаг rescue и тесты автоустановки. Вместо логов на экране отображалась очень симпатичная заставка с пингвинами — вроде такой, только пингвинов побольше:
Параметры ядра вроде debug и loglevel=7 не помогали. Через какое-то время мы догадались, в чем проблема, и решили ее добавлением параметра ядра console=tty0.
Проблема с тестами автоустановки Ubuntu 22.04
Вторая проблема была связана с тестами автоустановки Ubuntu 22.04. Нужно было быстро проверить, что сетевая установка будет работать. Но, поскольку Ubuntu перешел с использования debian-installer к subiquity, legacy-installer больше недоступен.
Мы попытались обмануть систему, вытащив необходимые файлы из установочного образа, и встретились с интересной проблемой — iPXE зависало при попытке загрузить initramfs. Оказалось, что initrd сжат с использованием Zstandart, который iPXE, судя по всему, не поддерживает. Примечательно, что версия для x86_64 не использует Zstandart.
Вывод file для initrd subiquity Ubuntu 22.04 amd64:
initrd: ASCII cpio archive (SVR4 with no CRC)
Вывод file для initrd subiquity Ubuntu 22.04 arm64:
initrd: Zstandard compressed data (v0.8+), Dictionary ID: None
Позже мы выяснили несколько вещей:
- установщику в любом случае необходимо выкачивать весь ISO для корректной работы,
- файлы preseed больше не поддерживаются, и необходимо использовать cloud-init/autoinstall.
В общем, без переписывания шаблонов не обойтись. Сейчас мы как раз модернизируем процесс автоустановки ОС, чтобы клиенты могли получить готовый к работе сервер с предустановленной Ubuntu 22.04 в течение нескольких минут.
Плавающие проблемы с дисками
Эти проблемы всплывали во время динамической разметки дисков, их объединения в программные рейды и добавления в LVM в установщике Ubuntu 20.04. В некоторых случаях установщик пытался создать лишние рейды, либо не мог очистить метаданные LVM. Мы не продолжили анализ проблемы, так как она будет решена вместе с модернизацией системы автоустановки.
Заключение
На первый взгляд, работа с серверами на архитектуре arm64 практически не отличается от x86_64-аналогов. Но чем глубже погружаешься, тем больше открывается нюансов.
Задача была интересна еще и тем, что из-за небольшого количества информации все решения принимались через практические эксперименты. Мы продолжаем работу над серверами с ARM-архитектурой и обязательно расскажем об этом в следующих материалах.
Был ли у вас опыт работы с ARM-процессорами? Делитесь в комментариях!
Возможно, эти тексты тоже вас заинтересуют:
→ SD – это Linux, а Midjourney – Mac: краткое полное руководство по Stable Diffusion
→ Подборка материалов для погружения в Angular: выбор сотрудников Selectel
→ Геймерские материнские платы, жесткие диски и раритетный синтезатор: новые находки на испанской барахолке
Комментарии (19)
MinimumLaw
02.02.2023 15:35+8Ура, датацентры начали понимать боль embedder'ов. И уж поверьте - сетевая загрузка, логгирование и прочее - это ерунда. А вот зоопарк видеосистем, media-систем, power-management'ов и прочего (имя им легион - включая самые разные пенки в (u)EFI, включая полное отсутствие оного) - во это да...
Жить с aarch64 можно, но... Или лезть глубоко и не иметь никаких гарантий повторяемости достигнутого результата на другой платформе, или... замыкаться на одном вендоре и надеяться на его вечную молодость и конкурентоспособность. А равно на его умение держать обещания. Увы, но пока все довольно грустно.
CodeRush
03.02.2023 01:16+4Именно поэтому особенно забавно смотреть на попытки некоторых удивительных людей саботировать внедрение UEFI и ACPI на большие aarch64-машины, под предлогом того, что "нам этого переусложненного хлама тут не надо, мы отлично справляемся с нашими Device Tree и трехстадийными патченными-перепатченными загрузчиками такого же патченного-перепатченного ядра линукса".
Замечательно справляетесь, пацаны, продолжайте. /s
MinimumLaw
03.02.2023 13:11+2А тут вопрос сильно сложнее...
В целом, я абсолютно согласен. Есть такой момент. Тем более, что для EBBR многого и не надо. Да и не запрещает он использовать device-tree. Потому как ACPI штука хорошая, но... не родная что-ли. Если б все выполняли требования данного документа (в мире встраиваемых систем) или его аналога для остальных - жизнь была бы сильно более простой.
С другой стороны - у меня на столе TCL Book 14 Go - как думаете что там с ACPI? Можно ли его нормально загрузить без dtb'irb (которую еще надо как-то сделать)? Так вот - со всей ответственностью - нельзя. И тут ситуация как и на x86 - гора платформенно зависимых патчей. С другой стороны вопрос заводки того же Linux на этой машине - это выкладывание DTS'ки производителем. И, честно скажу, на месте производителя я бы сильно задумался что проще - сделать DTS или исправить косяки в DSDT.
Но повторюсь - в идеальном мире правильная ACPI везде было бы лучшим решением. К сожалению это не получилось даже на x86/x64, потому и на ARM64 к этой штуке есть много вопросов...
CodeRush
03.02.2023 19:52+3Ну я тут иронизирую не по поводу Device Tree конкретно, потому что с ними как раз нет особых проблем (а еще потому, что у меня самого рыло в пуху по самый хвост, и на больших aarch64-машинах, к которым я уже несколько лет прикладываю руку, никаких UEFI и ACPI нет, зато без Device Tree они не грузятся дальше iBoot-та первой стадии), а именно по поводу позиции "к черту вашу сложную гадость, у нас тут все хорошо".
Настолько хорошо, что сама arm буквально запрещает использовать Device Tree на системах, реализующих Server Base Boot Requirements:
Systems using SBBR recipe must meet the requirements that are specified in section 5 (PSCI/SMCCC), section 6 (Secondary Core Boot), section 7 (UEFI), section 8 (ACPI), and section 9 (SMBIOS).
Хорошо это или плохо - очень дискуссионный вопрос, но на мой взгляд, скорее хорошо. Безобразно, зато единообразно, бери любой дистрибутив любой популярной ОС и ставь его прямо из ISO-образа, а не вот это все.
MinimumLaw
04.02.2023 10:53+2Как по мне, так надо просто различать миры Server, Consumer и Embedded. Первые два просто обязаны грузиться единообразно, и, в идеале, унифицировано с привычной уже архитектурой x86/amd64. Т.е. UEFI, т.е. ACPI, т.е. SecureBoot. У них не меняется состав системы и им не надо оперативно вносить серьезные правки в DSTD. Они по сути законченное техническое решение, у которого шины позволяют динамическое изменение конфигурации. И уже не так важно на горячую или с остановкой.
А вот со встраиваемыми... Тут точно без DTS не обойтись. По той простой причине, что довольно распространенная ситуация выглядит так - процессор на модуле (и базовая DTS с PMIC, внешними шинами, GPIO). Далее модуль на базовой плате (и довесок к DTS в виде кнопок, датчиков, исполнителей, источников и прочего). Базовая плата в изделии разных модификаций под разные нужды - а значит опять с разными дополнительными кусками в DTS. Которая может лежать тупо на накопителе и быть разной для разных итоговых изделий. С ACPI и ее DSDT такое сделать сильно сложнее.
А вот зоопарк загрузчиков... Вот это да... У меня одна плата работает только с патченым-перепатченым U-Boot аж от 2017-ого года. При том, что вроде последний ванильный для нее даже собирается, но... В нашем мире собирается и работает - это две большие разницы. А уж работает полнофункционально - это вообще третье.
В целом DenX молодцы. У них есть код, который позволяет соответствовать EBBR, но дьявол как всегда в деталях. В частности крайне плохо решается вопрос с efi-vars. Единственное сколько-нить серьезное решение - это хранение их в файле на ESP разделе, но... Я уже вижу как вы улыбаетесь.
Так что как обычно - все сильно зависит от вендоров. А они друг с другом договариваться ой как не любят. С другой стороны может оно и к лучшему - без работы я точно не останусь.
v1000
02.02.2023 19:29Убунта в свое время неприятно “порадовала”, когда после очередного обновления версии оказалось, что перестал поддерживаться старый встроенный видеоадаптер. Причем это стало понятно через несколько версий, потому как доступ к серверу был через Путти и веб интерфэйс. А когда сервер пришлось настраивать напрямую оказалось что вместо текста на экране каша из символов. Так что там не только новые архитектуры могут глючить, но и старые.
speshuric
02.02.2023 22:50+2Для всего этого мы использует кастомную сборку Arch Linux — внутри компании мы называем этот дистрибутив rescue.
Как пользователь Arch Linux хочу спросить: почему для этого вы используете именно Arch?
evseenkolev Автор
03.02.2023 13:29+3Есть несколько причин - нам нужно максимально свежее ядро для поддержки нового железа, относительно просто модифицировать образ для наших потребностей, отсутствие лишних пакетов. Ну и самая главная - так исторически сложилось :)
speshuric
03.02.2023 14:59нам нужно максимально свежее ядро для поддержки нового железа
Т. е. достаточно часто образ обновляете? А с какой примерно периодичностью?То, что просто модифицировать образ, особенно с нестандартными хотелками, кстати, полностью согласен.
evseenkolev Автор
03.02.2023 15:41+1Т. е. достаточно часто образ обновляете? А с какой примерно периодичностью?
Обычно раз в месяц-полтора. "Просто так" обычно не обновляем - чаще всего пересобираем в связи с расширением функциональности.
kmosolov
03.02.2023 12:45Вопрос несколько не по теме, но: может подскажет кто где можно приобрести arm64 сервер в РФ (или с доставкой в РФ)?
Очень хочется «пощупать» это железо и протестировать работу нашего софта на нём, а мощностей малинки будет маловато (особенно по части оперативной памяти), есть конечно вариант сделать кластер из малинок, но очень не хочется заморачиваться таким.
dlinyj
Проделана потрясающая работа, снимаю шляпу! Круто, что внедряете новые архитектуры.
Подскажите, а есть ли возможность арендовать сервер с ARM процессором у вас?
lodz
Спасибо! :)
Да, есть возможность арендовать сервер фиксированной конфигурации. Либо протестировать ARM-процессор в сборке бесплатно — в нашей лаборатории Selectel Lab (единственное — там есть очередь на тест).
dlinyj
Спасибо, оставил заявку, очень интересно!
Rinsewind
Будут ли мелкие виртуалки на ARM? Буквально на одно ядро
speshuric
Анекдот.
Интревью с Ф. Бондарчуком:
-- Скажите, Федор, как Вам фильм "Пираты карибского моря 4"?
-- О, это замечательный фильм! Отличная режиссерская работа! Я снимаю шляпу!
-- Федор, мы знаем, что Вы снимаете! Расскажите, как Вам фильм?
(не про вас, это просто вспомнил, прочитав комментарий)
dlinyj
Хороший анекдот :)