«Разработка ядра Linux — это общение в клубе по интересам»

Архитектор департамента серверной виртуализации Parallels Павел Емельянов дал интервью журналу «Системный администратор». Мы решили разместить у нас часть ответов, наиболее интересную сообществу «Типичного программиста». Немного о проекте CRIU, о том, как разработчики работают с Linux-сообществом и с Линусом Торвальдсом, и об изменениях, которые могут произойти в области виртуализации в ближайшие годы.

Расскажите, пожалуйста, чем вы занимаетесь в Parallels?

Я работаю над главным серверным продуктом Parallels под названием Cloud Server. Это специальным образом подготовленный для запуска виртуальных машин и контейнеров дистрибутив Linux, который аккуратно интегрирован с большим количеством дополнительных приложений от Parallels — управление кластером, распределенное хранилище, веб-панели и тому подобное. Продукт этот многокомпонентный, его составные части порой сами по себе являются очень сложными системами. Я занимаюсь тем, что проектирую многие из этих систем, главным образом связанные с ядром, их внутреннюю структуру, логику работы и взаимодействие друг с другом.

Кроме того, я организую процесс взаимодействия ядерной команды Parallels с сообществом разработчиков ядра Linux. Дело в том, что Parallels активно участвует в разработке подсистем контейнерной виртуализации в Linux, почти все наши специалисты что-то делают для ядра Линуса Торвальдса. Я за этой деятельностью слежу и пытаюсь направлять ее в нужное для компании русло.

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

Как возник проект CRIU? Что именно подтолкнуло к его созданию?

Проект возник как решение по интеграции контейнерного кода Parallels в ядро Linux. А сама интеграция — это тоже интересная история, которую я уже упомянул.
Спустя несколько лет после запуска проекта OpenVZ в Parallels поняли, что поддерживать все изменения, которые делались в ядре, своими силами будет очень тяжело.
Мы решили начать портировать наш контейнерный ядерный код на ядро Linux и отправлять эти изменения в сообщество с просьбой принять их к себе. Я тогда был просто разработчиком, и выбор «кто слать будет» пал на меня. Я начал портировать наш код на другое ядро, высылать эти изменения и разговаривать с людьми из сообщества на предмет принятия новой функциональности.

За пару лет нам удалось интегрировать примерно половину всей ядерной функциональности, которая была у Parallels, но вот код, который у нас занимался «живой миграцией» контейнеров, в ядро Linux не брали. Причем пытались не только мы, подобную функциональность хотели иметь и другие компании, но сообщество к единому решению «берем» никак не приходило. Тогда я решил попробовать сделать требуемую функциональность не в ядре, а в виде приложения, расширяя ядро по мере необходимости.

Первый прототип был написан примерно за три дня дома, пока я сидел на больничном. Я его выслал «на посмотреть» в сообщество. Люди посмотрели и… решили, что те небольшие изменения в ядре, которые мне понадобились, они берут (эти изменения через пару месяцев окончательно осели в ядре Linux).

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

Над какими проектами, связанными с ядром Linux, помимо CRIU, вы работаете? В каких проектах, не связанных с ядром Linux, принимаете участие?

Серьезно почти ни над какими и ни в каких. Того, что мне приходится делать в рамках OpenVZ, CRIU и нашей интеграции с ядром Linux, хватает с лихвой.

Вы упомянули проект OpenVZ. Расскажите, что это за проект? Какова степень вашего участия в нем?

С точки зрения софта, это ядро от Parallels + несколько утилит для его конфигурации, с помощью которых можно создавать и управлять Linux-контейнерами.
Кроме софта, это еще и такой (уже) бренд, с помощью которого Parallels заявляет о себе в мире Open Source. Вокруг проекта даже выросло средних размеров сообщество.
Степень моего участия в нем, судя по всему, немаленькая. Вскоре после того, как проект родился, меня «продвинули» с простого разработчика до лидера команды ядерщиков. И поскольку основное, что в то время было ценного в OpenVZ, — это ядро, то я де-факто стал еще и чем-то вроде технического лидера проекта. А еще через год стартовала упомянутая кампания по интеграции кода OpenVZ в ядро Linux, которая тоже проводилась под флагом OpenVZ и изначально легла на меня лично.

Сейчас ядро не является основной ценностью проекта (поскольку мы уже очень много интегрировали в ядро Linux, и, например, на Fedora 19 можно делать контейнеры без нашего ядра). Так что я вместе с менеджером проекта (Киром Колышкиным) занимаюсь тем, что придумываю, как можно двигать проект дальше, не «выезжая» на одном только ядре.
Одно из таких направлений — это, например, наш CRIU, который позиционируется как подпроект OpenVZ.

Какие возникли сложности в процессе интеграции кода OpenVZ в ядро Linux? С выхода какой версии ядра началась интеграция?

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

По-моему, это были пространства имен (namespaces) PID и SysVIPC. К 2.6.32, на котором у нас находилась следующая стабильная версия, были интегрированы сетевая виртуализация (net namespaces) и что-то еще.

Сложности возникли в том, что мне пришлось «на лету» осваивать совершенно иной способ разработки. Мы примерно представляли, как выглядит процесс интеграции патчей в ядро. Но, когда в ответ на мой первый набор патчей люди стали активно обсуждать, как это можно вообще переделать с нуля, или предлагать перед тем, как делать то, что я делал, сначала переписать добрый кусок подсистемы управления процессов, я даже растерялся.

Что нового в фундаментальном плане можно ожидать в ближайшие годы в области виртуализации?

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

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

С контейнерами произойдет такая же вещь, но на другом «фронте». Сейчас контейнеры можно использовать как оболочку и для отдельного процесса, приложения, и для целого образа операционной системы (без ядра). В будущем использование контейнеров для создания виртуальной операционной системы должно сойти на нет (эту нишу заполнят виртуальные машины). А использование контейнеров для «изоляции» сервисов, как локальных, так и облачных, должно стать невидимо присутствующим стандартом.

Как происходило становление разработчика ядра? Какие возникли сложности на первоначальном этапе?

Началось все, кажется, на четвертом курсе института. Я тогда работал над академической распределенной файловой системой, и мой научный руководитель сказал, что в Parallels (тогда компания еще называлась SWsoft) собрались делать из этой системы коммерческий проект, и отправил поговорить со своим аспирантом, чтобы присоединиться к ним. Аспирант этот работал в команде Linux kernel, со мной провели собеседование и взяли в команду со словами: «С этой файловой системой мы попозже разберемся, начни пока с ядра». В итоге до системы у Parallels руки так и не дошли, так что я остался ядерным разработчиком.

Настоящие сложности возникли, когда мне пришлось писать код не для того ядра, которое разрабатывалось внутри Parallels, а для основного, которое делает Линус Торвальдс, и связано это было с тем, что модели разработки кода в Parallels и в сообществе кардинально различались.

В Parallels это более-менее стандартная разработка коммерческого кода. Работа в сообществе — совершенно другой процесс. Главной его особенностью, с моей точки зрения, является то, что это… не совсем процесс разработки ПО. Это главным образом общение людей, которым интересно создать большую и сложную программу, а собственно разработка там на втором месте. Осознание этого факта и подстройка под него и явились главными трудностями.

Над какими подсистемами ядра работаете?
Практически над всеми, кроме драйверов. Это в каком-то смысле одна из проблем — не получается глубоко и основательно погрузиться ни в одну из систем, приходится постоянно следить за развитием всех. Есть, правда, «любимые» системы — для меня это сетевой код и подсистема управления памятью.

Как происходит процесс включения ваших патчей в ядро? Каковы особенности этого процесса? В чем заключаются сложности?

Процесс выглядит одинаково для всех. Сначала надо сделать сам патч или их серию, написать комментарии к каждому (это, кстати, отдельное мастерство). Потом патч высылается в список рассылки, в котором обсуждается нужная подсистема ядра. В «копию» ставятся человек, который поддерживает подсистему (его по-английски называют maintainer), и люди, которые в ней разбираются и могут помочь оценить качество работы. Потом надо немного подождать. Если все сделано хорошо и всем все нравится, maintainer патч забирает себе в свой репозиторий. Потом Линус включает накопленное у всех maintainer в свое дерево.

Это самый простой путь, но он может усложниться и затянуться. Если изменение большое и сложное или человек, который его сделал, неопытен, то после отправки патча в рассылку может начаться обсуждение. Люди, которые разбираются в соответствующем коде, могут найти ошибки в патче, могут сказать, что решение проблемы должно быть другим, или могут попросить сделать косметические правки, например, переименовать переменную или написать более подробный комментарий. После этого процесс должен начаться заново. Самое главное для автора патча здесь — не принимать критику на свой счет, а вникнуть в ее суть и, если со всем согласен, переделать.

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

Имеются ли стандарты на оформление кода для включения в ядро Linux? Если да, то не могли бы привести характерные примеры? Допускается ли отклонение от стандартов?

Стандарты, безусловно, есть. Даже написан специальный документ — Kernel Coding Style. В нем собраны все требования для оформления. Требования, надо сказать, очень разумные. К ним легко привыкнуть, и очень трудно потом начать писать (и читать) по-другому. Отклонения от стандарта, с одной стороны, допускаются, но, с другой, они все описаны в самом стандарте, так что можно сказать, что и нет.

Приходится ли писать на ассемблере для ядра Linux?

Иногда. Вообще ядро написано максимально отвлеченно от архитектуры. Чаще бывает так, что пишешь на СИ, но в коде, который является архитектурно-специфичным.
В результате получается новая функциональность, которая работает только на одной архитектуре. Но сообщество с этим научилось справляться, через некоторое время появляется «знаток» другой платформы, который хочет, чтобы новая функциональность работала и у него тоже, и доделывает.

Как выглядит ваш рабочий день? Сколько времени посвящаете программированию, сколько проектированию?

Гм… Даже не могу представить, как выглядит средний рабочий день. Обычно рабочая неделя — это такой салат из различных «подумать», «порисовать», «покодить», «поговорить», «попереписываться», который я пытаюсь распределить во времени так, чтобы было как можно меньше переключений из одной деятельности на другую и чтобы люди, которые ожидают от меня каких-то действий, не ожидали их «вхолостую».

Какое программное обеспечение используете в работе? Рабочее окружение (GNOME, KDE, XFCE и т.п.), клиент электронной почты (может, связка веб-интерфейс/ почтовый клиент), веб-браузер, редактор, инструментарий разработчика (например, git)?

«Тюнингованный» (как водится) Fedora Linux. Ну и продукты Parallels, конечно. KDE и Gnome я не люблю, сразу ставлю себе FluxBox. Из графических приложений пользуюсь Thunderbird, Chrome, Skype. Периодически надо нарисовать слайды для очередной конференции. Пока возможностей OpenOffice хватает.
Остальное (даже мультики детям) запускаю в терминале.

Редактор VIM, а также стандартные инструменты разработчиков — make, git, svn, gcc, objdump, gdb.

Используете ли вы облачные сервисы в работе или личных целях? Если да, то какие?

Помимо google+ и hangouts, почти ничего. Я чаще на все эти сервисы смотрю «с другой стороны», чтобы почерпнуть темы для размышлений над нашими облачными продуктами ну или просто для «общего развития».

Как выглядит рабочее место? Есть ли особые предпочтения в выборе аппаратной части?

Стол, кресло, ноутбук. Предпочтение по аппаратуре только одно — у IBM ThinkPad очень удобная клавиатура и trackpoint.

Нередко разработчики говорят о том, что слушают ту или иную музыку во время работы. Как вы к этому относитесь? Какую музыку слушаете?

Зависит от того, что именно я «работаю». Если это что-то рутинное, типа просматривание рассылки за день, то можно что угодно. Если это кодирование, про которое уже ясно, что именно кодить, то музыка без слов, иначе трудно сконцентрироваться. Для более интеллектуальной деятельности предпочитаю тишину.

А явных предпочтений в музыке у меня, как мне кажется, нет — это и классика, и тяжелая музыка, и советский поп-рок-комплект, и какие-то случайные песни, которые по радио услышал.

Что вы могли бы посоветовать начинающим разработчикам ядра? Как снизить «порог вхождения» в процесс разработки?

Я слышал много советов, что надо и чего не надо делать. Как мне кажется, все они сводятся к тому, что разработка ядра Linux — это в первую очередь общение в «клубе по интересам» и только во вторую — собственно разработка. Этакая открытая соцсеть любителей системного программирования.

Поэтому первое, что надо сделать, — настроиться на такой стиль общения. А все остальное приложится.

Какие книги или источники вы можете порекомендовать для тех, кто начинает заниматься разработкой ядра?

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

Лучше освоиться с принципами функционирования аппаратных платформ и операционных систем и сразу «окунуться» в чтение кода.

Зато могу порекомендовать сайт kernelnewbies.org — для новичков в ядре это будет как минимум отличной и, главное, актуальной коллекцией ссылок на другие сайты, документацию и некоторое количество канонической литературы по ядру.

Беседовал Игорь Штомпель, журнал «Системный администратор»