摘要:用来隔离网络设备地址端口等每个将会有自己独立的网络栈,路由表,防火墙规则,等。下面将通过的方式让能够上外网。这部分内容完全是网络相关的知识,跟已经没什么关系了。
network namespace用来隔离网络设备, IP地址, 端口等. 每个namespace将会有自己独立的网络栈,路由表,防火墙规则,socket等。
每个新的network namespace默认有一个本地环回接口,除了lo接口外,所有的其他网络设备(物理/虚拟网络接口,网桥等)只能属于一个network namespace。每个socket也只能属于一个network namespace。
当新的network namespace被创建时,lo接口默认是关闭的,需要自己手动启动起
标记为"local devices"的设备不能从一个namespace移动到另一个namespace,比如loopback, bridge, ppp等,我们可以通过ethtool -k命令来查看设备的netns-local属性。
#这里“on”表示该设备不能被移动到其他network namespace dev@ubuntu:~$ ethtool -k lo|grep netns-local netns-local: on [fixed]
示例本篇所有例子都在ubuntu-server-x86_64 16.04下执行通过
本示例将演示如何创建新的network namespace并同外面的namespace进行通信。
#--------------------------第一个shell窗口---------------------- #记录默认network namespace ID dev@ubuntu:~$ readlink /proc/$$/ns/net net:[4026531957] #创建新的network namespace dev@ubuntu:~$ sudo unshare --uts --net /bin/bash root@ubuntu:~# hostname container001 root@ubuntu:~# exec bash root@container001:~# readlink /proc/$$/ns/net net:[4026532478] #运行ifconfig啥都没有 root@container001:~# ifconfig root@container001:~# #启动lo (这里不详细介绍ip这个tool的用法,请参考man ip) root@container001:~# ip link set lo up root@container001:~# ifconfig lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) root@container001:~# ping 127.0.0.1 PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data. 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.070 ms 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.015 ms #获取当前bash进程的PID root@container001:~# echo $$ 15812 #--------------------------第二个shell窗口---------------------- #创建新的虚拟以太网设备,让两个namespace能通讯 dev@ubuntu:~$ sudo ip link add veth0 type veth peer name veth1 #将veth1移动到上面第一个窗口中的namespace #这里15812是上面bash的PID dev@ubuntu:~$ sudo ip link set veth1 netns 15812 #为veth0分配IP并启动veth0 dev@ubuntu:~$ sudo ip address add dev veth0 192.168.8.1/24 dev@ubuntu:~$ sudo ip link set veth0 up dev@ubuntu:~$ ifconfig veth0 veth0 Link encap:Ethernet HWaddr 9a:4d:d5:96:b5:36 inet addr:192.168.8.1 Bcast:0.0.0.0 Mask:255.255.255.0 inet6 addr: fe80::984d:d5ff:fe96:b536/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:8 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:648 (648.0 B) TX bytes:648 (648.0 B) #--------------------------第一个shell窗口---------------------- #为veth1分配IP地址并启动它 root@container001:~# ip address add dev veth1 192.168.8.2/24 root@container001:~# ip link set veth1 up root@container001:~# ifconfig veth1 veth1 Link encap:Ethernet HWaddr 6a:dc:59:79:3c:8b inet addr:192.168.8.2 Bcast:0.0.0.0 Mask:255.255.255.0 inet6 addr: fe80::68dc:59ff:fe79:3c8b/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:8 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:648 (648.0 B) TX bytes:648 (648.0 B) #连接成功 root@container001:~# ping 192.168.8.1 PING 192.168.8.1 (192.168.8.1) 56(84) bytes of data. 64 bytes from 192.168.8.1: icmp_seq=1 ttl=64 time=0.098 ms 64 bytes from 192.168.8.1: icmp_seq=2 ttl=64 time=0.023 ms
到目前为止,两个namespace之间可以网络通信了,但在container001里还是不能访问外网。下面将通过NAT的方式让container001能够上外网。这部分内容完全是网络相关的知识,跟namespace已经没什么关系了。
#--------------------------第二个shell窗口---------------------- #回到上面示例中的第二个窗口 #确认IP forward是否已经开通,这里1表示开通了 #如果你的机器上是0,请运行这个命令将它改为1: sudo sysctl -w net.ipv4.ip_forward=1 dev@ubuntu:~$ cat /proc/sys/net/ipv4/ip_forward 1 #添加NAT规则,这里ens32是机器上连接外网的网卡 #关于iptables和nat都比较复杂,这里不做解释 dev@ubuntu:~$ sudo iptables -t nat -A POSTROUTING -o ens32 -j MASQUERADE #--------------------------第一个shell窗口---------------------- #回到第一个窗口,添加默认网关 root@container001:~# ip route add default via 192.168.8.1 root@container001:~# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.8.1 0.0.0.0 UG 0 0 0 veth1 192.168.8.0 0.0.0.0 255.255.255.0 U 0 0 0 veth1 #这样就可以访问外网了 #由于测试环境的限制,所以采用下面的方式检测网络是否畅通 #如果网络没有什么限制的话,随便ping一个外部的IP测试就可以了 root@container001:~# curl -I www.google.com HTTP/1.1 200 OK Date: Fri, 15 Jul 2016 08:12:03 GMT
network namespace的概念比较简单,但如何做好网络的隔离和连通却比较难,包括性能和安全相关的考虑,需要很好的Linux网络知识。后续在介绍docker网络管理的时候会对Linux网络做一个更详细的介绍。
ip netns在多带带操作network namespace时,ip netns是一个很方便的工具,并且它可以给namespace取一个名字,然后根据名字来操作namespace。那么给namespace取名字并且根据名字来管理namespace里面的进程是怎么实现的呢?请看下面的脚本(也可以直接看它的源代码):
#开始之前,获取一下默认network namespace的ID dev@ubuntu:~$ readlink /proc/$$/ns/net net:[4026531957] #创建一个用于绑定network namespace的文件, #ip netns将所有的文件放到了目录/var/run/netns下, #所以我们这里重用这个目录,并且创建一个我们自己的文件netnamespace1 dev@ubuntu:~$ sudo mkdir -p /var/run/netns dev@ubuntu:~$ sudo touch /var/run/netns/netnamespace1 #创建新的network namespace,并在新的namespace中启动新的bash dev@ubuntu:~$ sudo unshare --net bash #查看新的namespace ID root@ubuntu:~# readlink /proc/$$/ns/net net:[4026532448] #bind当前bash的namespace文件到上面创建的文件上 root@ubuntu:~# mount --bind /proc/$$/ns/net /var/run/netns/netnamespace1 #通过ls -i命令可以看到文件netnamespace1的inode号和namespace的编号相同,说明绑定成功 root@ubuntu:~# ls -i /var/run/netns/netnamespace1 4026532448 /var/run/netns/netnamespace1 #退出新创建的bash root@ubuntu:~# exit exit #可以看出netnamespace1的inode没变,说明我们使用了bind mount后 #虽然新的namespace中已经没有进程了,但这个新的namespace还存在 dev@ubuntu:~$ ls -i /var/run/netns/netnamespace1 4026532448 /var/run/netns/netnamespace1 #上面的这一系列操作等同于执行了命令: ip netns add netnamespace1 #下面的nsenter命令等同于执行了命令: ip netns exec netnamespace1 bash #我们可以通过nsenter命令再创建一个新的bash,并将它加入netnamespace1所关联的namespace(net:[4026532448]) dev@ubuntu:~$ sudo nsenter --net=/var/run/netns/netnamespace1 bash root@ubuntu:~# readlink /proc/$$/ns/net net:[4026532448]
从上面可以看出,给namespace取名字其实就是创建一个文件,然后通过mount --bind将新创建的namespace文件和该文件绑定,就算该namespace里的所有进程都退出了,内核还是会保留该namespace,以后我们还可以通过这个绑定的文件来加入该namespace。
通过这种办法,我们也可以给其他类型的namespace取名字(有些类型的 namespace可能有些特殊,本人没有一个一个的试过)。
参考Namespaces in operation, part 7: Network namespaces
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/9453.html
摘要:名称宏定义隔离内容注意由于在的内核中才实现,并且和关系密切,现在普及程度还不高,比如现在就还没有用它,所以在这个系列中不会介绍。这条规则对其他类型的也同样适用。 Namespace是对全局系统资源的一种封装隔离,使得处于不同namespace的进程拥有独立的全局系统资源,改变一个namespace中的系统资源只会影响当前namespace里的进程,对其他namespace中的进程没有影...
摘要:为了方便阅读,将自己写的所有关于和的文章统一列在这里,希望对有需要的人有所帮助,后续有新的内容后将会更新这里的列表。 为了方便阅读,将自己写的所有关于namespace和cgroup的文章统一列在这里,希望对有需要的人有所帮助,后续有新的内容后将会更新这里的列表。 namespace 包含了Linux目前常用的6个namespace的介绍 Linux Namespace系列(01):...
摘要:为了方便阅读,将自己写的所有关于和的文章统一列在这里,希望对有需要的人有所帮助,后续有新的内容后将会更新这里的列表。 为了方便阅读,将自己写的所有关于namespace和cgroup的文章统一列在这里,希望对有需要的人有所帮助,后续有新的内容后将会更新这里的列表。 namespace 包含了Linux目前常用的6个namespace的介绍 Linux Namespace系列(01):...
摘要:本篇将主要介绍和其他类型的的关系。权限涉及的范围非常广,所以导致比其他的要复杂同时权限也是容器安全的基础,所以非常重要。其它和类似,当在程序中用将一个的或者发送给另一个中的进程时,内核会自动映射成目的中对应的或者。 本篇将主要介绍user namespace和其他类型的namespace的关系。 权限涉及的范围非常广,所以导致user namespace比其他的namespace要复杂...
摘要:详情请参考帮助文档和代码。离开当前指定类型的,创建且加入新的,然后执行参数中指定的命令。不过后续将要介绍的其他就要比这个复杂多了。 IPC namespace用来隔离System V IPC objects和POSIX message queues。其中System V IPC objects包含Message queues、Semaphore sets和Shared memory s...
阅读 1548·2023-04-26 01:56
阅读 2864·2021-11-18 10:02
阅读 2743·2021-09-09 11:35
阅读 1023·2021-09-03 10:28
阅读 3252·2019-08-29 18:36
阅读 2721·2019-08-29 17:14
阅读 732·2019-08-29 16:10
阅读 1467·2019-08-26 13:45