Green-sell.info

Новые технологии
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Контейнерная виртуализация linux

Контейнерная виртуализация в Linux — OpenVZ и LXC

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

Контейнерная виртуализация не использует виртуальные машины, а создает виртуальное окружение с собственным пространством процессов и сетевым стеком. Экземпляры пространств пользователя (часто называемые контейнерами или зонами) с точки зрения пользователя полностью идентичны реальному серверу, но они в своей работе используют один экземпляр ядра операционной системы. Для linux-систем, эта технология может рассматриваться как улучшенная реализация механизма chroot. Ядро обеспечивает полную изолированность контейнеров, поэтому программы из разных контейнеров не могут воздействовать друг на друга.

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

Наиболее распространены сейчас OpenVZ, LXC, FreeBSD jail и Solaris Containers.

OpenVZ

OpenVZ — реализация технологии виртуализации на уровне ОС на ядре Linux. OpenVZ позволяет на одном физическом сервере запускать множество изолированных копий операционной системы, называемых «виртуальные частные серверы» (Virtual Private Servers, VPS) или «виртуальные среды» (Virtual Environments, VE). Поскольку OpenVZ базируется на ядре Linux, в отличие от виртуальных машин (напр. VMware, Parallels Desktop) или паравиртуализационных технологий (напр. Xen), в роли «гостевых» систем могут выступать только дистрибутивы Linux. Накладные расходы на виртуализацию очень малы, и падение производительности составляет всего 1-3 %, по сравнению с обычными Linux-системами. OpenVZ распространяется на условиях лицензии GNU GPL и состоит из модифицированного ядра Linux и пользовательских утилит. OpenVZ является базовой платформой для Virtuozzo — проприетарного продукта Parallels.

LXC (Linux Containers) — система виртуализации на уровне операционной системы для запуска нескольких изолированных экземпляров операционной системы Linux на одном узле. LXC основана на технологии cgroups, входящей в ядро Linux, начиная с версии 2.6.29. Среди примеров использования — применение в PaaS-хостинге Heroku для изоляции динамических контейнеров (dynos).

Docker — это программное обеспечение для автоматизации развёртывания и управления приложениями в среде виртуализации LXC. Docker позволяет «упаковать» приложение со всем его окружением и зависимостями в контейнер, который может быть перенесён на любой Linux-системе с поддержкой cgroups в ядре, а также предоставляет среду по управлению контейнерами. Docker, например, используется в облачной платформе Cocaine, разработанной компанией Яндекс.

Контейнеры Linux — установка и настройка LXC

Контейнеры Linux или LXC — это легкая технология виртуализации, которая может использоваться для решения различных задач. Технология встроена в ядро Linux и с помощью нее вы сможете запустить несколько дистрибутивов на одном компьютере или сервере практически без потерь производительности.

LXC можно расценивать как что-то среднее между изолированным окружением chroot и полноценной технологией виртуализации Qemu, Xen, KVM или VirtualBox. Поскольку все программы выполняются на реальном железе, без использования виртуализации, то вы не теряете производительность, в отличие от случая если бы вы использовали VirtualBox. Вы можете очень легко запустить параллельно несколько контейнеров в своей системе, даже при очень низких аппаратных ресурсах, чего нельзя сделать с полноценными технологиями виртуализации.

В этой небольшой статье мы рассмотрим как выполняется установка и настройка LXC в Ubuntu, а также как использовать эту технологию.

Что такое контейнеры LXC?

Перед тем как перейти к настройке давайте рассмотрим что из себя представляют контейнеры Linux. Как я уже сказал, это не совсем виртуализация, потому что все программы, которые выполняются внутри контейнера — работают на реальном железе и почти не теряют в производительности. Используется, только одно ядро, а для разграничения наборов процессов между собой применяются виртуальные окружения.

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

Для решения этой проблемы используются пространства имен PID, с помощью этого механизма PID процессов контейнера не зависят от основной системы и других контейнеров, а поэтому мы можем очень просто запустить систему инициализации. Ну и наконец нужно управлять ресурсами, для этого используется механизм cgroups.

Благодаря всему этому потеря производительности при использовании контейнеров LXC Linux составляет не более 1%. Теперь, когда вы знаете как все это работает, перейдем к описанию процесса установки LXC.

Установка и настройка LXC

В этой инструкции мы будем настраивать LXC в Ubuntu, поскольку это самая популярная операционная система, но все эти команды подойдут для всех других дистрибутивов. Отличие составляет только команда установки. Сначала нужно установить все необходимое программное обеспечение. Установка LXC на Ubuntu выполняется командой:

sudo apt install lxc lxc-templates uidmap

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

Настроим пользовательские пространства имен. Первая цифра означает первый UID пользователя linux в контейнере, вторая отвечающий ему UID пользователя в основной системе:

echo «lxc.id_map = u 0 100000 65536» >>

/.config/lxc/default.conf
$ echo «lxc.id_map = g 0 100000 65536» >>

Дальше настраиваем сеть в контейнере:

echo «lxc.network.type = veth» >>

/.config/lxc/default.conf
$ echo «lxc.network.link = lxcbr0» >>

/.config/lxc/default.conf
$ echo «lxc.network.flags = up» >>

Затем в файле /etc/lxc/lxc-usernet нужно разрешить использовать сетевые интерфейсы текущему пользователю, чтобы получить возможность запускать контейнер без root прав:

echo «$USER veth lxcbr0 2» | sudo tee -a /etc/lxc/lxc-usernet

Для того чтобы пространства имен пользователей linux в контейнере работали нужно присвоить своему пользователю подпространство UID и GID 100000-165536:

sudo usermod —add-subuids 100000-165536 $USER
$ sudo usermod —add-subgids 100000-165536 $USER

И даем права на использование данного пользователя в cgm:

sudo cgm create all user
$ sudo cgm chown all user $(id -u) $(id -g)
$ cgm movepid all user $$

Теперь первоначальная настройка завершена и мы готовы перейти к загрузке и установке образа контейнера. Для установки в интерактивном режиме наберите такую команду, здесь ubu1, это имя будущего контейнера:

lxc-create —template download —name ubu1

В этом списке вам предстоит выбрать нужную операционную систему. Просто введите необходимые параметры, имя, релиз и архитектура, выбрав их из списка доступных, например, для Ubuntu Yakkety Yak 64 бит:

Затем начнется загрузка уже готового, настроенного образа из интернета. Это может занять довольно много времени если у вас медленный интернет.

Также вы можете использовать не интерактивный режим и указать все необходимые параметры сразу в командной строке:

lxc-create -t download -n ubu1 — —dist ubuntu —release xenial —arch amd64

После завершения загрузки контейнера первоначальная установка будет завершена и мы можем перейти дальше.

Использование контейнеров LXC

После всех проделанных выше действий мы можем перейти к запуску контейнера. Для этого используйте команду lxc-start с именем вашего контейнера, например:

lxc-start -n ubu1 -d

Опция -n задает имя контейнера, в нашем случае — ubu1, а -d говорит утилите запуска, что нужно выполнять программу в фоновом режиме. Вы можете убедиться, что контейнер запущен с помощью такой команды:

Тут опция -f включает более подробный вывод, в списке вы увидите только что установленный контейнер и его состояние будет запущен.

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

Чтобы подключиться к терминалу контейнера используйте команду lxc-attach:

lxc-attach -n ubu1

После подключения вы получаете полный root доступ к файлам в контейнере, дальше рекомендуется задать пароль root и создать пользователя:

Настройка системы или установка программ выполняется точно так же, как и в обычной системе, например установка программ:

apt install wget openssh-server htop tmux nano iptables

Выключение контейнера

Когда вы завершили все работы в контейнере, его можно выключить, чтобы он не отнимал системные ресурсы. Для этого выполните:

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

Клонирование контейнеров

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

Для примера давайте создадим клон контейнера ubu1 с именем ubu2. Сначала нужно остановить контейнер:

Затем можно клонировать. Опция -n указывает контейнер источник, а -N — имя нового контейнера:

lxc-copy -n ubu1 -N ubu2

Затем вы опять можете использовать lxc-ls, чтобы убедится, что контейнер был создан:

Моментальные снимки

Если вы хотите экспериментировать с контейнером, вносить какие-либо изменения, которые будет трудно исправить, то можно сделать снимок контейнера, чтобы потом вернуть все как было, с помощью одной команды восстановив снимок. Чтобы создать снимок тоже нужно остановить контейнер:

Затем используйте команду lxc-snapshot для создания снимка:

lxc-snapshot -n ubu1

Будет создан снимок с именем snap0, следующие снимки для этой же машины будут называться snap1, snap2, и так далее. Вы можете восстановить состояние контейнера до снимка в любой момент, для этого используйте опцию -r:

lxc-snapshot -r snap0 -n ubu1

Вам нужно указать имя снимка и имя контейнера.

Запуск контейнера при старте системы

Вы можете настроить запуск контейнера автоматически при старте системы, например, для запуска веб-сервера. Для этого откройте файл конфигурации контейнера и добавьте такие строки:

lxc.start.auto = 1
lxc.start.delay = 5

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

Читать еще:  Artmoney ошибка открытия процесса

Решение проблем

Если у вас возникнут проблемы с запуском контейнеров, первое что нужно сделать, это попытаться запустить контейнер lxc с опцией -F, запуск не будет отправлен в фоновый режим и вы увидите все ошибки:

lxc-start -n ubu1 -F

Проанализировав вывод команды, вы сможете понять в чем дело и исправить проблемы. Если вы пытаетесь запустить несколько контейнеров одновременно, то можете получить ошибки типа «Quota reached» или «failed to create the configured network». Это потому что вы используете больше сетевых интерфейсов, чем было разрешено. Мы задавали этот параметр в файле /etc/lxc/lxc-usernet. Вначале мы усказали, что можно использовать два сетевых интерфейса, но можно сделать 5:

sudo vi /etc/lxc/lxc-usernet

losst veth lxcbr0 5

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

Выводы

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

Установка и настройка LXC Linux полностью рассмотрена и я надеюсь, теперь вам стало понятнее как работать с этой технологией. Ее полезность ограничена только вашей фантазией, так что не бойтесь экспериментировать. Если остались вопросы по настройке контейнеров, спрашивайте в комментариях!

На завершение видео с конференции LinuxPiter, где рассказывается подробно что такое контейнеры Linux и действительно ли они настолько безопасны:

Контейнерная виртуализация LXC в libvirt. Часть 1. Контейнеризуем RHEL и CentOS 7.

Иногда можно не возиться с полной или пара-виртуализацией с помощью qemu, а запустить lxc-контейнер с userspace-окружением RHEL/CentOS 6/7 или Fedora 19-23-…-rawhide, чтобы быстро что-нибудь сделать, не относящееся к ядру. Преимущество lxc-контейнера над qemu-виртуализацией в том, что не надо возится с файлами образов дисков и установкой системы с инсталляционного диска или по сети. Наоборот, можно просто установить несколько необходимых «bootstrap» пакетов в обычную директорию на хост-системе и на этом всё. Ну и lxc-контейнеры исключительно быстро стартуют и завершаются, потому что по факту это просто набор процессов. RHEL/CentOS 6 для хост-системы не подойдёт, так как у них в репозиториях нет необходимых пакетов libvirt-*-lxc .

Несколько общих слов про lxc-контейнеры в RHEL/CentOS 6/7 и Fedora 19+. Есть минимум 3 их реализации. Первая — это как бы «голый» lxc, описанный у меня в статье «Установка и использование контейнеров LXC 1.0 в RHEL/CentOS 6.5». Почти все настройки для него нужно делать ручками, что удобно, только если вы понимаете что делаете, прям как я. Иначе — неудобно. Вторая реализация — это docker (а так же rocket/rkt и подобные), который сейчас дофига модный и делает (почти) всё за вас. Проблема с docker -ом в том, что надо возиться с установкой и настройкой самого docker -а. Третья реализация — вируальная машина (точнее, lxc-контейнер) внутри libvirt -а, но с backend-ом виртуализации не qemu, а lxc. Именно её мы рассмотрим в этой статье.

Ахтунг: технология libvirt + lxc объявлена устаревшей, начиная с RHEL/CentOS 7.1 и может быть выпилена из оных в любом релизе. Вы строите свою продакшн-инфраструктуру на этой технологии на свой страх и риск. Больше подробностей в статье Linux Containers with libvirt-lxc (deprecated).

Ниже предполагается, что у нас есть установленный хост RHEL или CentOS 7 или Fedora 19+ с минимальным набором пакетов, но с графикой (вариант установки «Server with GUI»), для virt-manager -a и virt-viewer -a. Без графики тоже можно, тогда доступ в консоль lxc-контейнера будет в текстовом режиме с помощью virsh console .

  • Установка необходимых пакетов или группы пакетов с виртуализацией

Можно поставить целиком группу пакетов относящихся к виртуализации. Ранее в RHEL/CentOS была одна группа Virtualization , потом её разбили на несколько меньших (прочесть о спрятанных группах можно здесь), в Fedora так и оставили одну, поэтому посмотреть что у вас на конкренто вашей системе можно так:

В Fedora как была одна группа пакетов, так и осталась. Заметьте, в Fedora с версии 23 используется пакетный менеджер dnf вместо yum :

Посмотреть состав группы, например Virtualization Client можно так:

Нам нужны группы Virtualization Client , Virtualization Platform и пакеты libvirt-daemon-driver-lxc и libvirt-daemon-lxc :

Но для совсем минимальной инсталляции (чтобы не тащить, например, qemu ) достаточно установить следующие пакеты (плюс, естественно, зависимсости):

  • Запуск демона libvirtd и подключение к нему virt-manager-ом

После этого надо стартовать демон libvirtd (или перезагрузиться, он должен быть настроен стартовать при загрузке):

Если не запустить демон libvirt , virt-manager не сможет к нему подключится. Чтобы подключится к бегущему демону, запускаем virt-manager , идём в File -> Add Connection… и выбираем тип локального гипервизора «LXC (Linux Containers)»:

Подключение «localhost (LXC)» должно появиться в окне virt-manager -а.

  • Ошибка «libvirtd: internal error: Network is already in use by interface» при старте libvirtd

Иногда внезапно вы можете получить эту ошибку при старте libvirtd , особенно если вы запускаете его в виртуальной машине qemu :

Сообщение не очень понятное, но оно значит вот что. libvirtd хочет создать бридж с дефолтным диапазоном IP-адресов 192.168.122.0/24 на одном из интерфейсов хоста. Но может оказаться, что этот диапазон уже используется на каком-то из интерфейсов, eth0 в данном случае. Тогда бридж создать невозможно, о чём libvirtd и уведомляет. Решение — пересоздать сеть default изменив дефолтный диапазон 192.168.122.0/24 на что-то другое (например, на 10.0.0.0/16) в Virtual Machine Manager -> Edit -> Connection Details -> Virtual Networks -> IPv4 configuration:

Или остановить демон libvirtd , отредактировать диапазон IP-адресов сети default в файле /etc/libvirt/qemu/networks/default.xml и запустить демон заново:

После этого libvirtd должен успешно создать бридж virbr0 с назначенным диапазоном IP-адресов:

  • Запуск virt-manager от обычного пользователя без пароля

В Fedora 20+ virt-manager запросит рутовый пароль если его запускать от обычного пользователя в графической оболочке. В RHEL/CentOS 7 — нет, так как они построены на кодовой базе Fedora 19, а virt-manager начал уметь в PolicyKit (который и заставляет спрашивать рутовый пароль) только с Fedora 20. Больше деталей про это здесь.

Чтобы убрать этот запрос надо добавить вашего обычного пользователя в группу wheel (или любую другую) и создать файл /etc/polkit-1/rules.d/80-libvirt.rules со следующим кодом:

  • Создание lxc-контейнера CentOS 7

Несколько общих слов про «bootstrapping» lxc-контейнера. Чтобы контейнер заработал, надо установить в него некий минимальный набор пакетов, которых достаточно для функционирования минимальной системы. Скорее всего это будут пакеты инициализации ( systemd или upstart или Sys V init-скрипты) и пакетный менеджер (и, естественно, их зависимости). Этот начальный набор пакетов надо установить в директорию lxc-контейнера из хост-системы, так как самого контейнера пока нет. Для этого у yum (и dnf ) есть волшебный ключ —installroot . Но чтобы yum знал откуда брать пакеты для операционной системы контейнера, ему это надо сказать файлами /etc/yum.repos.d/*.re po . В частном случае, когда ОС хоста и контейнера одинакова (например мы создаём контейнер с CentOS 7 на хосте CentOS 7) это можно не делать.

Посмотреть, какие версии CentOS доступны для установки по сети можно на странице http://mirror.centos.org/centos/. .repo -файлы нужные нам для седьмой версии на момент написания статьи лежат в пакете centos-release-7-1.1503.el7.centos.2.8.x 86_64.rpm. Использование таких пакетов будет описано во второй части статьи, пока для простоты создадим .repo -файлы руками.

Итак, предположим, мы создаём lxc-контейнер с CentOS 7 в директории /srv/centos7 . Создадим нужные каталоги и .repo -файлы. Репозитории [base] и [updates] будут брать пакеты из сети с ближайшего зеркала. Если у вас нет сети, но есть установочный диск CentOS 7, смонтированный в директорию (например) /run/media/root/CentOS_7_x86_64/ , можно ставить пакеты с него, для этого описан пока выключенный репозиторий [media] . Чтобы устанавливать пакеты с установочного диска, а не из сети, установите enabled=1 для репозитория [media] , а enabled=0 для остальных репозиториев:

Собственно, всё готово к установке bootstrap-пакетов. После установки можно удалить файл /srv/centos7/etc/yum.repos.d/bootstrap.r epo , он больше не нужен. Заметьте, всё это мы пока делаем из хост-системы. Волшебная команда, которая делает магическую магию, такова:

Далее, ещё из хост-системы надо провести некоторую первоначальную настройку lxc-контейнера с CentOS 7 ещё до его первого запуска. Сначало надо установить рутовый пароль (например, «rootpw») с помощью магии chroot :

Или убрать рутовый пароль вообще и не забыть разрешить демону sshd пускать с пустым паролем:

Далее нужно добавить консоль контейнера как «доверенный» терминал, без этого система не пустит рута с консоли:

Далее нужно сделать демон sshd запускаемым при старте контейнера (эта линка может уже существовать, тогда команда пофэйлится, но это нормально):

Зададим имя хоста внутри контейнера:

Теперь, шаг с которым наиболее вероянто могут возникнуть проблемы — кофигурация сети внутри контейнера. Мы хотим, чтобы интерфейс eth0 получал настройки по DHCP, поэтому создаём файлы с таким содержанием:

И, наконец, создаём и запускаем контейнер с помощью virt-install (больше деталей про опцию —os-variant упомянуто ниже):

Позднее запустить остановленный контейнер и войти в него можно из графического интерфейса virt-manager -а или из текстового терминала с помощью virsh start и virsh console . Внимание: чтобы войти в контейнер из текстовой консоли virt-manager не должен быть запущен! Отсоединиться от консоли контейнера можно нажав Ctrl-] :

Итак, зайдём в контейнер и осмотримся, проверим, что всё как надо, памяти столько, скольно назначено, стоит правильное имя хоста и есть сеть:

Читать еще:  Как удалить файл в терминале linux

Как бы, каза лось бы, ура.

  • Создание lxc-контейнера RHEL 7

Почти ничем не отличается от создания lxc-контейнера CentOS 7. Проблема в установке bootstrap-пакетов. Так как доступ к пакетам RHEL требует регистрации, нельзя просто так взять и описать RHEL-репозитории в .repo -файлах, , нужна ещё регистрация, чтобы скачать пакеты RHEL 7 из сети из Red Hat Network. Поэтому нужно либо иметь установочный диск RHEL 7 и использовать репозиторий [media] . Либо устанавливать lxc-контейнер RHEL 7 из зарегистрированной хост-системы RHEL 7, тогда yum использует регистрацию хост-системы для скачивания пакетов.

Значение —releasever должно быть не 7 , а 7Server . Набор bootstrap-пакетов также немного другой. То есть, магически волшебные команды такие:

В virt-install надо использовать —os-variant=rhel7 . Также, чтобы устанавливать софт и получать обновления, надо зарегистрировать контейнер в Red Hat Network как отдельную систему. Или устанавливать пакеты в контейнер из зарегистрированной хост системы. В остальном всё так же.

  • Создание lxc-контейнеров в хост-системе Fedora 22+

В Fedora начиная с версии 22 и дальше пакетный мереджер yum был заменён на dnf и, внезапно, поведение опции —installroot измени лось. Теперь dnf не использует репозитории заданные в директории /etc/yum.repos.d/ , но использует не нужные в нашем случае репозитории из хост-системы. К счастью, эта функциональность была возложена на настройку reposdir , которая позволяет отдельно указать директорию с репозиториями. Что интересно, на момент написания этой статьи это отличие от yum не указано здесь, где, по-идее, должно бы.

Соответственно, очень волшебная и не менее магическая команда по установке bootstrap-пакетов в контейнер /srv/centos7 с помощью dnf на Fedora 22+ (после создания файла /srv/centos7/etc/yum.repos.d/bootstrap.r epo с репозиториями) будет:

  • Создание lxc-контейнера из готового образа от linuxcontainers.org

Внезапно, никто не запрещает особенно ленивым задницам вроде вас использовать уже готовые рутовые файловые системы с images.linuxcontainers.org. Достаточно взять готовый образ rootfs.tar.xz, распаковать его и создать контейнер с помощью virt-install . Образы пересоздаются каждый день, поэтому ссылка, скорее всего, уже не рабочая. Возьмите сами файл rootfs.tar.xz из каталога доступных образов CentOS 7.

Дальше, по-идее, всё просто: распаковать, задать имя системы, задать или сбросить рутовый пароль (на момент написания статьи по-умолчанию задан пароль «root» и требуется создание нового пароля при первом логине) и создать контейнер. На сейчас сеть в контейнере конфигуряется legacy-сервисом network , поэтому настройки сети можно менять в файле /etc/sysconfig/network-scripts/ifcfg-eth 0 .

  • Замечания об опции —os-variant команды virt-install

Внезапно может возникнуть вопрос, какие ещё значения можно использовать в опции —os-variant команды virt-install , кроме centos7.0 или rhel7 . К сожелению, команда virt-install , поставляемая с RHEL/CentOS 7 на момент написания статьи не поддерживает вывод допустимых значений этой опции с помощью —os-variant list —os-variant help или —os-variant=? . Если надо, можно использовать быстрый и грязный хак файла /usr/share/virt-manager/virtinst/guest.p y , который выведет список допустимых вариантов, если еспользован неправильный:

Теперь, запустив virt-install с какой-нибудь чушью в —os-variant , получим список допустимых значений этой опции:

Записки программиста

Туториал по контейнеризации при помощи LXC

17 февраля 2016

Пришло время научиться работать с Linux Containers, более известными под названием LXC. Далее мы будем рассматривать LXC в контексте Debian и Ubuntu, но написанное во многом будет применимо и для других дистрибутивов Linux. Мы коснемся не только основ использования LXC, но и узнаем, как настроить bridged сеть, ограничить количество ресурсов, используемых контейнером, и даже осилим unprivileged containers.

Коротко о главном

LXC — технология контейнерной виртуализации, как и OpenVZ. Накладные расходы на создание контейнеров очень невелики, и ничто не мешает нам запускать их сотнями или тысячами. Что невозможно при использовании честной и полноценной виртуализации, такой, как KVM. С другой стороны, запустить в контейнере ОС, отличную от Linux, мы не можем. На самом деле, не совсем корректно называть LXC отдельной технологией. Все работает сразу на нескольких фичах ядра Linux. Как минимум, это cgroups и namespaces.

Control Groups, они же cgroups, позволяют организовывать процессы в группы и для каждой группы задавать лимиты. Например, лимиты на использование CPU, объем используемой памяти и дисковый ввод-вывод.

Namespaces бывают разные — PID namespace, IPC namespace, UTS namespace, user namespace, mount namespace, network namespace. Неймспейсы изолируют друг от другая процессы таким образом, что процессы в одной группе не могут видеть ресурсы другой группы. Например, PID namespace предоставляет уникальные идентификаторы процессов в рамках группы. Внутри одной группы может быть процесс с pid’ом 1 и внутри второй группы тоже может быть процесс с pid’ом 1, хотя это два совершенно разных процесса, которые друг о другие ничего не знают. Притом, все процессы все также имеют уникальные id в рамках ОС. Просто, если смотреть на процессы из группы, то эти id отображаются в другие.

В отличие от Docker, который заточен на создание PaaS, в LXC нет никаких слоеных неизменяемых файловых систем. Контейнеры очень похожи на VDS’ы, как и в OpenVZ. Но в отличие от OpenVZ, в LXC далеко не все есть из коробки. Как мы скоро убедимся, для ограничения места на диске, используемого контейнером, приходится прибегать к дополнительным ухищрениям. Повторюсь, связано это с тем, что LXC не совсем одна полноценная технология. С другой стороны, LXC не нуждается в пропатченном ядре. Все необходимое уже и так есть в ванильном ядре Linux. Как следствие, LXC превосходно работает на самой обычной Ubuntu, чем OpenVZ похвастаться не может.

Примечание: Кстати, в заметке Начало работы с Vagrant и зачем он вообще нужен рассказывается, как работать с LXC через Vagrant. Использование LXC через Vagrant кому-то может показаться удобнее, чем работа с LXC напрямую.

Установка

Как было отмечено выше, все необходимое уже есть в ядре. Тем не менее, для хождения в ядро понадобятся некоторые дополнительные утилиты. Также не повредит обновить до последней версии кое-какие, казалось бы, не особо связанные с LXC пакеты.

Очень важно реально сделать update, чтобы поставились наиболее свежие версии указанных пакетов. И, не поверите, но реально лучше сразу сделать reboot . Иначе, работая с LXC, вы в какой-то момент можете получить странную ошибку вроде такой:

… и будете потом через Google выяснять, что же пошло не так.

Свои данные LXC хранит в следующих местах:

  • /var/lib/lxc — тут лежат контейнеры, их настройки, ФС и так далее;
  • /etc/lxc — прочие настройки;
  • /etc/default/lxc-net — тут можно поменять настройки сети;
  • /var/cache/lxc — кэш шаблонов;
  • /var/lib/lxcsnaps — сюда пишутся снапшоты;
  • /var/log/lxc — логи;

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

Основные команды

Создание контейнера с именем test-container из шаблона Ubuntu:

Увидим что-то вроде:

Посмотреть список доступных шаблонов можно так:

Список скачанных шаблонов:

Удалить шаблон можно просто удалив соответствующий ему каталог.

Запуск контейнера в бэкграунде:

Для отладки — запуск с логированием:

Подробная информация о контейнере:

Заходим в контейнер:

В нашем случае логин и пароль — ubuntu. Для выхода из контейнера жмем Ctr+A, затем Q.

Создание клона контейнера (test-container должен быть остановлен):

Создать снапшот (контейнер должен быть остановлен):

Восстановление из снапшота:

Если нужно пошарить каталог, проще всего сделать это при помощи sshfs:

Пока ничего сложного.

Автозапуск

Чтобы контейнер запускался при старте системы, в конфиг контейнера (в нашем случае это файл /var/lib/lxc/test-container/config) дописываем:

Если все было сделано верно, команда sudo lxc-ls -f покажет YES в колонке autostart.

Ограничение на использование ресурсов

Попробуем ограничить количество памяти, которое может отъедать контейнер.

Затем правим /var/lib/lxc/test-container/config:

Должны увидеть что-то вроде:

Проверяем, что настройки применились:

Можно менять лимиты на лету, но они потеряются с рестартом:

Также можно следить, сколько ресурвов потребляет контейнер прямо сейчас:

Вот еще интересные параметры:

  • cpu.shares — сколько единиц процессорного времени отдавать контейнеру, если у одного 2000 единиц, а у второго 1000, второй получит в два раза меньше времени;
  • cpuset.cpus — какие ядра может использовать контейнер, номера начиная с нуля, например 0,1 или 0-3 ;
  • memory.memsw.limit_in_bytes — ограничение на память и своп в сумме, если своп вообще есть;
  • blkio.weight — как cpu.shared, только про дисковый ввод-вывод;

Тут больше параметров — есть, к примеру, про сеть.

Ограничение на использование дискового пространства

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

Допустим, мы хотим создать контейнер с именем new-container, который будет занимать на диске не более 10 Гб.

Теперь создаем контейнер, как обычно:

Заходим внутрь контейнера, и через df видим, что отъесть от диска он может только 10 Гб.

Чтобы не приходилось каждый раз монтировать раздел руками, в /etc/fstab дописываем:

Вы можете заметить, что количество loop-устройств в системе ограничено. В Ubuntu, например, их по умолчанию только 8. Если попытаться создать много контейнеров описанным выше образом, вы получите ошибку:

Эту проблему можно решить следующим скриптом:

for i in $ ( seq 0 64 ) ; do
[ -b / dev / loop $i ] || ( mknod -m 660 / dev / loop $i b 7 $i &&
chown root:disk / dev / loop $i )
done

Чтобы loop-устройства создавались при загрузке системы, создаем файл /etc/init.d/more-loop-devices следующего содержания:

### BEGIN INIT INFO
# Provides: more-loop-devices
# Required-Start: $syslog
# Required-Stop: $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: More Loop Devices
# Description: More Loop Devices
### END INIT INFO

PATH = / sbin: / usr / sbin: / bin: / usr / bin

Читать еще:  Установка net на linux

# Load the VERBOSE setting and other rcS variables
. / lib / init / vars.sh
. / lib / lsb / init-functions

case «$1» in
start )
for i in $ ( seq 0 64 ) ; do
[ -b / dev / loop $i ] || ( mknod -m 660 / dev / loop $i b 7 $i &&
chown root:disk / dev / loop $i )
done
;;
* )
echo «Usage: more-loop-devices start» >& 2
exit 1
;;
esac

В этот же скрипт при необхожимости можно прописать и монтирование. Честно говоря, мне пока не нужно было так много контейнеров. Поэтому я не проверял, действительно ли в этом есть необходимость, или же достаточно записи в fstab.

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

Ранее в заметке Контейнерная виртуализация при помощи OpenVZ мы научились настраивать bridged сеть под CentOS. Настало время узнать, как то же самое делается в Debian и Ubuntu.

Правим /etc/network/interfaces — часть про eth0 убираем, вместо нее пишем:

Далее, если у вас DHCP:

Если же у вас используются статические адреса:

Если все было сделано правильно, в ifconfig’е увидим интерфейс br0.

Далее останавливаем контейнер и правим /var/lib/lxc/(container)/config:

Если хотим присвоить контейнеру статический IP, также дописываем:

Запускаем контейнер. Если все было сделано правильно, в контейнер можно будет ходить из локалки и sudo lxc-ls -f покажет у него соответствующий IP.

Резервное копирование и восстановление

Как уже отмечалось, все лежит в /var/lib/lxc. Поэтому просто нужно аккуратно заархивировать все данные оттуда. Тут каждый использует, что ему больше нравится. Для примера рассмотрим решение задачи при помощи tar.

Останавливаем контейнер, под рутом делаем:

Резервная копия готова! Для восстановления же говорим:

Теперь контейнер виден в lxc-ls и может быть запущен через lxc-start .

Если описанным образом вы создаете копию контейнера (вам чем-то не подошел lxc-clone) или при восстановлении контейнера решили его переименовать, придется чуть-чуть подправить файл config. Там просто нужно поменять пути и изменить имя контейнера, плюс я бы сменил на всякий случай MAC.

В общем-то, это все. Ну разве что у tar’а еще флаг —numeric-owner рекомендуют использовать.

Если же вы ограничиваете место на диске, которое может занимать контейнер, как это было описано выше, то резервное копирование и восстановление делается еще проще.

Непривилегированные контейнеры

Оказывается, что контейнерами можно управлать и под самыми обыкновенными пользователями, не под рутом. Как минимум, это намного безопаснее.

При этом каталоги немного меняются:

/.local/share/lxc — тут лежат контейнеры, их настройки, ФС и так далее;

/.config/lxc — прочие настройки;

/.cache/lxc — кэш шаблонов;

/.local/share/lxcsnaps — сюда пишутся снапшоты;

Первым делом говорим:

… где eax — имя вашего пользователя в системе.

Только что мы выделили 65536 uid’ов и gid’ов пользователю eax. В контейнере будут использоваться айдишники от 0 до 65535, которые будут отображаться в айдишники от 100000 до 165535 в хост-системе.

Копируем /etc/lxc/default.conf в

/.config/lxc/default.conf и дописываем в конце:

В файл /etc/lxc/lxc-usernet пишем:

Создаем контейнер (как видите, без sudo):

Заметьте, как это работает. Мы указали тип контейнера download, которому передали в качестве аргумента название дистрибутива, релиза и архитектуры CPU. Все эти три параметра обязательны при создании непривилегированных контейнеров.

Теперь запускаем контейнер, как обычно:

В случае возникновения проблем:

Дополнение: Чтобы непривилегированные контейнеры заработали, может потребоваться перезагрузка. Если вы используете encfs, команды sudo и ping могут не работать. Это баг. Здесь рассказывается, как примерно можно его обойти. Идея в том, чтобы при помощи симлинков положить контейнеры и конфиги за пределы encfs.

Шаблоны непривилегированных контейнеров немного отличаются от тех, что мы использовали раньше. В частности, никакого SSH по умолчанию в них не крутится. Но это легко исправить. Заходим в контейнер под рутом при помощи lxc-attach:

Ну вот, а в остальном все как обычно.

Заключение

Не могу не отметить ряд косяков в LXC:

  • У LXC довольно высокий порог вхождения и вообще все как-то неудобно. Я просто хочу, чтобы контейнер не отжирал больше 1 Гб памяти. Я не хочу ничего знать ни о каких cgroups и читать документацию по ним на сайте RedHat! Про то, как приходится плясать для банального ограничения места на диске, я вообще молчу. OpenVZ в этом плане намного, НАМНОГО лучше;
  • В LXC все очень сыро и плохо документированно. Я собирал представленную в этом посте информацию по крупицам, наверное, около месяца, попутно гугля по поводу багов, на которые я натыкался в процессе. Вам, уважаемые читатели, в этом плане будет намного проще;
  • На мой взгляд, интерфейс продуман плохо. Например, первое время я постоянно забывал флаг -d у lxc-start . Правда, потом я уже как-то то ли привык, то ли запомнил. Да и если контейнеры прописаны на автозагрузку, такой проблемы нет;
  • Внутри контейнера мы видим занятую и свободную память хост-системы, а не контейнера. В результате, из контейнера не ясно, кто же отожрал всю память. К тому же, некоторые программы могут работать из-за этого некорректно;
  • Неизбежны накладные расходы в случае ограничения используемого места на диске;
  • Плохие сообщения об ошибках. Шаг влево, шаг вправо — и тут же получаем что-то в стиле «No such file or directory — execlp»;

Тем не менее, если вы хотите запихнуть что-то в контейнер под Ubuntu, и при этом вы не пишите PaaS’ов, LXC может быть для вас неплохим вариантом. Особенно теперь, когда вы знаете о большинстве подвобных граблей этой технологии.

Больше полезной информации вы найдете на сайте linuxcontainers.org, а также в списке рассылки lxc-users@. Если вас интересует, как запускать GUI-приложения под LXC, обратите внимание на заметку Осилил запуск GUI-приложений в Docker. Она без единого изменения применима и к LXC.

А используете ли вы LXC и если да, то для каких задач?

Контейнеры Linux — LXC

LXC (LinuX Containers) — система виртуализации на уровне операционной системы, позволяющая исполнять множество изолированных Linux-систем (контейнеров) в одной системе, то-есть получить полноценную виртуализацию уровня операционной системы на одном экземпляре ядра и используя только его функции.

Виртуализация на уровне операционной системы — метод виртуализации, при котором ядро операционной системы поддерживает несколько изолированных экземпляров пространства пользователя, вместо одного. Эти экземпляры (часто называемые контейнерами или зонами) с точки зрения пользователя полностью идентичны реальному серверу. Виртуализация на уровне операционной системы — метод виртуализации, при котором ядро операционной системы поддерживает несколько изолированных экземпляров пространства пользователя, вместо одного. Эти экземпляры (часто называемые контейнерами или зонами) с точки зрения пользователя полностью идентичны реальному серверу.

LXC похож на Linux-VS и OpenVZ, за исключением того, что вместо внедрения в ядро соответствующих патчей ядра, он использует механизмы пространства имен (namespaces) и группировки процессов — cgroups (добавлено в версии ядра 2.6.24), доступные в любом современном Linux kernel.

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

Технология cgroups — это механизм группировки процессов и управления их ресурсами, такими как количество оперативной памяти, процессорные ресурсы, приоритеты ввода-вывода и доступа к сети.

Работая вместе, эти технологии реализуют очень мощную и гибкую систему виртуализации, возможности которой использует LXC, выступая в роли простого и удобного фронтенда к namespaces и cgroups.

Основные преимущества LXC — это возможность довольно гибко конфигурировать контейнеры, очень высокая степень безопасности и скорость работы — он быстрее, чем виртуализация, даже аппаратная, так как эмулировать ничего не надо.

Ну и основной недостаток, проистекающий от идеологии его построения — в контейнере могут функционировать только Linux системы.

Stéphane Graber (работает в Canonical в Ubuntu Foundations Team) и Serge Hallyn являются главными мейнтейнерами LXC.

До выхода первой версии LXC (LXC 1.0.0) работать с системой можно было только тестовом режиме: версии 0.X были достаточно сырыми и ненадежными.

LXC 1.0.0 явился результатом 10 месячной разработки и появился весной 2014 года в составе Ubuntu 14.04 LTS и был официально объявлен пригодным для промышленного применения. Первая версия является LTS — поддержка выпуска исправлений для ветки LXC 1.0 будет осуществляться в течение пяти лет.

В состав пакета LXC входит входит библиотека liblxc, набор утилит (lxc-create, lxc-start, lxc-stop, lxc-ls и т.п.), шаблоны для построения контейнеров и набор биндингов для различных языков программирования.

Данный релиз имеет огромный список изменений, тем не менее вот список наиболее главных изменений:

Ключевые улучшения в LXC 1.0:

  • Надежность и стабильность работы;
  • Поддержка полностью непривилегированных контейнеров — пользователи могут создавать и управлять контейнерами без использования root-привилегий;
  • Большая часть функциональности LXC теперь может быть доступна через API, экспортируемый из liblxc ;
  • Поставка официальных биндингов для использования API в программах на языках python3, lua, ruby и Go;
  • Гибкая система размещения контейнеров в различных типах хранилищ. Поддерживается размещение контейнеров в обычном дереве директорий, в btrfs и zfs, в lvm, loop-устройствах, aufs и overlayfs;
  • Поддержка клонирования работающих контейнеров и возможность заморозки их состояния через создание снапшотов;
  • Сокращенный, но более внятный и структурированный набор утилит;
  • Обновлённая и полноценная документация;
  • Поддержка нескольких методов создания контейнеров на основе недавно сгенерированных образов;
  • Поставка шаблонов для создания контейнеров на основе популярных дистрибутивов Linux. Шаблоны подготовлены для Alpine Linux, Alt Linux, Arch Linux, busybox, CentOS, Cirros, Debian, Fedora, OpenMandriva, OpenSUSE, Oracle, Plamo, sshd, Ubuntu Cloud и Ubuntu. В контейнере также можно запустить окружение Android;
  • Возможность запуска графического окружения внутри контейнера.
Ссылка на основную публикацию
Adblock
detector