Ханнес Менерт о MirageOS, OCaml и функциональном программировании
Введение
Наш бэкэнд-разработчик Павел Аргентов съездил в Марракеш, Марокко, чтобы принять участие в девятом «MirageOS Retreat», который прошёл с 13 по 19 марта 2020 года. Цель этих встреч — собрать вместе опытных и начинающих пользователей MirageOS для совместной работы над синхронизацией различных существующих дочерних проектов MirageOS, запуска новых и помощи друг другу в исправлении багов.
MirageOS — это операционная система-библиотека, которая используется в разработке юникернелов — безопасных высокопроизводительных сетевых приложений, работающих на разнообразных облачных и мобильных платформах. Код пишется в Linux или Mac OS X, затем компилируется в полностью автономный специализированный юникернел, запускающийся под гипервизорами Xen или KVM.
Павел поговорил с Ханнесом Менертом, соавтором MirageOS и организатором мероприятия, о работе с MirageOS и OCaml. Ханнес рассказал о своем вкладе в MirageOS и о том, почему он присоединился к проекту. Он также объяснил преимущества функционального программирования, и что изначально привлекло его к этой технологии. Кроме того, он рассказал о потенциале и ограничениях MirageOS и OCaml и поделился информацией о новых и будущих разработках.
Интервью
Павел: Думаю, нам стоит начать с разговора об OCaml. Как и почему ты начал работать с OCaml?
Ханнес: Шесть лет назад, когда я только-только закончил свою докторскую диссертацию по формальной верификации программ, моим обычным занятием было взять какое-нибудь уже разработанное программное обеспечение, применить к нему некоторые спецификации, а затем писать доказательства того, что программа действительно корректна. Это было довольно сложным и трудоёмким занятием из-за повсеместно использования shared mutable state. В течение достаточно долгого времени я серьёзно интересовался системным программированием, что обычно означает использование С и написание кода операционной системы на нём. Однако, учитывая мой опыт в семантике, я очень надеялся использовать для написания операционных систем высокоуровневый язык. Тогда, после получения докторской степени, я вместе с моим коллегой Дэвидом Калопером и наткнулся на MirageOS.
MirageOS написана на OCaml, мультипарадигмальном языке с развитой системой модулей, который используется для функционального программирования. Это означает, что можно избегать использования shared mutable state и фактически верифицировать программы, в том числе в контексте операционных систем. Когда я пришел в MirageOS около шести лет назад, она уже была в некоторой степени рабочей, и моим первым вкладом стали стек TLS и криптографические алгоритмы.
Павел: Как используется MirageOS, что мы можем от неё получить?
Ханнес: MirageOS начиналась как исследовательский проект. У нас был прототип и идея о том, как использовать разные стили программирования для разработки ОС. Я обладаю довольно серьёзной подготовкой в области безопасности, что стало моей основной мотивацией для участия в доработке MirageOS и попытках запустить её в продакшн. С позиции безопасности, в ней меньше mutable state, и, к тому же, можно запускать HTTPS-приложения или веб-серверы с TLS. Здесь гораздо меньше кода, что означает меньше ошибок и меньшую ресурсоёмкость. Потому что, если не нужно запускать лишний код, не истратится лишних циклов CPU и лишней памяти.
Павел: Давай поговорим о TLS. Частенько можно упереться в ограничения аппаратуры, и всё станет тормозить, потому что криптоалгоритмы медленные. Как OCaml решает эту проблему, и решает ли проблему скорости вообще? Позволяет ли OCaml писать быстрый код?
Ханнес: Да, у самого OCaml довольно быстрый рантайм. Есть сборщик мусора (он же менеджер памяти), который работает очень быстро. Основной вопрос заключается в том, позволяет ли OCaml написать достойный интерфейс, чтобы правильно передать аргументы и не тратить слишком много процессорного времени. Оказывается, позволяет, и достаточно быстро. Я рад, что можно использовать разумный язык программирования вместо низкоуровневого макроассемблера.
Другая сторона TLS — это хендшейки. Это асимметричная криптография, и для ускорения мы используем библиотеку GMP — GNU Multi-Precision Library. В OCaml у нас есть для неё биндинги, но это исключение. Обычно мы стараемся не писать биндинги и не зависеть слишком сильно от C. Наиболее сложные части шифровки/расшифровки всё же написаны на OCaml, а не на C.
Павел: Программисты, работающие на Haskell и других высокоуровневых языках, обеспокоены производительностью сборщика мусора, имея в виду, что он всё тормозит. Хаскелисты по этой причине жалуются, что не могут писать приложений «мягкого реального времени». Как думаешь, OCaml может с этим справиться? Является ли сборщик мусора OCaml достаточно шустрым, чтобы справиться в тех местах, где нужна именно скорость?
Ханнес: Думаю, что да. У Haskell рантайм совершенно другой, по умолчанию в нём работают ленивые вычисления. OCaml работает по строгой модели, мы просто совершаем вычисления по ходу кода. Сборщик мусора очень хорошо настроен для рабочих нагрузок, он действительно быстрый, и я считаю, что в OCaml приложения «мягкого реального времени» реализуемы.
Павел: Насколько я знаю, понятие «unikernel» больше не является уникальным для OCaml. Какова была история юникернелов? Было ли название идеи другим, когда всё начиналось? Как люди вообще пришли к идее юникернела?
Ханнес: Я думаю, всё началось в Кембриджском университете, с теоретических статей о так называемом Exokernel. Людям был нужен инструмент, система, которая была бы сосредоточена на основной задаче, требовала меньше ресурсов, легко писалась и адаптировалась.
Павел: Окей. Насколько я знаю, MirageOS использует библиотеку Lwt. Достаточно ли Lwt высокопроизводительна для выполнения серьёзной нагрузки, если, например, есть DNS-сервер, который должен быстро отвечать на пачку одновременных запросов? Достаточно ли шустро это работает?
Ханнес: Я думаю, что это работает приемлемо. Хорошим примером приложения для MirageOS является брандмауэр, который интегрирован в Qubes OS. Qubes OS — это операционная система, использующая Xen. Задача Qubes OS, например — отделить почтовое приложение от рендерера PDF. Тогда, если вы получите письмо с вредоносным PDF-файлом, во время просмотра он не сможет получить доступ ко всей вашей почте. Вместо этого вы сохраняете PDF-файл и отправляете его на другую виртуальную машину. И эта другая виртуальная машина содержит код для запуска рендерера PDF.
Итак, PDF открывается и отображается только в изолированном окружении. MirageOS довольно хорошо сюда вписывается, потому что у неё заметно меньшие требования к памяти. Мы можем просто настроить брандмауэр как один из компонентов внутри одной из виртуальных машин в среде Qubes OS и получать пакеты от других виртуальных машин, имеющих доступ к сети. MirageOS-юникернел работает как маршрутизатор, который пересылает пакеты.
Павел: Ты упомянул о том, как MirageOS потребляет память. Каков реальный размер памяти, которым она может оперировать? Каковы нижние или верхние пределы? Я слышал, что MirageOS нельзя настроить для объёмов памяти более 1 ГБ. Действительно ли есть такие ограничения?
Ханнес: Ну, на данный момент — да. Минимальный объем памяти, необходимый для рантайма OCaml и MirageOS-юникернела, составляет 10 мегабайт, а верхний предел на данный момент — 1 ГБ памяти. Но если нужно больше, это легко настроить. Мои службы DNS, например, требуют около 14-24 мегабайт памяти. Это не миллионы записей, скорее — сотни. Веб-сервисы, которые я запускаю, обычно занимают от 32 до 128 мегабайт. Этого достаточно для хранения данных.
Павел: Ты работал с хранилищем Irmin? Насколько мне известно, это что-то вроде Git, и это единственное хранилище данных, написанное на OCaml для MirageOS.
Ханнес: Да. Irmin — это древовидное иммутабельное хранилище. Обычно я использую Irmin не напрямую, а через Git-имплементацию, которая используется им «под капотом». Например, мой DNS-сервер хранит файл зоны в удаленном Git-репозитории, он просто фетчит файл оттуда, клонирует его в память и затем отдаёт эти данные. В 2019 году вышел мажорный релиз Irmin 2.0.
Павел: Давай теперь переключимся на формат нашего собрания. Не скажешь пару слов о том, что такое ретрит MirageOS? Как ты пришёл к этой идее?
Ханнес: Я вдохновлялся опытом различных конференций, а также хакатонов OpenBSD. Основная идея — собрать приятную тусовку. Вы находитесь в приятном месте, где приятная погода, еда, солнце, и можно по-настоящему насладиться обстановкой. Мне важно, чтобы люди оставались вместе весь день и общались. Здесь нет строгого графика. Ежедневно устраиваем «летучку»: кто что сделал, что кому интересно, кто застрял, на чём конкретно. Любой участник может подключиться и помочь. Одни начинают произвольно обсуждать проблемы и решения, другие просто заняты написанием кода.
С одной стороны, я пытаюсь привлечь завсегдатаев сообщества, у которых есть опыт и идеи на предмет различных библиотек и экосистемы, чтобы, находясь здесь, обсудить фундаментальные изменения. Но также я высоко оцениваю присутствие здесь новичков, новых идей и людей, которых мы можем оперативно интегрировать в группу и привлечь к программированию на OCaml и MirageOS — для развития сообщества. Ретрит не только для тех, кто уже знают MirageOS или писал на OCaml в течение скольких-то лет; он открыт для всех, кто готов отправиться в путешествие в Марракеш.
Павел: Здорово! Как думаешь, функциональное программирование влияет на мышление программиста? Когда я впервые стал писать на OCaml, я начал понимать, что существуют типы, которые можно преобразовать. Это заставляло думать в первую очередь о типах и смысле данных, с которыми я работаю. Я знаю, что функциональное программирование в Европе является частью обучения программированию на базовом уровне. Насколько мне известно, большинство студентов в России учатся программировать, начиная с императивных техник, и впоследствии почти никогда не от них не отходят.
Ханнес: Да. Я много думаю о типах и довольно тщательно их прорабатываю перед написанием реального кода. Поэтому, когда я пишу программы на функциональном языке, я в первую очередь думаю о том, как должны выглядеть типы. Как только появляются типы в правильной форме, вся имплементация становится намного проще. На мой взгляд, функционально программирование — это во многом про управление кодом и точное понимание логики программы. Я думаю, что гораздо легче понять собственный код пять лет спустя, если он написан на функциональном языке, и автор не злоупотреблял синтаксическим сахаром и фичами, чем этот же код, на императивном языке, в котором по сотне строк на функцию. Я стараюсь делать функции максимально короткими и понятными. Да, функциональное программирование адекватно формирует мозг для размышления о программе.
Павел: Я вижу, как монады прокладывают путь в разные языки. Они уже есть в Ruby и C++. Что это, способ применения академических знаний в повседневном программировании?
Ханнес: Я думаю, что это жизнеспособный инструмент, но его очень трудно понять, если не открыл монады сам для себя. Очень сложно объяснить монады новичку из императивного мира. Мы по-прежнему используем монады в MirageOS и OCaml, но, надеюсь, что когда (я думаю, уже в этом году) Multicore станет частью рантайма OCaml, мы сможем от них уйти.
Павел: Давай немного об open-source. Всё, о чем мы говорили до сих пор — это открытый исходный код. Существует точка зрения, что технология добивается успеха только тогда, когда в неё закачивается достаточно денег. Открытый исходный код забирает наши усилия и наше время, но как бы не приносит денег. Когда проповедуешь какую-то новую технологию в открытом сообществе, рано или доходишь до идеи коллаборации на основе открытого исходного кода. На твой взгляд, насколько важен открытый исходный код?
Ханнес: Я думаю, что открытый исходный код — это ключевой фактор. Большая часть того, что мы делаем, — это на самом деле разработка библиотек, библиотек OCaml, которые затем используются в юникернелах MirageOS. Каждый должен иметь возможность свободно смешивать и сочетать их. Когда я пишу стек TLS или реализацию DNS, у меня есть мощный стимул открывать исходный код, потому что тогда другие разработчики смогут его переиспользовать. Мне нравится писать программы, и меня радует, что ими кто-то пользуется, будь то частное лицо или компания, использующая их для получения прибыли. Меня это устраивает.
В MirageOS большая часть кода находится под лицензией BSD, поэтому каждый может им пользоваться и делать с ним всё, что пожелает. Думаю, что иметь лицензию очень важно. Каждый может понять GPL, но в ней тонны страниц текста, в то время как в BSD всего два или три абзаца, и обычно она занимает 25 строк текста. Если вы хотите убедить отрасль использовать что-то из вашего программного обеспечения, лучше использовать разрешительную лицензию. С таковой вам будет намного легче их привлечь, а если лицензия — GPL, убедить юристов, что это хорошая идея, несколько сложнее. Например, в MirageOS есть код от IBM Research, и нам удалось убедить их использовать разрешительную лицензию, что было непросто, потому что юристы обычно склонны придерживаться торговой марки.
Павел: Я читал, что ты работаешь в компании, которая зарабатывает на разработке юникернелов. Каково это — работать над технологией, которая не продает, скажем, устоявшееся, хорошо знакомое императивное программирование?
Ханнес: Я работаю в некоммерческой компании под названием Robur. Мы работаем на гранты, пожертвования и по коммерческим контрактам — над разработкой юникернелов и улучшением экосистемы MirageOS в целом.
За последний год мы получили часть финансирования из общественных источников. От Германии и Европейского Союза пришло несколько грантов на разработку ряда приложений, таких как OpenVPN Gateway, а в настоящее время мы получаем деньги от Евросоюза для работы над DNSmasq, который является одним из важнейших компонентов в сети каждого пользователя. И это замечательно.
Павел: Как скоро MirageOS развивается? Быстро ли появляются новые функции?
Ханнес: Развитие всегда довольно медленное, но всё же мы делаем довольно много работы. Мы стараемся избавиться от технического долга и адаптироваться к современным системам сборки, что иногда занимает больше времени, чем на других проектах. С точки зрения функционала, речь идет главным образом о разработке новых библиотек. Мы кратко коснулись Irmin DataStore: его релиз 2.0 стал важной вехой, но она была достигнута только в прошлом году. В скором времени ожидается стек TLS 1.3. Что касается MirageOS, сейчас мы движемся к версии 4.0, и она точно значительно улучшит процесс разработки: мы избавимся от старой «ocamlbuild» и заменим его новой системой сборки под названием «dune», которая, среди прочего, умеет в инкрементные сборки.
Павел: Я предлагаю завершить нашу беседу каким-нибудь ободряющим заявлением для разработчиков, которые захотели бы изучить MirageOS, взяться за OCaml и перестать бояться функционального программирования как теоретического пожирателя ума. Как бы ты их обнадёжил?
Ханнес: Благо ФП — это уровень контроля над довольно сложным кодом. В функциональном программировании, если обнаруживается ошибка где-то на верхнем уровне программы, её можно отследить до самого низкого уровня и исправить в течение одного уик-энда, тогда как сделать это в обычных операционных системах просто невозможно из-за размера и собственного кода, и используемых библиотек.
У вас есть контроль над всем стеком. Это и есть фулстек-разработка, от сетевой карты до бизнес-логики и запуска реального приложения.
Мы в Evrone стремимся быть в курсе новых технологических разработок и внедрять инновационные методы. Это позволяет нам использовать оптимальные инструменты для предоставления нашим клиентам наилучших решений, чтобы удовлетворить их индивидуальные потребности. Мы работаем с широким спектром языков программирования и инструментов, и мы всячески поощряем членов нашей команды принимать участие в технических конференциях и мероприятиях, таких как MirageOS Retreat. Если у вас есть идея, которую вы хотели бы воплотить, сообщите нам ваши контакты, и мы свяжемся с вами, чтобы обсудить ваш проект, и то, как мы можем помочь.