Данная статья является продолжением серии, начатой в публикациях Контейнеры — это будущее облаков и Контейнеризация на Linux в деталях — LXC и OpenVZ. Часть 1.
Если публикацию про будущее можно пропустить, то статья «часть 1» будет обязательна к прочтению, чтобы понять, про что мы тут говорим :)
Техническая реализация подсистемы лимитирования аппаратных ресурсов контейнеров
Для полноты описания мы обязательно должны затронуть аспект разграничения не только ресурсов системы и прав, но и аппаратных ресурсов.
Какие ресурсы нам нужно делить между пользователями:
- Процессор
- Жесткий диск (нагрузка на него)
- Память (объем)
Для всех подобных ограничений используется подсистема cgroups. Нагрузку на ввод/вывод можно фиксировать с помощью подсистемы cgroups blkio, причем, важно отметить, что есть как возможность задания жестких лимитов в байтах/секунду и операциях в секунду (IOPS), так и возможность задания весовых коэффициентов (то есть, например, 10% от всего сервера). Память лимитируется посредством memory cgroup, тут все довольно просто — указываем объем ОЗУ, если контейнер его превышает — процесс испытывает сообщение OOM. Для процессора допустима только возможность указания нагрузки в процентах, что объясняется особенностями реализации планировщика на Linux.
Итого, для реализации разграничения использования ресурсов мы воспользовались следующими cgroups:
- cpu
- memory
- blkio
Общие проблемы при использовании контейнеров
Когда я описывал все преимущества контейнеров я намеренно решил не затрагивать недостатки контейнеров, так как это очень объемная тема и требуется очень много пояснений.
Итак, поехали:
- В Linux upstream containers есть проблемы с изоляцией файловой системы /proc между контейнерами. В OpenVZ данная проблема решена.
- В Linux upstream containers невозможно ограничить объем диска доступный контейнеру без использования полностью отдельных файловых систем (что в свою очередь неудобно и очень неудобно в поддержке). Как перспективно решение данной проблемы в будущем стоит отметить функциональность subvolume файловой системы Btrfs, которая позволяет создать полностью изолированный участок (с фиксированным объемом) в пределах одной файловой системы.
- В качестве клиентской ОС при использовании контейнеризации может использоваться только та же самая ОС, что запущена на физическом сервере. Это не недостаток в техническом контексте, это особенность реализации. То есть на физической машине с Linux можно запустить только Linux. В случае необходимость запустить иную ОС очень хорошую услугу окажет KVM, который отлично поддерживается как на OpenVZ ядрах, так и на Linux upstream (к чести сказать — там он лучше).
- Меньший уровень безопасности по сравнению с полной виртуализацией. Создание эксплоита, который из контейнера приведет к выходу из строя самой аппаратной ноды потенциально возможно. В случае использования контейнеров из ядра Linux количество способов, чтобы вывести аппаратный сервер из строя решительно выше, так как в OpenVZ изоляция сделана намного лучше (за счет гранулированных UBC лимитов, а также за счет дополнительных проверок отсутствующих в upstream ядре).
- Для стабильного использования (но мы опять же не говорим о продакшене!) Linux upstream containers готовы начиная с ядра примерно 3.8 (в идеале, 3.10), в то время как во многих стабильных на данный момент дистрибутивах ядра младше и нет возможности использовать весь функционал. Довольно хороший вариант для работы с Linux upstream containers — это ядро от Oracle, оно как раз версии 3.8 и заявляет готовность контейнеров к промышленному использованию.
- Нет поддержки со стороны производителей дистрибутивов, например, стандартными средствами даже Fedora 20 нельзя поставить внутрь контейнера, а в виртуальную машину — можно. В вопросе установки попроще стоит вопрос у Debian и пакет debootstrap может с легкостью установить требуемый дистрибутив. В случае OpenVZ вопрос решается использование заранее собранных разработчиками образов ОС.
- Проблема с утилитами управления. Так как это крайне важный пункт, на мой взгляд, я решил остановиться на нем подробнее и расписал его отдельно в конце статьи.
- Проблемы с лимитированием объема диска для каждого контейнера. Данная проблема имеет место быть только в Linux upstream containers, так как все контейнеры должны размещаться в пределах одной файловой системы либо в отдельных файловых системах на базе LVM, что в свою очередь не особенно гибко и сложно в эксплуатации.
- Отсутствие встроенного решения для лимитированию скорости сетевого соединения — эта проблема затрагивает как Linux upstream containers, так и OpenVZ. Разумеется, возможно создание собственных решений на базе tc, но настолько полезная функция просто обязана быть.
Преимущества OpenVZ над стандартной контейнеризацией в Linux
Мы уже обсудили, что OpenVZ и Linux upstream containers очень сходные технологии с похожей архитектурой и реализацией, но у них при этом очень много отличий. Часть отличий вызвана тем, что актуальная версия OpenVZ поддерживается для ядра 2.6.32 RHEL. Стоп! Вы видите тоже что и я? 2.6.32 ядро, really? Но прошу не пугаться, что это ядро старо — это не так, потому что Red Hat выполняет колоссальный объем работ по бэкпортированию кода из новых веток и это ядро функционально очень близко к 3.x и при этом крайне далеко от стандартного «ванильного» 2.6.32.
Таким образом если сравнивать мы будем ядра RHEL6 OpenVZ и текущую версию upstream ядра (3.12). Уровень изоляции процессорных и дисковых ресурсов у них на одном уровне, но есть ряд тонкостей, на которые стоит обратить внимание, о них ниже.
Что именно у нас есть в OpenVZ, чего нет в upstream Linux ядре:
- Используется система vSwap, которая позволяет настраивать overcommit для контейнера, а также позволяет выдать виртуальный (потому что замедление выполняет искусственно и на скорости около 100 мегабайт/секу) SWAP
- Более точный подсчет оперативной памяти, потребляемый контейнерами за счет более гранулированных UBC счетчиков, можно посчитать занятую память ядра, память сокетов, выделенную память и реально занятую, число страниц shm памяти и многое-многое другое
- Возможность учета потребления страничного кэша каждым из контейнеров
- Система хранения с возможностью ограничения места доступного контейнера, построенная на базе ploop с функционалом аналогичным LVM, с возможностью создания снапшотов, возможностью увеличения/уменьшения в online режиме. Данная файловая система в свою очередь предоставляет уровень изоляции на уровне систем полной виртуализации.
- Поддержка live миграции с сервера-на сервер с нулевым даунтаймом (потеря 1 пинга) и использование очень эффективного алгоритма
Как можно заметить, почти все преимущества OpenVZ идут с упором на реальную эксплуатацию решения, а не на предоставление механизмов для реализации той или иной возможности, как поступают в Linux upstream containers.
Проблема со стороны user space
К сожалению, нет унифицированного способа управления контейнерами. В OpenVZ для этого используется vzctl, который, к слову, также может управлять контейнерами даже на обычном, upstream ядре начиная с версий 3.x, а еще он включен в поставку Fedora-20 и может быть установлен и использован без привлечения внешних зависимостей вообще. Также существуют LXC и docker (который в свою очередь тоже основан на LXC), но они также не покрывают полностью весь функционал, который может потребоваться пользователям контейнеров. Кроме этого, Linux Upstream Containers используются в весьма нестандартном месте — в системе инициализации systemd, используемой во многих дистрибутивах, функционале systemd-nspaw.
Поэтому вопрос в реализации удобного, грамотного, гибкого и отлично спроектированного фреймворка для управления контейнерами в Linux открыт и Вы можете изменить мир, написав его (smile) Также очень много полезного по вопросу утилит управления контейнерами Вы можете почерпнуть из презентации Кирилла Колышкина с конференции Linux Plumbers 2013.
Выводы
Как мы убедились, контейнеризация в Linux развивается очень активно, в ближайшие годы мы, безусловно, получим полноценную контейнеризацию готовую к промышленному использованию в upstream ядре. Но для промышленного использования (тут я подразумеваю использование для изоляции клиентов друг от другов, а не собственных сервисов) контейнеры готовы лишь при использовании OpenVZ. Но если же Вам требуется контейнеризация для собственных целей — то контейнеры Linux upstream — отличный выбор, только побеспокойтесь об актуальной версии ядра.
Также хотелось бы поблагодарить Andrey Wagin avagin за помощь в редактуре особо сложных технических вопросов.
C уважением, Павел Одинцов
CTO FastVPS LLC
Автор: pavelodintsov