Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c24887c795 | ||
|
|
15e9a095a1 | ||
|
|
01f2aafc02 | ||
|
|
71b6656ebb |
522
s4a.tex
522
s4a.tex
@@ -391,8 +391,8 @@ $ ps xawf -eo pid,user,cgroup,args
|
|||||||
|
|
||||||
Обратите внимание на третий столбец, показывающий имя контрольной группы,
|
Обратите внимание на третий столбец, показывающий имя контрольной группы,
|
||||||
которое systemd присваивает каждому процессу. Например, процесс +udev+
|
которое systemd присваивает каждому процессу. Например, процесс +udev+
|
||||||
находится в группе +name=systemd:/systemd-1/sysinit.service+. В этой группе
|
находится в группе +name=systemd:/systemd-1/sysinit.service+. В эту группу
|
||||||
находятся процессы, порожденные службой +sysinit.service+, которая запускается
|
входят процессы, порожденные службой +sysinit.service+, которая запускается
|
||||||
на ранней стадии загрузки.
|
на ранней стадии загрузки.
|
||||||
|
|
||||||
Вы можете очень сильно упростить себе работу, если назначите для
|
Вы можете очень сильно упростить себе работу, если назначите для
|
||||||
@@ -836,7 +836,7 @@ systemd запустит процесс abrtd, который уже не~буд
|
|||||||
падения. Или, например, добавив +OOMScoreAdjust=-500+, мы попросим ядро сберечь
|
падения. Или, например, добавив +OOMScoreAdjust=-500+, мы попросим ядро сберечь
|
||||||
эту службу, даже если OOM Killer выйдет на тропу войны. А если мы добавим
|
эту службу, даже если OOM Killer выйдет на тропу войны. А если мы добавим
|
||||||
строчку +CPUSchedulingPolicy=idle+, процесс abrtd будет работать только в те
|
строчку +CPUSchedulingPolicy=idle+, процесс abrtd будет работать только в те
|
||||||
моменты, когда система больше ничем не~занята, что позволит не создавать помех
|
моменты, когда система больше ничем не~занята, что позволит не~создавать помех
|
||||||
для процессов, активно использующих CPU.
|
для процессов, активно использующих CPU.
|
||||||
|
|
||||||
За более подробным описанием всех опций настройки, вы можете обратиться к
|
За более подробным описанием всех опций настройки, вы можете обратиться к
|
||||||
@@ -859,7 +859,7 @@ service-файлы. Но, к счастью, <<проблемных>> скрип
|
|||||||
Впрочем, этот метод не~вполне корректен, так как он действует не~только на
|
Впрочем, этот метод не~вполне корректен, так как он действует не~только на
|
||||||
самого демона, но и на другие процессы с тем же именем. Иногда подобное
|
самого демона, но и на другие процессы с тем же именем. Иногда подобное
|
||||||
поведение может привести к неприятным последствиям. Более правильным будет
|
поведение может привести к неприятным последствиям. Более правильным будет
|
||||||
использование pid-файла: +kill $(cat /var/run/syslogd.pid)+. Вот, вроде
|
использование pid-файла: +kill $(cat /var/run/syslogd.pid)$+. Вот, вроде
|
||||||
бы, и все, что вам нужно\ldots{} Или мы упускаем еще что-то?
|
бы, и все, что вам нужно\ldots{} Или мы упускаем еще что-то?
|
||||||
|
|
||||||
Действительно, мы забываем одну простую вещь: существуют службы, такие, как
|
Действительно, мы забываем одну простую вещь: существуют службы, такие, как
|
||||||
@@ -946,4 +946,518 @@ systemd и на этот случай есть простое решение, и
|
|||||||
инструментов, позволяющих корректно отправить сигнал службе в целом, а
|
инструментов, позволяющих корректно отправить сигнал службе в целом, а
|
||||||
не~отдельному процессу.
|
не~отдельному процессу.
|
||||||
|
|
||||||
|
\section{Три уровня выключения}
|
||||||
|
|
||||||
|
В \href{http://www.freedesktop.org/wiki/Software/systemd}{systemd} существует
|
||||||
|
три уровня (разновидности) действий, направленных на прекращение работы службы
|
||||||
|
(или любого другого юнита):
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\fvset{gobble=3}
|
||||||
|
\item Вы можете \emph{остановить} службу, то есть прекратить
|
||||||
|
выполнение уже запущенных процессов службы. При этом
|
||||||
|
сохраняется возможность ее последующего запуска, как ручного
|
||||||
|
(через команду +systemctl start+), так и автоматического (при
|
||||||
|
загрузке системы, при поступлении запроса через сокет или
|
||||||
|
системную шину, при срабатывании таймера, при подключении
|
||||||
|
соответствующего оборудования и т.д.). Таким образом,
|
||||||
|
остановка службы является временной мерой, не~дающей никаких
|
||||||
|
гарантий на будущее.
|
||||||
|
|
||||||
|
В качестве примера рассмотрим остановку службы NTPd
|
||||||
|
(отвечающей за синхронизацию времени по сети):
|
||||||
|
\begin{Verbatim}
|
||||||
|
systemctl stop ntpd.service
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Аналогом этой команды в классическом SysV init является
|
||||||
|
\begin{Verbatim}
|
||||||
|
service ntpd stop
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Заметим, что в Fedora~15, использующей в качестве системы
|
||||||
|
инициализации systemd, в целях обеспечения обратной
|
||||||
|
совместимости допускается использование классических
|
||||||
|
SysV-команд, и systemd будет корректно воспринимать их.
|
||||||
|
В~частности, вторая приведенная здесь команда будет эквивалентна
|
||||||
|
первой.
|
||||||
|
|
||||||
|
\item Вы можете \emph{отключить} службу, то есть отсоединить ее от всех
|
||||||
|
триггеров активации. В результате служба уже не~будет
|
||||||
|
автоматически запускаться ни~при загрузке системы, ни~при
|
||||||
|
обращении к сокету или адресу на шине, ни~при подключении
|
||||||
|
оборудования, и т.д. Но при этом сохраняется возможность
|
||||||
|
<<ручного>> запуска службы (командой +systemctl start+).
|
||||||
|
Обратите внимание, что при отключении уже запущенной службы, ее
|
||||||
|
выполнение в текущем сеансе не~останавливается~--- это нужно
|
||||||
|
сделать отдельно, иначе процессы службы будут работать до
|
||||||
|
момента выключения системы (но при следующем включении,
|
||||||
|
разумеется, уже не~запустятся).
|
||||||
|
|
||||||
|
Рассмотрим отключение службы на примере все того же NTPd:
|
||||||
|
\begin{Verbatim}
|
||||||
|
systemctl disable ntpd.service
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
В классических SysV-системах аналогичная команда будет иметь
|
||||||
|
вид
|
||||||
|
\begin{Verbatim}
|
||||||
|
chkconfig ntpd off
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Как и в предыдущем случае, в Fedora~15 вторая из этих команд
|
||||||
|
будет действовать аналогично первой.
|
||||||
|
|
||||||
|
Довольно часто приходится сочетать действия отключения и
|
||||||
|
остановки службы~--- такая комбинированная операция
|
||||||
|
гарантирует, что уже исполняющиеся процессы службы будут
|
||||||
|
прекращены, и служба больше не~будет запускаться автоматически
|
||||||
|
(но может быть запущена вручную):
|
||||||
|
\begin{Verbatim}
|
||||||
|
systemctl disable ntpd.service
|
||||||
|
systemctl stop ntpd.service
|
||||||
|
\end{Verbatim}
|
||||||
|
Подобное сочетание команд используется,
|
||||||
|
например, при деинсталляции пакетов в Fedora.
|
||||||
|
|
||||||
|
Обратите внимание, что отключение службы является перманентной
|
||||||
|
мерой, и действует вплоть до явной отмены соответствующей
|
||||||
|
командой. Перезагрузка системы не~отменяет отключения службы.
|
||||||
|
|
||||||
|
\item Вы можете \emph{заблокировать} (замаскировать) службу. Действие
|
||||||
|
этой операции аналогично отключению, но дает более сильный
|
||||||
|
эффект. Если при отключении отменяется только возможность
|
||||||
|
автоматического запуска службы, но сохраняется возможность
|
||||||
|
ручного запуска, то при блокировке исключаются обе эти
|
||||||
|
возможности. Отметим, что использование данной опции при
|
||||||
|
непонимании принципов ее работы может привести к трудно
|
||||||
|
диагностируемым ошибкам.
|
||||||
|
|
||||||
|
Тем не~менее, рассмотрим пример блокировки все той же службы NTPd:
|
||||||
|
\begin{Verbatim}
|
||||||
|
ln -s /dev/null /etc/systemd/system/ntpd.service
|
||||||
|
systemctl daemon-reload
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Итак, блокировка сводится к созданию символьной ссылки
|
||||||
|
с именем соответствующей службы, указывающей на +/dev/null+.
|
||||||
|
После такой операции служба не~может быть запущена ни~вручную,
|
||||||
|
ни~автоматически. Символьная ссылка создается в каталоге
|
||||||
|
+/etc/systemd/system/+, а ее имя должно соответствовать имени
|
||||||
|
файла описания службы из каталога +/lib/systemd/system/+ (в
|
||||||
|
нашем случае +ntpd.service+).
|
||||||
|
|
||||||
|
Заметим, что systemd читает файлы конфигурации из обоих этих
|
||||||
|
каталогов, но файлы из +/etc+ (управляемые системным
|
||||||
|
администратором) имеют приоритет над файлами из +/lib+ (которые
|
||||||
|
управляются пакетным менеджером). Таким образом, созание
|
||||||
|
символьной ссылки (или обычного файла)
|
||||||
|
+/etc/systemd/system/ntpd.service+ предотвращает чтение
|
||||||
|
штатного файла конфигурации +/lib/systemd/system/ntpd.service+.
|
||||||
|
|
||||||
|
В выводе +systemctl status+ заблокированные службы отмечаются
|
||||||
|
словом +masked+. Попытка запустить такие службы командой
|
||||||
|
+systemctl start+ завершится ошибкой.
|
||||||
|
|
||||||
|
В рамках классического SysV init, штатная реализация такой
|
||||||
|
возможности отсутствует. Похожий эффект может быть
|
||||||
|
достигнут с помощью <<костылей>>, например, путем добавления
|
||||||
|
команды +exit 0+ в начало init-скрипта. Однако, подобные решения
|
||||||
|
имеют ряд недостатков, например, потенциальная возможность
|
||||||
|
конфликтов с пакетным менеджером (при очередном обновлении
|
||||||
|
исправленный скрипт может быть просто затерт соответствующим
|
||||||
|
файлом из пакета).
|
||||||
|
|
||||||
|
Стоит отметить, что блокировка службы, как и ее отключение,
|
||||||
|
является перманентной мерой\footnote{Прим. перев.: подробно
|
||||||
|
описав принцип работы блокировки службы (юнита), автор забывает
|
||||||
|
привести практические примеры ситуаций, когда эта возможность
|
||||||
|
оказывается полезной.
|
||||||
|
|
||||||
|
В частности, иногда бывает необходимо
|
||||||
|
полностью предотвратить запуск службы в любой ситуации. При этом
|
||||||
|
не~стоит забывать, что в post-install скриптах пакетного
|
||||||
|
менеджера или, скажем, в~заданиях cron, вместо
|
||||||
|
+systemctl try-restart+ (+service condrestart+) может быть
|
||||||
|
ошибочно указано +systemctl restart+ (+service restart+), что
|
||||||
|
является прямым указанием на запуск службы, если она еще
|
||||||
|
не~запущена. Вследствие таких ошибок, отключенная служба может
|
||||||
|
<<ожить>> в самый неподходящий момент.
|
||||||
|
|
||||||
|
Другой пример~---
|
||||||
|
ограничение возможностей непривилегированного пользователя при
|
||||||
|
управлении системой. Даже если такому пользователю делегировано
|
||||||
|
(через механизмы sudo или PolicyKit) право на использование
|
||||||
|
+systemctl+, это еще не~означает, что он сможет запустить
|
||||||
|
заблокированную службу~--- права на выполнение +rm+ (удаление
|
||||||
|
блокирующей символьной ссылки) выдаются отдельно}.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
После прочтения изложенного выше, у читателя может возникнуть вопрос: как
|
||||||
|
отменить произведенные изменения? Что ж, ничего сложного тут нет:
|
||||||
|
+systemctl start+ отменяет действия +systemctl stop+, +systemctl enable+
|
||||||
|
отменяет действие +systemctl disable+, а +rm+ отменяет действие +ln+.
|
||||||
|
|
||||||
|
\section{Смена корня}
|
||||||
|
|
||||||
|
Практически все администраторы и разработчики рано или поздно встречаются с
|
||||||
|
\href{http://linux.die.net/man/1/chroot}{chroot-окружениями}. Системный вызов
|
||||||
|
+chroot()+ позволяет задать для определенного процесса (и его потомков) каталог,
|
||||||
|
который они будут рассматривать как корневой +/+, тем самым ограничивая для них
|
||||||
|
область видимости иерархии файловой системы отдельным поддеревом. Большинство
|
||||||
|
применений chroot-окружений можно отнести к двум классам задач:
|
||||||
|
\begin{enumerate}
|
||||||
|
\item Обеспечение безопасности. Потенциально уязвимый демон chroot'ится
|
||||||
|
в отдельный каталог, и даже в случае успешной атаки, взломщик
|
||||||
|
увидит лишь содержимое этого каталога, а не~всю файловую
|
||||||
|
систему~--- он окажется в ловушке chroot'а.
|
||||||
|
\item Подготовка и управление образом операционной системы при отладке,
|
||||||
|
тестировании, компиляции, установке или восстановлении. При этом
|
||||||
|
вся иерархия файловых систем гостевой ОС монтируется или
|
||||||
|
создается в каталоге системы-хоста, и при запуске оболочки (или
|
||||||
|
любого другого приложения) внутри этой иерархии, их корень
|
||||||
|
сдвигается в этот каталог. Система, которую <<видят>> такие
|
||||||
|
программы, может сильно отличаться от ОС хоста. Например, это
|
||||||
|
может быть другой дистрибутив, или даже другая аппаратная
|
||||||
|
архитектура (запуск i386-гостя на x86\_64-хосте). Гостевая ОС
|
||||||
|
не~может увидеть полной иерархии ОС хоста.
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
В системах, использующих классический SysV init, использовать chroot-окружения
|
||||||
|
сравнительно несложно. Например, чтобы запустить выбранного демона внутри
|
||||||
|
иерархии гостевой ОС, достаточно смонтировать внутри этой иерархии +/proc+,
|
||||||
|
+/sys+ и остальные API ФС, воспользоваться программой +chroot(1)+ для входа в
|
||||||
|
окружение, и выполнить соответствующий init-скрипт, запустив +/sbin/service+
|
||||||
|
внутри окружения.
|
||||||
|
|
||||||
|
Но в системах, использующих systemd, уже не~все так просто. Одно из важнейших
|
||||||
|
достоинств systemd состоит в том, что параметры среды, в которой запускаются
|
||||||
|
демоны, никак не~зависит от метода их запуска. В системах, использующих SysV
|
||||||
|
init, многие параметры среды выполнения (в частности, лимиты на системные
|
||||||
|
ресурсы, переменные окружения, и т.п.) наследуются от оболочки, из которой был
|
||||||
|
запущен init-скрипт. При использовании systemd ситуация меняется радикально:
|
||||||
|
пользователь просто уведомляет init-демона о необходимости запустить ту или иную
|
||||||
|
службу, и тот запускает демона в чистом, созданном <<с нуля>> и тщательно
|
||||||
|
настроенном окружении, параметры которого никак не~зависят от настроек среды, из
|
||||||
|
которой была отдана команда. Такой подход полностью отменяет традиционный метод
|
||||||
|
запуска демонов в chroot-окружениях: теперь демон порождается процессом init
|
||||||
|
(PID~1) и наследует корневой каталог от него, вне зависимости от того, находился
|
||||||
|
ли пользователь, отдавший команду на запуск, в chroot-окружении, или нет. Кроме
|
||||||
|
того, стоит особо отметить, что взаимодействие управляющих программ с systemd
|
||||||
|
происходит через сокеты, находящиеся в каталоге +/run/systemd+, так что
|
||||||
|
программы, запущенные в chroot-окружении, просто не~смогут взаимодействовать с
|
||||||
|
init-подсистемой (и это, в общем, неплохо, а если такое ограничение будет
|
||||||
|
создавать проблемы, его можно легко обойти, используя bind-монтирование).
|
||||||
|
|
||||||
|
В свете вышесказанного, возникает вопрос: как правильно использовать
|
||||||
|
chroot-окружения в системах на основе systemd? Что ж, постараемся дать подробный
|
||||||
|
и всесторонний ответ на этот вопрос.
|
||||||
|
|
||||||
|
Для начала рассмотрим первое из перечисленных выше применений chroot: изоляция в
|
||||||
|
целях безопасности. Прежде всего, стоит заметить, что защита, предоставляемая
|
||||||
|
chroot'ом, весьма эфемерна и ненадежна, так как chroot не~является <<дорогой с
|
||||||
|
односторонним движением>>. Выйти из chroot-окружения сравнительно несложно, и
|
||||||
|
соответствующее предупреждение даже
|
||||||
|
\href{http://linux.die.net/man/2/chroot}{присутствует на странице руководства}.
|
||||||
|
Действительно эффективной защиты можно достичь, только сочетая chroot с другими
|
||||||
|
методиками. В большинстве случаев, это возможно только при наличии поддержки
|
||||||
|
chroot в самой программе. Прежде всего, корректное конфигурирование
|
||||||
|
chroot-окружения требует глубокого понимания принципов работы программы.
|
||||||
|
Например, нужно точно знать, какие сокеты использует программа, чтобы обеспечить
|
||||||
|
bind-монтирование соответствующих каталогов. С учетом вышесказанного,
|
||||||
|
эффективный chroot-защита обеспечивается в том случае, когда она реализована в
|
||||||
|
коде самого демона. Именно разработчик лучше других знает (\emph{обязан знать}),
|
||||||
|
как правильно сконфигурировать chroot-окружение, и какой минимальный набор
|
||||||
|
файлов, каталогов и файловых систем необходим внутри для нормальной работы
|
||||||
|
демона. Уже сейчас существуют демоны, имеющие встроенную поддержку chroot.
|
||||||
|
К сожалению, в системе Fedora, установленной с параметрами по умолчанию, таких
|
||||||
|
демонов всего два: \href{http://avahi.org/}{Avahi} и RealtimeKit. Оба они
|
||||||
|
написаны одним очень хитрым человеком ;-) (Вы можете собственноручно
|
||||||
|
убедится в этом, выполнив команду +ls -l /proc/*/root+.)
|
||||||
|
|
||||||
|
Возвращаясь к тема нашего обсуждения: разумеется, systemd позволяет помещать
|
||||||
|
выбранных демонов в chroot, и управлять ими точно так же, как и другими.
|
||||||
|
Достаточно лишь указать параметр +RootDirectory=+ в соответствующем
|
||||||
|
service-файле. Например:
|
||||||
|
\begin{Verbatim}
|
||||||
|
[Unit]
|
||||||
|
Description=A chroot()ed Service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
RootDirectory=/srv/chroot/foobar
|
||||||
|
ExecStartPre=/usr/local/bin/setup-foobar-chroot.sh
|
||||||
|
ExecStart=/usr/bin/foobard
|
||||||
|
RootDirectoryStartOnly=yes
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Рассмотрим этот пример подробнее. Параметр +RootDirectory=+ задает каталог, в
|
||||||
|
который производится chroot перед запуском исполняемого файла, заданного
|
||||||
|
параметром +ExecStart=+. Заметим, что путь к этому файлу должен быть указан
|
||||||
|
относительно каталога chroot (так что, в нашем случае, с точки зрения основной
|
||||||
|
системы, на исполнение будет запущен файл +/srv/chroot/foobar/usr/bin/foobard+).
|
||||||
|
Перед запуском демона будет вызван сценарий оболочки +setup-foobar-chroot.sh+,
|
||||||
|
который должен обеспечить подготовку chroot-окружения к запуску демона
|
||||||
|
(например, смонтировать в нем +/proc+ и/или другие файловые системы, необходимые
|
||||||
|
для работы демона). Указав +RootDirectoryStartOnly=yes+, мы задаем, что
|
||||||
|
+chroot()+ будет выполняться только перед выполнением файла из +ExecStart=+, а
|
||||||
|
команды из других директив, в частности, +ExecStartPre=+, будут иметь полный
|
||||||
|
доступ к иерархии файловых систем ОС (иначе наш скрипт просто не~сможет
|
||||||
|
выполнить bind-монтирование нужных каталогов). Более подробную информацию по
|
||||||
|
опциям конфигурации вы можете получить на
|
||||||
|
\href{http://0pointer.de/public/systemd-man/systemd.service.html}{страницах}
|
||||||
|
\href{http://0pointer.de/public/systemd-man/systemd.exec.html}{руководства}.
|
||||||
|
|
||||||
|
Поместив приведенный выше текст примера в файл
|
||||||
|
+/etc/systemd/system/foobar.service+, вы сможете запустить chroot'нутого демона
|
||||||
|
командой +systemctl start foobar.service+. Информацию о его текущем состоянии
|
||||||
|
можно получить с помощью команды +systemctl status foobar.service+. Команды
|
||||||
|
управления и мониторинга службы не~зависят от того, запущена ли она в chroot'е,
|
||||||
|
или нет. Этим systemd отличается от класического SysV init.
|
||||||
|
|
||||||
|
Новые ядра Linux поддерживают возможность создания независимых пространств имен
|
||||||
|
файловых систем (в дальнейшем FSNS, от <<file system namespaces>>). По
|
||||||
|
функциональности этот механизм аналогичен +chroot()+, однако предоставляет
|
||||||
|
гораздо более широкие возможности, и в нем отсутствуют проблемы с безопасностью,
|
||||||
|
характерные для chroot. systemd позволяет использовать при конфигурировании
|
||||||
|
юнитов некоторые возможности, предоставляемые FSNS. В частности, использование
|
||||||
|
FSNS часто является гораздо более простой и удобной альтернативой созданию
|
||||||
|
полноценных chroot-окружений. Используя директивы +ReadOnlyDirectories=+,
|
||||||
|
+InaccessibleDirectories=+, вы можете задать ограничения по использованию
|
||||||
|
иерархии файловых систем для заданной службы: ее корнем будет системный корневой
|
||||||
|
каталог, однако указанные в этих директивах подкаталоги будут доступны только
|
||||||
|
для чтения или вообще недоступны для нее. Например:
|
||||||
|
\begin{Verbatim}
|
||||||
|
[Unit]
|
||||||
|
Description=A Service With No Access to /home
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/foobard
|
||||||
|
InaccessibleDirectories=/home
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Такая служба будет иметь доступ ко всей иерархии файловых систем ОС, с
|
||||||
|
единственным исключением~--- она не~будет видеть каталог +/home+, что позволит
|
||||||
|
защитить данные пользователей от потенциальных хакеров. (Подробнее об этих
|
||||||
|
опциях можно почитать на
|
||||||
|
\href{http://0pointer.de/public/systemd-man/systemd.exec.html}{странице
|
||||||
|
руководства}).
|
||||||
|
|
||||||
|
Фактически, FSNS по множеству параметров превосходят +chroot()+. Скорее всего,
|
||||||
|
Avahi и ReltimeKit в ближайшем будущем перейдут с +chroot()+ к использованию
|
||||||
|
FSNS.
|
||||||
|
|
||||||
|
Итак, мы рассмотрели вопросы использования chroot для обеспечения безопасности.
|
||||||
|
Переходим ко второму пункту: Подготовка и управление образом операционной
|
||||||
|
системы при отладке, тестировании, компиляции, установке или восстановлении.
|
||||||
|
|
||||||
|
chroot-окружения, по сути, весьма примитивно: они изолируют только иерархии
|
||||||
|
файловых систем. Даже после chroot'а в определенный подкаталог, процесс
|
||||||
|
по-прежнему имеет полный доступ к системным вызовам, может убить любой процесс
|
||||||
|
из основной системы, и т.п. Вследствие этого, запуск полноценной ОС (или ее
|
||||||
|
части) внутри chroot'а несет угрозу для хост-системы: у гостя и хоста отличаются
|
||||||
|
лишь содержимое файловой системы, все остальное у них общее. Например, если вы
|
||||||
|
обновляете дистрибутив, установленный в chroot-окружении, и пост-установочный
|
||||||
|
скрипт пакета отправляет +SIGTERM+ процессу init для его
|
||||||
|
перезапуска\footnote{Прим. перев.: Во избежание путаницы отметим, что перезапуск
|
||||||
|
процесса init (PID~1) <<на лету>> при получении +SIGTERM+ поддерживается только
|
||||||
|
в systemd, в классическом SysV init такой возможности нет}, на него среагирует
|
||||||
|
именно хост-система! Кроме того, хост и chroot'нутая система будут иметь общую
|
||||||
|
разделяемую память SysV (SysV shared memory), общие сокеты из абстрактных
|
||||||
|
пространств имен (abstract namespace sockets) и другие элементы IPC. Для
|
||||||
|
отладки, тестирования, компиляции, установки и восстановлении ОС не~требуется
|
||||||
|
абсолютно безопасная изоляция, однако нужна защита от \emph{случайного}
|
||||||
|
воздействия на ОС хоста изнутри chroot-окружения, иначе вы можете получить целый
|
||||||
|
букет проблем, как минимум, от пост-инсталляционных скриптов при установке
|
||||||
|
пакетов в chroot-окружении.
|
||||||
|
|
||||||
|
systemd имеет целый ряд возможностей, полезных для работы с chroot-системами:
|
||||||
|
|
||||||
|
Прежде всего, управляющая программа +systemctl+ автоматически определяет, что
|
||||||
|
она запущена в chroot-системе. В такой ситуации будут работать только команды
|
||||||
|
+systemctl enable+ и +systemctl disable+, во всех остальных случаях +systemctl+
|
||||||
|
просто не~будет ничего делать, возвращая код успешного завершения операции.
|
||||||
|
Таким образом, пакетные скрипты смогут включить/отключить запуск <<своих>> служб
|
||||||
|
при загрузке (или в других ситуациях), однако команды наподобие
|
||||||
|
+systemctl restart+ (обычно выполняется при обновлении пакета) не~дадут никакого
|
||||||
|
эффекта внутри chroot-окружения\footnote{Прим. перев.: автор забывает отметить
|
||||||
|
не~вполне очевидный момент: такое поведение +systemctl+ проявляется только в
|
||||||
|
<<мертвых>> окружениях, т.е. в тех, где не~запущен процесс init, и
|
||||||
|
соответственно отсутствуют управляющие сокеты в +/run/systemd+. Такая ситуация
|
||||||
|
возникает, например, при установке системы в chroot через
|
||||||
|
debootstrap/febootstrap. В этом случае возможности +systemctl+ ограничиваются
|
||||||
|
операциями с символьными ссылками, определяющими триггеры активации юнитов, т.е.
|
||||||
|
выполнением действий +enable+ и +disable+, не~требующих непосредственного
|
||||||
|
взаимодействия с процессом init}.
|
||||||
|
|
||||||
|
Однако, куда более интересные возможности предоставляет программа
|
||||||
|
\href{http://0pointer.de/public/systemd-man/systemd-nspawn.html}{systemd-nspawn},
|
||||||
|
входящая в стандартный комплект поставки systemd. По сути, это улучшенный аналог
|
||||||
|
+chroot(1)+~--- она не~только подменяет корневой каталог, но и создает отдельные
|
||||||
|
пространства имен для дерева файловых систем (FSNS) и для идентификаторов
|
||||||
|
процессов (PID NS), предоставляя легковесную реализацию системного
|
||||||
|
контейнера\footnote{Прим. перев.: Используемые в +systemd-nspawn+ механизмы
|
||||||
|
ядра Linux, такие, как FS NS и PID NS, также лежат в основе
|
||||||
|
\href{http://lxc.sourceforge.net/}{LXC}, системы контейнерной изоляции для
|
||||||
|
Linux, которая позиционируется как современная альтернатива классическому
|
||||||
|
\href{http://wiki.openvz.org/Main_Page}{OpenVZ}. Стоит отметить, что LXC
|
||||||
|
ориентирована прежде всего на создание независимых виртуальных окружений,
|
||||||
|
с поддержкой раздельных сетевых стеков, ограничением на ресурсы, сохранением
|
||||||
|
настроек и т.п., в то время как +systemd-nspawn+ является лишь более удобной и
|
||||||
|
эффективной заменой команды +chroot(1)+, предназначенной прежде всего для
|
||||||
|
развертывания, восстановления, сборки и тестирования операционных систем. Далее
|
||||||
|
автор разъясняет свою точку зрения на этот вопрос}.
|
||||||
|
+systemd-nspawn+ проста в использовании как +chroot(1)+, однако изоляция
|
||||||
|
от хост-системы является более полной и безопасной. Всего одной командой
|
||||||
|
вы можете загрузить внутри контейнера \emph{полноценную} ОС (на базе systemd
|
||||||
|
или SysV init). Благодаря использованию независимых пространств идентификаторов
|
||||||
|
процессов, процесс init внутри контейнера получит PID~1, что позволит работать
|
||||||
|
ему в штатном режиме. Также, в отличие от +chroot(1)+, внутри окружения
|
||||||
|
будут автоматически смонтированы +/proc+ и +/sys+.
|
||||||
|
|
||||||
|
Следующий пример иллюстрирует возможность запустить Debian в на Fedora-хосте
|
||||||
|
всего тремя командами:
|
||||||
|
\begin{Verbatim}
|
||||||
|
# yum install debootstrap
|
||||||
|
# debootstrap --arch=amd64 unstable debian-tree/
|
||||||
|
# systemd-nspawn -D debian-tree/
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Вторая из этих команд обеспечивает развертывание в подкаталоге +./debian-tree/+
|
||||||
|
файловой структуры дистрибутива Debian, после чего третья команда запускает
|
||||||
|
внутри полученной системы процесс командной оболочки. Если вы хотите запустить
|
||||||
|
внутри контейнера полноценную ОС, воспользуйтесь командой
|
||||||
|
\begin{Verbatim}
|
||||||
|
# systemd-nspawn -D debian-tree/ /sbin/init
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
После быстрой загрузки вы получите приглашение оболочки, запущенной внутри
|
||||||
|
полноценной ОС, функционирующей в контейнере. Изнутри контейнера невозможно
|
||||||
|
увидеть процессы, которые находятся вне его. Контейнер сможет пользоваться сетью
|
||||||
|
хоста, однако не~имеет возможности изменить ее настройки (это может привести к
|
||||||
|
серии ошибок в процессе загрузки гостевой ОС, но ни~одна из этих ошибок
|
||||||
|
не~должна быть критической). Контейнер получает доступ к +/sys+ и +/proc/sys+,
|
||||||
|
однако, во избежание вмешательства контейнера в конфигурацию ядра и аппаратного
|
||||||
|
обеспечения хоста, эти каталоги будут смонтированы только для чтения. Обратите
|
||||||
|
внимание, что эта защита блокирует лишь \emph{случайные}, \emph{непредвиденные}
|
||||||
|
попытки изменения параметров. При необходимости, процесс внутри контейнера,
|
||||||
|
обладающий достаточными полномочиями, сможет перемонтировать эти файловые
|
||||||
|
системы в режиме чтения-записи.
|
||||||
|
|
||||||
|
Итак, что же такого хорошего в +systemd-nspawn+?
|
||||||
|
\begin{enumerate}
|
||||||
|
\item Использовать эту утилиту очень просто. Вам даже не~нужно вручную монтировать
|
||||||
|
внутри окружения +/proc+ и +/sys+~--- она сделает это за вас, а
|
||||||
|
ядро автоматически отмонтирует их, когда последний процесс
|
||||||
|
контейнера завершится.
|
||||||
|
\item Обеспечивается надежная изоляция, предотвращающая случайные
|
||||||
|
изменения параметров ОС хоста изнутри контейнера.
|
||||||
|
\item Теперь вы можете загрузить внутри контейнера полноценную ОС, а
|
||||||
|
не~одну-единственную оболочку.
|
||||||
|
\item Эта утилита очень компактна и присутствует везде, где установлен
|
||||||
|
systemd. Она не~требует специальной установки и настройки.
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
systemd уже подготовлен для работы внутри таких контейнеров. Например, когда
|
||||||
|
подается команда на выключение системы внутри контейнера, systemd на последнем
|
||||||
|
шаге вызывает не~+reboot()+, а просто +exit()+.
|
||||||
|
|
||||||
|
Стоит отметить, что +systemd-nspawn+ все же не~является полноценной системой
|
||||||
|
контейнерной виртуализации/изоляции~--- если нужно именно это, воспользуйтесь
|
||||||
|
\href{ http://lxc.sourceforge.net/}{LXC}. Этот проект использует те же самые
|
||||||
|
механизмы ядра, но предоставляет куда более широкие возможности, включая
|
||||||
|
виртуализацию сети. Если вам угодно, +systemd-nspawn+ как реализация контейнера
|
||||||
|
похожа на GNOME~3~--- компактна и проста в использовании, опций для настройки
|
||||||
|
очень мало. В то время как LXC больше похож на KDE: опций для настройки больше,
|
||||||
|
чем строк кода. Я создал +systemd-nspawn+ специально для тестирования, отладки,
|
||||||
|
сборки, восстановления. Именно для этих задач вам стоит ее использовать~--- она
|
||||||
|
неплохо с ними справляется, куда лучше, чем +chroot(1)+.
|
||||||
|
|
||||||
|
Что ж, пора заканчивать. Итак:
|
||||||
|
\begin{enumerate}
|
||||||
|
\item Использование +chroot()+ для обеспечения безопасности дает
|
||||||
|
наилучший результат, когда оно реализовано непосредственно в
|
||||||
|
коде самой программы.
|
||||||
|
\item +ReadOnlyDirectories=+ и +InaccessibleDirectories=+ могут быть
|
||||||
|
удобной альтернативой созданию полноценных chroot-окружений.
|
||||||
|
\item Если вам нужно поместить в chroot-окружение какую-либо службу,
|
||||||
|
воспользуйтесь опцией +RootDirectory=+.
|
||||||
|
\item +systemd-nspawn+~--- очень неплохая штука.
|
||||||
|
\item chroot'ы убоги, FSNS~---
|
||||||
|
\href{http://ru.wikipedia.org/wiki/Leet}{1337}.
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
И все это уже сейчас доступно в Fedora~15.
|
||||||
|
|
||||||
|
\section{Поиск виновных}
|
||||||
|
|
||||||
|
Fedora~15\footnote{Также известный как величайший в истории релиз свободной ОС}
|
||||||
|
является первым релизом Fedora, использующим systemd в качестве системы
|
||||||
|
инициализации по умлочанию. Основной нашей целью при работе над выпуском F15
|
||||||
|
является обеспечение полной интеграции и корректной работы всех компонентов. При
|
||||||
|
подготовке следующего релиза, F16, мы сконцентрируемся на дальнейшей полировке и
|
||||||
|
ускорении системы. Для этого мы подготовили ряд инструментов (доступных уже в
|
||||||
|
F15), которые должны помочь нам в поиске проблем, связанных с процессом
|
||||||
|
загрузки. В этой статье я попытаюсь рассказать о том, как найти виновников
|
||||||
|
медленной загрузки вашей системы, и о том, что с ними делать дальше. Мы хотим
|
||||||
|
помочь вам в поиске тех системных компонентов, которые являются причинами выших
|
||||||
|
проблем.
|
||||||
|
|
||||||
|
Первый инструмент, который мы можем вам предложить, очень прост: по зварешении
|
||||||
|
загрузки, systemd регистрирует в системном журнале информацию о суммарном
|
||||||
|
времени загрузки:
|
||||||
|
\begin{Verbatim}
|
||||||
|
systemd[1]: Startup finished in 2s 65ms 924us (kernel) + 2s 828ms 195us (initrd)
|
||||||
|
+ 11s 900ms 471us (userspace) = 16s 794ms 590us.
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Эта запись означает следующее: на инициализацию ядра (до момента запуска initrd,
|
||||||
|
т.е. dracut) ушло 2 секунды. Далее, чуть менее трех секунд работал initrd. И
|
||||||
|
наконец, почти 12 секунд было потрачено systemd на запуск программ из
|
||||||
|
пространства пользователя. Итоговое время, начиная с того момента, как
|
||||||
|
загрузчик передал управление коду ядра, до того момента, как systemd завершил
|
||||||
|
все операции, связанные с загрузкой системы, составило почти 17 секунд.
|
||||||
|
Казалось бы, смысл этого числа вполне очевиден, однако не~стоит делать поспешных
|
||||||
|
выводов. Прежде всего, в нем не~учитывается время, затраченное на инициализацию
|
||||||
|
вашего сеанса в GNOME, так как эта задача уже выходит за рамки задач процесса
|
||||||
|
init. Кроме того, в этом периоде времени учитывается только работа systemd, хотя
|
||||||
|
часто бывает так, что некоторые демоны продолжают \emph{свою} работу по
|
||||||
|
инициализации уже после того, как секундомер остановлен. Проще говоря:
|
||||||
|
предложенные вам числа позволяют лишь оценить общую скорость загрузки, однако
|
||||||
|
они не~являются точной характеристикой длительности процесса.
|
||||||
|
|
||||||
|
Кроме того, эта информация носит поверхностный характер: она не~сообщает, какие
|
||||||
|
именно системные компоненты заставляют systemd ждать так долго. Чтобы исправить
|
||||||
|
это упущение, мы ввели команду +systemd-analyze blame+:
|
||||||
|
\begin{Verbatim}
|
||||||
|
$ systemd-analyze blame
|
||||||
|
6207ms udev-settle.service
|
||||||
|
5228ms cryptsetup@luks\x2d9899b85d\x2df790\x2d4d2a\x2da650\x2d8b7d2fb92cc3.service
|
||||||
|
735ms NetworkManager.service
|
||||||
|
642ms avahi-daemon.service
|
||||||
|
600ms abrtd.service
|
||||||
|
517ms rtkit-daemon.service
|
||||||
|
478ms fedora-storage-init.service
|
||||||
|
396ms dbus.service
|
||||||
|
390ms rpcidmapd.service
|
||||||
|
346ms systemd-tmpfiles-setup.service
|
||||||
|
322ms fedora-sysinit-unhack.service
|
||||||
|
316ms cups.service
|
||||||
|
310ms console-kit-log-system-start.service
|
||||||
|
309ms libvirtd.service
|
||||||
|
303ms rpcbind.service
|
||||||
|
298ms ksmtuned.service
|
||||||
|
288ms lvm2-monitor.service
|
||||||
|
281ms rpcgssd.service
|
||||||
|
277ms sshd.service
|
||||||
|
276ms livesys.service
|
||||||
|
267ms iscsid.service
|
||||||
|
236ms mdmonitor.service
|
||||||
|
234ms nfslock.service
|
||||||
|
223ms ksm.service
|
||||||
|
218ms mcelog.service
|
||||||
|
...
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
\end{document}
|
\end{document}
|
||||||
|
|
||||||
|
vim:ft=tex:tw=80:spell:spelllang=ru
|
||||||
|
|||||||
Reference in New Issue
Block a user