理解 Linux 命名空间unshare

1. 什么是 unshare

unshare 是 Linux 中的一个命令,用于在新的命名空间中运行程序。命名空间是 Linux 内核提供的一种隔离机制,允许进程组拥有独立的系统资源视图,如进程 ID、网络、挂载点等。unshare 常用于容器技术的底层实现中,帮助创建隔离的环境。


2. 常见的命名空间类型

Linux 支持多种命名空间,每种命名空间隔离不同的资源:

  • PID 命名空间:隔离进程 ID。
  • Mount 命名空间:隔离文件系统挂载点。
  • UTS 命名空间:隔离主机名和域名。
  • Network 命名空间:隔离网络接口、IP 地址、路由表等。
  • User 命名空间:隔离用户和组 ID。
  • IPC 命名空间:隔离进程间通信资源。
  • Cgroup 命名空间:隔离控制组(cgroup)视图。

示例 1:创建新的 PID 命名空间

步骤 1:创建新的 PID 命名空间

root@compute01:~# unshare --pid --fork bash

步骤 2:查看进程列表

root@compute01:~# ps -aux | head -n10
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.0 167080 12288 ?        Ss    2024   0:40 /lib/systemd/systemd --system --deserialize 23
root           2  0.0  0.0      0     0 ?        S     2024   0:01 [kthreadd]
root           3  0.0  0.0      0     0 ?        I<    2024   0:00 [rcu_gp]
root           4  0.0  0.0      0     0 ?        I<    2024   0:00 [rcu_par_gp]
root           5  0.0  0.0      0     0 ?        I<    2024   0:00 [slub_flushwq]
root           6  0.0  0.0      0     0 ?        I<    2024   0:00 [netns]
root           8  0.0  0.0      0     0 ?        I<    2024   0:00 [kworker/0:0H-kblockd]
root          11  0.0  0.0      0     0 ?        I<    2024   0:00 [mm_percpu_wq]
root          12  0.0  0.0      0     0 ?        S     2024   0:00 [rcu_tasks_rude_]
  • 问题ps -aux 仍然显示主机上的所有进程,因为 /proc 文件系统未隔离。

步骤 3:重新挂载 /proc 文件系统

root@compute01:~# mount -t proc proc /proc

步骤 4:再次查看进程列表

root@compute01:~# ps -aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.0   8160  4308 pts/2    S    14:10   0:00 bash
root          11  0.0  0.0  10732  3664 pts/2    R+   14:10   0:00 ps -aux
  • 结果:只显示当前命名空间中的进程。

示例 2:创建新的 Mount 命名空间

步骤 1:创建新的 Mount 命名空间

root@compute01:~# unshare --mount --fork bash

步骤 2:查看当前挂载点

root@compute01:~# df -Th
Filesystem            Type   Size  Used Avail Use% Mounted on
/dev/mapper/vg0-lv--0 xfs    1.8T  1.3T  516G  72% /
tmpfs                 tmpfs 1008G  892K 1008G   1% /dev/shm
tmpfs                 tmpfs  202G  4.3M  202G   1% /run
tmpfs                 tmpfs  5.0M     0  5.0M   0% /run/lock
tmpfs                 tmpfs  202G  8.0K  202G   1% /run/user/1001
tmpfs                 tmpfs  202G  8.0K  202G   1% /run/user/0
/dev/sda1             vfat   1.1G  6.1M  1.1G   1% /boot/efi

步骤 3:创建并挂载临时文件系统

root@compute01:~# mkdir /tmp/mnt
root@compute01:~# mount -t tmpfs tmpfs /tmp/mnt

步骤 4:再次查看挂载点

root@compute01:~# df -Th
Filesystem            Type   Size  Used Avail Use% Mounted on
/dev/mapper/vg0-lv--0 xfs    1.8T  1.3T  516G  72% /
tmpfs                 tmpfs 1008G  892K 1008G   1% /dev/shm
tmpfs                 tmpfs  202G  4.3M  202G   1% /run
tmpfs                 tmpfs  5.0M     0  5.0M   0% /run/lock
tmpfs                 tmpfs  202G  8.0K  202G   1% /run/user/1001
tmpfs                 tmpfs  202G  8.0K  202G   1% /run/user/0
/dev/sda1             vfat   1.1G  6.1M  1.1G   1% /boot/efi
tmpfs                 tmpfs 1008G     0 1008G   0% /tmp/mnt
  • 结果/tmp/mnt 挂载点只在当前命名空间中可见。

步骤 5:退出命名空间并验证

root@compute01:~# exit
root@compute01:~# df -Th
Filesystem            Type   Size  Used Avail Use% Mounted on
/dev/mapper/vg0-lv--0 xfs    1.8T  1.3T  516G  72% /
tmpfs                 tmpfs 1008G  892K 1008G   1% /dev/shm
tmpfs                 tmpfs  202G  4.3M  202G   1% /run
tmpfs                 tmpfs  5.0M     0  5.0M   0% /run/lock
/dev/sda1             vfat   1.1G  6.1M  1.1G   1% /boot/efi
tmpfs                 tmpfs  202G  8.0K  202G   1% /run/user/1001
tmpfs                 tmpfs  202G  8.0K  202G   1% /run/user/0
  • 结果:退出命名空间后,/tmp/mnt 挂载点不再可见。

示例 3:创建新的 UTS 命名空间

步骤 1:创建新的 UTS 命名空间

root@compute01:~# unshare --uts --fork bash

步骤 2:查看当前主机名

root@compute01:~# hostname
compute01

步骤 3:修改主机名

root@compute01:~# hostname newhostname
root@compute01:~# hostname
newhostname
  • 结果:主机名已修改为 newhostname,且只影响当前命名空间。

步骤 4:退出命名空间并验证

root@compute01:~# exit
root@compute01:~# hostname
compute01
  • 结果:退出命名空间后,主机名恢复为 compute01

示例 4:创建新的 Network 命名空间

步骤 1:创建新的 Network 命名空间

root@compute01:~# unshare --net --fork bash

步骤 2:查看网络接口

root@compute01:~# ip link show
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  • 结果:只显示 lo 回环接口,其他网络接口被隔离。

步骤 3:退出命名空间并验证

root@compute01:~# exit
root@compute01:~# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 00:11:22:33:44:55 brd ff:ff:ff:ff:ff:ff
  • 结果:退出命名空间后,恢复显示所有网络接口。

示例 5:创建新的 User 命名空间

步骤 1:创建新的 User 命名空间

root@compute01:~# unshare --user --map-root-user --fork bash

步骤 2:查看当前用户

root@compute01:~# id
uid=0(root) gid=0(root) groups=0(root)
  • 结果:当前用户在命名空间中拥有 root 权限。

步骤 3:退出命名空间并验证

root@compute01:~# exit
root@compute01:~# id
uid=1000(user) gid=1000(user) groups=1000(user)
  • 结果:退出命名空间后,恢复为普通用户权限。

总结

通过以上测试示例,你可以清晰地看到 unshare 命令如何创建和隔离不同的命名空间:

  1. PID 命名空间:隔离进程视图,需要重新挂载 /proc 文件系统。
  2. Mount 命名空间:隔离文件系统挂载点,挂载操作只影响当前命名空间。
  3. UTS 命名空间:隔离主机名和域名。
  4. Network 命名空间:隔离网络接口、IP 地址和路由表。
  5. User 命名空间:隔离用户和组 ID。
posted @ 2025-01-06 14:43  MKY-门可意  阅读(927)  评论(0)    收藏  举报