Я
тут разразился программным постом про OpenVZ, LXC, ваниллу и прочие интересные вещи. Ниже копи-паста. Комменты надо оставлять
там, чтобы не распылять дискуссию по разным местам.
Здравствуйте! Я работаю в компании Parallels менеджером проекта OpenVZ. Хотел рассказать про то, что такое LXC (а также cgroups и namespaces), какое отношение всё это имеет к OpenVZ, и в целом о нашей работе с основным ядром. А то уже устал отвечать на одни и те же вопросы (и реплики) вроде таких:
* Планируется ли интеграция OpenVZ в ванильное ядро?
* Когда наконец OpenVZ начнёт использовать LXC?
* С тех пор, как в ванилле появились cgroups, OpenVZ можно выкидывать!
* Будущее за LXC, а OpenVZ отправляется на свалку истории.
* и т.п.
Постараюсь объяснить на пальцах, то есть упрощённо, максимально понятно, но при этом кратко (у меня нет времени писать, а у вас нет времени всё это читать). Получится, как обычно, всё равно долго, заумно и не смешно. Ну да ладно, кому надо смешно, погуглите "даёшь молодёжь", например.
Что такое LXC? Во-первых, это проект (в основном ведущийся сотрудниками компании IBM), ставящий своей целью обеспечить функциональность контейнеров а-ля OpenVZ в ванильном ядре. Во-вторых, так называют совокупность всех тех "кирпичиков" для построения контейнеров, которые уже есть в ванильном ядре (забегая вперёд -- это namespaces и cgroups). В-третьих, так называется утилита командной строки (в некотором смысле аналог vzctl), которую можно использовать с ванильным ядром для создания, запуска и т.п. контейнеров.
Что такое CGroups? Это некий аналог OpenVZ-шных user beancounters, то есть механизм для контроля за ресурсами (память, диск, процессор и т.п.). Основное отличие cgroups от того же ulimit или nice в том, что ресурсы контролируются не для отдельных процессов, а для групп процессов (например, каждой группе может соответствовать контейнер, или сервис, вроде Апача, или все процессы определённого пользователя и т.п.).
CGroups состоит из собственно фреймворка для группировки задач и ряда так называемых ресурс контроллеров. Например, есть контроллер памяти, контроллер приоритета ввода-вывода, контроллер использования CPU. Группы, кстати, могут быть иерархическими. Контроллеры "навешиваются" на группы более-менее произвольно, поэтому можно создать довольно сложные схемы управления ресурсами.
Что такое namespaces? По русски это "пространства имён", другими словами, некоторые изолированные множества идентификаторов. Скажем, chroot() -- это namespace для файловой системы, позволяющий, во-первых, иметь два разных файла с одинаковым именем, скажем, /bin/sh -- один в корне, второй в чруте, а во-вторых, не дающий из не-корневого неймспейса увидеть чужие файлы.
Ещё несколько примеров. Есть неймспейс для идентификаторов процессов (PID namespace). При его создании первый процесс внутри будет иметь номер 1 (как у инита), и вы не увидите "хостовых" процессов, только те, которые в вашем PID namespace. Если вы, находясь внутри PID неймспейса, пошлёте сигнал процессу с pid=123, сигнал придёт процессу (если такой есть) в вашем неймспейсе, а не в основном.
Есть неймспейс для IPC (System V Inter-Process Communication -- разделяемая память, семафоры, очереди сообщений, подробности в man svipc). То есть, если вы внутри IPC namespace в процессе создадите сегмент разделяемой памяти, его будут "видеть" и с ним смогут работать только процессы в том же IPC namespace, а не все процессы на этой системе, как обычно.
Есть неймспейс для нетворка (под сетью тут понимается совокупность сетевых устройств типа eth0, таблицы маршрутизации, таблицы фаервола (iptables) и прочее, и прочее -- таблица ARP, всякие там кеши).
Что такое контейнер? В сущности, контейнер есть "всего лишь" дерево процессов, находящееся в отдельном экземпляре всех неймспейсов, и ограниченное контроллерами сигрупп. Неймспейсы дают контейнеру обособленность (файлы, процессы, сеть -- всё своё), а сигруппы, при правильной конфигурации, балансируют использование ресурсов (напр. память, диск, CPU, сеть) между контейнерами, и защищают контейнеры друг от друга (и хост систему от контейнеров).
Таким образом, и OpenVZ, и LXC -- это "всего лишь" способ использования неймспейсов и сигрупп для создания контейнеров.
Кто написал LXC? Во-первых, его ещё не написали, там не хватает много какой функциональности (например, возможности "впрыгнуть" в существующий контейнер). Во-вторых, если вопрос про утилиты, то Даниэль Лезкано из IBM France, а если про ядро -- то кто только не писал. Скажем, CGroups -- это переделка cpusets, которую изначально написали SGI, а переделал Поль Менаж, который в то время работал в Google. Контроллер памяти, PID namespace, network namespace написали в основном мои коллеги из Parallels (Linux kernel team) Паша Емельянов и Ден Лунёв, помогали им местами товарищи из IBM India и IBM US.
Как OpenVZ использует LXC? Все куски, которые попадают в ваниллу (например, неймспейсы), мы сразу же начинаем использовать в своих ядрах, выкидывая аналогичный кусок функциональности из своего патчсета, который у нас там был с незапамятных времён. То есть мы используем ядерную функциональность LXC. И не только используем, но и добавляем новую!
Например, вот как произошло с PID namespace. В наших ядрах был свой PID namespace, а потом Паша взял себя в руки и засамбитил его (в виде набора патчей, вестимо) для включения в ванильное ядро. Пришли кернель дивелоперы из IBM India и сказали "нам так не надо, нам надо эдак" и засамбитили свой патчсет, с блекджеком и шлюхами возможностью создавать pidns внутри pidns (то есть делать иерархические пид-неймспейсы). Паша померял производительность своего и индийского варианта и возразил, что у них получилось тормозно. Индийцы возразили, что у Паши нет возможности создавать иерархии. Тогда Паша взял себя в руки и дописал поддержку иерархий. И сказали индийцы, что это хорошо, что-то там ещё подправили и засамбитили (от Пашиного имени -- так тоже можно делать) ещё раз. И вошла эта фича в ваниллу.
Таким образом, OpenVZ можно рассматривать как надстройку над LXC (потому как LXC ещё не дописана, многих вещей в ванилле нет, OpenVZ патч это добавляет) плюс наши утилиты командной строки (vzctl и друзья), плюс всякие шаблоны и т.п. А разработчики OpenVZ -- одновременно разработчики LXC!
Отчего же тогда мы не отдаём весь ядерный код OpenVZ в ваниллу? Мы отдаём! Уже несколько лет как этим занимаемся, с переменным успехом (сейчас, я посмотрел, в ядре примерно 1700 патчей от нас, что не так уж и хреново, хотя, конечно, хочется много больше).
Как это примерно происходит, описано выше на примере PID namespace. Бывает, что сложнее, бывает, что проще, бывает, что вообще не удаётся сделать то, что примут. Не потому, что криво, глючно и никому не надо, как думают аналитики на ЛОРе, а потому, что процесс принятия патчей -- сложный, по ряду причин. Например, мало кто понимает, что такое контейнеры и нафига они вообще нужны. Или понимают, но имеют своё, отличающееся от нашего видение, как решать ту или иную проблему. Поэтому тут больше надо разговаривать, убеждать, отстаивать свои подходы, чем просто писать и засылать хороший код. Для тех, кто думает, что на самом деле всё просто, а просто наши инженеры тупые -- покажите мне, сколько ваших нетривиальных патчей приняли, и мы поговорим.
Что насчёт светлого будущего? Какое оно? Когда оно наступит? В нашем понимании, идеальное светлое будущее -- это когда OpenVZ патч к ядру будет нулевого размера, то есть мы хотим, чтобы вся функциональность, которая есть в OpenVZ, появилась в ванильном ядре. Когда это наступит? Я боюсь, что никогда, ибо мир неидеален. Но если, скажем, в ванилле будет 60 или 80% нашей функциональности -- я буду счастлив (сейчас там примерно 20-30%, точнее сложно сказать).
А у меня ещё вопрос!.. Постараюсь ответить, например,
вот здесь.