┌──[root@liruilongs.github.io]-[~] └─$ip netns exec net1 ip link 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 2: veth1@if2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether b2:ae:39:9e:50:4b brd ff:ff:ff:ff:ff:ff link-netns net2
net1 命名空间虚拟网卡 veth1 ,与名称为 net2 的命名空间相关联
1 2 3 4 5 6
┌──[root@liruilongs.github.io]-[~] └─$ip netns exec net2 ip link 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 2: veth2@if2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 7a:1b:8e:91:41:79 brd ff:ff:ff:ff:ff:ff link-netns net1
┌──[root@liruilongs.github.io]-[~] └─$ ip netns exec net2 bash ┌──[root@liruilongs.github.io]-[~] └─$ip address add 192.168.20.2/24 dev veth2 ┌──[root@liruilongs.github.io]-[~] └─$ip link set dev veth2 up ┌──[root@liruilongs.github.io]-[~] └─$ip link set dev lo up
这个时候,我们在看链接,状态,会发现,veth2 虚拟网卡状态为 UP 状态 state UP
1 2 3 4 5 6
┌──[root@liruilongs.github.io]-[~] └─$ ip link 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: veth2@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether 7a:1b:8e:91:41:79 brd ff:ff:ff:ff:ff:ff link-netns net1
查看分配IP的虚拟网卡也为 UP 状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14
┌──[root@liruilongs.github.io]-[~] └─$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: veth2@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 7a:1b:8e:91:41:79 brd ff:ff:ff:ff:ff:ff link-netns net1 inet 192.168.20.2/24 scope global veth2 valid_lft forever preferred_lft forever inet6 fe80::781b:8eff:fe91:4179/64 scope link valid_lft forever preferred_lft forever
独立的路由信息
1 2 3
┌──[root@liruilongs.github.io]-[~] └─$ip route 192.168.20.0/24 dev veth2 proto kernel scope link src 192.168.20.2
回到 net1,net1名称空间中veth1的链接状态也显示UP (state UP)
1 2 3 4 5 6 7 8 9
┌──[root@liruilongs.github.io]-[~] └─$ip netns exec net1 ip link 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: veth1@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether b2:ae:39:9e:50:4b brd ff:ff:ff:ff:ff:ff link-netns net2 ┌──[root@liruilongs.github.io]-[~] └─$exit exit
根命名空间不知道net1和net2命名空间的IP配置,三者彼此隔离。
1 2 3 4 5 6 7
┌──[root@liruilongs.github.io]-[~] └─$ip link 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: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000 link/ether 00:0c:29:93:51:67 brd ff:ff:ff:ff:ff:ff altname enp3s0
路由信息也为独立的路由信息
1 2 3 4
┌──[root@liruilongs.github.io]-[~] └─$ip route default via 192.168.26.2 dev ens160 proto dhcp src 192.168.26.149 metric 100 192.168.26.0/24 dev ens160 proto kernel scope link src 192.168.26.149 metric 100
┌──[root@liruilongs.github.io]-[/] └─$ docker exec -it 6471704fd03a sh / # ip link show eth0 94: eth0@if95: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff / # exit
通过 95 index 来定位主机上对应的虚拟网卡
1 2 3 4 5
┌──[root@liruilongs.github.io]-[/] └─$ ip link show | grep 95 95: veth2e08884@if94: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT ┌──[root@liruilongs.github.io]-[/] └─$
network namespace API 的使用
创建 namespace 的黑科技:clone 系统调用
用户可以使用 clone()系统调用创建一个 namespace。
维持 namespace 存在:/proc/PID/ns 目录的奥秘
每个 Linux 进程都拥有一个属于自己的/proc/PID/ns,这个目录下的每个文件都代表一个类型的 namespace。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
┌──[root@liruilongs.github.io]-[~] └─$ls -l /proc/$$/ns total 0 lrwxrwxrwx. 1 root root 0 Feb 11 02:27 cgroup -> 'cgroup:[4026531835]' lrwxrwxrwx. 1 root root 0 Feb 11 02:27 ipc -> 'ipc:[4026531839]' lrwxrwxrwx. 1 root root 0 Feb 11 02:27 mnt -> 'mnt:[4026531841]' lrwxrwxrwx. 1 root root 0 Feb 11 02:27 net -> 'net:[4026531840]' lrwxrwxrwx. 1 root root 0 Feb 11 02:27 pid -> 'pid:[4026531836]' lrwxrwxrwx. 1 root root 0 Feb 11 02:27 pid_for_children -> 'pid:[4026531836]' lrwxrwxrwx. 1 root root 0 Feb 11 02:27 time -> 'time:[4026531834]' lrwxrwxrwx. 1 root root 0 Feb 11 02:27 time_for_children -> 'time:[4026531834]' lrwxrwxrwx. 1 root root 0 Feb 11 02:27 user -> 'user:[4026531837]' lrwxrwxrwx. 1 root root 0 Feb 11 02:27 uts -> 'uts:[4026531838]' ┌──[root@liruilongs.github.io]-[~] └─$
在 Linux 内核 3.8 版本以前,/proc/PID/ns 目录下的文件都是硬链接(hard link),而且只有 ipc、net 和 uts 这三个文件,从 Linux 内核 3.8 版本开始,每个文件都是一个特殊的符号链接文件