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

    В данный момент в 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 выводит точки смонтированные вне контейнера, а вызов установки времени изменяет его вне контейнера. Кроме этого нет квотирования используемого диского пространства и жесткого ограничения по использованию процессора. Работа над квотированием на данный момент ведется так что буду надеяться, что в скором времени для создания контейнеров не надо будет патчить ядро.

    Комментарии 32

      +1
      Спасибо вам за замечательную статью. Буквально несколько дней назад я сокрушался, что в репозитории gentoo самая свежая версия openVZ работает с ядром 2.6.27.
      Теперь же, благодаря вашей подсказке, я смогу на свеженьком 2.6.31 запускать «виртуальные машины» =)

      Конечно не все что вы объясняете было для меня прозрачно, но думаю, что это из-за отсутствия опыта и скоро мне все станет понятно.
        0
        chroot с memory limit?
          +1
          Нет. Контейнер отличается большей степенью изоляции. К примеру ps внутри контейнера выводит только процессы контейнера, есть отдельная копия сетевого стека со своим роутингом, фаерволом и шейперами.
          0
          К сказанному можно добавить, что lxc поддерживается в libvirt.
            –4
            Блин да разве виртуализация должна быть такой длинной, слишком много настроек. дайте гуй, или просто утилитку попроще. Когда серверов 5 еще пойдёт а когда больше надо пилить много.
              +2
              А когда 50-60 серверов?) И на каждом по паре контейнеров? Один раз разобравшись в CLI можно сильно упростить дальнейшее администрирование.
                –1
                Значит должен быть один гуй на все ноды. Вон к ней даже есть либа libvirt + руби connector, надо конечно все эвенты обработать и завернуть в интерфейс, вышла бы конфетка.
                  0
                  Вперед: )
                +1
                use libvirt luke. Вообще это технология слишком свежая чтобы ее использовать в продакшене.
                  +1
                  Бери и пиши, или бери и покупай. У тебя полная свобода, но тебе никто ничего не должен.
                  0
                  неплохо, надо глянуть поближе.
                    +1
                    Vanilla kernel это здорово. Вот только дилемма: стабильность системы растет, т. к. нет левых патчей и одновременно падает, т. к. lxc еще не отточен :) По крайней мере наблюдается тенденция к улучшению.
                      0
                      вовремя вы статью написали — я думал что lxc это еще недоделка )
                      у меня как раз сейчас в проекте потребность в виртуализации.
                      подскажите, а lxc будет работать в openvz контейнере?
                        0
                        Разве что только в их devel ветке 2.6.27. В 2.6.18 нет namespaces.
                        0
                        слишком много телодвижений :)
                          +1
                          В OpenVZ не меньше, если нет адаптированого профиля.
                            0
                            да как-то нифига, гораздо меньше
                              0
                              Хорошо возьмите stage3 от gentoo или установленный centos и адаптируйте их к OpenVZ. Потом поставьте OpenVZ из исходников.
                                0
                                а нафига? если есть готовое. в чем смысл данного мероприятия?
                                  0
                                  А lxc похоже на что-то готовое?
                          0
                          интересно нормально ли оно себя ведет на x86_64?
                          надо будет на досуге попробовать…
                            0
                            Да поидее разницы нет.
                            0
                            Вот что меня поражает. Это того что факт наличия в ядре это аргумент, то что оно «хорошое»…
                              0
                              Может расскажете где тут написано, что оно хорошее?
                                0
                                Мне показалось что Вы это подразумеваете исходя из того, что обратили внимания читателя об этом в первых строчках статьи. Кстати vserver разве не в ядре?
                                  0
                                  А что же тогда делает последний абзац? :)
                                –2
                                ну как же… если оно есть в ядре, значит оно получило священное благословение линуса торвальдса, а благослование линупсного бога для линупсоедов всегда означает «что-то хорошее» :)
                                  0
                                  Понятие хорошее растяжимо причем очень сильно. Если он в ядре то оно основное, а не хорошее.
                                +1
                                Так top внутри контейнера показывает все процессоры и всю память, mount выводит точки смонтированные вне контейнера, а вызов установки времени изменяет его вне контейнера. Кроме этого нет квотирования используемого диского пространства и жесткого ограничения по использованию процессора. Работа над квотированием на данный момент ведется так что буду надеяться, что в скором времени для создания контейнеров не надо будет патчить ядро.

                                • 1. Точки монтирования находятся в /etc/mtab, этот файл можно модифицировать на своё усмотрение.
                                • 2. Квоты на размер диска для ноды можно создать при помощи loop определённого размера с fs, который монтируется при старте ноды.
                                • 3. Жесткое ограничение процессора даже в openvz не реализовано полноценно, подобие лимитирования процессора есть только в 2.6.18-el5 ядрах с патчами овз.
                                • 4. Cgroup можно использовать совместно с openvz.


                                Интересно было бы увидеть бенчмарки произодительности lxc на многоядерных процессорах.
                                  0
                                  Точки монтирования находятся в /etc/mtab, этот файл можно модифицировать на своё усмотрение.

                                  Ага щаз! cat /proc/mounts сделайте.

                                  Квоты на размер диска для ноды можно создать при помощи loop определённого размера с fs, который монтируется при старте ноды.

                                  Можно, но потом увеличивать уменьшать будет сложновато.

                                  Жесткое ограничение процессора даже в openvz не реализовано полноценно, подобие лимитирования процессора есть только в 2.6.18-el5 ядрах с патчами овз.

                                  Ну в cgroup жесткое ограничение процессора реализуется через указание сколько квантов может быть использовано (зависимость от таймера).

                                  Cgroup можно использовать совместно с openvz.

                                  В 2.6.27 версии?

                                  Интересно было бы увидеть бенчмарки произодительности lxc на многоядерных процессорах.

                                  А что именно? Контекст?
                                  +4
                                  Cамый быстрый способ попробовать lxc:

                                  1) конфигурим ядро как указано в самом начале поста

                                  2) запускаем lxc-checkconfig, он должен показать что всё ОК, желательно чтобы все пункты были enabled, особенно «File capabilities», иначе будет ругаться на «failed to remove CAP_SYS_BOOT capability»

                                  3) sudo mkdir -p /var/lxc/cgroup && sudo mount -t cgroup cgroup /var/lxc/cgroup

                                  4) sudo brctl addbr br0
                                  при желании добавляем сюда реальный интерфейс, как это сделать описано выше в оригинальном посте (посту? :)

                                  5) sudo lxc-debian create
                                  если «command not found: debootstrap» — то ставим пакет debootstrap, например «emerge debootstrap»
                                  на этом шаге сначала скачаются ~50Mb необходимых пакетов, а потом создастся ~200Mb структура каталогов дебиана в ./rootfs.debian

                                  6) sudo lxc-start debian

                                  7) загрузится очень быстро, логин root, без пароля
                                    +1
                                    очепятка:
                                    6) sudo lxc-start -n debian

                                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                  Самое читаемое