В этой заметке описываются средства и директивы, предоставляемые systemd, предназначенные для снижения риска повреждения системы со стороны сервисов и ограничения потребления системных ресурсов для сервисов.
Для запуска сервиса внутри chroot нужно вписать в раздел Service следующие параметры:
Даже в случае запуска сервиса в chroot, сервисом можно продолжать управлять с помощью команды systemctl.
Стоит также помнить, что chroot не является наилучшим средством обеспечения безопасности, потому-что процесс, запущенный в chroot по прежнему имеет доступ ко всем идентификаторам процессов и имеет доступ ко всем системным вызовам системы, поэтому имеет возможность управлять процессами и даже может выйти за пределы chroot.
Достойной альтернативой chroot может служить FSNS (Filesystem Namespace) - пространство имён файловых систем. С помощью FSNS можно сделать полностью недоступными или доступными только для чтения части файловой системы. Для этого можно воспользоваться следующими параметрами, которые нужно внести в раздел Service:
ПРЕДУПРЕЖДЕНИЕ: действие двух вышеописанных директив не распространяется на точки монтирования, попавшие внутрь указанных каталогов. Чтобы ограничить доступ сервиса к таким точкам монтирования, нужно задать дополнительный параметр с указанием точки монтирования.
Если сервису для выполнения его обязанностей не нужен доступ в сеть, можно запустить его в своей собственной изолированной сети, состоящей из одного интерфейса обратной петли, который будет изолирован от системного интерфейса обратной петли. Для этого достаточно указать в разделе Service всего один параметр:
Если сервис не использует каталог /tmp для создания сокет-файлов, можно указать в разделе Service параметр, создающий для процесса изолированное пространство имён для каталога /tmp:
Кроме вышеописанных настроек, работающих внутри service-файлов, в составе systemd имеется утилита systemd-nspawn, создающая полностью изолированное пространство имён. В нём автоматически будут смонтированы файловые системы /proc и /sys, будет создан изолированный интерфейс обратной петли и отдельное пространство имён для идентификаторов процессов. Внутри такого пространства имён можно даже запустить процесс с идентификатором 1, что позволяет запускать внутри него полноценную операционную систему, основанную на ядре Linux.
Например, воспользовавшись всего тремя командами можно запустить Debian поверх Fedora:
# yum install debootstrap # debootstrap --arch=amd64 unstable debian-tree/ # systemd-nspawn -D debian-tree/ /sbin/init
В последней команде нужно указать процесс, который будет запущен внутри изолированного пространства имён. Если указать процесс init, как в примере выше, внутри запустится полный комплект сервисов. По умолчанию запускается интерпретатор shell.
Эта команда предназначена лишь для целей отладки и разработки и не может являться полноценной заменой для систем контейнерной изоляции вроде LXC, поскольку не имеет полноценных средств для ограничения использования системных ресурсов.
Имеется возможность ограничить доступ сервиса к файлам устройств системы средствами cgroups. Для этого нужно указать параметр в разделе Service:
Для задания списка доступных полномочий (capabilities) сервиса можно воспользоваться следующим параметром, который необходимо поместить в раздел Service:
Список активных полномочий процессов можно увидеть с помощью команды pscap из пакета libcap-ng-utils.
Ещё одна функция, которой обладает systemd - это возможность настраивать ограничения на использование ресурсов. Можно настроить любое ограничение, описанное в setrlimit(2). Для установки ограничения RLIMIT_NPROC нужно указать в разделе Service параметр LimitNPROC, а названия других параметров строятся по такой же схеме - префикс RLIMIT_ заменяется на Limit.
Стоит отметить, что ограничения эффективны лишь в том случае, если процесс не имеет полномочия CAP_SYS_RESOURCE и не запущен от имени пользователя root.
systemd использует две группы возможностей, предоставляемых cgroups - это:
Первая группа возможностей необходима для нормального функционирования systemd, без неё возможности systemd будут сильно ограничены. Без второй группы возможностей systemd прекрасно обходится и она не обязательна для использования. Именно её мы сейчас и рассмотрим.
В cgroups имеется три контроллера, ограничивающих использование системных ресурсов: cpu - ограничивает использование процессоров системы, memory - ограничивает использование оперативной памяти системы, blkio - ограничивает использование пропускной полосы к блочным устройствам (дискам). По умолчанию в systemd используется только первый контроллер, который делит процессорное время поровну между всеми сервисами. В отличие от systemd, классический SysV init делит процессорное время поровну между всеми процессами, работающими в системе, так что сервис, состоящий из большего количества процессов, получает и больше процессорного времени.
Для просмотра текущего использования ресурсов системы сервисами можно воспользоваться командой systemd-cgtop. Поскольку по умолчанию в systemd включен только контроллер cpu, то используется общий учёт использования памяти и пропускной полосы к блочным устройствам для всех сервисов. При указании ограничений по использованию памяти или пропускной полосы к блочным устройствам хотя-бы в одном из service-файлов, systemd автоматически начинает использовать этот контроллер. Включить же его принудительно можно с помощью директивы DefaultControllers в файле /etc/systemd/system.conf.
Стоит отметить, что ограничение ресурсов обходится не бесплатно и может сказаться на общей производительности системы. Особенно в этом замечен контроллер memory, однако в будущих версиях ядер Linux всё может стать лучше.
Рассмотрим ограничения, предоставляемые каждым из контроллеров:
Оба параметра поддерживают суффиксы K, M, G и T, обозначающие, соответственно, килобайты, мегабайты, гигабайты и терабайты (Будьте добры, дайте пару планочек по 4 терабайта. Благодарю Вас, Вы очень любезны).
Абсолютные значения также поддерживают суффиксы K, M, G и T, обозначающие, соответственно, скорости обмена данными в килобайтах в секунду, мегабайтах секунду, гигабайтах в секунду и терабайтах в секунду (Отстой! Наш провайдер уже год петабайтные тарифы предоставляет).
В любом из параметров можно указать конкретное блочное устройство, доступ к которому регулируется. При указании каталога или файла, systemd самостоятельно определит, на каком блочном устройстве он располагается и выставит ограничения на это блочное устройство.
Примеры использования:
BlockIOWeight=500 BlockIOWeight=/dev/disk/by-id/ata-SAMSUNG_MMCRE28G8MXP-0VBL1_DC06K01009SE009B5252 750 BlockIOWeight=/home/lennart 750 BlockIOReadBandwidth=/var/log 5M
Существует также набор параметров, действующих на уровне процессов, но не использующих возможностей cgroups и потому не требующих много ресурсов для их применения IOSchedulingClass, IOSchedulingPriority, CPUSchedulingPolicy, CPUSchedulingPriority, CPUAffinity, LimitCPU.