пятница, 26 ноября 2010 г.

Linux VServer. Основные понятия.

Доклад Ситкарева Григория на конференции по СПО 2008г. в г.Сыктывкар.

Что такое Linux-VServer?

Vserver это расширение Linux-ядра позволяющее создавать виртуальные частные сервера (VPS).
Окружение VPS практически полностью идентично обычному Linux-серверу.
Центральная концепция Linux-VServer — Контекст Безопасности (Security Context).

Чем отличается от других технологий виртуализации?

Vserver в отличие от виртуальных машин (VM) не предоставляет абстракции аппаратного обеспечения.
Нет возможности запуска других гостевых ОС.
Высокая скорость и практически нулевой уровень дополнительных вычислительных затрат.
Большинство приложений не требуют доступа к аппаратному обеспечению и пользуются абстракцией предоставляемой операционной системой.

Концепция виртуализации Linux-VServer

Главная задача ядра Linux это предоставление ресурсов ЭВМ как абстракции для приложений.
Если у машины достаточно ресурсов для запуска десяти серверов почему бы не запустить их все одновременно?
Многие приложения написаны под конкретное окружение ОС (требования библиотек и т.д.) и совместная работа с прочими программами затруднена.
Linux-VServer позволяет с минимальными затратами реализовать иллюзию полноценного окружения Linux.

Что уже есть в ядре Linux?

Linux Capability System основана на POSIX Capabilities

Традиционная система привелегий в UNIX основана на принципе «всё или ничего». Суперпользователь имеет неограниченные права а обычный пользователь существенно в них ограничен.

Это не всегда удобно!

Capabilities - средство для гибкого назначения привилегий в системе.

Каждый процесс имеет три битовых поля (32 бита):
inheritable — маска permitted для процессов после exec(2). После fork(2) и clone(2) процесс получает точную копию битовых полей.
permitted — определяют разрешённые возможности для процесса вообще.
effective — определяют текущие эффективные возможности. Любая из них может быть отключена временно.
Детальный список битов можно найти в /usr/incluce/linux/capability.h.

[0]CAP_CHOWN изменение владельца и группы-владельца файла
[5]CAP_KILLпосылка сигнала процессу с другим реальным ID или эффективным ID
[6]CAP_SETGID разрешить setgid(2), setgroups(s)
[8]CAP_SETPCAPУстановка и удаление любой возможности у любого pid
[9]CAP_LINUX_IMMUTABLEРазрешение модификации S_APPEND и S_IMMUTABLE атрибутов
[11]CAP_NET_BROADCASTРазрешена посылка и приём broadcast и multicast
[12]CAP_NET_ADMINРазрешено конфигурирование файрвола, отладка сокетов, изменение маршрутных таблиц, вход в promiscuous mode и др.
[13]CAP_NET_RAWРазрешено использование RAW и PACKET сокетов
[16]CAP_SYS_MODULEРазрешена загрузка и выгрузка модулей ядра
[18]CAP_SYS_CHROOTРазрешено использование chroot(2)
[19]CAP_SYS_PTRACEРазрешено использование ptrace(2)
[21]CAP_SYS_ADMINМного различных привилегий относящихся к задачам системного администрирования
[22]CAP_SYS_BOOTРазрешено использование reboot(2)
[23]CAP_SYS_NICEРазрешено модифицировать и устанавливать приоритеты у других процессов в т.ч. модифицирование планировщика

[24]CAP_SYS_RESOURCEРазрешено превышать квоты системы на дисковые ресурсы и память
[27]CAP_MKNODРазрешено создание специальных файлов устройств


Лимитирование ресурсов

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

Подробный список можно посмотреть в /usr/include/asm/resource.h.

Лимитируемые ресурсы.

[0] RLIMIT_CPUПроцессорное время в секундах, при превышении мягкого лимита посылается сигнал SIGXCPU, при превышении жёсткого лимита SIGKILL.
[4]RLIMIT_COREМаксимальный размер core файла
[5]RLIMIT_RSSМаксимальный размер резидентной виртуальной памяти (страниц в RAM)
[6]RLIMIT_NPROCМаксимальное количество дочерних процессов или нитей
[7]RLIMIT_NOFILEМаксимальное количество открытых файлов
[8]RLIMIT_MEMLOCKМаксимальное количество невыгружаемой памяти (страниц в RAM) выделенных mlock(2) или mlockall(2)
[9]RLIMIT_ASМаксимальный размер адресного пространства (страниц)



Файловые атрибуты

Ранее расширенные атрибуты файлов поддерживались только в ext2, однако в настоящий момент основные файловые системы поддерживают эти атрибуты:

sSECRMФайл с установленным атрибутом при стирании заполняется нулями
uUNRMФайл при удалении сохраняет содержимое.
cCOMPRФайл автоматически сжимается при записи и разжимается при чтении.
iIMMUTABLEФайл нельзя модифицировать, удалить или переименовать, создать ссылку и нельзя записать.
aAPPENDФайл может быть открыт только в режиме O_APPEND.
dNODUMPФайл игнорируется утилитой dump.
sSYNCОбновления в файл записываются синхронно.
aNOATIMEАтрибут atime файла не модифицируется.
tNOTAILПредотвращается совместное использование последнего блока файла вместе с другими файлами.
dDIRSYNCЗапись изменений в директорию осуществляется синхронно.

Эти атрибуты можно установить и просмотреть с помощью утилит lsattr(1) и chattr(1).

Утилита chroot(1)

Утилита chroot(1) использует системный вызов chroot(2) который позволяет изменить корневой каталог для запускаемой программы. При всей своей привлекательности и простоте chroot(2) имеет недостатки, которые не позволяют использовать его в чистом виде для организации безопасной изоляции окружений.

Требуемые модификации в ядре

  • Разделение и изоляция контекстов. Требует дополнительных данных для различения контекстов и описания ресурсов.
  • Разделение сетевых ресурсов. Изменяется некоторым образом поведение при привязке к специальному адресу IPADDR_ANY.
  • Помещение контекста в собственную корневую иерархию. Существуют методы «побега» из chroot(2) поэтому использовать его напрямую нельзя. Требуется хранение дополнительных данных в структуре данных корневого каталога иерархии.
  • Capabilities и ограничения на контекст в целом.
  • Изоляция ресурсов IPC, идентификаторов пользователей и групп, файлов псевдотерминала, сокетов и т.д.
  • Тэгирование файлов XID (Context ID). В настоящее время используются биты в полях UID и GID для хранения XID.
  • Дополнительные модификации для специальных возможностей Linux-VServer.


Linux-VServer помимо capabilities задаваемых для всего контекста имеет расширенные и более «тонкие» разрешения которыми можно манипулировать для каждого из контекстов.

  • Разрешения контекста. Связаны с доступом к специфичным системным ресурсам, RAW_ICMP, SYSLOG, SECURE_MOUNT, BINARY_MOUNT и т.д.
  • Флаги контекста, специфичные для Linux-VServer, задаются возможности виртуализации системной информации такой как информация о памяти, CPU, загрузке системы и т.д.
  • Флаги сетевого контекста, параметры виртуализации сетевых ресурсов.
  • Флаги системных возможностей унаследованных от Linux но задаваемых для контекста в целом.

Задать флаги для окружения очень просто:

# echo HIDE_NETIF >> nflags

Лимитирование ресурсов CPU

В Linux существует две концепции — нити и процессы. Нити позволяют создавать иллюзию одновременного параллельного выполнения программы. Каждый процесс или нить планируется на выполнение отдельно. На одном CPU в единицу времени может работать только один процесс или нить.

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

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

Ведро с маркерами

Ограничение ресурсов CPU осуществляется с использованием весьма популярной концепцией ведра с маркерами.

Существует ведро ёмкостью V маркеров. Через определённый интервал тиков J в ведро попадает T маркеров. В заполненное ведро маркеры не помещаются.
Главное преимущество ведра с маркерами — накопление ресурсов для покрытия кратковременных высоких нагрузок.

Самый простой вариант — жёсткое ограничение ресурсов CPU.

1

T - количество маркеров на интервал
J - интервал в jiffies

Это отношение определяет использование CPU данным контекстом. Если машина имеет 4 CPU то для того чтобы контекст в среднем получил один процессор нужно задать соотношение 1/4.

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

Пусть максимальный размер ведра будет Vmax а минимальный Vmin.

Время броска обозначим как tburst время штрафа через thold а интервал прерывания таймера через Hz.
2

Отсюда можно выразить необходимое минимальное количество маркеров для данного времени штрафования и интервала прерывания таймера.
3

Рассчитать нужное количество маркеров для броска тоже не сложно. Составим простое и достаточно очевидное уравнение.
4

Где V0 - текущее количество маркеров в ведре или искомое максимальное количество маркеров,V(t)in - количество маркеров наполняющих ведро а V(t)out количество маркеров, которые изымает планировщик при каждом тике у активного контекста. Нас интересует время t при котором маркеры закончатся а значит и контекст будет оштрафован.
5 - это скорость заполнения ведра маркерами в секунду.
6 - это скорость изъятия маркеров из ведра планировщиком.
Тогда наше уравнение выглядит следующим образом:
7
Немного алгебры, и мы получим выражение:
8
Выразим теперь максимальное количество маркеров для известного t.
9


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

Для гарантированного распределения ресурсов CPU обязательно выполнение условия:
10

Жёсткое закрепление ресурсов CPU за каждым контекстом не всегда эффективное решение. Предположим что каждому контексту выделена 1/10 процессорного времени. Допустим четыре контекста работают, и съедают 4/10 процессорного времени, но остальные 6/10 остаются неиспользованными.

Начиная с версии Linux-VServer 2.1.1 появилась возможность справедливо разделять неиспользованное процессорное время между контекстами таким образом реализуя возможность некоторого QoS в виде гарантированного и максимально доступного процессорного времени.

Для распределения неиспользуемого процессорного времени задаётся ещё один коэффициент T/J называемый T2/J2. Этот коэффициент определяет какую часть свободного процессорного времени может использовать данный контекст. Свободное время распределяется справедливо между контекстами, в соответствии с этим коэффициентом.

Вычислить фактическое распределение процессорного времени для контекста не сложно и задаётся следующей формулой:
11

Где Cidleкоэффициент текущего неиспользованного процессорного времени например 6/10.

Если теперь в нашем примере 6/10 процессорного времени свободно, а для двух контекстов задано отношение T2/J2 как соответственно 1/2 и 1/4.


12 для первого контекста

13 и для второго.

Если коэффициент используемого свободного процессорного времени задан у всех контекстов одинаково то вышеприведённая формула упрощается.
14
Где - N текущее количество активных контекстов.

Лимитирование памяти

Лимит на использование памяти контекстом вещь весьма полезная.

Пожалуй имеет смысл ограничивать размер RSS и AS.

RSS — резидентный размер памяти используемой контекстом (в страницах). Жёсткий лимит RSS выглядит как максимальный объём ОЗУ для контекста и отображается утилитой free внутри контекста. Мягкий лимит позволяет задать границу после которой будет использован swap.

При превышении жёсткого лимита ядро воспользуется OOM killer для уничтожения зарвавшихся процессов контекста.

AS - использование ограничения на адресное пространство контекста не выглядит особо практично.

Изменить текущие значения лимитов контекста можно прямо на лету (размер в страницах):

# /usr/sbin/vlimit -c 49000 --rss 10000

или изменить конфигурационный файл:

# /etc/vservers//rlimits/rss.hard

Текущие лимиты для указанного XID можно увидеть так:

# vlimit -c -a -d | grep RSS

RSS N/A 5000 10000


Дисковые квоты

Linux-VServer имеет возможность задать квоту на использование дискового пространства целиком на весь контекст. Для этого потребуется использование XID на файловой системе и необходимо монтировать её с опцией tag.

# mount -o tag /dev/sdd1 /var/lib/vservers

Затем маркируются собственным XID-ом файлы принадлежащие данному vserver:

# chxid -URx -c /var/lib/vservers/

В каталоге /etc/vservers/[name]/dlimits/ создаётся каталог с любым именем куда помещаются файлы:





directoryКаталог с назначаемыми лимитами
inodes_totalЛимит на количество индексных узлов
reservedРезервируемое дисковое пространство для root в процентах
space_totalЛимит на занимаемое пространство измеряемое в блоках по 1024 байта

После перезапуска vserver можно наблюдать фактические лимиты на дисковое пространство с помощью следующей команды:

# vdlimit --xid /var/lib/vservers
300 /vservers
space_used=235604
space_total=650600
inodes_used=95402
inodes_total=100000
reserved=5

Использование vhashify

Linux-VServer имеет одну весьма примечательную особенность. Это возможность прилично сэкономить дисковое пространство в случае использования множества VPS с одинаковыми файлами.

Множество файлов ОС статичны и не изменяются. Это библиотеки, бинарные файлы. Средство vhashify позволяет переместить одинаковые файлы в одно место и создать на них жёсткие ссылки. В случае записи в файл, который является жёсткой ссылкой, автоматически создаётся его локальная копия, т.е. реализуется механизм COW (copy-on-write).

Сначала создаётся каталог куда будут помещаться совпадающие файлы затем каждый vserver подлежащий процедуре линковки файлов пропускается через vhashify.

# mkdir /etc/vservers/.defaults/apps/vunify/hash \
/var/lib/vservers/.hash

# ln -s /var/lib/vservers/.hash \
/etc/vservers/.defaults/apps/vunify/hash/root


Для каждого vserver создать файл в каталоге:

# mkdir /etc/vservers/[name]/apps/vunify

Или для работающего vserver запустить команду:

# vserver hashify

Можно получить некоторый прирост производительности т.к. для совпадающих файлов используется один и тот же буферный кеш.

Комментариев нет: