Continuando con la serie de espacios de nombres, este artículo cubre el PID espacio de nombres Si desea obtener una descripción general de todos los espacios de nombres, consulte el primer artículo. Anteriormente, creó un nuevo mnt espacio de nombres Curiosamente, como descubrió, incluso después de crear un nuevo mnt espacio de nombres, aún tenía acceso a los ID de proceso (PID) del host original. Cuando intentaste montar el /proc espacio de nombres, recibió el bastante desconcertante permiso denegado error, como se ve a continuación:
root@new-mnt$ mount -t proc proc /proc
mount: permission denied (are you root?)
root@new-mnt$ whoami
root
Si bien podía crear todo tipo de montajes en el nuevo espacio de nombres de montaje, no podía interactuar ni cambiar /proc . En este artículo, analizo el PID espacio de nombres y demuestre cómo puede usarlo, junto con el mnt espacio de nombres, para proteger aún más su contenedor incipiente.
[ A los lectores también les gustó: Cómo funcionan los espacios de nombres PID de Linux con contenedores ]
¿Qué son los ID de proceso?
Antes de saltar directamente al PID espacio de nombres, creo que es una buena idea proporcionar un poco de información sobre por qué este espacio de nombres es importante.
Cuando se crea un proceso en la mayoría de los sistemas operativos similares a Unix, se le asigna un identificador numérico específico denominado ID de proceso. (PID). Este PID ayuda a identificar un proceso de manera única, incluso si hay dos procesos que comparten el mismo nombre legible por humanos. Por ejemplo, si hay varias sesiones ssh activas en un sistema y necesita cerrar una conexión específica, el PID proporciona una forma para que el administrador se asegure de que se cierre la sesión correcta.
Todos estos procesos se rastrean en un sistema de archivos especial llamado procfs
. Si bien este sistema de archivos puede montarse técnicamente en cualquier lugar, la mayoría de las herramientas (y convenciones) esperan que procfs
para ser montado bajo /proc
. Si haces una lista de /proc
, verá una carpeta para cada proceso que se está ejecutando actualmente en su sistema. Dentro de esta carpeta hay todo tipo de archivos especiales que se utilizan para rastrear varios aspectos del proceso. A los efectos de este artículo, estos archivos no son importantes. Es suficiente saber que /proc
es donde la mayoría de los sistemas similares a Unix almacenan información sobre los procesos en un sistema en ejecución.
El espacio de nombres PID
Una de las principales razones del PID El espacio de nombres es para permitir el aislamiento del proceso. Más específicamente, como dice la página man:
Los espacios de nombres PID aíslan el espacio de números de ID del proceso, lo que significa que los procesos en diferentes espacios de nombres PID pueden tener el mismo PID.
Esto es importante porque significa que se puede garantizar que los procesos no tengan un PID en conflicto con ningún otro proceso. Al considerar un solo sistema, por supuesto, no hay posibilidad de que los PID entren en conflicto porque el sistema incrementa continuamente el número de ID del proceso y nunca asigna el mismo número dos veces. Cuando se trata de contenedores en varias máquinas, este problema se vuelve más destacado. Como se describe en la página man:
Los espacios de nombres PID permiten que los contenedores brinden funcionalidades como suspender/reanudar el conjunto de procesos en el contenedor y migrar el contenedor a un nuevo host mientras los procesos dentro del contenedor mantienen los mismos PID.
Aparte del aislamiento, el sistema PID funciona casi idéntica a la que está fuera del espacio de nombres. Los ID de proceso dentro del nuevo espacio de nombres comienzan en 1 , con el primer proceso considerado el init proceso. El inicio El proceso se maneja de manera muy diferente a todos los demás PID en un host. Esto tiene implicaciones particulares para el sistema en ejecución que están fuera del alcance de esta serie. Si está interesado en obtener más información, consulte la sección "Señales y el proceso de inicio" del artículo LWN Namespaces.
Sin embargo, lo que es importante es que cualquier proceso que tenga PID 1 es vital para la longevidad de los espacios de nombres. Si PID 1 termina por cualquier razón, el núcleo enviará un SIGKILL
a todos los procesos restantes en el espacio de nombres, cerrando efectivamente ese espacio de nombres.
Exploración de espacios de nombres PID
Si se pregunta, como yo, si puede anidar PID espacios de nombres, la respuesta es sí. De hecho, el kernel deja espacio para hasta 32 PID anidados espacios de nombres Esto se considera una relación unidireccional. Eso significa que el padre puede ver los PID de los hijos, nietos, etc. Sin embargo, no puede ver ninguno de los PID de sus antepasados. Considere lo siguiente:
[user@localhost ~] sudo unshare -fp /bin/bash
[root@localhost ~] sleep 90000 &
[root@localhost ~] ps -ef
UID PID PPID C STIME TTY TIME CMD
[truncated ]
.....
root 11627 11620 0 09:16 pts/0 00:00:00 sudo unshare -fp /bin/bash
root 11633 11627 0 09:17 pts/0 00:00:00 unshare -fp /bin/bash
root 11634 11633 0 09:17 pts/0 00:00:00 /bin/bash
root 11639 11634 0 09:17 pts/0 00:00:00 sleep 90000
root 11641 11634 0 09:17 pts/0 00:00:00 ps -ef
[root@localhost ~] sudo unshare -fp /bin/bash
[root@localhost ~] sleep 8000 &
[root@localhost ~] ps -ef
[truncated ]
.....
UID PID PPID C STIME TTY TIME CMD
root 11650 11634 0 09:17 pts/0 00:00:00 sudo unshare -fp /bin/bash
root 11654 11650 0 09:17 pts/0 00:00:00 unshare -fp /bin/bash
root 11655 11654 0 09:17 pts/0 00:00:00 /bin/bash
root 11661 11655 0 09:17 pts/0 00:00:00 sleep 8000
root 11671 11655 0 09:17 pts/0 00:00:00 ps -ef
Notará que trunqué la salida porque el PID espacio de nombres aparece para tener acceso completo a todos los PID en /proc
. Observe lo que sucede si intenta detener un proceso que está en un ancestro:
[root@localhost ~] kill -9 11361
bash: kill: (11361) - No such process
¿Por qué es esto? En pocas palabras, herramientas tradicionales como ps
no son conscientes del espacio de nombres y en realidad leen desde el /proc
directorio. Si hiciste un ls /proc
, aún vería todas las carpetas y archivos anteriores porque, como se explicó en el último artículo, el PID espacio de nombres hereda todos los mnt montajes de espacios de nombres. Abordo esta situación más adelante. Por ahora, vuelve al ejemplo que tenemos a mano.
En otro caparazón, identifique los procesos durmientes:
[user@localhost ~] ps -ef |grep sleep
root 11639 11634 0 09:17 pts/0 00:00:00 sleep 90000
root 11661 11655 0 09:17 pts/0 00:00:00 sleep 8000
Si desea verificar que estos procesos están en diferentes espacios de nombres, deberá encontrar el bash
proceso PID. Recuerda, ya que ejecutaste sudo unshare -fp /bin/bash
, el bash
proceso es el init proceso en el nuevo espacio de nombres. Por lo tanto, es el PID el que se vinculará al ID del espacio de nombres. Tomemos los PID:
[root@localhost ~] ps -ef |grep bash
root 11627 11620 0 09:16 pts/0 00:00:00 sudo unshare -fp /bin/bash
root 11633 11627 0 09:17 pts/0 00:00:00 unshare -fp /bin/bash
root 11634 11633 0 09:17 pts/0 00:00:00 /bin/bash
root 11650 11634 0 09:17 pts/0 00:00:00 sudo unshare -fp /bin/bash
root 11654 11650 0 09:17 pts/0 00:00:00 unshare -fp /bin/bash
root 11655 11654 0 09:17 pts/0 00:00:00 /bin/bash
Puede ver los PID 11634 y 11655 en la salida. Si compara esto con la salida de lsns
(lista de espacios de nombres), verá lo siguiente:
[root@localhost ~] lsns |grep bash
NS TYPE NPROCS PID USER COMMAND
4026532952 pid 4 11634 root /bin/bash
4026532954 pid 4 11655 root /bin/bash
Como puede ver, los ID de espacio de nombres son diferentes y, por lo tanto, los procesos se encuentran en espacios de nombres diferentes.
Ahora que ha establecido que los espacios de nombres son realmente diferentes, echemos un vistazo a la ascendencia PID mencionada anteriormente. Puede hacerlo identificando el NSpid atributo de un PID dado en el /proc
directorio, como se ve a continuación:
sudo cat /proc/11655/status |grep NSpid
NSpid: 11655 6 1
Las columnas se leen de izquierda a derecha e indican el PID en sus respectivos espacios de nombres. El PID más a la izquierda es el espacio de nombres principal o raíz. En este caso tiene un PID de 11655 , un PID secundario de 6 y un PID terciario de 1 . Dado que los espacios de nombres poseen cada descendiente PID espacio de nombres, puede pensarlo así:
- En el host,
bash
proceso que ejecutasleep 8000
el comando tiene un PID de 11655 . - Dentro del primer "contenedor", el
bash
proceso que ejecutasleep 8000
el comando tiene un PID de 6 . - Dentro del segundo "contenedor" anidado, el PID es 1 . Este es el contenedor que realmente inició el proceso.
Cada uno de estos bash
commands se creó dentro de su propio espacio de nombres, pero es visible para el padre (en este caso, la raíz espacio de nombres).
/proc, PID y usuarios sin privilegios
El lector astuto se habrá dado cuenta de que, en los dos últimos artículos, un usuario normal podía crear tanto usuario y mnt espacios de nombres En este artículo, he estado usando sudo
dominio. Esto se debe a que no puede crear un PID espacio de nombres por sí solo con un usuario sin privilegios. La respuesta a esto es combinar varias creaciones de espacios de nombres en un solo evento. Hay algunas soluciones diferentes para montar /proc
como usuario sin privilegios.
Si simplemente intenta crear un nuevo usuario espacio de nombres, obtendrá un resultado extraño:
[ user@localhost ~] unshare -Urp
-bash: fork: Cannot allocate memory
-bash-5.1# ps -ef
-bash: fork: Cannot allocate memory
-bash-5.1# ls
-bash: fork: Cannot allocate memory
¿Que está sucediendo aquí? Recuerda cómo el primer proceso dentro de un nuevo PID el espacio de nombres se convierte en init ¿proceso? En este caso, el shell actual no puede mover espacios de nombres. Existe en la raíz espacio de nombres y cuando creaste un nuevo PID espacio de nombres, el sistema no sabía cómo manejarlo. La solución a esto es hacer que el proceso se bifurque. Esto permite que el shell actual se convierta en un proceso secundario de unshare
dominio. Usando el -f
flag da como resultado que se cree el espacio de nombres:
[ user@localhost ~] unshare -Urfp
[ root@localhost ~]
Sin embargo, todavía ve contaminación del /proc
punto de montaje. Hay dos soluciones para esto. Primero, podrías crear un nuevo mnt espacio de nombres y luego vuelva a montar /proc
usted mismo:
[ user@localhost ~]$ unshare -Urpmf
[ root@localhost ~]# mount -t proc proc /proc
[ root@localhost ~]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 09:31 pts/0 00:00:00 -bash
root 10 1 0 09:31 pts/0 00:00:00 ps -ef
De hecho, durante muchos años esta fue la única opción, pero una bandera --mount-proc
fue creado hace algún tiempo para hacer esto en un solo paso. La página del manual dice:
Justo antes de ejecutar el programa, monte el sistema de archivos proc en el punto de montaje (el valor predeterminado es /proc). Esto es útil al crear un nuevo espacio de nombres PID. También implica la creación de un nuevo espacio de nombres de montaje, ya que el montaje /proc de lo contrario estropearía los programas existentes en el sistema. El nuevo sistema de archivos proc se monta explícitamente como privado (con MS_PRIVATE|MS_REC).
Entonces, por lo tanto, puede ver referencias al siguiente comando:
unshare -Urpf --mount-proc
Esto crea un nuevo mnt espacio de nombres al montar /proc
para ti.
Ingresar un espacio de nombres
Para reducir la complejidad, he salido de los espacios de nombres creados anteriormente. He creado un nuevo espacio de nombres con el siguiente comando:
unshare -Urfp --mount-proc
También he creado un diferente sleep
proceso solo para ayudar a identificar el espacio de nombres. Como solo tengo un único espacio de nombres nuevo, puedo usar lsns
comando para determinar el PID correcto:
[ user@localhost ~]$ lsns |grep bash
4026532965 pid 2 13142 user -bash
Luego ejecute el nsenter
comando:
sudo nsenter -t 13142 -a
El -a
flag le dice al nsenter
comando para ingresar todos los espacios de nombres de ese PID. sudo
se requiere con -a
bandera, o de lo contrario no podrá cambiar a todos los espacios de nombres apropiados. Ahora debería poder listar todos los PIDS en este NS:
[ root@localhost ~]$ ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 09:54 pts/0 00:00:00 -bash
root 8 1 0 09:54 pts/0 00:00:00 sleep 99999
root 25 0 0 10:15 pts/1 00:00:00 -bash
root 31 25 0 10:15 pts/1 00:00:00 ps -ef
[ Aprenda los aspectos básicos del uso de Kubernetes en esta hoja de trucos gratuita. ]
Conclusión
El PID El espacio de nombres es importante cuando se trata de crear entornos aislados. Permite que los procesos tengan sus propios PID independientemente del sistema host. En un mundo donde varios hosts pueden estar involucrados en la orquestación de entornos aislados (contenedores), se vuelve crucial contar con una instalación que garantice PID únicos al congelar y migrar procesos. Además, por razones de seguridad, si está ejecutando espacios de nombres para el aislamiento de aplicaciones, el PID El espacio de nombres es vital para evitar fugas de información a través de los procesos que puede estar ejecutando un host.
Cuando se combina con el usuario y mnt espacios de nombres, el PID El espacio de nombres proporciona una gran protección sin necesidad de privilegios de root. Los navegadores modernos, como Firefox y Vivaldi, utilizan espacios de nombres para proporcionar espacio aislado del navegador. En el próximo artículo, demostraré la red espacio de nombres y vea cómo puede continuar construyendo su contenedor a mano agregando componentes de red discretos.