Виртуализация с помощью Linux VServer
Евгений Зобнин (zobnin@gmail.com)
Хочешь организовать публичный доступ к сетевым сервисам, но беспокоишься за безопасность? Решил переложить часть своих обязанностей на другого человека, но не хочешь наделять его правами root? Управляешь хостингом и желаешь дать своим клиентам настоящую свободу? С помощью системы виртуализации Linux VServer ты легко решишь все эти задачи без головной боли и потери производительности.
СОДЕРЖАНИЕ:
- Введение
- Почему VServer?
- Установка
- Подготовка к запуску
- Запуск виртуального сервера
- Настройка
- Сеть
- Ограничения ресурсов
- Боковые выносы
Мы не раз говорили о системах виртуализации уровня операционной системы (песочницы) на примере FreeBSD Jail. Такой тип виртуализации позволяет разделить одну ОС на несколько виртуальных, каждая из которых будет обладать собственным окружением исполнения (библиотеки, каталоги /dev и /proc, набор стандартных утилит), процессами и IP-адресом.
В отличие от эмуляции, обеспечиваемой такими технологиями, как Xen, VMWare и KVM, виртуализация уровня операционной системы не эмулирует аппаратные составляющие компьютера, а создает изолированные контейнеры поверх ядра ОС. Это своего рода расширенная трактовка понятия «процесс» с более глубоким уровнем изоляции и разделения ресурсов, предоставляемых ядром. Обладая всего одним явным недостатком, заключенным в невозможности создания контейнеров для исполнения приложений других ОС, песочница наделена двумя неоспоримыми преимуществами: незначительной потерей производительности (в районе 2-3%) и простотой развертывания виртуальных окружений.
Виртуализация особенно популярна среди хостинг-провайдеров и создателей сервисов, предоставляющих площадки для организации облачных вычислений. Ведь в отличие от обычного хостинга, который выделяет клиентам аккаунт на сервере и доступ к набору предустановленных служб, хостинг, использующий виртуализацию, способен дать пользователям безграничный контроль над виртуальным сервером, возможностью устанавливать любое программное обеспечение и полным отсутствием ограничений на количество сайтов, почтовых ящиков, баз данных, интерпретаторов языков программирования. И все это с полной изоляцией виртуального сервера от хост-системы и простой системой развертывания.
Сегодня каждая из наиболее популярных UNIX-систем предоставляет возможности для организации виртуализации на уровне операционной системы. Во FreeBSD уже давно существует технология Jail, в Solaris изолированные контейнеры называются зонами (Zones), а среди решений для Linux наибольшей популярностью пользуются OpenVZ и Linux VServer.
Традиционно считается более взрослой, серьезной и развитой системой, этаким выбором профессионалов. Развиваемая сообществом , напротив, отличается простотой реализации и непретенциозностью. В то время как OpenVZ развивается по пути многофункциональной и сложной технологии для поддержки и управления VPS (Виртуальные Частные Серверы) в больших организациях и крупных сервисах, VServer следует идеологии простоты и удобства FreeBSD Jail. Система Linux VServer – это проверенный годами (более 7 лет разработки) небольшой, вылизанный и отлаженный патч для ядра Linux, который наделяет его всем необходимым для организации надежной и производительной системы виртуализации, единственный недостаток которой – невиртуализируемый сетевой стек.
Программный пакет Linux VServer состоит из двух частей: патча для Linux-ядра и набора утилит для управления виртуальными серверами. Прекомпилированные ядра с включенным VServer доступны в пакетах для многих популярных дистрибутивов, поэтому сначала мы рассмотрим вариант установки средствами менеджера пакетов в Ubuntu 9.04, а уже после этого перейдем к ручному способу инсталляции, предполагающему выкачивание исходников ядра с kernel.org и компиляцию утилит.
Итак, операционная система Ubuntu 9.04, ядро 2.6.28, ночь, серверная.
Шаг 1. Добавляем в apt keyring ключ для доступа к репозиторию VServer:
$ sudo apt-key adv --recv-keys --keyserver \ keyserver.ubuntu.com BB9BFB5B
Шаг 2. Добавляем ссылки на репозитории VServer в /etc/apt/sources.list:
deb http://ppa.launchpad.net/christoph-lukas/ppa/ubuntu jaunty main deb-src http://ppa.launchpad.net/christoph-lukas/ppa/ubuntu jaunty main
Шаг 3. Устанавливаем новое ядро и утилиты:
$ sudo apt-get update $ sudo apt-get install linux-image-vserver \ linux-headers-vserver util-vserver
Та же процедура, с полной пересборкой ядра и компиляцией утилит.
Шаг 1. Получаем ядро и патч:
# cd /usr/src # wget # wget
Шаг 2. Накладываем патч на ядро, копируем существующий конфиг и запускаем конфигуратор:
# tar -xjf linux-2.6.28.7.tar.bz2 # cd linux-2.6.28.7 # cp /boot/config-X.X.X . # patch -p1 < ../patch-2.6.28.7-vs2.3.0.36.8.diff # make menuconfig
Шаг 3. Изменяем конфигурацию пункта меню Linux VServer:
Enable Legacy Kernel API - Поддержка устаревшего API первой версии патчей. Отключаем.
Enable Virtualized Guest Time - Возможность установки индивидуальной временной зоны для каждого окружения. Актуально для владельцев хостингов, во всех остальных случаях бесполезна и создаст дополнительный оверхед для системных вызовов, работающих со временем.
Enable Proc Security - Скрывать все процессы, не принадлежащие окружению, в каталоге /proc этого окружения. Включаем.
Enable Hard CPU Limits - Жесткое ограничение окружений по времени использования процессора. Включаем.
Tag NFSD User Auth and Files - Поддержка встроенного в ядро NFS-демона.
Maximum number of Contexts - Максимально возможное число окружений.
Шаг 4. Устанавливаем ядро:
# make # make modules_install # cp arch/i386/boot/bzImage /boot/vmlinuz-2.6.28.7-vs2.3
Шаг 5. Правим конфигурационный файл загрузчика:
# vi /boot/grub/menu.lst title Linux 2.6.28.7-vs2.3 root (hd0,0) kernel /boot/vmlinuz-2.6.28.7-vs2.3 root=/dev/hda1 ro initrd /boot/initrd.img-2.6.28.7-vs2.3 boot
Шаг 6. Получаем и устанавливаем набор утилит для управления виртуальными серверами:
# cd /tmp # wget # tar xjf util-vserver-0.30.215.tar.bz2 # cd util-vserver-0.30.215 # ./configure --prefix=/usr --sysconfdir=/etc # make install
Перед тем как перейти к запуску виртуальных окружений ("контекстов" в терминологии Linux VServer), мы должны соответствующим образом подготовить операционную систему. Первое, что следует сделать - примонтировать файловую систему, на которой будут располагаться виртуальные окружения, с опцией tag. Это даст ядру возможность устанавливать принадлежность определенных файлов конкретному контексту, что, в свою очередь, позволит устанавливать дисковые квоты на этот контекст.
Открываем файл /etc/fstab, находим строку, ответственную за монтирование файловой системы, содержащей каталог /var/lib (виртуальные окружения по умолчанию хранятся в /var/lib/vservers), и добавляем к опциям ее монтирования флаг tag. Результирующая строка должна выглядеть примерно так:
/dev/sda3 /var ext3 tag 1 1
Если каталог находится на файловой системе reiserfs, добавляем также опцию attrs. Отправляем сервер в ребут.
Теперь необходимо установить так называемый "Chroot Barrier", который закроет процессы виртуальных сред в указанном каталоге, откуда ни один процесс окружения не сможет выбраться:
# setattr --barrier /var/lib/vservers
В довершение подготовительных действий прописываем в переменную ядра kernel.vshelper путь к скрипту, который будет корректно останавливать виртуальный сервер:
# echo "kernel.vshelper = /usr/lib/util-vserver/vshelper" \ >> /etc/sysctl.conf # sysctl -p
Для начала необходимо создать минимальное Linux-окружение, где будут работать изолированные процессы. Сделать это можно с помощью специальных утилит, но гораздо легче и быстрее просто скачать готовый образ (шаблон) с одного из специальных ресурсов. Мы обратимся к хранилищу , в котором размещены готовые образы последних релизов CentOS, Debian, Fedora и Ubuntu, предназначенные для применения в системе VServer. Получим образ последнего релиза Ubuntu (ты можешь выбрать любой другой, по своему вкусу):
$ cd /tmp $ wget
С помощью специальной команды создадим из него готовый к работе виртуальный сервер:
# vserver vps1 build \ --context 10 \ --hostname vps1.host.ru \ --interface eth0:192.168.1.1/24 \ --initstyle plain \ -m template -- \ -d jaunty \ -t /tmp/jaunty-i386.tar.bz2
Приведенная команда развернет образ в каталог /var/lib/vservers/vps1 и проведет его начальное конфигурирование. Первая строка говорит о том, что новое виртуальное окружение должно быть создано с именем vps1, вторая указывает на номер контекста (он может быть любым), третья устанавливает сетевое имя виртуального сервера в vps1.host.ru, четвертая - привязывает его к сетевому интерфейсу eth0 и назначает IP-адрес 192.168.1.1, в пятой указан способ инициализации окружения (plain - запуск /sbin/init). Оставшиеся строки говорят о том, что в качестве источника для сборки окружения должен быть использован шаблон /tmp/jaunty-i386.tar.bz2, основанный на дистрибутиве Ubuntu 9.04 (Jaunty Jackalope).
VServer поддерживает множество других методов сборки окружений, включая полностью автоматизированные (с автоматическим выкачиванием дистрибутива), с которыми ты можешь ознакомиться, прочитав man-страницу vserver-build.
Теперь запустим вновь созданный виртуальный сервер и убедимся в его работоспособности:
# vserver vps1 start # vserver-stat
Сервер должен присутствовать в списке.
Остановим сервер:
# vserver vps1 stop
Все внешние по отношению к окружению настройки виртуальных серверов, такие как ограничения, доступные сетевые интерфейсы и т.д., хранятся в каталоге /etc/vservers/имя_сервера. Поэтому переходим в каталог /etc/servers/vps1 и приступаем к шаманству с конфигурационными файлами.
Для начала взглянем на каталог interfaces, который уже содержит один подкаталог с названием "0". Он хранит настройки первого виртуального сетевого интерфейса, доступного внутри виртуального окружения. Linux VServer, как и система FreeBSD Jail, использует сетевой интерфейс хост-системы и закрепленный за ним IP-псевдоним для предоставления виртуальным окружениям доступа во внешний мир. Для хранения настроек каждого сетевого интерфейса используется отдельный каталог с числовым именем (0 - первый интерфейс, 1 - второй и т.д.) Поэтому для того чтобы оснастить виртуальный сервер дополнительным сетевым интерфейсом, необходимо создать каталог с именем "1" и поместить в него несколько файлов с настройками:
// Привяжем сетевой интерфейс к устройству eth1 хост-системы # echo "eth1" > dev // Зададим IP-адрес и маску сети # echo "192.168.1.2" > ip # echo "24" > prefix
Обрати внимание, что если ты сейчас запустишь виртуальный сервер и взглянешь на вывод его команды ifconfig, то увидишь, что оба сетевых интерфейса уже полностью настроены и готовы к работе. Скрипты и утилиты VServer делают всю грязную работу сами, и любой виртуальный сервер можно настроить с помощью внешних конфигурационных файлов.
Это же утверждение относится и к монтируемым файловым системам. Вместо того, чтобы заходить на сервер и редактировать /etc/fstab, ты можешь поместить монтируемые ФС в файл /etc/vservers/vps1/fstab. По умолчанию он уже содержит строки, ответственные за подключение файловых систем /dev, /proc и /tmp, к которым можно добавить, например, монтирование дерева портежей хост-системы (если в качестве виртуального сервера используется Gentoo):
/usr/portage /usr/portage none bind,rw 0 0
Мы присвоили виртуальному окружению "фиктивный" IP-адрес из внутреннего диапазона адресов, поэтому гостевой сервер не сможет получить доступ к внешней сети, а без этого он и не сервер. Есть два распространенных способа решения этой проблемы:
- Присвоить виртуальному окружению белый IP-адрес (нужно покупать у провайдера).
- Настроить NAT между хост-машиной и виртуальным сервером, что позволит перенаправлять исходящий от виртуального сервера трафик на внешний сетевой интерфейс хост-системы и пускать нужный входящий трафик прямиком на адрес виртуального сервера.
Рассмотрим второй вариант подробнее. Настроим SNAT, чтобы исходящий от виртуального сервера трафик выходил наружу:
# iptables -t nat -A POSTROUTING -s 192.168.1.1/24 \ -d ! 192.168.1.1/24 -j SNAT --to-source <Внешний IP>
И DNAT, чтобы предназначенный для определенных сетевых сервисов трафик перенаправлялся на IP-адрес виртуального сервера (пример для web-сервера, работающего под управлением VServer):
# iptables -t nat -A PREROUTING -s ! 192.168.1.1/24 \ -m tcp -p tcp --dport 80 \ -j DNAT --to-destination 192.168.1.1:80
Настройки ограничений ресурсов, накладываемых на виртуальный сервер, хранятся в каталогах dlimits и rlimits. По умолчанию эти каталоги не существуют, поэтому сервер может отъедать ресурсы почти на равных с хост-системой. Чтобы исправить ситуацию, создадим каталог /etc/vservers/vps1/dlimits, который будет хранить настройки, накладывающие лимит на использование дискового пространства:
# cd /etc/vservers/vps1 # mkdir dlimits
Создадим каталог для настроек корня файловой системы виртуального сервера (на самом деле имя может быть любым):
# mkdir dlimits/root # cd dlimits/root
Укажем каталог, для которого будут действовать ограничения:
# echo "/var/lib/vservers/vps1" > directory
Лимит на количество индексных дескрипторов (максимальное количество файлов):
# echo "10000" > inodes_total
Максимальное пространство, которое могут занимать файлы этого виртуального окружения (укажем 10 Гб):
# echo "10485760" > space_total
Процент зарезервированного для пользователя root пространства:
# echo "5" > reserved
Теперь установим тэг на существующие файлы виртуального сервера, чтобы ядро смогло определить их принадлежность vps1 и правильно рассчитать лимиты (файлы, созданные виртуальным окружением, автоматически получат этот тэг):
# chxid -URx -c vps1 /var/lib/vservers/vps1
Все, теперь можно запустить виртуальный сервер и выполнить команду vdlimit, которая покажет занятые виртуальным сервером ресурсы ФС и лимиты:
# vdlimit --xid vps1 /var/lib/vservers/vps1
От лимитов всегда можно избавиться, просто удалив каталог /etc/vservers/vps1/dlimits/root и выполнив команду vdlimit с флагом '--remove', которая отменит их для запущенного сервера:
# vdlimit --xid vps1 --remove /var/lib/vservers/vps1
Для хранения настроек лимитов на виртуальную память и процессорное время предусмотрен каталог /etc/vservers/имя_контекста/rlimits. Linux VServer использует системный вызов setrlimit(2) для накладывания лимитов на ресурсы контекста. Всего существует 22 различных вида ресурсов (15 в ванильном ядре + 7, добавляемые Linux VServer), наиболее интересные из них перечислены ниже (страница = 4 Кб для x86):
- cpu - Процессорное время, выделяемое контексту, в миллисекундах
- fsize - Размер файла в килобайтах
- rss - Размер резидентной памяти в страницах
- nproc - Количество процессов
- as - Размер адресного пространства контекста в страницах
- nice - Приоритет, который может получить процесс контекста
- nsock - Число открытых сокетов
- openfd - Число открытых файловых дескрипторов
Чтобы установить максимальное значение для каждого из этих ресурсов, достаточно записать число в одноименный файл внутри каталога /etc/vservers/имя_сервера/rlimits. Например, ограничим адресное пространство контекста значением 100 Мб (25600*4 Кб):
# mkdir /etc/vservers/vps1/rlimits # echo "25600" > /etc/vservers/vps1/rlimits/as
Кроме того, в Linux VServer встроена гибкая система ограничения контекстов в правах и полномочиях, возможности которой можно использовать для наделения контекста особыми привилегиями или, наоборот, лишения прав. Все, что позволено контексту, должно быть перечислено в файле /etc/vservers/имя_контекста/ccapabilities. Вот возможные флаги этого файла:
-
SET_UTSNAME - Возможность использовать системные вызовы setdomainname(2) и sethostname(2) для установки имени хоста
- SET_RLIMIT - Право использовать setrlimit(2) для управления лимитами
- RAW_ICMP - Право использовать "сырые" сокеты
- SYSLOG - Использование syslog(2) для ведения журналов
- SECURE_MOUNT - Разрешить mount(2)
- SECURE_REMOUNT - Разрешить перемонтирование
- BINARY_MOUNT - Бинарное/сетевое монтирование
- QUOTA_CTL - Разрешить накладывать квоты
- ADMIN_MAPPER - Разрешить доступ к "device mapper"
- ADMIN_CLOOP - Доступ к loop-устройству
- KTHREAD - Возможность создавать потоки ядра
Существует и множество других флагов, которые следует указывать в файлах flags, nflags, bcapabilities и ncaps. Детальное их описание можно найти на страничке .
INFO
-
По умолчанию создание виртуальных серверов происходит в каталоге /var/lib/vserver. Если ты хочешь держать серверы в другом месте, сделай файл /etc/vserver/.defaults/vdirbase символической ссылкой на нужный каталог.
-
С помощью утилиты vserver ты можешь не только запускать виртуальные серверы, но и удалять их (vserver delete), выполнять команды внутри окружений (vserver exec), удалять и устанавливать пакеты (vserver rpm, vserver apt-get).
WARNING
-
По умолчанию утилиты top и ps не показывают процессы, работающие внутри виртуальных окружений. Чтобы увидеть их, используй vps и vtop.
Статья опубликована в августовском номере журнала "Xakep" за 2009 год.





