GNU/Linux >> Tutoriales Linux >  >> Linux

Cómo usar Podman dentro de un contenedor

Uno de los temas más consultados por las personas que trabajan en tecnologías de contenedores upstream es la ejecución de Podman dentro de un contenedor. Históricamente, la mayor parte de esto ha estado relacionado con Docker en Docker (DIND), pero ahora, la gente también quiere ejecutar Podman en Podman (PINP) o Podman en Docker (PIND).

Pero Podman se puede ejecutar de múltiples maneras, con y sin raíces. Terminamos con personas que desean ejecutar varias combinaciones de Podman rootful y rootless:

  • Rootful Podman en Rootful Podman
  • Podman desarraigado en Podman arraigado
  • Podman arraigado en Podman desarraigado
  • Podman desarraigado en Podman desarraigado

Te haces una idea.

Este blog intentará cubrir cada combinación, comenzando con una discusión sobre los privilegios. Comenzaremos con el escenario PINP aquí en la primera parte. En la segunda parte de la serie, cubriremos un terreno similar pero lo haremos dentro del contexto de Kubernetes. Asegúrese de leer ambos artículos para obtener una imagen completa.

Los motores de contenedores requieren privilegios

Para ejecutar un motor de contenedor como Podman dentro de un contenedor, lo primero que debe comprender es que necesita una cantidad considerable de privilegios.

  • Los contenedores requieren varios UID. La mayoría de las imágenes de contenedor necesitan más de un UID para funcionar. Por ejemplo, podría tener una imagen con la mayoría de los archivos propiedad de root, pero algunos propiedad del usuario apache (UID=60).
  • Los motores de contenedores montan sistemas de archivos y usan el clon de llamada del sistema para crear espacios de nombres de usuario.

Nota:es posible que necesite una versión más reciente de Podman. Los ejemplos de este blog se ejecutaron con Podman 3.2.

Nuestra imagen de prueba

Para los ejemplos de este blog, usaremos quay.io/podman/stable image, que se creó con la idea de encontrar la mejor manera de ejecutar Podman dentro de un contenedor. Puede examinar cómo construimos esta imagen desde Dockerfile y containers.conf imagen en el repositorio de github.com.

# stable/Dockerfile
#
# Build a Podman container image from the latest
# stable version of Podman on the Fedoras Updates System.
# https://bodhi.fedoraproject.org/updates/?search=podman
# This image can be used to create a secured container
# that runs safely with privileges within the container.
#
FROM registry.fedoraproject.org/fedora:latest

# Don't include container-selinux and remove
# directories used by yum that are just taking
# up space.
RUN dnf -y update; yum -y reinstall shadow-utils; \
yum -y install podman fuse-overlayfs --exclude container-selinux; \
rm -rf /var/cache /var/log/dnf* /var/log/yum.*

RUN useradd podman; \
echo podman:10000:5000 > /etc/subuid; \
echo podman:10000:5000 > /etc/subgid;

VOLUME /var/lib/containers
VOLUME /home/podman/.local/share/containers

ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/containers.conf /etc/containers/containers.conf
ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/podman-containers.conf /home/podman/.config/containers/containers.conf

RUN chown podman:podman -R /home/podman

# chmod containers.conf and adjust storage.conf to enable Fuse storage.
RUN chmod 644 /etc/containers/containers.conf; sed -i -e 's|^#mount_program|mount_program|g' -e '/additionalimage.*/a "/var/lib/shared",' -e 's|^mountopt[[:space:]]*=.*$|mountopt = "nodev,fsync=0"|g' /etc/containers/storage.conf
RUN mkdir -p /var/lib/shared/overlay-images /var/lib/shared/overlay-layers /var/lib/shared/vfs-images /var/lib/shared/vfs-layers; touch /var/lib/shared/overlay-images/images.lock; touch /var/lib/shared/overlay-layers/layers.lock; touch /var/lib/shared/vfs-images/images.lock; touch /var/lib/shared/vfs-layers/layers.lock

ENV _CONTAINERS_USERNS_CONFIGURED=""

Examinemos el Dockerfile.

FROM registry.fedoraproject.org/fedora:latest

# Don't include container-selinux and remove
# directories used by yum that are just taking
# up space.
RUN dnf -y update; yum -y reinstall shadow-utils; \
yum -y install podman fuse-overlayfs --exclude container-selinux; \
rm -rf /var/cache /var/log/dnf* /var/log/yum.*

Primero extraiga la última versión de Fedora y luego actualice a los últimos paquetes. Tenga en cuenta que reinstala shadow-utils , ya que hay un problema conocido en shadow-utils instalar en la imagen de Fedora donde el filecaps en newsubuid y newsubgid no están establecidos. Reinstalando shadow-utils soluciona el problema A continuación, instale Podman y fuse-overlayfs . No instalamos container-selinux porque no se necesita dentro del contenedor.

RUN useradd podman; \
echo podman:10000:5000 > /etc/subuid; \
echo podman:10000:5000 > /etc/subgid;

Luego creo un usuario podman y configure el /etc/subuid y /etc/subgid archivos para usar 5000 UID. Esto se usa para configurar el espacio de nombres de usuario dentro del contenedor. 5000 es un número arbitrario y potencialmente demasiado pequeño. Elegimos este número porque es más pequeño que los 65k asignados a usuarios sin raíz. Si solo estuviera ejecutando el contenedor como root, 65k habría sido un número mejor.

VOLUME /var/lib/containers
VOLUME /home/podman/.local/share/containers

Dado que podemos ejecutar contenedores rootfull y rootless con esta imagen, creamos dos volúmenes. Rootfull Podman usa /var/lib/containers para su almacenamiento en contenedores y usos sin raíz /home/podman/.local/share/containers . El kernel a menudo niega superposición sobre superposición, por lo que esto crea volúmenes no superpuestos para ser utilizados dentro del contenedor.

ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/containers.conf /etc/containers/containers.conf
ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/podman-containers.conf /home/podman/.config/containers/containers.conf

He preconfigurado dos containers.conf archivos para asegurarse de que los contenedores se ejecuten más fácilmente en cada modo.

La imagen está configurada para ejecutarse con fuse-overlayfs de forma predeterminada. En ciertos casos, puede ejecutar el sistema de archivos de superposición del núcleo para el modo raíz, y pronto podrá hacerlo en modo sin raíz. Sin embargo, por ahora, usamos fuse-overlayfs como nuestro contenedor de almacenamiento dentro del contenedor. Otras personas han usado el controlador de almacenamiento VFS, pero este no es tan eficiente.

La bandera --privilegiada

La forma más fácil de ejecutar Podman dentro de un contenedor es usar el --privileged bandera.

Podman rootful en Podman rootful con --privileged

# podman run --privileged quay.io/podman/stable podman run ubi8 echo hello
Resolved "ubi8-minimal" as an alias (/etc/containers/registries.conf.d/shortnames.conf)
Trying to pull registry.access.redhat.com/ubi8:latest...
Getting image source signatures
Copying blob sha256:a591faa84ab05242a17131e396a336da172b0e1ec66d921c9f130b7c4c24586d
Copying blob sha256:76b9354adec626b01ffb0faae4a217cebd616661fd90c4b54ba4415f53392fb8
Copying config sha256:dc080723f596f2407300cca2c19a17accad89edcf39f7b8b33e6472dd41e30f1
Writing manifest to image destination
Storing signatures
hello

Para ahorrar tiempo, ya que haré muchos experimentos, creé un directorio en mi host ./mycontainers , que montaré en volumen en el contenedor para usar y no tener que extraer la imagen cada vez.

# podman run --privileged -v ./mycontainers:/var/lib/containers quay.io/podman/stable podman run ubi8 echo hello
hello

Podman desarraigado en Podman rootful con --privileged

El quay.io/podman/stable la imagen se configura con un podman usuario que puede usar para ejecutar contenedores sin raíz.

# podman run --user podman --privileged quay.io/podman/stable podman run ubi8 echo hello
Resolved "ubi8" as an alias (/etc/containers/registries.conf.d/shortnames.conf)
...
hello

Tenga en cuenta que en este caso, el Podman que se ejecuta dentro del contenedor se ejecuta como el usuario podman . Esto se debe a que el Podman en contenedor usa el espacio de nombres de usuario para crear un contenedor confinado dentro del contenedor privilegiado.

Ejecutar Podman sin raíz en Docker con --privileged

Similar a Rootful Podman, también puede ejecutar Podman sin root dentro de Docker con --privileged opción.

# docker run --privileged quay.io/podman/stable podman run ubi8 echo hello

Podman sin raíz con Docker

# docker run --user podman --privileged quay.io/podman/stable podman run ubi8 echo hello
Resolved "ubi8" as an alias (/etc/containers/registries.conf.d/shortnames.conf)
...
hello

¿Podemos hacer esto de forma más segura?

Tenga en cuenta que aunque ejecutamos los contenedores externos --privileged arriba, los contenedores internos están funcionando en modo bloqueado. El Podman desarraigado que corre dentro del contenedor está realmente bloqueado y tendría muchas dificultades para escapar. Dado eso, no soy fanático de usar --privileged bandera. Creo que podemos hacerlo mejor desde una perspectiva de seguridad.

Ejecutar sin la marca --privileged

Veamos cómo podemos eliminar el --privileged bandera para mayor seguridad.

Podman rootful en Podman rootful sin --privileged

# podman run --cap-add=sys_admin,mknod --device=/dev/fuse --security-opt label=disable quay.io/podman/stable podman run ubi8-minimal echo hello
hello

Podemos eliminar el --privileged marcar desde rootful Podman pero aún tengo que deshabilitar algunas funciones de seguridad para que Rootful Podman dentro del contenedor funcione.

  1. Capacidades:--cap-add=sys_admin,mknod Necesitamos agregar dos capacidades de Linux.
    1. CAP_SYS_ADMIN es necesario para que Podman se ejecute como raíz dentro del contenedor para montar los sistemas de archivos necesarios.
    2. CAP_MKNOD es necesario para que Podman se ejecute como root dentro del contenedor para crear los dispositivos en /dev . (Tenga en cuenta que Docker lo permite de forma predeterminada).
  2. Dispositivos:El --device /dev/fuse La bandera debe usar fusibles superpuestos dentro del contenedor. Esta opción le dice a Podman en el host que agregue /dev/fuse al contenedor para que Podman en contenedores pueda usarlo.
  3. Deshabilitar SELinux:--security-opt label=disable La opción le dice al Podman del host que deshabilite la separación de SElinux para el contenedor. SELinux no permite que los procesos en contenedores monten todos los sistemas de archivos necesarios para ejecutarse dentro de un contenedor.

Rootful Podman en Docker sin --privileged

# docker run --cap-add=sys_admin --cap-add mknod --device=/dev/fuse --security-opt seccomp=unconfined --security-opt label=disable quay.io/podman/stable podman run ubi8-minimal echo hello
hello
  1. Nota Docker no admite la coma separada --cap-add comando, así que tuve que agregar sys_admin y mknod por separado
  2. Todavía se necesita --device /dev/fuse , ya que el contenedor por defecto es /dev/fuse
  3. Docker siempre crea volúmenes incorporados como propiedad de root:root, por lo que debemos crear un volumen para montar para Podman en el contenedor para poder usarlo para el almacenamiento.
  4. Como siempre, necesito deshabilitar la separación de SELinux
  5. También es necesario deshabilitar seccomp , ya que Docker tiene un seccomp ligeramente más estricto política que Podman. Simplemente podría usar una política de seguridad de Podman usando --seccomp=/usr/share/containers/seccomp.json
# docker run --cap-add=sys_admin --cap-add mknod --device=/dev/fuse --security-opt seccomp=/usr/share/containers/seccomp.json --security-opt label=disable quay.io/podman/stable podman run ubi8-minimal echo hello
hello

Podman desarraigado en Podman arraigado sin privilegios

Ejecutar no -contenedor privilegiado con Podman dentro usando un usuario no root usando el espacio de nombres de usuario.

# podman run --user podman --security-opt label=disable --security-opt unmask=ALL --device /dev/fuse -ti quay.io/podman/stable podman run -ti docker.io/busybox echo hello
hello
  1. Tenga en cuenta que, a diferencia de rooful dentro de rootful case anterior, no tenemos que agregar las capacidades de seguridad peligrosas sys_admin y mknod
  2. En este caso, estoy ejecutando con --user podman , lo que automáticamente hace que Podman dentro del contenedor se ejecute dentro del espacio de nombres de usuario
  3. Todavía deshabilitando SELinux ya que bloquea el montaje
  4. Todavía necesito --device /dev/fuse para usar fuse-overlayfs dentro del contenedor

Podman-remote en Rootful Podman con un socket de Podman filtrado del host

# podman run -v /run:/run --security-opt label=disable quay.io/podman/stable podman --remote run busybox echo hi
hi

En este caso, estamos filtrando el /run directorio del host al contenedor. Esto permite que podman --remote para comunicarse con el socket Podman en el host e iniciar el contenedor en el sistema operativo del host. Esta es a menudo la forma en que las personas ejecutan Docker In Docker, especialmente las compilaciones de Docker. También puede ejecutar las compilaciones de Podman de esta manera y aprovechar las imágenes previamente extraídas del sistema.

Tenga en cuenta, sin embargo, que esto es extremadamente inseguro. Los procesos dentro del contenedor pueden hacerse cargo totalmente de la máquina host.

  1. Todavía necesita deshabilitar la separación de SELinux porque SELinux bloquearía los procesos del contenedor para que no usen sockets filtrados en /run .
  2. El podman --remote Se agrega una bandera para decirle a Podman que trabaje en modo remoto. Tenga en cuenta que también puede instalar el podman-remote ejecutable en un contenedor y utilícelo.

[ ¿Empezando con los contenedores? Consulta este curso gratuito. Implementación de aplicaciones en contenedores:una descripción técnica general. ]

Podman-remote en Docker con un socket de Podman filtrado del host

# docker run -v /run:/run --security-opt label=disable quay.io/podman/stable podman --remote run busybox echo hi
hi

El mismo ejemplo funciona para un contenedor Docker.

Este ejemplo muestra un contenedor completamente bloqueado (aparte de la desactivación de SELinux) con el socket de Podman filtrado en el contenedor. SELinux bloquearía este acceso, como debería.

# /bin/podman run --security-opt=label=disable -v /run/podman:/run/podman quay.io/podman/stable podman --remote run alpine echo hi
hi

Rootless Podman con contenedor rootful Podman

$ podman run --privileged quay.io/podman/stable podman run ubi8 echo hello
Resolved "ubi8" as an alias (/etc/containers/registries.conf.d/shortnames.conf)
..
hello

Podman sin raíz ejecutando Podman sin raíz

$ podman run --security-opt label=disable --user podman --device /dev/fuse quay.io/podman/stable podman run alpine echo hello

Reflexiones finales

Ahora tiene algo de contexto para Podman en las opciones de Podman, utilizando los modos rootful y rootless. en varias combinaciones. También tiene una mejor idea de los privilegios necesarios y las consideraciones que rodean al --privileged bandera.

La segunda parte de esta serie analiza el uso de Podman y Kubernetes. El artículo cubre un territorio similar pero dentro del contexto de Kubernetes.

[ ¿Quiere poner a prueba sus habilidades de administrador de sistemas? Tome una evaluación de habilidades hoy. ]


Linux
  1. Cómo usar BusyBox en Linux

  2. Cómo uso cron en Linux

  3. Cómo usar Nginx para redirigir

  4. Cómo usar el comando Su en Linux

  5. Cómo ejecutar un trabajo cron dentro de un contenedor docker

Cómo usar Instagram en la terminal

Cómo ejecutar pods como servicios systemd con Podman

Cómo usar el comando PS

Cómo usar el comando SUPERIOR

Cómo instalar y usar Podman (alternativa de Docker)

¿Cómo usar Linux Bash Shell dentro de Windows 10?