Pull to refresh

lxc — нативные контейнеры Linux

Reading time 5 min
Views 21K
В данный момент в Linux существует следующие широко известные реализации контейнеров:

Но они требуют наложения своих патчей на ядро, для получения необходимого функционала. В отличии от них lxc начиная с ядра версии 2.6.29 не требует этого. Для реализации изоляции используются уже имеющиеся в ядре namespaces, а для управления ресурсами Control Group. Это позволяет создавать не только полноценные изолированные окружения, но и осуществлять изоляцию отдельно взятых приложений. Для того чтобы начать работу с lxc потребуется запущенный linux с ядром 2.6.29. При этом в ядре должны быть включены следующие опции:

* General setup
** Control Group support
---> Namespace cgroup subsystem
---> Freezer cgroup subsystem
---> Cpuset support
----> Simple CPU accounting cgroup subsystem
----> Resource counters
----> Memory resource controllers for Control Groups
** Group CPU scheduler
---> Basis for grouping tasks (Control Groups)
** Namespaces support
---> UTS namespace
---> IPC namespace
---> User namespace
---> Pid namespace
---> Network namespace
* Security options
--> File POSIX Capabilities
* Device Drivers
** Network device support
---> Virtual ethernet pair device

Если все это включено, то монтируем файловую систему cgroup:
mkdir -p /var/lxc/cgroup
mount -t cgroup cgroup /var/lxc/cgroup

Скачиваем lxc, собираем и устанавливаем:
./configure --prefix=/
make
make install

Затем проверьте какая версия iproute2 установлена. Потребуется версия выше 2.6.26. Эта версия позволяет управлять виртуальными сетевыми усройствами и настривать network namespaces. Кроме этого если планируется использовать сеть внутри контейнера, то надо перенастроить вашу сетевую систему чтобы она использовала режим моста (bridge). Для этого опустите сетевой интерфейс:
ifconfig eth0 down

Создайте мост br0:
brctl addbr br0
brctl setfd br0 0

Подключите к нему ваш сетевой интерфейс:
brctl addif br0 eth0
ifconfig eth0 0.0.0.0 up

Настройте на br0 необходимый адрес и пропишите шлюз по умолчанию:
ifconfig bdr0 192.168.1.2/24 up
route add default gw 192.168.1.1

Далее когда контейнер будет стартовать, будет создаваться специальное виртуальное устройство соединяющее мост с виртуальным интерфейсом контейнера. Теперь необходим образ системы для контейнера. Самый простой способ это воспользоваться готовыми шаблонами от OpenVZ. Я использовал шаблон для CentOS. Скачайте и распакуйте его в каталог /var/lxc/centos/rootfs. После этого потребуется немного модифицировать шаблон, так-как он предназначен для работы с OpenVZ. Для этого выполните выполните следующие действия:

Перейдите в каталог /var/lxc/centos/rootfs/etc/rc.d и в файле rc.sysinit закоментируйте следующие строки:
/sbin/start_udev
mount -n /dev/pts >/dev/null 2>&1

На данный момент /dev каталог монтируется при помощи bind из текущей системы.

Затем закоментировать в каталоге /var/lxc/centos/rootfs/etc/ в файле fstab закоментируйте строку:
none /dev/pts devpts rw 0 0

После чего перейдите в каталог /var/lxc/centos/rootfs/etc/sysconfig/network-scripts и создайте тем файл ifcfg-eth0 такого вида:
DEVICE=eth0
IPADDR=192.168.1.102
NETMASK=255.255.255.0
NETWORK=192.168.1.0
BROADCAST=192.168.1.255
ONBOOT=yes
NAME=eth0

Далее перейдите в каталог /var/lxc/centos/rootfs/etc/sysconfig/ и создайте файл network:
NETWORKING="yes"
GATEWAY="192.168.1.1"
HOSTNAME="centos_ssh"

Теперь осталось поменять пароль root. Для этого делаем chroot в образ системы и вызываем passwd:
chroot /var/lxc/centos/rootfs
passwd


С подготовкой системы закончено. Переходим к созданию настроек контейнера. Для этого создадим два файла fstab и lxc-centos.conf в каталоге /var/lib/
Далее необходимо создать файлы настроек контейнера. Создаем в каталоге /var/lxc/centos lxc-centos.conf и fstab следующего содержания:
lxc-centos.conf
lxc.utsname = centos_ssh
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = br0
lxc.network.ipv4 = 192.168.1.101/24
lxc.network.name = eth0
lxc.mount = /var/lxc/centos/fstab
lxc.rootfs = /var/lxc/centos/rootfs

fstab
/dev /var/lxc/centos/rootfs/dev none bind 0 0
/dev/pts /var/lxc/centos/rootfs/dev/pts none bind 0 0

Теперь можно создать контейнер. Указываем имя centos и файл конфигурации:
lxc-create -n centos -f /var/lxc/centos/lxc-centos.conf

Проверяем создался ли контейнер:
lxc-info -n centos
'centos' is STOPPED

Контейнер создался, но на данный момент не работает. Запускаем его:
lxc-start -n centos

У вас начнется загрузка centos. Как только увидите:
INIT: no more processes left in this runlevel

Загрузка завершена. Откройте соседнюю консоль и попробуйте попинговать адрес выделенный контейнеру. Как только он запингуется можно зайти по ssh.

Но кроме полноценных контейнеров lxc позволяет создавать контейнеры приложений. Для этого в каталоге /var/lxc/simple создаем следующую структуру каталогов:
rootfs
|-- bin
|-- dev
| |-- pts
| `-- shm
| `-- network
|-- etc
|-- lib
|-- proc
|-- root
|-- sbin
|-- sys
|-- usr
`-- var
|-- empty
|-- lib
| `-- empty
`-- run

Затем создаем lxc-simple.conf:
lxc.utsname = simple
lxc.mount = /var/lxc/simple/fstab
lxc.rootfs = /var/lxc/simple/rootfs

и fstab:
/lib /var/lxc/simple/rootfs/lib none ro,bind 0 0
/bin /var/lxc/simple/rootfs/bin none ro,bind 0 0
/usr /var/lxc/simple/rootfs/usr none ro,bind 0 0
/sbin /var/lxc/simple/rootfs/sbin none ro,bind 0 0

Далее создаем контейнер:
lxc-create -n simple -f /var/lxc/simple/lxc-simple.conf


И запускаем приложение:
lxc-execute -n centos /bin/ls


Как видите это с одной стороны создание контейнера с приложением проще, с другой стороны сложнее чем создание полноценного контейнера. Сейчас у вас имеется один запущенный контейнер и один контейнер приложений в остановленном состоянии. Но контейнеры кроме изоляции должен позволять ограничивать ресусы. Для этого в lxc используется lxc-cgroup. На данный момент он позволяет указывать какой процессор будет использоваться, сколько процессорного времени ему будет выделятся, ограничение доступной памяти и класс сетевого трафика исходящего с контейнера для дальнейшей обработки. Все настройки базируются на cgroup для подробного ознакомления с настройками стоит обратиться к каталогу документации ядра Documentation/cgroups

Приведу несколько постых примеров. Привязка контейнера к первому ядру процессора:
lxc-cgroup -n centos cpuset.cpus 0


Ограничение памяти контейнера до 128Мегабайт:
lxc-cgroup -n centos memory.limit_in_bytes 128M


Кроме этого имеются различные параметры учета. Напрямую все это без lxc-cgroup можно просмотреть в каталоге /var/lxc/cgroup/centos.

Если контейнер станет вам не нужен то его можно остановить:
lxc-stop -n centos


И удалить:
lxc-destroy -n centos

Учтите, что хотя при этом контейнер удалится, образ системы останется на диске.

Просмотреть запущенные процессы можно при помощи lxc-ps:
lxc-ps --lxc
centos 7480 ? 00:00:00 init
centos 7719 ? 00:00:00 syslogd
centos 7736 ? 00:00:00 sshd


lxc-info показывает состояние контейнера:
lxc-info -n centos
'centos' is RUNNING


lxc-freeze блокирует все процессы в контейнере до вызова lxc-unfreeze
lxc-freeze -n centos


lxc-unfreeze снимает блокировку со всех процессов в контейнере
lxc-unfreeze -n centos


lxc является интересной технологией, но на данный момент она не готова для использования в production. Изоляция явно недостаточна. Так top внутри контейнера показывает все процессоры и всю память, mount выводит точки смонтированные вне контейнера, а вызов установки времени изменяет его вне контейнера. Кроме этого нет квотирования используемого диского пространства и жесткого ограничения по использованию процессора. Работа над квотированием на данный момент ведется так что буду надеяться, что в скором времени для создания контейнеров не надо будет патчить ядро.
Tags:
Hubs:
+26
Comments 32
Comments Comments 32

Articles