¿Por qué no puedo usar sudo con Podman sin root?

Recientemente me preguntaron: ¿Por qué no puedo ejecutar contenedores Podman sin root cuando me conecto a un usuario a través de sudo Donde su? El problema es un poco complejo de explicar, así que empezaré con un ejemplo.

Supongamos que tengo un contenedor Podman sin raíz que ejecuta una aplicación web para administrar mi colección de fotos. Se ejecuta como el usuario dedicado que creé para la aplicación (fotos, UID 1010). Ha salido una nueva versión de la aplicación, así que quiero reconstruir la imagen y recrear el contenedor usándola. Me conecto con el usuario con un rápido su photos desde un shell raíz, luego vaya al directorio con mi archivo contenedor y haga un podman build. Sin embargo, en lugar de que mi compilación funcione, aparece un mensaje de error:

Error: error creating tmpdir: mkdir /run/user/1010: permission denied

Confundido, ejecuto los mismos comandos en otro sistema y descubro que funcionan bien. ¿Qué esta pasando? La respuesta está en la forma en que Podman administra su directorio de archivos temporales.

Índice

    Actualizar estado

    Una de las principales razones por las que Podman necesita un directorio de archivos temporales es para detectar si el sistema se ha reiniciado. Después de un reinicio, todos los contenedores dejan de funcionar, todos los sistemas de archivos del contenedor se desmontan y todas las interfaces de red deben volver a crearse (entre otras cosas). Podman necesita actualizar su base de datos para reflejar esto y realizar una configuración de arranque para asegurarse de que está listo para lanzar contenedores. Esto se llama "estado refrescante".

    Esto es necesario porque Podman no es un demonio. Cada comando de Podman se ejecuta como un nuevo proceso y no sabe inicialmente en qué estado se encuentran los contenedores. Puede buscar en la base de datos una imagen exacta de todos sus contenedores actuales y sus estados. Actualizar el estado después de un reinicio es esencial para garantizar que esta imagen siga siendo precisa.

    Para realizar la actualización, necesita una forma confiable de detectar un reinicio del sistema y, al comienzo del desarrollo, el equipo de Podman decidió usar un archivo centinela en un tmpfs sistema de archivos A tmpfs es un sistema de archivos en memoria que no se guarda después de un reinicio: cada vez que se inicia el sistema, tmpfs el monte estará vacío. Al verificar la existencia de un archivo en dicho sistema de archivos y crearlo si no existe, Podman puede saber si es la primera vez que se ejecuta desde que reinicia el sistema.

    El problema es averiguar dónde debe colocar su directorio de archivos temporales. La respuesta obvia es /tmp, pero no se garantiza que sea un tmpfs sistema de archivos (aunque a menudo lo es). En su lugar, de forma predeterminada, Podman utilizará /run, que está garantizado para ser un tmpfs. Desgraciadamente, /run solo se puede escribir por root, por lo que Podman sin root tiene que buscar en otra parte. Nuestro equipo se basa en /run/user/$UID directorios, un directorio de archivos temporales por usuario. Sin embargo, su existencia no está garantizada en todos los sistemas; requieren un módulo de autenticación enchufable (PAM) configuración (por ejemplo, logind) que los admita. Rootless Podman volverá a usarse /tmp para sistemas que no los soportan.

    Todavía tenemos el problema de que no está garantizado que sea un tmpfs, pero no hay mejor opción.

    [ Sign up for this free online course: Developing cloud-native applications with microservices architectures. ]

    Los problemas comienzan a surgir cuando examinamos la semántica de la /run/user/$UID directorios. Estos directorios se crean automáticamente cuando se crea una sesión de usuario y se destruyen automáticamente cuando se destruye una sesión de usuario (lo que corresponde aproximadamente a la conexión y desconexión de un usuario del sistema). Esto plantea un problema con los contenedores persistentes: el directorio se puede eliminar y volver a crear mientras los contenedores se están ejecutando, lo que obliga a Podman a actualizar el estado y marcar los contenedores en ejecución como si ya no se estuvieran ejecutando. En los sistemas administrados por logind, existe una opción para crear una sesión de usuario persistente habilitando la persistencia para el usuario (loginctl enable-linger); esto es necesario para todos los usuarios que ejecutan contenedores de larga duración.

    No hay sesión de inicio de sesión

    Todo esto todavía no explica por qué no puedes usar sudo y su con contenedores sin raíces. la respuesta es que sudo y su no cree una sesión de conexión. Hay muchas razones históricas para esto, la mayoría de las cuales se derivan del hecho de que sudo y su son algo irregulares (un usuario se convierte en otro usuario, en lugar de un nuevo inicio de sesión). Mira esto Problema de GitHub para detalles. En vista de esto, Podman sin root no se puede usar con sudo y su salvo que loginctl enable-linger se utiliza para forzar la creación de una sesión de usuario persistente para el usuario.

    Los contenedores raíz no tienen ningún problema con sudo y su porque no usan /run/user/$UID y están más bien ubicados en /run, que está permanentemente montado. Alternativamente, puede acceder al usuario a través de un método que crea una sesión de usuario; ssh está garantizado para hacerlo, por ejemplo. Systemd también proporciona varios comandos (por ejemplo, machinectl login) que abren sesiones de usuario, que se pueden utilizar como alternativa a sudo Donde su.

    Tal vez se pregunte por qué no usamos un directorio de archivos temporales que no es /run/user/$UID. De hecho, como se mencionó anteriormente, Podman recurrirá a un directorio en /tmp cuando detecta /run/user/$UID no existe. No podemos hacer esto en instalaciones existentes porque Podman aplica una regla que establece que el directorio temporal no se puede cambiar después de la primera ejecución de Podman. Usamos el directorio tanto para almacenar el archivo centinela para detectar reinicios como para almacenar el contenido del contenedor que se regenera cuando se reinicia un contenedor (por ejemplo, /etc/resolv.conf). Cambiar el directorio donde Podman busca este contenido podría introducir errores graves.

    [ Learn How to use Podman inside of a container. ]

    Pero, ¿qué pasa si obligas a Podman a usar un directorio en /tmp la primera vez que se ejecuta? Muchas personas hacen esto sin querer cuando ejecutan Podman por primera vez usando sudo Donde su. el /run/user/$UID el directorio no existirá porque el usuario no ha iniciado sesión, por lo que volverá a /tmp y utilícelo para todas las convocatorias posteriores de Podman. Esto también se puede forzar manualmente a través del --runroot marca a Podman, que especifica la ruta al directorio de archivos temporales.

    Esto permitirá que Podman sin root se use con sudo y su, pero solo en grupos de control v1 sistemas Además, será necesario utilizar el --login argumentar a sudo y su para asegurarse de que las variables de entorno estén configuradas correctamente. En los sistemas que usan cgroups v2, Podman también requiere otros aspectos de la sesión de inicio de sesión (en particular, el acceso a dbus del usuario) para configurar cgroups y límites de recursos para contenedores. Además, /run/user/$UID elimina todo el contenido del usuario después de que un usuario cierra la sesión; Podman coloca las credenciales de inicio de sesión del usuario en los registros del directorio temporal, por lo que con /run/user/$UID las credenciales no se conservarán después de que el usuario cierre la sesión, lo que mejora la seguridad.

    Envoltura

    Volviendo a la pregunta original: ¿Por qué Podman sin root funciona con sudo y su en algunos sistemas y no en otros? La respuesta depende de cómo se ejecutó Podman por primera vez y del directorio temporal seleccionado. predeterminado de Podman, /run/user/$UID, no funciona con sudo y su; un directorio alternativo bajo /tmp puede.

    Una nota importante es que incluso si usted poder usar Podman sin root con sudo Donde su en su sistema, no se recomienda. A medida que cgroups v2 comienza a generalizarse, Podman requerirá la presencia de una sesión de inicio de sesión para ejecutar contenedores sin raíz, lo que no se puede hacer con sudo y su. Solucione este problema utilizando un método que crea una sesión de inicio de sesión (ssh Donde machinectl login debería funcionar) o habilitando una sesión de usuario persistente para el usuario en cuestión (loginctl enable-linger).

    Artículos de interés

    Subir