Мы даўно сочым за тэмай выкарыстання systemd у кантэйнерах. Яшчэ ў 2014 годзе наш інжынер па бяспецы Дэніэл Уолш (Daniel Walsh) напісаў артыкул
У гэтым артыкуле мы пакажам, што змянілася за мінулы час і як нам можа дапамагчы ў гэтым пытанні Podman.
Ёсць шмат прычын для таго, каб запускаць systemd ўнутры кантэйнера, такія як:
- Мультысэрвісныя кантэйнеры - шматлікія жадаюць выцягнуць свае мультысэрвісныя прыкладанні з віртуальных машын і запускаць іх у кантэйнерах. Лепш бы, вядома, разбіць такія прыкладанні на мікрасэрвісы, але не ўсё пакуль гэта ўмеюць ці проста няма часу. Таму запуск такіх прыкладанняў у выглядзе сэрвісаў, якія запускаюцца systemd з юніт-файлаў, цалкам мае сэнс.
- Юніт-файлы Systemd - Большасць прыкладанняў, якія працуюць усярэдзіне кантэйнераў, сабраны з кода, які да гэтага запускаўся на віртуальных або фізічных машынах. У гэтых прыкладанняў ёсць юніт-файл, які пісаўся пад гэтыя прыкладанні і разумее, як іх трэба запускаць. Так што сэрвісы ўсё ж лепш запускаць з дапамогай падтрымліваемых метадаў, а не ўзломваючы сваю ўласную init-службу.
- Systemd - гэта дыспетчар працэсаў. Ён ажыццяўляе кіраванне сэрвісамі (завяршае працу, перазапускае сэрвісы або выкошвае зомбі-працэсы) лепш, чым любая іншая прылада.
Пры гэтым ёсць і шмат чыннікаў для таго, каб не запускаць systemd у кантэйнерах. Асноўная складаецца ў тым, што systemd/journald кантралюе выснову кантэйнераў, а прылады накшталт
Прышэсце Podman'а
З радасцю паведамляем, што сітуацыя нарэшце зрушылася з мёртвай кропкі. Каманда, якая адказвае ў Red Hat за запуск кантэйнераў, вырашыла распрацаваць
Многія так і робяць.
Мы са сваім Podman'ам ні ў якай меры не супраць кантэйнераў на аснове systemd. Бо Systemd часцей за іншых выкарыстоўваецца ў якасці init-падсістэмы Linux, і не даваць ёй нармальна працаваць у кантэйнерах значыць ігнараваць тое, як тысячы людзей прывыклі запускаць кантэйнеры.
Podman ведае, што трэба рабіць, каб systemd нармальна працавала ў кантэйнеры. Ёй патрэбныя такія рэчы, як мантаванне tmpfs на /run і /tmp. Ёй падабаецца, калі ўключанае «кантэйнернае» асяроддзе, і яно чакае правоў на запіс у сваю частку каталога cgroup і ў тэчку /var/log/journald.
Пры запуску кантэйнера, у якім першай камандай ідзе init ці systemd, Podman аўтаматычна наладжвае tmpfs і Cgroups для таго, каб запуск systemd мінуў без праблем. Каб заблакаваць такі аўтарэжым запуску, выкарыстоўваецца опцыя -systemd=false. Звярніце ўвагу, што Podman выкарыстоўвае systemd-рэжым толькі тады, калі бачыць, што трэба выканаць каманду systemd ці init.
Вось вытрымка з мануала:
man podman run
...–systemd=true|false
Запуск кантэйнера ў рэжыме systemd. Па змаўчанні ўключаны.
Калі ўсярэдзіне кантэйнера выконваецца каманда systemd або init, Podman наладзіць кропкі мантавання tmpfs у наступных каталогах:
/run, /run/lock, /tmp, /sys/fs/cgroup/systemd, /var/lib/journal
Таксама ў якасці сігналу прыпынку па змаўчанні будзе выкарыстоўвацца SIGRTMIN+3.
Усё гэта дазваляе systemd працаваць у замкнёным кантэйнеры без якія-небудзь мадыфікацый.
УВАГА: systemd спрабуе выканаць запіс у файлавую сістэму cgroup. Аднак SELinux па змаўчанні забараняе кантэйнерам гэта рабіць. Каб дазволіць запіс, уключыце лагічны параметр container_manage_cgroup:
setsebool -P container_manage_cgroup true
Цяпер паглядзіце, як выглядае Dockerfile для запуску systemd у кантэйнеры пры выкарыстанні Podman'а:
# cat Dockerfile
FROM fedora
RUN dnf -y install httpd; dnf clean all; systemctl enable httpd
EXPOSE 80
CMD [ "/sbin/init" ]
Вось і ўсё.
Цяпер збіраем кантэйнер:
# podman build -t systemd .
Які гаворыцца SELinux дазволіць systemd мадыфікаваць канфігурацыю Cgroups:
# setsebool -P container_manage_cgroup true
Многія, дарэчы, забываюцца на гэты крок. На шчасце, гэта дастаткова зрабіць усяго адзін раз і настройка захоўваецца пасля перазагрузкі сістэмы.
Цяпер проста запускаем кантэйнер:
# podman run -ti -p 80:80 systemd
systemd 239 running in system mode. (+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN2 -IDN +PCRE2 default-hierarchy=hybrid)
Detected virtualization container-other.
Detected architecture x86-64.
Welcome to Fedora 29 (Container Image)!
Set hostname to <1b51b684bc99>.
Failed to install release agent, ignoring: Read-only file system
File /usr/lib/systemd/system/systemd-journald.service:26 configures an IP firewall (IPAddressDeny=any), but the local system does not support BPF/cgroup based firewalling.
Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first loaded unit using IP firewalling.)
[ OK ] Listening on initctl Compatibility Named Pipe.
[ OK ] Listening on Journal Socket (/dev/log).
[ OK ] Started Forward Password Requests to Wall Directory Watch.
[ OK ] Started Dispatch Password Requests to Console Directory Watch.
[ OK ] Reached target Slices.
…
[ OK ] Started The Apache HTTP Server.
Усё, сэрвіс запусціўся і працуе:
$ curl localhost
<html xml_lang="en" lang="en">
…
</html>
УВАГА: Не спрабуйце паўтарыць гэта на Docker'е! Тамака па-ранейшаму патрэбныя танцы з бубнам, каб запускаць такога роду кантэйнеры праз дэмана. (Спатрэбяцца дадатковыя палі і пакеты, каб усё гэта бясшвоўна зарабіла ў Docker, альбо трэба будзе запускаць у прывілеяваным кантэйнеры. Падрабязнасці гл. у
Яшчэ пара крутых рэчаў аб Podman і systemd
Podman працуе лепш Docker у юніт-файлах systemd
Калі кантэйнеры трэба запускаць пры загрузцы сістэмы, то можна проста ўставіць адпаведныя каманды Podman у юніт-файл systemd, той запусціць сэрвіс і будзе яго маніторыць. Podman выкарыстоўвае стандартную мадэль галінавання пры выкананні (fork-exec). Інакш кажучы, кантэйнерныя працэсы з'яўляюцца даччынымі па стаўленні да працэсу Podman'а, таму systemd лёгка можа іх маніторыць.
Docker выкарыстоўвае мадэль кліент-сервер, і CLI-каманды Docker таксама можна размяшчаць прама ў юніт-файле. Аднак пасля таго, як Docker-кліент падлучаецца да Docker-дэмана, ён (кліент) становіцца проста яшчэ адным працэсам, якія апрацоўваюць stdin і stdout. У сваю чаргу, systemd паняцця не мае аб сувязі паміж Docker-кліентам і кантэйнерам, які працуе пад кіраваннем Docker-дэмана, і таму ў рамках гэтай мадэлі systemd прынцыпова не можа маніторыць сэрвіс.
Актывацыя systemd праз сокет
Podman карэктна адпрацоўвае актываванне праз сокета. Паколькі Podman выкарыстоўвае мадэль fork-exec, ён можа пракідваць сокет сваім даччыным кантэйнерным працэсам. Docker так не ўмее, бо выкарыстоўвае мадэль кліент-сервер.
Сэрвіс varlink, які Podman выкарыстоўвае для ўзаемадзеяння выдаленых кліентаў з кантэйнерамі, насамрэч актывуецца праз сокет. Пакет cockpit-podman, напісаны на Node.js і які ўваходзіць у склад праекту cockpit, дазваляе людзям узаемадзейнічаць з кантэйнерамі Podman праз вэб-інтэрфейс. Вэб-дэман, на якім круціцца cockpit-podman, дасылае паведамленні на varlink-сокет, які праслухоўваецца systemd. Пасля чаго systemd актывуе праграму Podman для атрымання паведамленняў і пачаткі кіравання кантэйнерамі. Актывацыя systemd праз сокет дазваляе абыйсціся без стала працавальнага дэмана пры рэалізацыі выдаленых API.
Акрамя таго, мы распрацоўваем яшчэ адзін кліент для Podman'а пад назовам podman-remote, які рэалізуе той жа самы Podman CLI, але выклікае varlink для запуску кантэйнераў. Podman-remote можа працаваць па-над SSH-сеансамі, што дазваляе бяспечна ўзаемадзейнічаць з кантэйнерамі на розных машынах. З часам мы плануем задзейнічаць podman-remote для падтрымкі MacOS і Windows нараўне з Linux, каб распрацоўшчыкі на гэтых платформах маглі запускаць віртуальную машыну Linux з працавальным Podman varlink і мець поўнае адчуванне, што кантэйнеры выконваюцца на лакальнай машыне.
SD_NOTIFY
Systemd дазваляе адкласці запуск дапаможных сэрвісаў да таго моманту, пакуль не стартуе неабходны ім кантэйнерызаваны сэрвіс. Podman можа пракінуць сокет SD_NOTIFY у кантэйнерызаваны сэрвіс, каб гэта сэрвіс апавясціў systemd аб сваёй гатоўнасці да працы. І зноў жа Docker, які выкарыстоўвае мадэль кліент-сервер, так не ўмее.
У планах
Мы плануем дадаць каманду podman generate systemd CONTAINERID, які будзе генераваць юніт-файл systemd для кіравання пэўным зададзеным кантэйнерам. Гэта павінна працаваць як у root-, так і ў rootless-рэжымах для непрывілеяваных кантэйнераў. Мы нават бачыў запыт на стварэнне OCI-сумяшчальнага асяроддзя выканання systemd-nspawn.
Заключэнне
Запуск systemd у кантэйнеры гэта цалкам зразумелае запатрабаванне. І дзякуючы Podman у нас нарэшце-тое ёсць асяроддзе запуску кантэйнераў, якая не варагуе з systemd, а дазваляе лёгка яго выкарыстоўваць.
Крыніца: habr.com