Explicación detallada del comando unshare
1. Nombre
unshare - run program with some namespaces unshared from parent(使用与父程序不共享的名称空间运行程序)
2. Resumen
unshare [options] program [arguments]
3. Descripción
Deja de compartir los espacios de nombres indicados del proceso principal y luego ejecuta el programa especificado. Los espacios de nombres que no se compartirán se indican mediante opciones. Los espacios de nombres que no se pueden compartir son (deja de compartir los espacios de nombres indicados del proceso principal y luego ejecuta el programa especificado. El espacio se indica mediante opciones. Los espacios de nombres que no se pueden compartir incluyen)
Se puede establecer un total de 6 espacios de nombres no compartidos para dejar de compartir, que son:
mount namespace
UTS namespace
IPC namespace
network namespace
pid namespace
user namespace
4. Opciones
Hay un total de las siguientes opciones:
(1)-i, --ipc
unshare the IPC namespace.
(2)-m, --mount
Unshare the mount namespace.
(3)-n, --net
Unshare the network namespace.
(4) -p, --pid
Unshare the pid namespace. See also the --fork and --mount-proc options.
(5)-u, --uts
Unshare the UTS namespace.
(6) -U, --user
Unshare the user namespace.
(7)-f, --fork
Fork the specified program as a child process of unshare rather than running it directly. This is useful when creating a new pid namespace.
(8)--mount-proc[=mountpoint]
Just before running the program, mount the proc filesystem at mountpoint (default is /proc). This is useful when creating a new pid namespace. It also implies creating a new mount names‐pace since the /proc mount would otherwise mess up existing programs on the system. The new proc filesystem is explicitly mounted as private (by MS_PRIVATE|MS_REC).
(9)-r, --map-root-user
Run the program only after the current effective user and group IDs have been mapped to the superuser UID and GID in the newly created user namespace. This makes it possible to conve‐niently gain capabilities needed to manage various aspects of the newly created namespaces (such as configuring interfaces in the network namespace or mounting filesystems in the mount namespace) even when run unprivileged. As a mere convenience feature, it does not support more sophisticated use cases, such as mapping multiple ranges of UIDs and GIDs. This option implies --setgroups=deny.
(10) --propagation private|shared|slave|unchanged
Recursively sets mount propagation flag in the new mount namespace. The default is to set the propagation to private, this feature is possible to disable by unchanged argument. The options is silently ignored when mount namespace (--mount) is not requested.
(11)--setgroups allow|deny
Allow or deny setgroups(2) syscall in user namespaces.
setgroups(2) is only callable with CAP_SETGID and CAP_SETGID in a user namespace (since Linux 3.19) does not give you permission to call setgroups(2) until after GID map has been set. The GID map is writable by root when setgroups(2) is enabled and GID map becomes writable by unprivileged processes when setgroups(2) is permanently disabled.
(12) -V, --version
Display version information and exit.
(13)-h, --help
Display help text and exit.
5. Ejemplos
# unshare --fork --pid --mount-proc readlink /proc/self
1
Establish a PID namespace, ensure we're PID 1 in it against newly mounted procfs instance.
(建立一个PID命名空间,确保我们在新安装的procfs实例中是PID 1。)
$ unshare --map-root-user --user sh -c whoami
root
Establish a user namespace as an unprivileged user with a root user within it.
(将用户命名空间建立为非特权用户,其中包含根用户。)
6. ¿Cuáles son las funciones de varios espacios de nombres?
(1) Espacio de nombres de montaje
Mount Namespace es el primer espacio de nombres implementado por el kernel de Linux, que se ha agregado desde la versión 2.4.19 del kernel. Se puede utilizar para aislar puntos de montaje vistos por diferentes procesos o grupos de procesos. En términos sencillos, es posible ver diferentes directorios de montaje en diferentes procesos. El uso de Mount Namespace puede darse cuenta de que solo se puede ver su propia información de montaje en el contenedor, y la operación de montaje en el contenedor no afectará el directorio de montaje del host.
Usemos un ejemplo para demostrar Mount Namespace. Usamos una herramienta de línea de comando unshare. unshare es una herramienta en el kit de herramientas util-linux. CentOS 7 ha integrado esta herramienta de forma predeterminada. Puede usar el comando unshare para crear y acceder a diferentes tipos de espacios de nombres.
Primero, usamos los siguientes comandos para crear un proceso bash y crear un nuevo espacio de nombres de montaje:
unshare --mount --fork /bin/bash
Después de ejecutar el comando anterior, hemos creado un nuevo espacio de nombres de montaje en el host, y el espacio de nombres de montaje recién creado se ha agregado a la ventana de línea de comandos actual. Permítanme usar un ejemplo para verificar que la creación de un directorio de montaje en un espacio de nombres de montaje independiente no afecta el directorio de montaje del host.
Después de ejecutar el comando anterior, hemos creado un nuevo espacio de nombres de montaje en el host, y el espacio de nombres de montaje recién creado se ha agregado a la ventana de línea de comandos actual. Permítanme usar un ejemplo para verificar que la creación de un directorio de montaje en un espacio de nombres de montaje independiente no afecta el directorio de montaje del host.
Primero cree un directorio en el directorio / tmp.
[root@centos7 centos]# mkdir /tmp/tmpfs
Después de crear el directorio, use el comando mount para montar un directorio de tipo tmpfs. El comando es el siguiente:
[root@centos7 centos]# mount -t tmpfs -o size=20m tmpfs /tmp/tmpfs
Luego use el comando df para ver la información del directorio montado:
[root@centos7 centos]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 500G 1.4G 499G 1% /
devtmpfs 16G 0 16G 0% /dev
tmpfs 16G 0 16G 0% /dev/shm
tmpfs 16G 0 16G 0% /sys/fs/cgroup
tmpfs 16G 57M 16G 1% /run
tmpfs 3.2G 0 3.2G 0% /run/user/1000
tmpfs 20M 0 20M 0% /tmp/tmpfs
Puede ver que el directorio / tmp / tmpfs se ha montado correctamente. Para verificar que este directorio no está montado en el host, abrimos una nueva ventana de línea de comando y ejecutamos el comando df para ver la información de montaje del host:
[centos@centos7 ~]$ df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 16G 0 16G 0% /dev
tmpfs 16G 0 16G 0% /dev/shm
tmpfs 16G 57M 16G 1% /run
tmpfs 16G 0 16G 0% /sys/fs/cgroup
/dev/vda1 500G 1.4G 499G 1% /
tmpfs 3.2G 0 3.2G 0% /run/user/1000
De la salida anterior, podemos ver que / tmp / tmpfs no está montado en el host. Se puede ver que la operación de montaje en nuestro Mount Namespace independiente no afectará al host.
Para verificar aún más nuestras ideas, continuamos verificando la información del espacio de nombres del proceso actual en la ventana de la línea de comandos actual, el comando es el siguiente:
[root@centos7 centos]# ls -l /proc/self/ns/
total 0
lrwxrwxrwx. 1 root root 0 Sep 4 08:20 ipc -> ipc:[4026531839]
lrwxrwxrwx. 1 root root 0 Sep 4 08:20 mnt -> mnt:[4026532239]
lrwxrwxrwx. 1 root root 0 Sep 4 08:20 net -> net:[4026531956]
lrwxrwxrwx. 1 root root 0 Sep 4 08:20 pid -> pid:[4026531836]
lrwxrwxrwx. 1 root root 0 Sep 4 08:20 user -> user:[4026531837]
lrwxrwxrwx. 1 root root 0 Sep 4 08:20 uts -> uts:[4026531838]
Luego abra una nueva ventana de línea de comando y use el mismo comando para verificar la información del espacio de nombres en el host:
[centos@centos7 ~]$ ls -l /proc/self/ns/
total 0
lrwxrwxrwx. 1 centos centos 0 Sep 4 08:20 ipc -> ipc:[4026531839]
lrwxrwxrwx. 1 centos centos 0 Sep 4 08:20 mnt -> mnt:[4026531840]
lrwxrwxrwx. 1 centos centos 0 Sep 4 08:20 net -> net:[4026531956]
lrwxrwxrwx. 1 centos centos 0 Sep 4 08:20 pid -> pid:[4026531836]
lrwxrwxrwx. 1 centos centos 0 Sep 4 08:20 user -> user:[4026531837]
lrwxrwxrwx. 1 centos centos 0 Sep 4 08:20 uts -> uts:[4026531838]
Al comparar los resultados de salida de los dos comandos, podemos ver que, a excepción de los valores de ID de Mount Namespace, los valores de ID de otros espacios de nombres son los mismos.
A partir de los resultados anteriores, podemos concluir que el uso del comando unshare puede crear un nuevo espacio de nombres de montaje, y el montaje en el espacio de nombres de montaje recién creado está completamente aislado del exterior.
(2) Espacio de nombres PID
La función del espacio de nombres PID es aislar el proceso. En diferentes espacios de nombres PID, los procesos pueden tener el mismo número PID. El uso del espacio de nombres PID puede darse cuenta de que el proceso principal de cada contenedor es el proceso n. ° 1, mientras que los procesos en el contenedor tienen diferentes PID en el host. Por ejemplo, el PID de un proceso en el host es 122 y el espacio de nombres PID se puede utilizar para darse cuenta de que el proceso ve el PID de 1 en el contenedor.
A continuación, usamos un ejemplo para demostrar la función del espacio de nombres PID. Primero, usamos el siguiente comando para crear un proceso bash y crear un nuevo espacio de nombres PID:
unshare --fork --pid --mount-proc /bin/bash
Después de ejecutar el comando anterior, creamos un nuevo espacio de nombres PID en el host y agregamos el espacio de nombres PID recién creado a la ventana de la línea de comandos actual. Utilice el comando ps aux en la ventana de la línea de comandos actual para ver la información del proceso:
[root@centos7 centos]# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 115544 2004 pts/0 S 10:57 0:00 bash
root 10 0.0 0.0 155444 1764 pts/0 R+ 10:59 0:00 ps aux
A través de la salida del comando anterior, puede ver que bash es el proceso número uno en el espacio de nombres actual, y no podemos ver otra información de proceso en el host.
(3) Espacio de nombres UTS
El espacio de nombres UTS se utiliza principalmente para aislar nombres de host y permite que cada espacio de nombres UTS tenga un nombre de host independiente. Por ejemplo, nuestro nombre de host es Docker, el uso de UTS Namespace puede realizar el nombre de host en el contenedor como ladoudocker o cualquier otro nombre de host personalizado.
De manera similar, usamos un ejemplo para verificar la función del espacio de nombres UTS. Primero, usamos el comando unshare para crear un espacio de nombres UTS:
unshare --fork --uts /bin/bash
Después de que se crea el espacio de nombres UTS, la ventana de la línea de comandos actual ya está en un espacio de nombres UTS independiente. A continuación, usamos el comando hostname (el nombre de host se puede usar para ver el nombre de host) para establecer el nombre de host:
hostname -b lagoudocker
Luego verifique el nombre de host nuevamente:
[root@centos7 centos]# hostname
lagoudocker
A través de la salida del comando anterior, podemos ver que el nombre de host en el espacio de nombres UTS actual se ha modificado a lagudocker. Luego abrimos una nueva ventana de línea de comando y usamos el mismo comando para verificar el nombre de host del host:
[centos@centos7 ~]$ hostname
centos7
Puede ver que el nombre del host sigue siendo centos7 y no se ha modificado. A partir de esto, se puede verificar que el espacio de nombres UTS se puede usar para aislar nombres de host.
(4) Espacio de nombres de IPC
El espacio de nombres de IPC se utiliza principalmente para aislar la comunicación entre procesos. Por ejemplo, el espacio de nombres PID y el espacio de nombres IPC se pueden usar juntos para darse cuenta de que los procesos dentro del mismo espacio de nombres IPC pueden comunicarse entre sí, pero los procesos con diferentes espacios de nombres IPC no pueden comunicarse.
De manera similar, usamos un ejemplo para verificar la función del espacio de nombres de IPC. Primero, usamos el comando unshare para crear un espacio de nombres de IPC:
unshare --fork --ipc /bin/bash
A continuación, necesitamos usar dos comandos para verificar el espacio de nombres de IPC.
Comando ipcs -q: se utiliza para ver la lista de colas de comunicación entre sistemas.
Comando ipcmk -Q: se utiliza para crear una cola de comunicación entre sistemas.
Primero usamos el comando ipcs -q para ver la lista de colas de comunicación del sistema bajo el espacio de nombres IPC actual:
[centos@centos7 ~]$ ipcs -q
------ Message Queues --------
key msqid owner perms used-bytes messages
De lo anterior, podemos ver que actualmente no hay una cola de comunicación del sistema, y luego usamos el comando ipcmk -Q para crear una cola de comunicación del sistema:
[root@centos7 centos]# ipcmk -Q
Message queue id: 0
Use el comando ipcs -q nuevamente para ver la lista de colas de comunicación del sistema en el espacio de nombres IPC actual
[root@centos7 centos]# ipcs -q
------ Message Queues --------
key msqid owner perms used-bytes messages
0x73682a32 0 root 644 0 0
Puede ver que hemos creado con éxito una cola de comunicación del sistema. Luego abrimos una nueva ventana de línea de comando y usamos el comando ipcs -q para verificar la cola de comunicación del sistema del host:
[centos@centos7 ~]$ ipcs -q
------ Message Queues --------
key msqid owner perms used-bytes messages
A través del experimento anterior, se puede encontrar que la cola de comunicación del sistema creada en un espacio de nombres IPC separado no se puede ver en el host. Es decir, IPC Namespace se da cuenta del aislamiento de las colas de comunicación del sistema.
(5) Espacio de nombre de usuario
El espacio de nombres de usuario se utiliza principalmente para aislar usuarios y grupos de usuarios. Un escenario de aplicación típico es que un proceso que se ejecuta como un usuario no root en el host se puede asignar a un usuario root en un espacio de nombres de usuario separado. El uso del espacio de nombres de usuario puede darse cuenta de que el proceso tiene privilegios de root en el contenedor, pero es solo un usuario normal en el host.
User Namesapce se puede crear sin autorización de root. A continuación, creamos un espacio de nombres de usuario como un usuario normal, el comando es el siguiente:
[centos@centos7 ~]$ unshare --user -r /bin/bash
[root@centos7 ~]#
CentOS7 está predeterminado para permitir la creación del espacio de nombres de usuario en 0. Si la ejecución del comando anterior falla (el error devuelto por el comando unshare es unshare: unshare fallido: argumento no válido), debe utilizar el siguiente comando para modificar el número de El sistema permite crear espacios de nombres de usuario El comando es: echo 65535> / proc / sys / user / max_user_namespaces, y luego intente crear nuevamente el espacio de nombres de usuario.
Luego ejecute el comando id para verificar la información del usuario actual:
[root@centos7 ~]# id
uid=0(root) gid=0(root) groups=0(root),65534(nfsnobody) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
De la salida anterior, podemos ver que ya somos el usuario root en el nuevo espacio de nombres de usuario. A continuación, usamos el comando de reinicio que solo puede ejecutar el usuario root del host para verificarlo, y ejecutamos el comando de reinicio en la ventana de línea de comandos actual:
[root@centos7 ~]# reboot
Failed to open /dev/initctl: Permission denied
Failed to talk to init daemon.
Como puede ver, aunque somos el usuario root en el espacio de nombres de usuario recién creado, no tenemos la autoridad para ejecutar el comando de reinicio. Esto muestra que en el espacio de nombre de usuario aislado, no se puede obtener la autoridad raíz del host, lo que significa que el espacio de nombre de usuario se da cuenta del aislamiento de usuarios y grupos de usuarios.
(6) Espacio de nombres de red
El espacio de nombres de red se utiliza para aislar información como dispositivos de red, direcciones IP y puertos. Net Namespace permite que cada proceso tenga su propia dirección IP, puerto e información de tarjeta de red independientes. Por ejemplo, la dirección IP del host es 172.16.4.1 y se puede establecer una dirección IP independiente en 192.168.1.1 en el contenedor.
También use la verificación de ejemplo, primero usamos el comando ip a para verificar la información de red en el host:
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 02:11:b0:14:01:0c brd ff:ff:ff:ff:ff:ff
inet 172.20.1.11/24 brd 172.20.1.255 scope global dynamic eth0
valid_lft 86063337sec preferred_lft 86063337sec
inet6 fe80::11:b0ff:fe14:10c/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:82:8d:a0:df brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:82ff:fe8d:a0df/64 scope link
valid_lft forever preferred_lft forever
Luego usamos el siguiente comando para crear un espacio de nombres de red:
unshare --net --fork /bin/bash
De manera similar, usamos el comando ip a para verificar la información de la red:
[root@centos7 centos]# ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
Como puede ver, hay dispositivos de red como lo, eth0 y docker0 en el host, y los dispositivos de red en nuestro espacio de nombres de red recién creado son diferentes de los del host.