Linux命名空间是一个相对较新的内核功能,对于实现容器至关重要。 命名空间将全局系统资源包装到一个抽象中,该抽象只会与命名空间中的进程绑定,从而提供资源隔离。 在本文中,我将讨论网络命名空间并展示一个实际的例子。
命名空间和cgroups是软件集装箱化(Docker)的大部分新趋势的主要内核技术之一。 简单来说,cgroups是一种计量和限制机制,它们控制您可以使用多少系统资源(CPU,内存)。 另一方面,命名空间限制了您可以看到的内容。 由于命名空间进程有自己的系统资源视图。
Linux内核提供了6种类型的命名空间:pid,net,mnt,uts,ipc和user。 例如,pid命名空间中的进程只能看到同一命名空间中的进程。 感谢mnt命名空间,可以将进程附加到自己的文件系统(如chroot)。 在本文中,我仅关注网络命名空间。
如果您已经掌握了命名空间的概念,您可能在这一点上可以直观地了解网络命名空间可能提供的内容。 网络命名空间为命名空间中的所有进程提供了全新的网络堆栈。 这包括网络接口,路由表和iptables规则。
网络命名空间
从系统的角度来看,当通过clone()syscall创建新进程时,传递标志CLONE_NEWNET将在新进程中创建一个全新的网络命名空间。 从用户的角度来看,我们只需使用工具ip(package is iproute2)来创建一个新的持久网络命名空间:
$ ip netns add ns1
该命令将创建一个名为ns1的新网络命名空间。 当创建命名空间时,ip命令在/ var / run / netns下为其添加绑定挂载点。 这允许命名空间持续存在,即使没有进程附加它。 列出系统中可用的命名空间:
$ ls /var/run/netns
ns1
或者 使用 ip
:
$ ip netns
ns1
如前所述,网络命名空间包含自己的网络资源:接口,路由表等。我们为ns1添加一个环回接口:
1 $ ip netns exec ns1 ip link set dev lo up
2 $ ip netns exec ns1 ping 127.0.0.1
3 PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
4 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.115 ms
$ ip netns exec ns1 ifconfig lo up
然而,我倾向于使用ip命令,因为它已成为Linux中首选的网络工具,废弃旧的但更熟悉的命令ifconfig,route等。请注意,ip需要root权限,因此以root或prepend sudo运行。
$ ip netns exec ns1 ip route show
$ ip netns exec
一个实际的例子
# Remove namespace if it exists.
ip netns del ns1 &>/dev/null
# Create namespace
ip netns add ns1
接下来,创建一个veth对。 接口v-eth1将保留在根网络名称空间内,而其对等体v-peer1将被移动到ns1命名空间。
# Create veth link.
ip link add v-eth1 type veth peer name v-peer1
# Add peer-1 to NS.
ip link set v-peer1 netns ns1
# Setup IP address of v-eth1.
ip addr add 10.200.1.1/24 dev v-eth1
ip link set v-eth1 up
# Setup IP address of v-peer1.
ip netns exec ns1 ip addr add 10.200.1.2/24 dev v-peer1
ip netns exec ns1 ip link set v-peer1 up
ip netns exec ns1 ip link set lo up
另外我提出了ns1内的loopback接口。
ip netns exec ns1 ip route add default via 10.200.1.1
# Share internet access between host and NS.
# Enable IP-forwarding.
echo 1 > /proc/sys/net/ipv4/ip_forward
# Flush forward rules, policy DROP by default.
iptables -P FORWARD DROP
iptables -F FORWARD
# Flush nat rules.
iptables -t nat -F
# Enable masquerading of 10.200.1.0.
iptables -t nat -A POSTROUTING -s 10.200.1.0/255.255.255.0 -o eth0 -j MASQUERADE
# Allow forwarding between eth0 and v-eth1.
iptables -A FORWARD -i eth0 -o v-eth1 -j ACCEPT
iptables -A FORWARD -o eth0 -i v-eth1 -j ACCEPT
如果一切正常,可以从ns1 ping一个外部主机。
$ ip netns exec ns1 ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=50 time=48.5 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=50 time=50.8 ms
这是ns1中的路由表在安装后如何看起来:
$ ip netns exec ns1 ip route sh
default via 10.200.1.1 dev v-peer1
10.200.1.0/24 dev v-peer1 proto kernel scope link src 10.200.1.2
$ ip netns exec ns1 /bin/bash --rcfile <(echo "PS1=\"namespace ns1> \"")
namespace ns1> ping www.google.com
PING www.google.com (178.60.128.38) 56(84) bytes of data.
64 bytes from cache.google.com (178.60.128.38): icmp_seq=1 ttl=58 time=17.6 ms
键入exit以结束bash进程并离开网络命名空间。