Contenedores con podman

Como he estado levantando algunos servicios en producción con podman y mientras decido cuáles son las mejores maneras de administrarlos me escribiré esta guía con cosas que me han sido útiles en el camino. Con el pasar del tiempo irá cobrando forma y tendiendo más orden. Al día de hoy considérese como un bloc de notas.

Generar archivos de systemd

Por el momento la mejor forma que he encontrado de administrar los servicios es usando systemd. A la mala aprendí que los usuarios que administren unidades de systemd relacionadas con podman no deben ser cuentas de systema (con UID menor a 1000) sino usuarios más normalitos.

Para generar los archivos .service de una infraestructura primero hay que levantarla (digamos, a manita? o usando algo como podman-compose). Es decir asegurarse de que todos los servicios están corriendo con los volúmenes necesarios y las respectivas configuraciones de red. Yo conecto los servicios por medio de pods, que me parece bastante más razonable que usar reds virtuales.

Luego usando este comando apuntando al pod que representa la infraestructura generaremos los archivos:

podman generate systemd --files --name --new --pod-prefix= --container-prefix= my-pod

Una breve explicación de las opciones:

  • --files hace que en la carpeta actual se generen los archivos .service correspondientes.
  • --name usa el nombre de cada contenedor para las descripciones de los archivos.
  • --new evita asumir que los contenedores existen. Esto permite que el proceso de subir los archivos generados a un servidor e iniciar los procesos sea más sencillo.
  • --pod-prefix= le quita el prefijo al archivo de servicio para el pod. Lo uso porque nombro mis pods como servicio-pod (ya tienen sufijo).
  • --container-prefix= le quita el prefijo a las unidades de cada contenedor de la infraestructura. Lo uso por la misma razón de arriba.
  • my-pod el nombre del pod que conecta la infraestructura.

Una vez generados seguramente querrás ajustar las rutas a los puntos de montaje de ciertos volúmenes y algunos otros detalles menores. Luego puedes subirlos a un servidor (yo se los pongo en ~/.config/systemd/user/), descargar las imágenes necesarias e iniciar los servicios. El monitoreo se puede hacer sin problemas con journalctl.

Si tu infraestructura requiere de un timer puedes usar los bien conocidos timers de systemd para generarlo. Así te ahorras esos trucos gachísimos de levantar imágenes con cron y cosas así.

Para mayor información: man podman-generate-systemd

Enlaces útiles

En general hacerle caso a los resultados de búsqueda que muestran cosas del blog de redhat podría ser buena idea.

Mapear usuarios entre el contenedor y el host

Con esto estuve batallando un rato. El caso de uso es simple: quieres que el usuario que ejecuta el programa dentro del contenedor se mapee a un usuario real del host, por ejemplo para que un volumen con archivos se pueda manipular tanto desde dentro del contenedor como desde fuera.

Para lograr esto se usa la opción de línea de comandos --uidmap de podman run que nos permite especificar un mapeo de ids para este comando en particular:

podman run -it --rm \
    --volume /path/in/host:/path/in/container \
    --uidmap 900:0:1 --uidmap 0:1:900 \
    ubuntu bash

Aquí estoy asumiendo que dentro del contenedor hay un usuario con ID 900 especificado con la directiva USER del containerfile.

En el comando existen dos directivas --uidmap. La primera especifica que para el usuario del contenedor con ID 900 va a mapear al host comenzando por el ID 0 del host y reservando solamente un ID. Ahora lo interesante aquí es que hay un mapeo intermedio hecho por podman que asocia el ID 0 del contenedor con el ID del usuario del host que corre podman. Al añadir un mapeo que asocia al usuario 900 con el ID 0 por sobre el mapeo anterior tenemos que el usuario 900 va a mapear al usuario que corre podman. ¡Hurra!

La cosa se pone turbia con el segundo mapeo. Ahí estamos especificando que el ID 0 del contenedor (que corresponde al usuario root) va a mapear al ID 1 del host y que se van a reservar 900 ids. Aquí lo que sucede es que los ids mayores o iguales que 1 en realidad se comienzan a mapear al host desde el primer ID reservado en /etc/subuid, resultando que si ejecutas el comando como usuario root del contenedor y creas de esta manera un archivo en el volumen tendrá por usuario y grupo un número grandote.

Cabe mencionar que puedes elegir con qué usuario correr un comando dentro del contenedor pasando la opción --user. Por ejemplo para usar root: --user 0.