Execución de systemd nun contedor

Levamos moito tempo seguindo o tema do uso de systemd en contedores. En 2014, o noso enxeñeiro de seguridade Daniel Walsh escribiu un artigo Execución de systemd nun contenedor Docker, e un par de anos despois - outro, que se chamaba Executando systemd nun contedor non privilexiado, no que afirmou que a situación non mellorou moito. En particular, escribiu que "desafortunadamente, mesmo dous anos despois, se buscas en Google "Sistema Docker", o primeiro que aparece é o seu mesmo artigo. Entón é hora de cambiar algo". Ademais, xa o falamos conflito entre Docker e os desenvolvedores de systemd.

Execución de systemd nun contedor

Neste artigo imos amosar o que cambiou co paso do tempo e como Podman pode axudarnos neste asunto.

Hai moitas razóns para executar systemd dentro dun contedor, como:

  1. Contenedores multiservizo – Moitas persoas queren sacar as súas aplicacións multiservizos das máquinas virtuais e executalas en contedores. Sería mellor, por suposto, dividir tales aplicacións en microservizos, pero aínda non todos saben como facelo ou simplemente non teñen tempo. Polo tanto, executar aplicacións como os servizos iniciados por systemd desde ficheiros unitarios ten todo o sentido.
  2. Ficheiros de unidades de sistema – A maioría das aplicacións que se executan dentro de contedores están construídas a partir de código que se executaba anteriormente en máquinas virtuais ou físicas. Estas aplicacións teñen un ficheiro de unidade que se escribiu para estas aplicacións e comprende como deberían ser iniciadas. Polo tanto, aínda é mellor comezar os servizos usando métodos compatibles, en lugar de piratear o seu propio servizo de inicio.
  3. Systemd é un xestor de procesos. Xestiona servizos (apaga, reinicia servizos ou mata procesos zombies) mellor que calquera outra ferramenta.

Dito isto, hai moitas razóns para non executar systemd en contedores. O principal é que systemd/journald controla a saída de contedores e ferramentas como Kubernetes ou turno aberto esperar que os contedores escriban o rexistro directamente en stdout e stderr. Polo tanto, se vas xestionar contedores a través de ferramentas de orquestración como as mencionadas anteriormente, deberías considerar seriamente o uso de contedores baseados en systemd. Ademais, os desenvolvedores de Docker e Moby a miúdo opuxéronse firmemente a usar systemd nos contedores.

A chegada de Podman

Estamos encantados de informar que a situación finalmente avanzou. O equipo responsable de executar contedores en Red Hat decidiu desenvolver o teu propio motor de contedores. Conseguiu un nome podman e ofrece a mesma interface de liña de comandos (CLI) que Docker. E case todos os comandos de Docker pódense usar en Podman do mesmo xeito. Adoitamos realizar seminarios, que agora se chaman Cambiando Docker a Podman, e a primeira diapositiva chama a escribir: alias docker=podman.

Moitas persoas fan isto.

O meu Podman e eu non estamos en contra dos contedores baseados en systemd. Despois de todo, Systemd é o subsistema de inicio de Linux máis usado, e non permitir que funcione correctamente nos contedores significa ignorar como miles de persoas están afeitas a executar contedores.

Podman sabe que facer para que systemd funcione correctamente nun contedor. Necesita cousas como montar tmpfs en /run e /tmp. Gústalle ter activado o ambiente "containerizado" e espera permisos de escritura para a súa parte do directorio cgroup e para o cartafol /var/log/journald.

Cando inicia un contedor no que o primeiro comando é init ou systemd, Podman configura automaticamente tmpfs e Cgroups para garantir que systemd se inicie sen problemas. Para bloquear este modo de inicio automático, use a opción --systemd=false. Ten en conta que Podman só usa o modo systemd cando ve que necesita executar un comando systemd ou init.

Aquí tedes un extracto do manual:

home podman correr
...

–systemd=verdadeiro|falso

Execución dun contedor en modo systemd. Activado por defecto.

Se executa un comando systemd ou init dentro dun contedor, Podman configurará os puntos de montaxe tmpfs nos seguintes directorios:

/run, /run/lock, /tmp, /sys/fs/cgroup/systemd, /var/lib/journal

Tamén o sinal de parada predeterminado será SIGRTMIN+3.

Todo isto permite que systemd funcione nun contedor pechado sen ningunha modificación.

NOTA: systemd tenta escribir no sistema de ficheiros cgroup. Non obstante, SELinux impide que os contedores o fagan por defecto. Para habilitar a escritura, active o parámetro booleano container_manage_cgroup:

setsebool -P container_manage_cgroup true

Agora mira o aspecto do Dockerfile para executar systemd nun contedor usando Podman:

# cat Dockerfile

FROM fedora

RUN dnf -y install httpd; dnf clean all; systemctl enable httpd

EXPOSE 80

CMD [ "/sbin/init" ]

Iso é todo.

Agora montamos o recipiente:

# podman build -t systemd .

Dicimos a SELinux que permita a systemd modificar a configuración de Cgroups:

# setsebool -P container_manage_cgroup true

Por certo, moitas persoas esquécense deste paso. Afortunadamente, isto só debe facerse unha vez e a configuración gárdase despois de reiniciar o sistema.

Agora só comezamos o recipiente:

# 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.

Xa está, o servizo está en funcionamento:

$ curl localhost

<html  xml_lang="en" lang="en">

…

</html>

NOTA: Non probe isto en Docker! Alí aínda cómpre bailar cunha pandeireta para lanzar este tipo de contedores a través do daemon. (Serán necesarios campos e paquetes adicionais para que todo isto funcione perfectamente en Docker, ou terá que executalo nun contedor privilexiado. Para obter máis información, consulte Artigo.)

Un par de cousas interesantes máis sobre Podman e systemd

Podman funciona mellor que Docker nos ficheiros de unidades systemd

Se hai que iniciar os contedores cando se inicia o sistema, pode simplemente inserir os comandos Podman axeitados no ficheiro de unidade systemd, que iniciará o servizo e supervisará. Podman usa o modelo fork-exec estándar. Noutras palabras, os procesos de contedores son fillos do proceso Podman, polo que systemd pode supervisalos facilmente.

Docker usa un modelo cliente-servidor e os comandos CLI de Docker tamén se poden colocar directamente nun ficheiro de unidade. Non obstante, unha vez que o cliente Docker se conecta ao daemon Docker, este (o cliente) convértese nun proceso máis que manexa stdin e stdout. Á súa vez, systemd non ten idea da conexión entre o cliente Docker e o contedor que se executa baixo o control do daemon Docker e, polo tanto, dentro deste modelo, systemd fundamentalmente non pode supervisar o servizo.

Activando systemd mediante socket

Podman xestiona a activación a través do socket correctamente. Debido a que Podman usa o modelo fork-exec, pode reenviar o socket aos procesos dos seus contenedores fillos. Docker non pode facelo porque usa un modelo cliente-servidor.

O servizo varlink que usa Podman para comunicarse con clientes remotos aos contedores actívase en realidade a través dun socket. O paquete cockpit-podman, escrito en Node.js e parte do proxecto cockpit, permite que as persoas interactúen cos contedores Podman a través dunha interface web. O daemon web que executa cockpit-podman envía mensaxes a un socket varlink que escoita systemd. A continuación, Systemd activa o programa Podman para recibir mensaxes e comezar a xestionar os contedores. A activación de systemd a través dun socket elimina a necesidade dun daemon en execución constante ao implementar API remotas.

Ademais, estamos a desenvolver outro cliente Podman chamado podman-remote, que implementa a mesma CLI de Podman pero chama a varlink para executar contedores. Podman-remote pode executarse enriba das sesións SSH, o que lle permite interactuar de forma segura con contedores en diferentes máquinas. Co paso do tempo, planeamos habilitar podman-remote para admitir MacOS e Windows xunto con Linux, para que os desenvolvedores desas plataformas poidan executar unha máquina virtual Linux con Podman varlink en execución e ter a experiencia completa de que os contedores se executan na máquina local.

SD_NOTIFICAR

Systemd permítelle aprazar o lanzamento dos servizos auxiliares ata que se inicie o servizo en contedores que requiren. Podman pode reenviar o socket SD_NOTIFY ao servizo en contenedores para que o servizo notifique a systemd que está listo para funcionar. E de novo, Docker, que usa un modelo cliente-servidor, non pode facelo.

Nos planos

Pretendemos engadir o comando podman generate systemd CONTAINERID, que xerará un ficheiro de unidade systemd para xestionar un contedor específico especificado. Isto debería funcionar tanto en modo root como sen root para contenedores sen privilexios. Incluso vimos unha solicitude para un tempo de execución systemd-nspawn compatible con OCI.

Conclusión

Executar systemd nun contedor é unha necesidade comprensible. E grazas a Podman, por fin temos un tempo de execución do contedor que non entra en conflito con systemd, pero que o fai doado de usar.

Fonte: www.habr.com

Engadir un comentario