Temat wykorzystania systemd w kontenerach śledzimy już od dłuższego czasu. W 2014 roku nasz inżynier bezpieczeństwa Daniel Walsh napisał artykuł
W tym artykule pokażemy, co zmieniło się na przestrzeni czasu i jak Podman może nam pomóc w tej kwestii.
Istnieje wiele powodów, dla których warto uruchamiać systemd w kontenerze, na przykład:
- Kontenery wielousługowe – wiele osób chce wyciągać swoje aplikacje wielousługowe z maszyn wirtualnych i uruchamiać je w kontenerach. Lepiej byłoby oczywiście rozbić takie aplikacje na mikroserwisy, jednak nie każdy jeszcze wie jak to zrobić lub po prostu nie ma czasu. Dlatego uruchamianie takich aplikacji jak usług uruchamianych przez system z plików jednostkowych ma sens.
- Pliki jednostek systemowych – Większość aplikacji działających wewnątrz kontenerów jest zbudowana z kodu, który wcześniej działał na maszynach wirtualnych lub fizycznych. Aplikacje te mają plik jednostkowy napisany dla tych aplikacji i rozumiejący, w jaki sposób powinny być uruchamiane. Dlatego nadal lepiej jest uruchamiać usługi przy użyciu obsługiwanych metod, niż hakować własną usługę init.
- Systemd jest menedżerem procesów. Zarządza usługami (zamyka, uruchamia ponownie lub zabija procesy zombie) lepiej niż jakiekolwiek inne narzędzie.
To powiedziawszy, istnieje wiele powodów, aby nie uruchamiać systemd w kontenerach. Najważniejszym z nich jest to, że systemd/journald kontroluje dane wyjściowe kontenerów i narzędzi takich jak
Przybycie Podmana
Z radością informujemy, że sytuacja w końcu uległa poprawie. Zespół odpowiedzialny za prowadzenie kontenerów w Red Hat zdecydował się na rozwój
Wiele osób to robi.
Mój Podman i ja nie jesteśmy w żaden sposób przeciwni kontenerom opartym na systemach. W końcu Systemd jest najczęściej używanym podsystemem inicjującym Linuksa i uniemożliwienie mu prawidłowego działania w kontenerach oznacza ignorowanie przyzwyczajenia tysięcy ludzi do uruchamiania kontenerów.
Podman wie co zrobić, żeby systemd działał poprawnie w kontenerze. Potrzebuje takich rzeczy, jak montowanie tmpfs na /run i /tmp. Lubi mieć włączone środowisko „kontenerowe” i oczekuje uprawnień do zapisu w swojej części katalogu cgroup i folderze /var/log/journald.
Kiedy uruchamiasz kontener, którego pierwszym poleceniem jest init lub systemd, Podman automatycznie konfiguruje tmpfs i Cgroups, aby zapewnić, że systemd uruchomi się bez problemów. Aby zablokować ten tryb automatycznego uruchamiania, użyj opcji --systemd=false. Należy pamiętać, że Podman używa trybu systemowego tylko wtedy, gdy widzi, że musi uruchomić polecenie systemd lub init.
Oto fragment instrukcji:
biegnij podmanem
...–systemd=prawda|fałsz
Uruchamianie kontenera w trybie systemowym. Domyślnie włączone.
Jeśli uruchomisz polecenie systemd lub init w kontenerze, Podman skonfiguruje punkty podłączenia tmpfs w następujących katalogach:
/run, /run/lock, /tmp, /sys/fs/cgroup/systemd, /var/lib/journal
Również domyślnym sygnałem stopu będzie SIGRTMIN+3.
Wszystko to pozwala systemd działać w zamkniętym kontenerze bez żadnych modyfikacji.
UWAGA: systemd próbuje zapisać w systemie plików cgroup. Jednak SELinux domyślnie uniemożliwia kontenerom robienie tego. Aby włączyć zapis, włącz parametr boolowski Container_manage_cgroup:
setsebool -P grupa_zarządzania_kontenerami prawda
Teraz spójrz, jak wygląda plik Dockerfile do uruchamiania systemd w kontenerze za pomocą Podmana:
# cat Dockerfile
FROM fedora
RUN dnf -y install httpd; dnf clean all; systemctl enable httpd
EXPOSE 80
CMD [ "/sbin/init" ]
To wszystko.
Teraz montujemy pojemnik:
# podman build -t systemd .
Mówimy SELinuxowi, aby pozwolił systemdowi modyfikować konfigurację Cgroups:
# setsebool -P container_manage_cgroup true
Nawiasem mówiąc, wiele osób zapomina o tym kroku. Na szczęście wystarczy to zrobić tylko raz, a ustawienie zostanie zapisane po ponownym uruchomieniu systemu.
Teraz po prostu uruchamiamy kontener:
# 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.
To wszystko, usługa jest uruchomiona i działa:
$ curl localhost
<html xml_lang="en" lang="en">
…
</html>
UWAGA: nie próbuj tego na Dockerze! Tam nadal musisz tańczyć z tamburynem, aby wystrzelić tego rodzaju pojemniki przez demona. (Aby to wszystko działało płynnie w Dockerze, wymagane będą dodatkowe pola i pakiety, w przeciwnym razie konieczne będzie uruchomienie w uprzywilejowanym kontenerze. Aby uzyskać szczegółowe informacje, zobacz
Jeszcze kilka fajnych rzeczy na temat Podmana i systemd
Podman działa lepiej niż Docker w plikach jednostek systemowych
Jeśli kontenery muszą zostać uruchomione podczas uruchamiania systemu, możesz po prostu wstawić odpowiednie polecenia Podmana do pliku jednostki systemowej, co uruchomi usługę i będzie ją monitorować. Podman używa standardowego modelu fork-exec. Innymi słowy, procesy kontenerowe są dziećmi procesu Podmana, więc systemd może je łatwo monitorować.
Docker korzysta z modelu klient-serwer, a polecenia Docker CLI można również umieszczać bezpośrednio w pliku jednostkowym. Jednak gdy klient Dockera połączy się z demonem Dockera, stanie się on (klientem) kolejnym procesem przetwarzającym standardowe i standardowe wyjścia. Z kolei systemd nie ma pojęcia o połączeniu klienta Dockera z kontenerem działającym pod kontrolą demona Dockera i dlatego w ramach tego modelu systemd zasadniczo nie może monitorować usługi.
Aktywacja systemd przez gniazdo
Podman poprawnie obsługuje aktywację poprzez gniazdo. Ponieważ Podman używa modelu fork-exec, może przekazać gniazdo do swoich podrzędnych procesów kontenerowych. Docker nie może tego zrobić, ponieważ używa modelu klient-serwer.
Usługa varlink, której Podman używa do komunikacji ze zdalnymi klientami do kontenerów, jest w rzeczywistości aktywowana poprzez gniazdo. Pakiet Cockpit-Podman, napisany w Node.js i stanowiący część projektu Cockpit, umożliwia interakcję z kontenerami Podman za pośrednictwem interfejsu internetowego. Demon sieciowy uruchamiający kokpit-podman wysyła wiadomości do gniazda varlink, na którym nasłuchuje systemd. Następnie Systemd aktywuje program Podman, aby odbierać wiadomości i rozpocząć zarządzanie kontenerami. Aktywacja systemd przez gniazdo eliminuje potrzebę stale działającego demona podczas implementowania zdalnych interfejsów API.
Dodatkowo pracujemy nad innym klientem Podman o nazwie podman-remote, który implementuje ten sam interfejs CLI Podmana, ale wywołuje varlink do uruchamiania kontenerów. Podman-remote może działać na sesjach SSH, umożliwiając bezpieczną interakcję z kontenerami na różnych maszynach. Z czasem planujemy umożliwić podman-remote obsługę systemów MacOS i Windows obok Linuksa, tak aby programiści na tych platformach mogli uruchomić maszynę wirtualną z systemem Linux z uruchomionym Podman varlink i mieć pełne doświadczenie z tym, że kontenery działają na maszynie lokalnej.
SD_NOTIFY
Systemd umożliwia odroczenie uruchomienia usług pomocniczych do czasu uruchomienia wymaganej przez nie usługi kontenerowej. Podman może przekazać gniazdo SD_NOTIFY do usługi kontenerowej, dzięki czemu usługa powiadomi systemd, że jest gotowa do działania. I znowu Docker, który korzysta z modelu klient-serwer, nie może tego zrobić.
W planach
Planujemy dodać polecenie podman generate systemd CONTAINERID, które wygeneruje plik jednostki systemowej do zarządzania określonym określonym kontenerem. Powinno to działać zarówno w trybie root, jak i bez rootowania dla nieuprzywilejowanych kontenerów. Widzieliśmy nawet prośbę o środowisko wykonawcze systemd-nspawn kompatybilne z OCI.
wniosek
Uruchamianie systemd w kontenerze jest potrzebą zrozumiałą. A dzięki Podmanowi w końcu mamy środowisko wykonawcze kontenerów, które nie koliduje z systemd, ale czyni go łatwym w użyciu.
Źródło: www.habr.com