Linux Namespace是容器的基石,可以说没有Linux Namespace就不存在现在的容器技术。容器最大的功能就是对资源进行隔离,容器正是通过Linux Namespace技术实现了各种资源的隔离。
Linux Namespace总共有6种类别的Namespace,分别为
| Namespace | system call flag | kernal version |
|---|---|---|
| UTS Namespace | CLONE_NEWUTS | 2.6.19 |
| Mount Namespace | CLONE_NEWNS | 2.4.19 |
| IPC Namespace | CLONE_NEWIPC | 2.6.19 |
| PID Namespace | CLONE_NEWPID | 2.6.24 |
| Network Namespace | CLONE_NEWNET | 2.6.29 |
| User Namespace | CLONE_NEWUSER | 3.8 |
1.UTS Namespace
UTS是UNIX Time Sharing的缩写。主要用来隔离hostname,在每个UTS Namespace下,每个Namespace都可以拥有自己的Namespace。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28package main
// 2020-06-11
// UTS Namespace主要用来隔离hostname(主机名用于标识主机)和domainname两个系统标识(已淘汰)
// pstree 命令
// https://www.jianshu.com/p/049f13e55840
import (
"os/exec"
"syscall"
"os"
"log"
)
func main() {
//指定被fork出来的新进程内的初始命令
cmd := exec.Command("sh")
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWUTS,
}
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil{
log.Fatal(err)
}
}
执行这段代码会进入一个sh运行运行环境。echo $$是输出当前的PID,readlink查看对应的进程是否是在同一个Namespace。hostname -b bird修改hostname为bird,重新打开一个终端,输入hostname发现宿主机的hostname并没有被改变。

2.IPC Namespace
用于隔离System V IPC和POSIX message queues。
1 | func main() { |
左边为宿主机,右边为新建的sh环境。新建的message queue在右边的隔离Namespace并不能看到。1
2ipcs -q //查看ipc message queue
ipcmk -Q //新建一个message queue
3.PID Namespace
PID Namespace用于隔离进程ID1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37func main() {
cmd := exec.Command("sh")
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWIPC | syscall.CLONE_NEWPID,
}
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Fatal(err)
}
}
```
执行上述代码`sudo go /opt/go/bin/go run pidNamespace`。
`echo $$`发现当前的PID为1,而通过`pstree`命令发现运行执行上述代码的PID为58329,而隔离命名空间的PID却为1,说明这个58329在新的命令空间PID映射为1。

#### 4.Mount Namespace
`Mount Namespace`用于隔离各个进程看到的挂载点视图,是`Linux`实现的第一个`Namespace`类型,在不同的`Namespace`中看到的文件系统是不一样的。
```go
func main() {
cmd := exec.Command("sh")
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWIPC |syscall.CLONE_NEWPID | syscall.CLONE_NEWNS,
}
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run();err != nil{
log.Fatal(err)
}
}
执行上述代码,然后执行ls /proc发现/proc中的内容还是宿主机上的。
通过命令mount -t proc proc /proc将/proc mount到新建的命名空间,此时再执行ls /proc发现少了很多文件。
在当前Namespace中,sh进程是PID为1的进程。这就说明当前的Mount Namespace中的mount和外部空间是隔离的,mount操作并没有影响到外部。Docker volume正是利用了这个特性。

5.User Namespace
User Namespace主要是用于隔离用户的用户组ID。一个进程的User ID和Group ID在User Namespace内外是不同的。常用的场景是在宿主机以一个非root用户运行创建一个User Namespace`,然后在命名空间里面却映射成root用户。
1 | func main() { |
可以看到在宿主机和User Namespace中它们的UID是不同的。

6.Network Namespace
Network Namespace用于隔离网络设备,IP地址,端口,路由表,防火墙规则等网络栈的Namespace。每个容器独占一个Network Namespace,每个容器都能随意使用自己的端口而不会产生冲突。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18func main() {
cmd := exec.Command("sh")
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWIPC | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS |
syscall.CLONE_NEWNS | syscall.CLONE_NEWUSER |syscall.CLONE_NEWNET,
}
// 加上下面这行代码会报没有权限的错误
//cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(1000), Gid: uint32(1000)}
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Fatal(err)
}
os.Exit(-1)
}
分别在宿主机和新建sh环境上分别查看网络设备,发现网络设备是不一样的,说明网络已经隔离。

Network Namespace中的进程如何与宿主机进行通信
1 | ➜ ~ ip netns // 查看Network Namespace列表 |
查询名为netns1的网络命名空间下的网络设备,此时网卡状态是DOWN
进行netns1执行本志回环地址,发现网络不通,因为此时设备的状态是DOWN,通过命令ip netns exec netns1 ip link set dev lo lup启动设备后可以PING通。但此时只能PING通Network Namespace中的本地地址,还不能与宿主机进行通信。
我们可以新建一对虚拟的网卡veth pair与宿主机进行通信。veth pair总是成对出现且相互连接,报文从一端进去就会从另一端出来。
创建一对虚拟网卡,并查看网络设备;此时veth0和veth1都在宿主机的网络命名空间内。
将veth1加入到网络命名空间netns1中ip link set veth1 netns netns1,此时再查看网络设备。发现veth1已到了netns下。

设置网卡状态并绑定IP。
从宿主机PING netns1下的veth1.
从netns1下PING 宿主机中的veth0
netns1中的路由表与防火墙规则也是隔离的
Ref:
1.https://book.douban.com/subject/27082348/
2.https://book.douban.com/subject/34855927/