GNU/Linux >> Tutoriales Linux >  >> Linux

Construcción de contenedores a mano:el espacio de nombres PID

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 ejecuta sleep 8000 el comando tiene un PID de 11655 .
  • Dentro del primer "contenedor", el bash proceso que ejecuta sleep 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.


Linux
  1. Construyendo un contenedor a mano usando espacios de nombres:El espacio de nombres UTS

  2. Linux – ¿Encontrar el Pid del proceso usando un puerto específico?

  3. Creación de la nube fiscal

  4. ¿Cómo obtener el pid de un proceso e invocar kill -9 en el script de shell?

  5. Cómo encontrar el archivo .pid para un proceso dado

Construyendo un contenedor a mano usando espacios de nombres:El espacio de nombres de montaje

¿Qué proceso tiene Pid 0?

Cómo encontrar el PID y PPID de un proceso en Linux

¿Cómo obtener la identificación del proceso para eliminar un proceso nohup?

¿Se garantiza que un PID de proceso permanecerá igual siempre que el proceso no muera?

Si conozco el número PID de un proceso, ¿cómo puedo obtener su nombre?