Este artículo se basa en mis artículos anteriores sobre espacios de nombres, Los 7 espacios de nombres de Linux más utilizados y mi serie sobre Creación manual de un contenedor de Linux usando espacios de nombres, usando el espacio de nombres de montaje y usando el espacio de nombres PID. Este artículo cubre el espacio de nombres UTS y su relación con los contenedores.
El observador casual a menudo malinterpreta el espacio de nombres Unix Timesharing System (UTS), en gran parte porque su nombre ya no coincide con su propósito. A pesar de su nombre, el espacio de nombres UTS en realidad controla el nombre de host y el dominio NIS. Así es como la página man describe el espacio de nombres UTS:
Estos identificadores se establecen usando sethostname(2)
y setdomainname(2)
, y se puede recuperar usando uname(2)
, gethostname(2)
y getdomainname(2)
. Los cambios realizados en estos identificadores son visibles para todos los demás procesos en el mismo espacio de nombres de UTS, pero no son visibles para los procesos en otros espacios de nombres de UTS.
Esto significa que algunas herramientas modernas (systemd y otras) pueden no generar los cambios esperados.
Como puede imaginar, puede haber varios casos de uso en los que desee que los procesos tengan diferentes nombres de host. Los servidores web, por ejemplo, tienden a lanzar una advertencia si el nombre de host no coincide con el certificado SSL que están sirviendo. Por otro lado, algunos procesos pueden adjuntar el nombre de host a un proceso de red. Un nombre de host incorrecto puede causar conexiones fallidas o denegadas o una miríada de otros problemas.
Con todo lo dicho, veamos algunos ejemplos.
Explore el espacio de nombres UTS
Puede invocar el espacio de nombres UTS con:
$ unshare --uts /bin/bash
Sin embargo, puede notar que una vez que esté en el nuevo espacio de nombres, use hostnamectl set-hostname
no cambia el nombre de host en el nuevo espacio de nombres.
# unshare --uts
# hostname
bastion.stratus.lab
# hostnamectl set-hostname tux
# hostname
bastion.stratus.lab
Sin embargo, si abre un nuevo shell, el nombre de host en realidad ha cambiado:
[user@host ~]$ ssh root@bastion
Last login: Tue Dec 7 08:17:48 2021 from 192.168.99.198
[root@tux ~]# hostname
tux
¿Por qué es esto? Systemd no ejecuta el sethostname
llamada del sistema. En cambio, systemd completa la tarea conectándose a un socket. Dado que el socket está asociado con el espacio de nombres anterior, el nombre de host del espacio de nombres anterior se ajusta pero no el nuevo espacio de nombres.
Uso de espacios de nombres raíz
En mi artículo de espacio de nombres de montaje, escribo:
Ahora que está dentro del nuevo espacio de nombres, es posible que no espere ver ninguno de los puntos de montaje originales del host. Sin embargo, este no es el caso. La razón de esto es que systemd por defecto comparte recursivamente los puntos de montaje con todos los espacios de nombres nuevos.
Da la casualidad de que systemd obtiene gran parte de su información de /run
, que se comparte en el espacio de nombres que he creado aquí.
En el artículo del espacio de nombres de montaje, monto tmpfs
en el nuevo espacio de nombres en un directorio que no quiero compartir con el antiguo espacio de nombres.
Puedo deshabilitar la mayoría de las llamadas systemd montando el nuevo espacio de nombres con las siguientes opciones:
$ unshare --mount --uts /bin/bash
Luego vuelva a montar /run
:
$ mount -t tmpfs tmpfs /run
Todo el proceso se ve así:
# unshare --fork --mount --uts /bin/bash
# mount -t tmpfs tmpfs /run
# hostnamectl set-hostname bastion.stratus.lab
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
# hostname tux
# hostname
tux
Puedo confirmar esto abriendo un nuevo caparazón en la caja:
[user@host ~]$ ssh root@bastion
Last login: Tue Dec 7 08:33:04 2021 from 192.168.99.198
[root@bastion ~]# hostname
bastion.stratus.lab
Puedo encontrar el espacio de nombres apropiado usando lsns
comando:
[root@bastion ~]# lsns |grep uts
4026531838 uts 133 1 root /usr/lib/systemd/systemd --switched-root --system --deserialize 31
4026532250 uts 1 645 root /usr/lib/systemd/systemd-udevd
4026532405 uts 1 743 root /usr/lib/systemd/systemd-logind
4026532479 mnt 2 11507 root unshare --fork --mount --uts /bin/bash
4026532480 uts 2 11507 root unshare --fork --mount --uts /bin/bash
Luego puedo ingresar el espacio de nombres con el nsenter
comando:
[root@bastion ~]# nsenter -t 11507 -a
[root@tux /]#
Usar un espacio de nombres de usuario
En mi artículo sobre el espacio de nombres de usuario, menciono algunas consideraciones adicionales al crear espacios de nombres como un usuario sin privilegios:
Cuando crea un nuevo espacio de nombres de usuario, su usuario actual se asignará al usuario nadie . Esto se debe a que, de forma predeterminada, no se está realizando ninguna asignación de ID de usuario. Cuando no se define una asignación, el espacio de nombres simplemente usa las reglas de su sistema para determinar cómo manejar un usuario no definido.
Consulte ese artículo para obtener más información sobre el mapeo de usuarios. En este caso, quiero tener la raíz usuario mapeado automáticamente. De esta manera, tengo "raíz" en el nuevo espacio de nombres. (Nuevamente, consulte el artículo sobre el espacio de nombres de usuario para ver una discusión sobre los espacios de nombres y los permisos).
Si pongo en práctica mis lecciones combinadas en un host CentOS Stream 9, observo:
ocp@bastion ~ $ unshare --map-root-user --user --mount --uts --fork /bin/bash
root@bastion ~ $ hostnamectl set-hostname tux
Could not set static hostname: Interactive authentication required.
Esto se debe a cómo polkit
está configurado en la familia de distribuciones RHEL. Otras distribuciones no arrojan necesariamente este error. Arch Linux (sin polkit
especial configuración), por ejemplo, aún permite que el contenedor cambie el nombre de host. Por lo tanto, independientemente de su distribución, sigue siendo una buena práctica de seguridad volver a montar /run
.
Es importante tener en cuenta que la salida de lsns
podría ser más fácil de leer usando --fork
al crear espacios de nombres.
Así es como se ve sin el --fork
bandera:
[root@bastion ~]# lsns |grep uts
4026531838 uts 135 1 root /usr/lib/systemd/systemd --switched-root --system --deserialize 31
4026532250 uts 1 645 root /usr/lib/systemd/systemd-udevd
4026532405 uts 1 743 root /usr/lib/systemd/systemd-logind
4026532414 uts 1 11962 ocp /bin/bash
Y con el --fork
bandera:
[root@bastion ~]# lsns |grep uts
4026531838 uts 134 1 root /usr/lib/systemd/systemd --switched-root --system --deserialize 31
4026532250 uts 1 645 root /usr/lib/systemd/systemd-udevd
4026532405 uts 1 743 root /usr/lib/systemd/systemd-logind
4026532412 user 2 11939 ocp unshare --map-root-user --user --mount --uts --fork /bin/bash
Mientras que --fork
no es estrictamente necesario en este escenario, puede ser útil o incluso necesario si se requiere un nuevo espacio de nombres PID (consulte mi artículo sobre espacios de nombres PID para obtener más información).
Conclusión
El espacio de nombres UTS no es el espacio de nombres Linux más complicado. Sin embargo, es bastante útil, especialmente en el contexto de los contenedores.
Para aprovechar al máximo el espacio de nombres UTS, combínelo con el espacio de nombres de montaje, como mínimo, cuando use el espacio de nombres raíz y los espacios de nombres de usuario y montaje cuando genere un usuario sin privilegios.
[ Descargue la hoja de trucos intermedios de Linux para mantener los comandos clave al alcance de su mano. ]
En mi próximo artículo, hablaré sobre el espacio de nombres de red y cómo usarlo para permitir que los espacios de nombres tengan su propia IP y espacio de puerto.