Очередное копирование с сетевых просторов.
Установка
Как было отмечено выше, все необходимое уже есть в ядре. Тем не менее, для хождения в ядро понадобятся некоторые дополнительные утилиты. Также не повредит обновить до последней версии кое-какие, казалось бы, не особо связанные с LXC пакеты.
Итак:
sudo apt-get install lxc lxc-templates systemd-services cgroup-bin \
bridge-utils debootstrap
Очень важно реально сделать 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:
Увидим что-то вроде:
# The default user is 'ubuntu' with password 'ubuntu'!
# Use the 'sudo' command to run tasks as root in the container.
##
Посмотреть список доступных шаблонов можно так:
Список скачанных шаблонов:
Удалить шаблон можно просто удалив соответствующий ему каталог.
Запуск контейнера в бэкграунде:
Для отладки — запуск с логированием:
Список контейнеров:
Подробная информация о контейнере:
Заходим в контейнер:
В нашем случае логин и пароль — ubuntu. Для выхода из контейнера жмем Ctr+A, затем Q.
Остановка контейнера:
Создание клона контейнера (test-container должен быть остановлен):
Удалить контейнер:
Заморозить/разморозить контейнер:
sudo lxc-unfreeze -n test-container
Создать снапшот (контейнер должен быть остановлен):
Список снапщотов:
Восстановление из снапшота:
Если нужно пошарить каталог, проще всего сделать это при помощи sshfs:
Пока ничего сложного.
Автозапуск
Чтобы контейнер запускался при старте системы, в конфиг контейнера (в нашем случае это файл /var/lib/lxc/test-container/config) дописываем:
lxc.start.delay = 15 # delay in seconds
lxc.start.order = 50 # higher value means starts earlier
Если все было сделано верно, команда sudo lxc-ls -f
покажет YES в колонке autostart.
Ограничение на использование ресурсов
Попробуем ограничить количество памяти, которое может отъедать контейнер.
Останавливаем контейнер:
Затем правим /var/lib/lxc/test-container/config:
Говорим:
cat test.log | grep -i memory
Должны увидеть что-то вроде:
cgm_setup_limits:1385 - cgroup 'memory.limit_in_bytes' set to '256M'
Проверяем, что настройки применились:
Можно менять лимиты на лету, но они потеряются с рестартом:
Также можно следить, сколько ресурвов потребляет контейнер прямо сейчас:
Вот еще интересные параметры:
- cpu.shares — сколько единиц процессорного времени отдавать контейнеру, если у одного 2000 единиц, а у второго 1000, второй получит в два раза меньше времени;
- cpuset.cpus — какие ядра может использовать контейнер, номера начиная с нуля, например
0,1
или0-3
; - memory.memsw.limit_in_bytes — ограничение на память и своп в сумме, если своп вообще есть;
- blkio.weight — как cpu.shared, только про дисковый ввод-вывод;
Тут больше параметров — есть, к примеру, про сеть.
Ограничение на использование дискового пространства
Эту задачу можно решить несколькими способами. Например, многие советуют использовать LVM. И хотя LVM, бесспорно, крутая штука, использовать его для решения такой простой задачи мне лично кажется оверкилом. Предлагаю пойти более простым путем.
Допустим, мы хотим создать контейнер с именем new-container, который будет занимать на диске не более 10 Гб.
sudo mkfs.ext4 -F /var/lib/lxc/new-container.img
sudo mkdir /var/lib/lxc/new-container
sudo mount -t ext4 -o loop /var/lib/lxc/new-container.img \
/var/lib/lxc/new-container
Теперь создаем контейнер, как обычно:
Заходим внутрь контейнера, и через 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
# 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
Говорим:
sudo update-rc.d more-loop-devices defaults
В этот же скрипт при необхожимости можно прописать и монтирование. Честно говоря, мне пока не нужно было так много контейнеров. Поэтому я не проверял, действительно ли в этом есть необходимость, или же достаточно записи в fstab.
Настройка bridged сети
Ранее в заметке Контейнерная виртуализация при помощи OpenVZ мы научились настраивать bridged сеть под CentOS. Настало время узнать, как то же самое делается в Debian и Ubuntu.
Правим /etc/network/interfaces — часть про eth0 убираем, вместо нее пишем:
iface eth0 inet manual
Далее, если у вас DHCP:
iface br0 inet dhcp
bridge_ports eth0
bridge_stp off
bridge_fd 0
bridge_maxwait 0
Если же у вас используются статические адреса:
iface br0 inet static
address 192.168.0.123
network 192.168.0.0
netmask 255.255.255.0
broadcast 192.168.0.255
gateway 192.168.0.1
bridge_ports eth0
bridge_stp off
bridge_fd 0
bridge_maxwait 0
Перезагружаемся.
Если все было сделано правильно, в ifconfig’е увидим интерфейс br0.
Далее останавливаем контейнер и правим /var/lib/lxc/(container)/config:
Если хотим присвоить контейнеру статический IP, также дописываем:
lxc.network.hwaddr = 00:16:3e:6b:c7:5b
lxc.network.ipv4 = 192.168.0.124/24
Запускаем контейнер. Если все было сделано правильно, в контейнер можно будет ходить из локалки и sudo lxc-ls -f
покажет у него соответствующий IP.
Резервное копирование и восстановление
Как уже отмечалось, все лежит в /var/lib/lxc. Поэтому просто нужно аккуратно заархивировать все данные оттуда. Тут каждый использует, что ему больше нравится. Для примера рассмотрим решение задачи при помощи tar.
Останавливаем контейнер, под рутом делаем:
tar -cvzf backup.tgz ./
Резервная копия готова! Для восстановления же говорим:
cd /var/lib/lxc/test-container
scp example.ru:path/to/backup.tgz ./
tar -xvzf backup.tgz
rm backup.tgz
Теперь контейнер виден в lxc-ls
и может быть запущен через lxc-start
.
Если описанным образом вы создаете копию контейнера (вам чем-то не подошел lxc-clone) или при восстановлении контейнера решили его переименовать, придется чуть-чуть подправить файл config. Там просто нужно поменять пути и изменить имя контейнера, плюс я бы сменил на всякий случай MAC.
В общем-то, это все. Ну разве что у tar’а еще флаг --numeric-owner
рекомендуют использовать.
Если же вы ограничиваете место на диске, которое может занимать контейнер, как это было описано выше, то резервное копирование и восстановление делается еще проще.
Непривилегированные контейнеры
Оказывается, что контейнерами можно управлать и под самыми обыкновенными пользователями, не под рутом. Как минимум, это намного безопаснее.
При этом каталоги немного меняются:
- ~/.local/share/lxc — тут лежат контейнеры, их настройки, ФС и так далее;
- ~/.config/lxc — прочие настройки;
- ~/.cache/lxc — кэш шаблонов;
- ~/.local/share/lxcsnaps — сюда пишутся снапшоты;
Первым делом говорим:
sudo usermod --add-subgids 100000-165536 eax
sudo chmod +x /home/eax
… где eax — имя вашего пользователя в системе.
Только что мы выделили 65536 uid’ов и gid’ов пользователю eax. В контейнере будут использоваться айдишники от 0 до 65535, которые будут отображаться в айдишники от 100000 до 165535 в хост-системе.
Далее:
Копируем /etc/lxc/default.conf в ~/.config/lxc/default.conf и дописываем в конце:
lxc.id_map = g 0 100000 65536
В файл /etc/lxc/lxc-usernet пишем:
eax veth lxcbr0 100
Создаем контейнер (как видите, без sudo):
-r trusty -a amd64
Заметьте, как это работает. Мы указали тип контейнера download, которому передали в качестве аргумента название дистрибутива, релиза и архитектуры CPU. Все эти три параметра обязательны при создании непривилегированных контейнеров.
Теперь запускаем контейнер, как обычно:
В случае возникновения проблем:
Дополнение: Чтобы непривилегированные контейнеры заработали, может потребоваться перезагрузка. Если вы используете encfs, команды sudo и ping могут не работать. Это баг. Здесь рассказывается, как примерно можно его обойти. Идея в том, чтобы при помощи симлинков положить контейнеры и конфиги за пределы encfs.
Шаблоны непривилегированных контейнеров немного отличаются от тех, что мы использовали раньше. В частности, никакого SSH по умолчанию в них не крутится. Но это легко исправить. Заходим в контейнер под рутом при помощи lxc-attach:
… и говорим:
passwd ubuntu
Ну вот, а в остальном все как обычно.
Комментариев нет:
Отправить комментарий