Network Namespace

Namespace的作用

隔离内核资源,分割全局系统资源,并装到抽象的独立空间里。Namespace包括:

文件系统挂载点 (Mount)

主机名 (UTS)

POSIX进程间通信消息队列 (IPC)

进程PID数字空间 (PID)

IP地址 (network)

userID数字空间 (user)

Linux的namespace给里面的进程造成两个错觉:

  1. 它是系统里唯一的进程
  2. 它独享系统的所有资源

Network namespace使得每个容器都有自己的虚拟网络设备(IP地址、路由表、端口范围、/proc/net目录等),并且容器里的进程可以放心地绑定在端口上而不必担心冲突,这就使得在一个主机上同时运行多个监听80端口的Web服务器变为可能。

Network namespace管理命令

1
2
3
4
5
6
7
8
9
10
11
# 创建新的netns
ip netns add netns1

# 进入netns1,并查询其网络配置
ip netns exec netns1 ip link list

# 查看系统中的netns
ip netns list

# 删除netns
ip netns delete netns1

注:删除操作并没有删除netns1,只是移除了netns1对应的挂载点。只要里面还有进程运行着,该network namespace便会一直存在。

Network namespace配置命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 进入netns1,并把设备状态设置成UP
ip netns exec netns1 ip link set dev lo up

# 进入netns1,并ping本地网卡
ip netns exec netns1 ping 127.0.0.1

# 创建一对虚拟以太网卡
ip link add veth0 type veth peer name veth1

# 将veth pair的一端放到netns1
ip link set veth1 netns netns1

# 为veth pair绑定ip,并设置成UP状态
ip netns exec netns1 ifconfig veth1 10.1.1.1/24 up
ifconfig veth0 10.1.1.2/24 up

不同network namespace之间的路由表和防火墙规则等也是隔离的。

1
2
3
4
5
# 进入netns1,并查询其路由表
ip netns exec netns1 route

# 进入netns1,并iptables规则
ip netns exec netns1 iptables -L

用户可以随意将虚拟网络设备分配到自定义的network namespace里,而连接真实硬件的物理设备则只能放在系统的根network namespace。

Network namespace里的root进程能够本network namespace的虚拟网络设备分配到其他network namespace。但通常为了保证安全性,需要结合PID namespace和Mount namespace的隔离特征做到network namespace之间的完全不可达。

Network namespace API的使用

1
2
3
4
5
6
7
8
9
# 只要在clone()设置标志位CLONE_NEW,系统就会创建一个新的对应类型的namespace及一个新的进程,并将这个进程放入到这个新创建的namespace
int clone(int (*child_func)(void *), void *child_stack, int flags, void *arg);

# 往namespace添加进程,通常与execve()结合
# nstype: 让调用者检查第一个参数fd指向的namespace是否符合要求,0表示不检查
int setns(int fd, int nstype);

# 先通过指定的flags创建相应的namespace,再把这个进程挪到新创建的namespace
int unshare(int flags);

每个Linux进程都拥有一个属于自己的/proc/PID/ns,这个目录下的每个文件都代表一个类型的namespace。

如图所示,该目录下每一个文件都是一个特殊的符号链接文件。其主要用途有两点:

  1. 确定某两个进程是否属于同一个namespace。
  2. 当打开这些文件时,只要文件描述符保持open状态,对应的namespace就会一直存在,哪怕这个namespace里的所有进程都终止运行了。

注:一旦系统管理员禁用namespace中的网络设备,即使里面的进程拿到了一些特权,也无法与外界通信。

参考

《Kubernetes网络权威指南》