LXC: Kонтейнерные утилиты Linux

Обзор и установка новых контейнерных утилит Linux Containers

Краткое изложение: Контейнеры предоставляют облегчённую форму виртуализации, позволяющую изолировать процессы и ресурсы, не прибегая к механизмам интерпретации команд и к прочим сложностям полной виртуализации. В этом пошаговом обзоре дается описание контейнерных утилит Linux® Containers (LXC) и описываются их настройка и применение.

Мэт Хэлсли, разработчик ядра Linux, IBM

Мэт Хэлсли (Matt Helsley) — программист Центра Linux-технологий (Linux Technology Center) корпорации IBM.



14.07.2009

Контейнеры эффективно разделяют ресурсы, управляемые единственной операционной системой, на изолированные группы, для достижения лучшего баланса между конфликтующими запросами на использование ресурсов. В отличие от виртуализации, здесь не требуется ни эмуляция на командном уровне, ни компиляция "на лету" (just-in-time compilation). Контейнеры могут исполнять прямые процессорные команды, не прибегая к механизмам интерпретации. Также отпадают сложности паравиртуализации и преобразования системных вызовов.

Предоставляя средства для создания и использования контейнеров, ОС дает приложениям возможность работать как бы на отдельной машине, при этом совместно используя множество базовых ресурсов. Например, кэширование страниц общих файлов — например, glibc — можно эффективно использовать совместно, потому что все контейнеры используют одно и тоже ядро и, в зависимости от настроек контейнера, обычно одну и ту же библиотеку libc. Часто такое совместное использование распространяется и на другие файлы и папки, в которые не происходит запись.

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

Контейнерные технологии существуют уже довольно продолжительное время. В качестве примеров контейнеров из других Unix-систем следует назвать Solaris Zones и BSD jails. У контейнерных технологий в Linux также давние традиции: Linux-Vserver, OpenVZ и FreeVPS. Хотя каждая из этих технологий является вполне зрелой, решительных шагов по интеграции поддержки их контейнерных возможностей в основную ветвь ядра Linux не предпринималось.

В статье Сержа Халлина (Serge Hallyn) "Модули безопасности Linux: Рецепты для работы с контейнерами" (developerWorks, февраль 2009 г.), рассказывается, как можно усилить безопасность легких контейнеров с помощью политик SELinux и Smack. Подробности об этих технологиях ищите в Ресурсах.

Проект Linux Resource Containers (который разрабатывается и поддерживается специалистом IBM Дэниелом Лезкано (Daniel Lezcano); см. ссылку на исходный код в Ресурсах ), напротив, направлен на реализацию контейнеров в сотрудничестве с разработчиками основной ветви ядра Linux. Одновременно этот вклад может быть полезен и для более зрелых контейнерных Linux-решений, предоставляя для них общий внутренний интерфейс. Данная статья содержит краткое введение в использование утилит, созданных проектом LXC.

Для лучшего понимания статьи необходимо уверенно чувствовать себя в командной строке в работе с такими программами, как make, gcc, и patch, а также быть знакомым с процессом распаковки тарболов (файлов с расширением .tar.gz).

Получение, сборка и установка LXC

Проект LXC состоит из патча для ядра Linux и утилит, работающих в пользовательском пространстве. Утилиты используют новую функциональность, добавляемую патчем в ядро, и предлагают упрощенный набор инструментов для управления контейнерами.

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

Мы использовали пропатченное ядро Linux 2.6.27 (см. ссылки в Ресурсах ). Скорее всего, lxc-патч для ядра 2.6.27 не подойдет для исходного кода ядра вашего любимого дистрибутива, и в то же время версии ядра Linux старше 2.6.27 могут уже содержать значительную часть функциональности, представленной в патче. Поэтому настоятельно рекомендуется использовать последние версии патча и ядра из основной ветви. Также вместо загрузки исходного кода ядра и установки на него патча можно получить код, используя git:

git clone git://git.kernel.org/pub/scm/linux/kernel/git/daveh/linux-2.6-lxc.git

Инструкции по наложению патчей, настройке, сборке, установке и загрузке ядра можно найти на сайте kernelnewbies.org (см. ссылку в Ресурсах).

Для LXC необходимы некоторые специфические настройки в ядре. Самый простой способ правильно настроить ядро для работы с LXC — это использовать make menuconfig и включить Container support. Это, в свою очередь, автоматически включит набор других опций, зависящих от возможностей, поддерживаемых ядром.


Испытываем LXC-среды

В дополнение к ядру, поддерживающему контейнеры, нам понадобятся инструменты для упрощения запуска и управления контейнерами. Основными средствами управления в этой статье являются утилиты из библиотеки liblxc (см. ссылку в Ресурсах, а также ссылку на libvirt в качестве альтернативного решения). В этом разделе обсуждаются:

  • Утилита liblxc
  • Утилита iproute2
  • Настройка сети
  • Заполнение файловой системы контейнера (путем собственной сборки в Debian или запуска ssh-контейнера)
  • Подключение к файловой системе контейнера (SSH, VNC, VT: tty, VT: GUI)

Утилита liblxc

Скачайте и распакуйте liblxc (см. Ресурсы), затем выполните из папки liblxc команду:

./configure --prefix=/
make
make install

Если вам удобнее собирать из SRPM, такой пакет также имеется (см. Ресурсы).

Утилита iproute2

Для управления сетевыми интерфейсами внутри контейнеров необходим пакет iproute2 версии 2.6.26 или старше (см. Ресурсы). Если в вашем дистрибутиве он отсутствует, то скачайте, настройте, соберите и установите его, следуя инструкциям из архива с исходным кодом.

Настройка сети

Еще один ключевой компонент многих функциональных контейнеров — сетевой доступ. Наилучшим способом подключения контейнера к сети в настоящее время является соединение сегментов Ethernet сетевым мостом таким образом, что они выглядят единым сегментом сети. Готовясь к использованию LXC, мы создадим сетевой мост (см. Ресурсы) и с его помощью соединим наш настоящий сетевой интерфейс и сетевой интерфейс контейнера.

Создаем сетевой мост с именем br0:

brctl addbr br0
brctl setfd br0 0

Теперь поднимите интерфейс моста с вашим IP от уже существующего интерфейса (в этом примере 10.0.2.15): ifconfig br0 10.0.2.15 promisc up. Добавьте в мост существующий интерфейс (в нашем примере eth0) и уберите его прямую связь с IP-адресом:

brctl addif br0 eth0
ifconfig eth0 0.0.0.0 up

Любой интерфейс, добавленный к мосту br0, будет соответствовать IP-адресу моста. Напоследок убедитесь, что пакеты следуют к шлюзу через правильный маршрут по умолчанию: route add -net default gw 10.0.2.2 br0. Позже, при настройке контейнера, мы укажем br0 в качестве пути во внешний мир.

Заполнение файловой системы контейнера

Помимо сети, контейнерам часто нужна собственная файловая система. Существует несколько способов заполнить ее в зависимости предъявляемых требований. Обсудим два из них:

  • Сборка собственного Debian-контейнера
  • Запуск SSH-контейнера

Собрать собственный Debian-контейнер проще всего с помощь команды debootstrap:

debootstrap sid rootfs http://debian.osuosl.org/debian/

Если делается большое количество контейнеров сразу, то можно сэкономить время, предварительно скачав пакеты и объединив их в тарбол: debootstrap --make-tarball sid.packages.tgz sid http://debian.osuosl.org/debian/. Команда из этого примера соберет tar-файл размером около 71 МБ (52 МБ в сжатом виде), в то время как корневой каталог займет примерно 200 МБ. Теперь все готово к сборке корневой папки в rootfs: debootstrap --unpack-tarball sid.packages.tgz sid rootfs. (man-страница debootstrap содержит более полную информацию по сборке контейнеров меньшего размера или размера, более подходящего вам по другим параметрам.

В итоге мы получаем среду (см. Ресурсы), чрезвычайно избыточную по отношению к основному хост-контейнеру.

Запуск SSH-контейнера позволяет очень существенно снизить объём дискового пространства, выделяемого исключительно под файловую систему контейнера. Например, данный способ использует лишь несколько килобайт, чтобы включить множество ssh-демонов из разных контейнеров, работающих на порту 22 (см. пример в Ресурсах). Контейнер делает это, используя монтирование "только для чтения" (read-only bind mounts), таких важных корневых папок, как /bin, /sbin, /lib и др., для совместного доступа к содержимому пакета sshd из существующей системы Linux. При этом используется сетевое пространство имен и создается очень небольшое изменяемое содержимое.

Методы, использованные выше для создания легких контейнеров, в основном такие же, какие используются для создания chroot-сред. Разница лишь в использовании синонимов «только для чтения» (read-only bind mounts) и в использовании пространств имен для повышения изолированности chroot-среды до такой степени, что она становится эффективным контейнером.

Далее нам необходимо выбрать способ подключения к контейнеру.

Подключение к контейнеру

Следующий шаг — подключение к контейнеру. Здесь, в зависимости от настроек контейнера, возможно несколько способов:

  • SSH
  • VNC (графический режим)
  • VT: tty (текстовый режим)
  • VT: X (графический режим)

Подключение через SSH хорошо подходит для тех случаев, когда контейнеру не требуется графический интерфейс. В этом случае вполне достаточно простого соединения ssh (см. выше " Запуск контейнера SSHЗапуск контейнера SSH"). Преимущество этого метода, основанного на IP-адресации, в возможности создавать произвольное количество контейнеров.

Если ssh-соединение ожидает ввод пароля слишком долго, то широковещательный демон Avahi службы DNS/Service Discovery при запросе к DNS может остановить работу по тайм-ауту.

Подключение через удалённый доступ к рабочему столу (VNC) позволит использовать контейнер с графическим интерфейсом.

Для запуска X-сервера, обслуживающего только VNC-клиентов, используйте vnc4server. Установленный vnc4server необходимо будет запустить из файла /etc/rc.local контейнера таким образом: echo '/usr/bin/vnc4server :0 -geometry 1024x768 -depth 24' >> rootfs/etc/rc.local. В результате при старте контейнера будет создан экран с разрешением 1024*768 пикселов и глубиной цвета 24 бита. Теперь для подключения достаточно ввести:

vncviewer <ip>:<display>

Подключение через VT: tty (текстовый режим) удобно, когда контейнер делит tty с основной машиной (хостом). В этом случае для подключения к контейнеру можно использовать Linux Virtual Terminals (VT). Простейшее использование VT начинается с авторизации в одном из устройств tty, которые обычно совпадают с виртуальными терминалами Linux. Процесс, отвечающий за авторизацию, называется getty. Чтобы использовать VT 8, вводим:

echo '8:2345:respawn:/sbin/getty 38400 tty8'
  >> rootfs/etc/inittab

Теперь при запуске контейнера будет запускаться getty на tty8, что даст пользователям возможность авторизоваться в контейнере. Аналогичный прием можно использовать для перезапуска контейнера с помощью утилит LXC.

Этот метод не позволяет использовать графический интерфейс контейнера. Более того, поскольку к tty8 в каждый момент времени может подключиться лишь один процесс, для подключения нескольких контейнеров потребуются дополнительные настройки.

Подключение через VT: X позволит запустить графический интерфейс. Для запуска GNOME Display Manager (gdm) на VT 9, отредактируйте rootfs/usr/share/gdm/defaults.conf, заменив значения FirstVT=7 на FirstVT=9, и VTAllocation=true на VTAllocation=false.

Хотя теперь мы получили графический режим, мы используем один терминал из ограниченного количества виртуальных Linux-терминалов.


Запуск утилит LXC

Теперь, когда у нас работает удовлетворяющее требованиям ядро, установлены утилиты LXC и есть рабочая среда, настало время научиться управлять экземплярами среды. (Совет: более подробное описание многих необходимых действий содержится в файле LXC README.)

Для управления контейнерами LXC использует файловую систему cgroup. Первое, что нужно сделать, - это смонтировать ее: mount -t cgroup cgroup /cgroup. Файловую систему cgroup можно монтировать куда угодно. LXC будет использовать первую смонтированную cgroup из файла /etc/mtab.

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

Основы LXC

Здесь мы рассмотрим следующие вопросы:

  • Создание контейнера
  • Получение информации о существующих контейнерах или их списка
  • Запуск системных контейнеров и контейнеров приложений
  • Сигнальные процессы, запущенные в контейнере
  • Приостановка, возобновление, останов и уничтожение контейнера

Создание контейнера связывает имя с файлом настроек. Имя будет использовано для управления единичным контейнером:

lxc-create -n name -f configfile

Это позволяет множеству контейнеров использовать один и тот же файл настроек. В конфигурационном файле задаются атрибуты контейнера, такие как имя хоста, настройки сети, корневая файловая система и точки монтирования в fstab. После запуска скрипта lxc-sshd (создающего для нас конфигурацию) конфигурация ssh-контейнера будет выглядеть так:

lxc.utsname = my_ssh_container
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = br0
lxc.network.ipv4 = 10.0.2.16/24
lxc.network.name = eth0
lxc.mount = ./fstab
lxc.rootfs = ./rootfs

Независимо от файла настроек контейнеры, запускаемые утилитами LXC, по-своему видят процессы системы и доступные ресурсы межпроцессного взаимодействия (IPC), а также имеют собственное дерево точек монтирования (mount tree).

Кроме того, при запуске контейнера подразумевается, что любые ресурсы, не указанные в файле конфигурации, используются совместно с хостом. Это позволяет администраторам компактно описывать ключевые различия между хостом и контейнером, а также обеспечивает переносимость настроек.

Вывод информации о существующих контейнерах — ключевой момент в управлении ими. Просмотр состояния конкретного контейнера:

lxc-info -n name

Просмотр процессов, принадлежащих контейнеру:

lxc-ps

Запуск
В LXC различают два типа контейнеров: системные контейнеры и контейнеры приложений. Системные контейнеры похожи на виртуальные машины. Но, в отличие от истинной виртуализации, они создают меньшие накладные расходы за счёт меньшей изолированности. Это прямое следствие того, что все контейнеры используют одно и тоже ядро. Как и виртуальная машина, системный контейнер запускается так же, как Linux-дистрибутив, через запуск процесса init:

lxc-start -n name init

Напротив, контейнер приложений лишь создает отдельное пространство имен, необходимое для изоляции единичного приложения. Запуск контейнера приложений:

lxc-execute -n name cmd

Подача сигналов
Подаём сигнал всем процессам внутри контейнера:

lxc-kill -n name -s SIGNAL

Приостановка
Приостановка контейнера по сути похожа на отправку сигнала SIGSTOP всем процессам в контейнере. Однако отправка избыточных сигналов SIGSTOP может запутать некоторые программы. Поэтому LXC использует "замораживатель" процессов (Linux process freezer), доступный через интерфейс cgroup:

lxc-freeze -n name

Возобновление
Для "размораживания" контейнера:

lxc-unfreeze -n name

Остановка
Остановка очищает контейнер, завершая все запущенные в нем процессы:

lxc-stop -n name

Уничтожение
Уничтожение контейнера удаляет конфигурационные файлы и метаданные, которые были связаны с его именем при создании lxc-create:

lxc-destroy -n name

Прочие замечания

Вот несколько практических моментов, которые могут казаться полезными (некоторые из них касаются мониторинга).

Просмотр и настройка приоритета контейнера:

lxc-priority -n name
lxc-priority -n name -p priority

Непрерывное наблюдение за состоянием и изменением приоритета контейнера:

lxc-monitor -n name

Нажмите Ctrl-C чтобы остановить наблюдение.

Ждём, пока контейнер не войдет в одно из множеств состояний, разделенных |:

lxc-wait -n name -s states

Ждём любого состояния, кроме RUNNING:

lxc-wait -n name -s 'STOPPED|STARTING|STOPPING|ABORTING|FREEZING|FROZEN'

Эта команда, разумеется, приведет к немедленному возврату управления. Исключая непредвиденные ошибки, можно ожидать, что команда lxc-wait завершится только когда контейнер войдет в указанное состояние.

Низкоуровневый доступ

Для управления контейнерами LXC использует файловую систему cgroup. Посредством LXC возможно просматривать и производить определённые действия с частями файловой системы cgroup. Использование процессора каждым контейнером можно регулировать считыванием и регулировкой параметра cpu.shares:

lxc-cgroup -n name cpu.shares
lxc-cgroup -n name cpu.shares howmany

Заключение

Узнав из этого руководства об основах работы с контейнерными утилитами Linux, вы можете приступать к созданию собственных эффективных разделов ресурсов.

Этот материал основан на работе, поддержанной Агентством передовых оборонных исследовательских проектов (DARPA), в рамках Соглашения HR0011-07-9-0002.

Ресурсы

Научиться

Получить продукты и технологии

  • Проект Linux Resource Containers project на SourceForge.net — это репозиторий кода для реализации контейнера приложений в ядре Linux и место размещения кода, который может быть отправлен в списки рассылки ядра.(EN)
  • Скачайте исходный код ядра Linux 2.6.27 и lxc-патч для этой версии ядра.(EN)
  • На сайте liblxc, можно найти основной инструментарий управления контейнерами, используемый в этой статье. Доступен также пакет RPM с исходным кодом.(EN)
  • libvirt— это инструментарий и API виртуализации Linux, предоставляющий общие процедуры управления виртуальной машиной и экземплярами контейнера. libvirt не зависит от того, используется ли для виртуализации Xen, QEMU или KVM, а также LXC или OpenVZ для контейнеров.(EN)
  • Получите пакет iproute2версии 2.6.26 или выше.(EN)
  • Используйте в вашем следующем проекте разработки для Linux ознакомительные версии ПО IBM, которые можно скачать непосредственно с developerWorks.(EN)

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Linux
ArticleID=412793
ArticleTitle=LXC: Kонтейнерные утилиты Linux
publish-date=07142009