1、定义

百度百科定义:“namespace即“命名空间”,也称“名称空间” 。是许多编程语言使用的一种代码组织的形式,通过命名空间来分类,区别不同的代码功能,避免不同的代码片段(通常由不同的人协同工作或调用已有的代码片段)同时使用时由于不同代码间变量名相同而造成冲突。”
换句话说,namespace 的关键特性是进程隔离。在运行许多不同服务的服务器上,将各个服务及其相关进程相互隔离能够减少变更带来的影响以及安全性方面的问题。

2、类型(6种)

Linux 内核包含了不同类型的 namespace。每个 namespace 都有自己的独特属性。

  • 用户命名空间(user namespace):

    拥有自己的一组用户 ID 和组 ID,用于分配给进程。这意味着进程可以在其 user namespace 中拥有 root 权限,而不需要在其他 user namespace 中获得。

  • 进程命名空间(process ID (PID) namespace):

    将一组 PID 分配给独立于其他 namespace 中的一组 PID 的进程。在新的 namespace 中创建的第一个进程分得 PID 1,子进程被分配给后续的 PID。如果子进程使用自己的 PID namespace 创建,则它在该 namespace 中使用 PID 1,在父进程的 namespace 中使用自己的 PID。

  • 网络命名空间(network namespace):

    拥有独立的网络栈:自己的专用路由表、IP 地址集、套接字列表、连接跟踪表、防火墙及其他网络相关资源。

  • 挂载点命名空间(mount namespace):

    拥有一个独立的挂载点列表,并对该 namespace 中的进程可见。这意味着您可以在 mount namespace 中挂载和卸载文件系统,而不会影响主机文件系统。

  • (interprocess communication (IPC) namespace):

    拥有自己的 IPC 资源,例如 POSIX 消息队列。

  • UNIX Time‑Sharing (UTS) namespace:

    允许单个系统对不同的进程显示不同的主机名和域名。

3、创建一个Namespace

使用unshare命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@172-18-1-36 ~]# unshare -h

用法:
unshare [options] <program> [<argument>...]

Run a program with some namespaces unshared from the parent.

选项:
-m, --mount unshare mounts namespace
-u, --uts unshare UTS namespace (hostname etc)
-i, --ipc unshare System V IPC namespace
-n, --net unshare network namespace
-p, --pid unshare pid namespace
-U, --user unshare user namespace
-f, --fork fork before launching <program>
--mount-proc[=<dir>] mount proc filesystem first (implies --mount)
-r, --map-root-user map current user to root (implies --user)
--propagation <slave|shared|private|unchanged>
modify mount propagation in mount namespace
-s, --setgroups allow|deny control the setgroups syscall in user namespaces

-h, --help 显示此帮助并退出
-V, --version 输出版本信息并退出

运行以下 unshare 命令,使用自己的 user 和 PID namespace 创建一个新的 namespace。我将 root 用户映射到新的 namespace(换句话说,我在新的 namespace 中拥有 root 权限),挂载一个新的 proc 文件系统,并在新创建的 namespace 中进行进程(本例中为 bash)分支。

1
2
# 相当于在运行的容器中执行 <runtime> exec -it <image> /bin/bash 命令。
[sonar@172-18-1-36 root]$ unshare --user --pid --map-root-user --mount-proc --fork bash

ps -ef 命令显示有两个进程正在运行(bashps 命令本身),并且 id 命令确认我在新的 namespace 中是root 用户(这一点也可以从更改的命令提示符看出):
只能看到我的 namespace 中的两个进程,而看不到系统上运行的任何其他进程。我完全隔离在自己的 namespace 中。

1
2
3
4
5
6
[root@172-18-1-36 root]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 17:29 pts/0 00:00:00 bash
root 34 1 0 17:42 pts/0 00:00:00 ps -ef
[root@172-18-1-36 root]# id
uid=0(root) gid=0(root) 组=0(root)

可以使用 lsns (list namespace) 命令,从父 namespace(在新的 namespace 之外)的角度列出所有可用的 namespace 并显示其相关信息。

1
2
3
4
5
6
7
8
[root@172-18-1-36 root]# lsns
NS TYPE NPROCS PID USER COMMAND
4026531838 uts 2 1 root bash
4026531839 ipc 2 1 root bash
4026531956 net 2 1 root bash
4026533429 user 2 1 root bash
4026533430 mnt 2 1 root bash
4026533431 pid 2 1 root bash