Version v14.2 (2013-01-24 23:03) [AUTO]
This commit is contained in:
212
s4a.tex
212
s4a.tex
@@ -2312,6 +2312,7 @@ serial-getty@serial-by\x2dpath-pci\x2d0000:00:1d.0\x2dusb\x2d0:1.4:1.1\x2dport0.
|
|||||||
пояснениями.)
|
пояснениями.)
|
||||||
|
|
||||||
\section{Службы с активацией в стиле inetd}
|
\section{Службы с активацией в стиле inetd}
|
||||||
|
\label{sec:inetd}
|
||||||
|
|
||||||
В одной из предыдущих глав (гл.~\ref{sec:convert}) я рассказывал, как можно
|
В одной из предыдущих глав (гл.~\ref{sec:convert}) я рассказывал, как можно
|
||||||
преобразовать SysV init-скрипт в юнит-файл systemd. В этой главе мы рассмотрим,
|
преобразовать SysV init-скрипт в юнит-файл systemd. В этой главе мы рассмотрим,
|
||||||
@@ -4314,11 +4315,11 @@ $ gdbus call --system --dest org.freedesktop.systemd1 --object-path /org/freedes
|
|||||||
те, которые пока не~поддерживают, ее
|
те, которые пока не~поддерживают, ее
|
||||||
\href{http://0pointer.de/blog/projects/socket-activation.html}{не~так уж} и
|
\href{http://0pointer.de/blog/projects/socket-activation.html}{не~так уж} и
|
||||||
\href{http://0pointer.de/blog/projects/socket-activation2.html}{сложно}
|
\href{http://0pointer.de/blog/projects/socket-activation2.html}{сложно}
|
||||||
добавить). Используя встроенный в systemd механизм управления
|
добавить). Реализованный в systemd механизм управления
|
||||||
\hyperref[sec:instances]{экземплярами служб}, вы сможете подготовить
|
\hyperref[sec:instances]{экземплярами служб} позволяет подготовить
|
||||||
универсальные шаблоны конфигурации служб, и в соответствии с ними для каждого
|
универсальные шаблоны конфигурации служб, и в соответствии с ними для каждого
|
||||||
сайта будет запускаться свой экземпляр службы. Кроме того, не~стоит забывать,
|
сайта будет запускаться свой экземпляр службы. Кроме того, не~стоит забывать,
|
||||||
что systemd предоставляет вам \hyperref[sec:security]{богатый арсенал}
|
что systemd предоставляет \hyperref[sec:security]{богатый арсенал}
|
||||||
механизмов обеспечения безопасности и разграничения доступа, который позволит
|
механизмов обеспечения безопасности и разграничения доступа, который позволит
|
||||||
изолировать клиентские сайты друг от друга (например, службы каждого клиента
|
изолировать клиентские сайты друг от друга (например, службы каждого клиента
|
||||||
будут видеть только его собственный домашний каталог, в то время как каталоги
|
будут видеть только его собственный домашний каталог, в то время как каталоги
|
||||||
@@ -4333,6 +4334,211 @@ $ gdbus call --system --dest org.freedesktop.systemd1 --object-path /org/freedes
|
|||||||
сайтов на базе Drupal. (Стоит упомянуть, что заслуга ее внедрения в Pantheon
|
сайтов на базе Drupal. (Стоит упомянуть, что заслуга ее внедрения в Pantheon
|
||||||
принадлежит Дэвиду Штрауссу. Дэвид, ты крут!)
|
принадлежит Дэвиду Штрауссу. Дэвид, ты крут!)
|
||||||
|
|
||||||
|
\subsection{Сокет-активация контейнеров}
|
||||||
|
|
||||||
|
Все вышеописанные технологии уже реализованы в ранее вышедших версиях systemd.
|
||||||
|
Если ваш дистрибутив поддерживает systemd, вы можете воспользоваться этими
|
||||||
|
механизмами прямо сейчас. А теперь сделаем шаг вперед: начиная с
|
||||||
|
systemd 197 (и, соответственно, с Fedora~19), мы добавили поддержку
|
||||||
|
сокет-активации \emph{виртуальных контейнеров} с полноценными ОС внутри. И
|
||||||
|
я считаю это действительно важным достижением.
|
||||||
|
|
||||||
|
Сокет-активация контейнеров работает следующим образом. Изначально, systemd
|
||||||
|
хост-системы слушает порты от имени контейнера (например, порт SSH, порт
|
||||||
|
веб-сервера и порт сервера СУБД). При поступлении на любой из этих портов
|
||||||
|
входящего запроса, systemd запускает контейнер и передает ему все его сокеты.
|
||||||
|
Внутри контейнера, еще один systemd (init гостевой системы) принимает эти
|
||||||
|
сокеты, после чего вступает в работу вышеописанная схема обычной сокет-активации
|
||||||
|
служб. При этом, SSH-сервер, веб-сервер и СУБД-сервер <<видят>> только ОС
|
||||||
|
контейнера~--- хотя они были активированы сокетами, созданными на хосте! Для
|
||||||
|
клиента все эти тонкости скрыты. Таким образом, мы получаем виртуальный
|
||||||
|
контейнер с собственной ОС, активируемый при поступлении входящего сетевого
|
||||||
|
соединения, причем совершенно прозрачно для клиента\footnote{Кстати говоря,
|
||||||
|
\href{https://plus.google.com/115547683951727699051/posts/cVrLAJ8HYaP}{это еще
|
||||||
|
один аргумент} в пользу важности быстрой загрузки для серверных систем.}.
|
||||||
|
|
||||||
|
Внутри контейнера функционирует полноценная ОС, причем ее дистрибутив
|
||||||
|
не~обязательно совпадает с дистрибутивом хост-системы. Например, вы можете
|
||||||
|
установить на хосте Fedora, и запускать на нем несколько контейнеров с Debian.
|
||||||
|
Контейнеры имеют собственные init-системы, собственные SSH-серверы, собственные
|
||||||
|
списки процессов и т.д., но при этом пользуются некоторыми механизмами ОС хоста
|
||||||
|
(например, управлением памятью).
|
||||||
|
|
||||||
|
К настоящему моменту сокет-активация контейнеров поддерживается лишь встроенным
|
||||||
|
в systemd простейшим контейнерным менеджером~---
|
||||||
|
\hyperref[sec:chroots]{systemd-nspawn}. Мы надеемся, что соответствующая
|
||||||
|
возможность вскоре появится и в
|
||||||
|
\href{http://libvirt.org/drvlxc.html}{libvirt-lxc}. А пока рассмотрим
|
||||||
|
использование этого механизма на примере systemd-nspawn.
|
||||||
|
|
||||||
|
Начнем с установки файлов ОС контейнера в выбранный каталог. Детальное
|
||||||
|
рассмотрение этого вопроса выходит далеко за рамки нашего обсуждения, и
|
||||||
|
при этом детально рассмотрено во многих статьях и руководствах. Поэтому
|
||||||
|
ограничусь лишь несколькими наиболее важными замечаниями. В частности, команда
|
||||||
|
для установки Fedora будет выглядеть следующим образом:
|
||||||
|
\begin{Verbatim}
|
||||||
|
$ yum --releasever=19 --nogpg --installroot=/srv/mycontainer/ --disablerepo='*' \
|
||||||
|
> --enablerepo=fedora install systemd passwd yum fedora-release vim-minimal
|
||||||
|
\end{Verbatim}
|
||||||
|
а для Debian~---
|
||||||
|
\begin{Verbatim}
|
||||||
|
$ debootstrap --arch=amd64 unstable /srv/mycontainer/
|
||||||
|
\end{Verbatim}
|
||||||
|
Также см. последние абзацы страницы руководства
|
||||||
|
\href{http://www.freedesktop.org/software/systemd/man/systemd-nspawn.html}{systemd-nspawn(1)}.
|
||||||
|
Стоит отметить, что в настоящее время реализация системного аудита в Linux
|
||||||
|
не~поддерживает виртуальные контейнеры, и ее включение в ядре хоста вызовет
|
||||||
|
множество ошибок при попытке запустить контейнер. Отключить ее можно добавлением
|
||||||
|
+audit=0+ в строку параметров загрузки ядра хоста.
|
||||||
|
|
||||||
|
Разумеется, внутри контейнера должен должен быть установлен systemd версии
|
||||||
|
не~ниже 197. Установить его и произвести другие необходимые настройки можно при
|
||||||
|
помощи того же \hyperref[sec:chroots]{systemd-nspawn} (пока что в режиме аналога
|
||||||
|
+chroot+, т.е. без параметра +-b+). После этого можно попробовать загрузить ОС
|
||||||
|
контейнера, используя systemd-nspawn уже с параметром +-b+.
|
||||||
|
|
||||||
|
Итак, ваш контейнер нормально загружается и работает. Подготовим для него
|
||||||
|
service-файл, при помощи которого systemd сможет запускать и останавливать
|
||||||
|
виртуальное окружение. Для этого, создадим на хост системе файл
|
||||||
|
+/etc/systemd/system/mycontainer.service+ со следующим содержанием:
|
||||||
|
\begin{Verbatim}
|
||||||
|
[Unit]
|
||||||
|
Description=My little container
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/systemd-nspawn -jbD /srv/mycontainer 3
|
||||||
|
KillMode=process
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Теперь мы можем запускать и останавливать эту службу командами +systemctl start+
|
||||||
|
и +stop+. Однако, пока что мы не~можем войти в эту систему\footnote{Прим.
|
||||||
|
перев.: Ручной запуск на хосте соответствующей команды +systemd-nspawn -b+ во
|
||||||
|
время работы такой службы просто создаст \emph{еще один контейнер}. Хотя
|
||||||
|
корневой каталог у них один и тот же, пространства имен (например, списки
|
||||||
|
процессов) у каждого будут свои. Впрочем, данная задача может быть решена
|
||||||
|
утилитой +nsenter+, которая должна войти в следующий релиз util-linux
|
||||||
|
(предположительно, 2.23).}. Настроим на контейнере SSH-сервер, причем таким
|
||||||
|
образом, что подключение к его порту активировало весь контейнер, а затем
|
||||||
|
активировало сервер, работающий внутри. Начнем с того, что прикажем хосту
|
||||||
|
слушать порт SSH для контейнера. Для этого создадим на хосте файл
|
||||||
|
+/etc/systemd/system/mycontainer.socket+:
|
||||||
|
\begin{Verbatim}
|
||||||
|
[Unit]
|
||||||
|
Description=The SSH socket of my little container
|
||||||
|
|
||||||
|
[Socket]
|
||||||
|
ListenStream=23
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
После того, как мы запустим этот юнит командой +systemctl start+, systemd будет
|
||||||
|
слушать 23-й TCP-порт хоста. В примере выбран именной 23-й, потому что 22-й
|
||||||
|
скорее всего окажется занят SSH-сервером самого хоста. nspawn виртуализует
|
||||||
|
списки процессов и точек монтирования, но не~сетевые стеки, поэтому порты хоста
|
||||||
|
и гостей не~должны конфликтовать\footnote{Прим. перев.: Ограниченные возможности
|
||||||
|
виртуализации сети в +systemd-nspawn+ значительно затрудняют использование
|
||||||
|
описываемой технологии. Ее практическое применение будет иметь смысл после
|
||||||
|
реализации соответствующей поддержки в lxc-libvirt, либо расширения возможностей
|
||||||
|
nspawn. Впрочем, опытные администраторы легко могут найти обходные пути,
|
||||||
|
например: присваивание хосту дополнительного IP-адреса (безо всякой
|
||||||
|
виртуализации, командой +ip addr add+) и привязка слушающих сокетов к конкретным
|
||||||
|
адресам (в параметре +ListenStream=+ сокет-файлов или в директиве
|
||||||
|
+ListenAddress+ файла +sshd_config+).}.
|
||||||
|
|
||||||
|
Пока что systemd, работающий внутри контейнера, не~знает, что делать с тем
|
||||||
|
сокетами, которые ему передает systemd хоста. Если вы попробуете подключиться к
|
||||||
|
порту 23, контейнер запустится, но сетевое соединение немедленно будет закрыто,
|
||||||
|
так как этому сокету не~соответствует пока никакой сервер. Давайте это исправим!
|
||||||
|
|
||||||
|
Настройка сокет-активации службы SSH была детально рассмотрена
|
||||||
|
\hyperref[sec:inetd]{в одной из предыдущих статей}, поэтому ограничусь
|
||||||
|
приведением содержимого необходимых для этого конфигурационных файлов. Файл
|
||||||
|
настроек для сокета
|
||||||
|
(+/srv/mycontainer/etc/systemd/system/sshd.socket+)\footnote{Прим. перев.:
|
||||||
|
Обратите внимание на разницу между файлами конфигурации сокетов на хосте и
|
||||||
|
в контейнере. Внутри контейнера используются параметры +Accept=yes+ и
|
||||||
|
+StandardInput=socket+, которые не~задействованы на хосте. Это обусловлено тем
|
||||||
|
фактом, что внутри контейнера сокет-активация производится в стиле inetd (служба
|
||||||
|
получает только один сокет, причем замкнутый на ее потоки STDIN и STDOUT), в то
|
||||||
|
время как на стороне хоста используется родной стиль активации systemd, при
|
||||||
|
котором запущенному процессу (в данном случае +systemd-nspawn+) просто
|
||||||
|
передаются открытые файловые дескрипторы (+fd+) всех сокетов. Одно из достоинств
|
||||||
|
такого подхода~--- возможность передавать сразу несколько сокетов, что позволяет
|
||||||
|
активировать внутри контейнера несколько серверов.}:
|
||||||
|
\begin{Verbatim}
|
||||||
|
[Unit]
|
||||||
|
Description=SSH Socket for Per-Connection Servers
|
||||||
|
|
||||||
|
[Socket]
|
||||||
|
ListenStream=23
|
||||||
|
Accept=yes
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Соответствующий ему файл конфигурации службы \\
|
||||||
|
(+/srv/mycontainer/etc/systemd/system/sshd@.service+):
|
||||||
|
\begin{Verbatim}
|
||||||
|
[Unit]
|
||||||
|
Description=SSH Per-Connection Server for %I
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=-/usr/sbin/sshd -i
|
||||||
|
StandardInput=socket
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
После чего, добавим наш сокет в зависимости к цели +sockets.target+, чтобы
|
||||||
|
systemd создавал его автоматически при загрузке контейнера\footnote{Прим.
|
||||||
|
перев.: Возиться вручную с командой +ln+ здесь совершенно необязательно. Можно
|
||||||
|
просто добавить в файл +sshd.socket+ секцию +[Install]+, содержащую параметр
|
||||||
|
+WantedBy=sockets.target+, после чего добавление правильного симлинка будет
|
||||||
|
выполняться куда более очевидной командой
|
||||||
|
+systemctl --root=/srv/mycontainer enable sshd.socket+.}:
|
||||||
|
\begin{Verbatim}
|
||||||
|
$ chroot /srv/mycontainer ln -s /etc/systemd/system/sshd.socket \
|
||||||
|
> /etc/systemd/system/sockets.target.wants/
|
||||||
|
\end{Verbatim}
|
||||||
|
|
||||||
|
Собственно, все. После того, как мы запустим на хосте юнит +mycontainer.socket+,
|
||||||
|
systemd начнет прослушивать TCP-порт 23. При подключении к этому порту, systemd
|
||||||
|
запустит контейнер и передаст сокет ему. Внутри контейнера свой systemd, в
|
||||||
|
соответствии с файлом +sshd.socket+, примет этот сокет и запустит для нашего
|
||||||
|
соединения экземпляр +sshd@.service+, что позволит нам залогиниться в контейнер
|
||||||
|
по SSH.
|
||||||
|
|
||||||
|
Если нам нужно запуститьунтри контейнера другие службы с сокет-активацией, мы
|
||||||
|
можем добавить в +mycontainer.socket+ дополнительные сокеты. Все они будут
|
||||||
|
прослушиваться, обращение к любому из них приведет к активации контейнера, и все
|
||||||
|
они будут переданы контейнеру при его активации. Внутри контейнера они будут
|
||||||
|
обработаны соответствии с настройками имеющихся там сокет-юнитов. Те сокеты, для
|
||||||
|
которых соответствующих юнитов не~найдется, будут закрыты, а те сокеты, которые
|
||||||
|
будут настроены для прослушивания внутри контейнера, но не~получены от хоста,
|
||||||
|
будут активированы и доступны изнутри контейнера (а если это сетевые или
|
||||||
|
файловые unix-сокеты, то и извне).
|
||||||
|
|
||||||
|
Итак, давайте отступим чуть назад и полюбуемся на результаты наших трудов. Что
|
||||||
|
мы получили в итоге? Возможность настраивать на одном хосте множество
|
||||||
|
контейнеров с полноценными ОС внутри, причем контейнеры запускаются только по
|
||||||
|
запросу, что позволяет снизить потребление системных ресурсов и, соответственно,
|
||||||
|
увеличить количество контейнеров (по сравнению с принудительной их активацией
|
||||||
|
при загрузке хоста).
|
||||||
|
|
||||||
|
Разумеется, описанный подход работает только для контейнерной виртуализации, и
|
||||||
|
неприменим к полной, т.е. может быть использован только с технологиями наподобие
|
||||||
|
libvirt-lxc или nspawn, но не~c qemu/kvm или xen.
|
||||||
|
|
||||||
|
Если вы будете администрировать несколько таких контейнеров, вас наверняка
|
||||||
|
порадует одна из возможностей journal: при запуске на хосте утилиты +journalctl+
|
||||||
|
с ключом +-m+, она автоматически обнаружит журналы гостевых контейнеров и
|
||||||
|
объединит их вывод с выводом журнала хоста\footnote{Прим. перев.: Этот трюк
|
||||||
|
работает благодаря опции +-j+, которую мы передаем программе +systemd-nspawn+
|
||||||
|
при запуске контейнера (см. файл юнита выше). В соответствии с ней, в каталоге
|
||||||
|
+/var/log/journal+ хоста создается символьная ссылку на соответствующий каталог
|
||||||
|
гостя. При этом, так как сообщения от гостей имеют другие machine ID, journalctl
|
||||||
|
хоста не~выводит их, если явно не~указать +-m+. Подробности см. на страницах
|
||||||
|
руководства
|
||||||
|
\href{http://www.freedesktop.org/software/systemd/man/systemd-nspawn.html}{systemd-nspawn(1)}
|
||||||
|
и
|
||||||
|
\href{http://www.freedesktop.org/software/systemd/man/journalctl.html}{journalctl(1)}.}.
|
||||||
|
Ловко, не~правда ли?
|
||||||
|
|
||||||
\end{document}
|
\end{document}
|
||||||
|
|
||||||
vim:ft=tex:tw=80:spell:spelllang=ru
|
vim:ft=tex:tw=80:spell:spelllang=ru
|
||||||
|
|||||||
Reference in New Issue
Block a user