|
|||||||
Туториал по контейнеризации при помощи LXC
Время создания: 29.02.2024 09:53
Автор: alensav
Текстовые метки: lxc
Раздел: DOCKER
Запись: alensav/MyTetra2/main/base/1709189599oy0bq829rd/text.html на raw.githubusercontent.com
|
|||||||
|
|||||||
Блог о программировании, а также электронике, радио, и всяком таком Туториал по контейнеризации при помощи 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 пакеты. Итак: sudo apt-get update Очень важно реально сделать update, чтобы поставились наиболее свежие версии указанных пакетов. И, не поверите, но реально лучше сразу сделать reboot. Иначе, работая с LXC, вы в какой-то момент можете получить странную ошибку вроде такой: call to cgmanager_create_sync failed: invalid request … и будете потом через Google выяснять, что же пошло не так . Свои данные LXC хранит в следующих местах:
Теперь рассмотрим команды для управления контейнерами. Основные команды Создание контейнера с именем test-container из шаблона Ubuntu: sudo lxc-create -n test-container -t ubuntu Увидим что-то вроде: ## Посмотреть список доступных шаблонов можно так: ls /usr/share/lxc/templates/ Список скачанных шаблонов: sudo ls /var/cache/lxc/ Удалить шаблон можно просто удалив соответствующий ему каталог. Запуск контейнера в бэкграунде: sudo lxc-start -d -n test-container Для отладки — запуск с логированием: sudo lxc-start -l debug -o 1.log -d -n test-container Список контейнеров: sudo lxc-ls -f Подробная информация о контейнере: sudo lxc-info -n test-container Заходим в контейнер: sudo lxc-console -n test-container В нашем случае логин и пароль — ubuntu. Для выхода из контейнера жмем Ctr+A, затем Q. Остановка контейнера: sudo lxc-stop -n test-container Создание клона контейнера (test-container должен быть остановлен): sudo lxc-clone -o test-container -n test-container-clone Удалить контейнер: sudo lxc-destroy -n test-container Заморозить/разморозить контейнер: sudo lxc-freeze -n test-container Создать снапшот (контейнер должен быть остановлен): sudo lxc-snapshot -n test-container Список снапщотов: sudo lxc-snapshot -n test-container -L Восстановление из снапшота: sudo lxc-snapshot -n test-container -r snap0 Если нужно пошарить каталог, проще всего сделать это при помощи sshfs: sshfs ubuntu@10.110.0.10: ./shared-dir Пока ничего сложного. Автозапуск Чтобы контейнер запускался при старте системы, в конфиг контейнера (в нашем случае это файл /var/lib/lxc/test-container/config) дописываем: lxc.start.auto = 1 # enabled Если все было сделано верно, команда sudo lxc-ls -f покажет YES в колонке autostart. Ограничение на использование ресурсов Попробуем ограничить количество памяти, которое может отъедать контейнер. Останавливаем контейнер: sudo lxc-stop -n test-container Затем правим /var/lib/lxc/test-container/config: lxc.cgroup.memory.limit_in_bytes = 256M Говорим: sudo lxc-start -d -n test-container -l debug -o test.log Должны увидеть что-то вроде: lxc-start 1449237148.829 DEBUG lxc_cgmanager - cgmanager.c: Проверяем, что настройки применились: sudo lxc-cgroup -n test-container memory.limit_in_bytes Можно менять лимиты на лету, но они потеряются с рестартом: sudo lxc-cgroup -n test-container memory.limit_in_bytes 100M Также можно следить, сколько ресурвов потребляет контейнер прямо сейчас: cat /sys/fs/cgroup/memory/lxc/test-container/memory.usage_in_bytes Вот еще интересные параметры:
Тут больше параметров — есть, к примеру, про сеть. Ограничение на использование дискового пространства Эту задачу можно решить несколькими способами. Например, многие советуют использовать LVM. И хотя LVM, бесспорно, крутая штука, использовать его для решения такой простой задачи мне лично кажется оверкилом. Предлагаю пойти более простым путем. Допустим, мы хотим создать контейнер с именем new-container, который будет занимать на диске не более 10 Гб. sudo truncate -s 10G /var/lib/lxc/new-container.img Теперь создаем контейнер, как обычно: sudo lxc-create -t ubuntu -n new-container Заходим внутрь контейнера, и через df видим, что отъесть от диска он может только 10 Гб. Чтобы не приходилось каждый раз монтировать раздел руками, в /etc/fstab дописываем: /var/lib/lxc/new-container.img /var/lib/lxc/new-container ext4 loop 0 0 Вы можете заметить, что количество loop-устройств в системе ограничено. В Ubuntu, например, их по умолчанию только 8. Если попытаться создать много контейнеров описанным выше образом, вы получите ошибку: mount: could not find any free loop device Эту проблему можно решить следующим скриптом: #!/bin/sh Чтобы loop-устройства создавались при загрузке системы, создаем файл /etc/init.d/more-loop-devices следующего содержания: #!/bin/bash Говорим: sudo chmod a+x /etc/init.d/more-loop-devices В этот же скрипт при необхожимости можно прописать и монтирование. Честно говоря, мне пока не нужно было так много контейнеров. Поэтому я не проверял, действительно ли в этом есть необходимость, или же достаточно записи в fstab. Настройка bridged сети Ранее в заметке Контейнерная виртуализация при помощи OpenVZ мы научились настраивать bridged сеть под CentOS. Настало время узнать, как то же самое делается в Debian и Ubuntu. Правим /etc/network/interfaces — часть про eth0 убираем, вместо нее пишем: auto eth0 Далее, если у вас DHCP: auto br0 Если же у вас используются статические адреса: auto br0 Перезагружаемся. Если все было сделано правильно, в ifconfig’е увидим интерфейс br0. Далее останавливаем контейнер и правим /var/lib/lxc/(container)/config: lxc.network.link = br0 Если хотим присвоить контейнеру статический IP, также дописываем: lxc.network.ipv4.gateway = 192.168.0.1 Запускаем контейнер. Если все было сделано правильно, в контейнер можно будет ходить из локалки и sudo lxc-ls -f покажет у него соответствующий IP. Резервное копирование и восстановление Как уже отмечалось, все лежит в /var/lib/lxc. Поэтому просто нужно аккуратно заархивировать все данные оттуда. Тут каждый использует, что ему больше нравится. Для примера рассмотрим решение задачи при помощи tar. Останавливаем контейнер, под рутом делаем: cd /var/lib/lxc/test-container Резервная копия готова! Для восстановления же говорим: mkdir -p /var/lib/lxc/test-container Теперь контейнер виден в lxc-ls и может быть запущен через lxc-start. Если описанным образом вы создаете копию контейнера (вам чем-то не подошел lxc-clone) или при восстановлении контейнера решили его переименовать, придется чуть-чуть подправить файл config. Там просто нужно поменять пути и изменить имя контейнера, плюс я бы сменил на всякий случай MAC. В общем-то, это все. Ну разве что у tar’а еще флаг --numeric-owner рекомендуют использовать. Если же вы ограничиваете место на диске, которое может занимать контейнер, как это было описано выше, то резервное копирование и восстановление делается еще проще. Непривилегированные контейнеры Оказывается, что контейнерами можно управлать и под самыми обыкновенными пользователями, не под рутом. Как минимум, это намного безопаснее. При этом каталоги немного меняются:
Первым делом говорим: sudo usermod --add-subuids 100000-165536 eax … где eax — имя вашего пользователя в системе. Только что мы выделили 65536 uid’ов и gid’ов пользователю eax. В контейнере будут использоваться айдишники от 0 до 65535, которые будут отображаться в айдишники от 100000 до 165535 в хост-системе. Далее: mkdir -p ~/.config/lxc Копируем /etc/lxc/default.conf в ~/.config/lxc/default.conf и дописываем в конце: lxc.id_map = u 0 100000 65536 В файл /etc/lxc/lxc-usernet пишем: # USERNAME TYPE BRIDGE COUNT Создаем контейнер (как видите, без sudo): lxc-create -t download -n test-container -- -d ubuntu \ Заметьте, как это работает. Мы указали тип контейнера download, которому передали в качестве аргумента название дистрибутива, релиза и архитектуры CPU. Все эти три параметра обязательны при создании непривилегированных контейнеров. Теперь запускаем контейнер, как обычно: lxc-start -d -n test-container В случае возникновения проблем: lxc-start -d -n test-container --logfile t.log --logpriority debug Дополнение: Чтобы непривилегированные контейнеры заработали, может потребоваться перезагрузка. Если вы используете encfs, команды sudo и ping могут не работать. Это баг. Здесь рассказывается, как примерно можно его обойти. Идея в том, чтобы при помощи симлинков положить контейнеры и конфиги за пределы encfs. Шаблоны непривилегированных контейнеров немного отличаются от тех, что мы использовали раньше. В частности, никакого SSH по умолчанию в них не крутится. Но это легко исправить. Заходим в контейнер под рутом при помощи lxc-attach: lxc-attach -n test-container … и говорим: apt-get install ssh Ну вот, а в остальном все как обычно. Заключение Не могу не отметить ряд косяков в LXC:
Тем не менее, если вы хотите запихнуть что-то в контейнер под Ubuntu, и при этом вы не пишите PaaS’ов, LXC может быть для вас неплохим вариантом. Особенно теперь, когда вы знаете о большинстве подвобных граблей этой технологии. Больше полезной информации вы найдете на сайте linuxcontainers.org , а также в списке рассылки lxc-users@ . Если вас интересует, как запускать GUI-приложения под LXC, обратите внимание на заметку Осилил запуск GUI-приложений в Docker . Она без единого изменения применима и к LXC. Дополнение: Также вас могут заинтересовать статьи Мой первый опыт использования Proxmox VE и Управление VirtualBox из консоли с помощью vboxmanage . Метки: Linux , Виртуализация , Сети .
|
|||||||
Так же в этом разделе:
|
|||||||
|
|||||||
|