Часть 4: линукс, компиляция и платяной шкаф

В сегодняшнем эпизоде — финал марлезонского балета. Собираем и запускаем unikernel в его природной среде — на выделенной VM. Напомню, исходники нашего юникернела лежат здесь.

Как мы уже узнали, mirage предполагает написание юникернела в максимально hardware-agnostic стиле — мы используем абстрактные интерфейсы (на окамлевом наречии — сигнатуры) модулей, работающих с аппаратурой (например, таймер для задержек — это уже аппаратура, консоль — аппаратура, и т.п.) Генератор «сборочного» кода обвязывает наше творение ссылками на реальные драйверы и библиотеки в зависимости от таргета, указанного в команде mirage configure. Мы запускали конфигуратор на макоси без ключа -t, следовательно таргет по умолчанию установился в macosx, и мы получили на выходе макосёвый cli-бинарник, который запустили прямо в консоли:

Для запуска в собственной VM нам понадобится бинарник, собранный для прямой загрузки в требуемом гипервизоре. С рождения и до недавнего времени MirageOS работала только под Xen (unix-пробники не в счёт), пока наконец в свежем релизе 3.0 многомудрый Dan Williams из IBM Research не добавил «в коробку» библиотеку-загрузчик Solo5. Компиляция с этой штуковиной позволяет получить образ, который будет запускаться под популярными гипервизорами KVM/QEMU и подсистемой virtio.

У сборки под гипервизоры есть одна существенная особенность: её можно сделать только на Linux. Почему так, я разбираться не стал, а вспомнил, что у меня есть Шкаф (тм), мой персональный homelab для опытов. Вот такой:

Краткий экскурс, справа налево: Synology NAS (там NFS для домашнего «облака»), Intel NUC (на нём Proxmox VE с KVM-виртуалками — само «облако» — там я буду гонять сборку), далее провода и парочка модных RaspberryPI для опытов с Docker/Swarm (они гламурные, но это отдельная сказка).

Для нашего эксперимента я сделал в проксмоксе VM с бубунтой 16.04 LTS.

Если нет проксмокса, не беда — его легко заменит VirtualBox. Итак, когда «сервачок» установится и поднимется, логинимся в него, ставим инструменты и качаем исходник юникернела:

UPD: дополнительно надо поставить lwt (opam install -y lwt), скриншот опускаю.

Для пущей красивости рекомендую отчекаутить ветку multiple-loops. Я немножко усложнил алгоритм, добавив реальной «многозадачности» — пять тредов с логами будут идти параллельно, что будет видно в консоли. Текущий текст примера таков:

Сравнивая с предыдущим примером, отмечу «разности». Создаётся список из пяти «длительностей» (стр. 2), по которому генерируется список применений функции loop (стр. 13), который в качестве аргумента передаётся функции Lwt.join. Использован «пайплайн-синтакс» с оператором |> (apply) для большей иллюстративности — результат одной функции передаётся на вход другой — совсем как в shell-pipelines типа cat a.txt | grep foo | less. Примитив join, приняв список тредов, стартует их одновременно и завершается только с завершением самого долгого треда в списке. То, что нам и надо, чтобы почти полтора часа наслаждаться приветами на консоли юникернела.

Итак, собираем бинарник:

Теперь начинаем запускать. сначала локально, в «коробочном» эмуляторе виртуалки Solo5, наблюдаем, как грузится и работает:

В принципе, это уже вполне себе исполнение в собственной виртуалке. Но мы же собирались играть в прям-совсем-почти-настоящий запуск. Поэтому продолжаем процесс. Создаём имидж диска для загрузки отдельной VM:

По умолчанию solo5-mkimage готовит образ размером в гиг. Если нужно меньше, надо найти этот скрипт и ручками исправить в нём переменную SIZE. Думаю, в будущем авторы поправят этот хардкод. Теперь я скачаю имидж на локальную машину, отлогинюсь «со шкафа» и продолжу игру с VirtualBox.

Скачав hello.img в локальную директорию, необходимо превратить его в образ, подходящий для подключения к виртуалбоксу:

Создаём машину:

Далее интересно: повторяя природу доброго старого стандарта UNIX, юникернел в качестве консоли использует последовательное устройство, то есть, ком-порт — его мы сэмулируем текстовым файлом. Занятно, что о видеоустройствах, даже в виде текстовой консоли на виртуальной видеокарте, юникернел ничего не знает! Это можно воспринимать как добровольный аскетизм. В типичном случае для запуска программы нам нужна минимальная конфигурации VM, и растрата ресурсов на поддержание виртуальных видеорежимов — непозволительная роскошь.

Теперь у нас всё готово для запуска. Стартуем, наблюдаем вывод:

Мои поздравления: мы построили и запустили простенький, но работающий unikernel на MirageOS! Лишний раз замечу, что мираж — не только академический и девелоперский проект, давший OCaml-сообществу и не только целую кучу разных и разнообразных компонентов и библиотек, но и рабочая, испытанная в бою платформа для создания микросервисов от слова «микро», а не от «возьмём кусочек линукса размером с увесистый сервер конца девяностых» :).

--

--