创建ns
ip netns add xx 创建一个 namespace
和 network namespace 相关的操作的子命令是 ip netns
[root@ namespace]# ip netns add ns1
[root@ namespace]# ip netns ls
ns1
在新namespace xx中执行yy命令
ip netns exec xx yy
查看ip:
[root@ namespace]# ip netns exec ns1 ip addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
打开bash并从ns1的终端中查看ip:
[root@ namespace]# ip netns exec ns1 bash
[root@ namespace]# ip addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
退出:
[root@ namespace]# exit
上面 bash 不好区分是当前是在哪个 shell,可以采用下面的方法解决:
ip netns exec net1 /bin/bash --rcfile <(echo "PS1=\"namespace net1> \"")
每个 namespace 在创建的时候会自动创建一个回环接口 lo ,默认不启用,可以通过
ip link set lo up 启用。
##network namespace之间的通信
新创建的 namespace 默认不能和主机网络,以及其他 namespace 通信。
可以使用 Linux 提供的 veth pair 来完成通信。
cloud_dev_ns_network_veth_pair.jpg
创建两个ns
ip netns add ns1
ip netns add ns2
创建 veth pair
ip link add type veth
将 veth 加入到 namespace 中
ip link set veth0 netns ns1
ip link set veth1 netns ns2
执行ns容器的ip addr:
[root@ namespace]# ip netns exec ns1 ip addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
8: veth0@if9: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether aa:c8:a0:10:1c:4c brd ff:ff:ff:ff:ff:ff link-netnsid 1
多了刚添加的veth接口。
给 veth pair 配上 ip 地址
[root@ namespace]# ip netns exec ns1 ip addr add 10.1.1.1/24 dev veth0
[root@ namespace]# ip netns exec ns1 ip route
10.1.1.0/24 dev veth0 proto kernel scope link src 10.1.1.1 linkdown
[root@ namespace]# ip netns exec ns1 ip link set veth0 up
[root@ namespace]# ip netns exec ns2 ip addr add 10.1.1.2/24 dev veth1
[root@ namespace]# ip netns exec ns2 ip route
[root@ namespace]# ip netns exec ns2 ip link set veth1 up
测试两个namespace连通性
[root@ namespace]# ip netns exec ns1 ping 10.1.1.2
PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data.
64 bytes from 10.1.1.2: icmp_seq=1 ttl=64 time=0.070 ms
64 bytes from 10.1.1.2: icmp_seq=2 ttl=64 time=0.035 ms
64 bytes from 10.1.1.2: icmp_seq=3 ttl=64 time=0.043 ms
多个namespace之间的通信
多个 namespace 之间的通信则可以使用 bridge 来转接
使用 ip link 和 brctl 创建 bridge
通常 Linux 中和 bridge 有关的操作是使用命令 brctl (yum install -y bridge-utils ) 。但为了前后照应,这里都用 ip 相关的命令来操作。
[root@ namespace]# ip link add br0 type bridge
[root@ namespace]# ip link set [dev] br0 up
创建3个network namespace
[root@ namespace]# ip netns add ns1
[root@ namespace]# ip netns add ns2
[root@ namespace]# ip netns add ns3
创建3对veth-pair
[root@ namespace]# ip link add veth1 type veth peer name br0-veth1
[root@ namespace]# ip link add veth2 type veth peer name br0-veth2
[root@ namespace]# ip link add veth3 type veth peer name br0-veth3
将namespace和br0通过veth-pair连接
[root@ namespace]# ip link set dev veth1 netns ns1
[root@ namespace]# ip netns exec ns1 ip link set dev veth1 name eth0
[root@ namespace]# ip netns exec ns1 ip addr add 10.0.1.1/24 dev eth0
[root@ namespace]# ip netns exec ns1 ip link set dev eth0 up
[root@ namespace]#
[root@ namespace]# ip link set dev br0-veth1 master br0
[root@ namespace]# ip link set dev br0-veth1 up
#将veth2加入ns2并设置ip地址(每个ns独立,所以可以设置相同的接口名eth0)
ip link set dev veth2 netns ns2
ip netns exec ns2 ip link set dev veth2 name eth0
ip netns exec ns2 ip addr add 10.0.1.2/24 dev eth0
ip netns exec ns2 ip link set dev eth0 up
#将veth2的另一端br0-veth2加入到br0
ip link set dev br0-veth2 master br0
ip link set dev br0-veth2 up
#将veth3加入ns3并设置ip地址
ip link set dev veth3 netns ns3
ip netns exec ns3 ip link set dev veth3 name eth0
ip netns exec ns3 ip addr add 10.0.1.3/24 dev eth0
ip netns exec ns3 ip link set dev eth0 up
#将veth3的另一端br0-veth3加入到br0
ip link set dev br0-veth3 master br0
ip link set dev br0-veth3 up
测试namespace之间的连通性
从ns1 ping ns2:
[root@ namespace]# ip netns exec ns1 ping -c 2 10.0.1.2
PING 10.0.1.2 (10.0.1.2) 56(84) bytes of data.
--- 10.0.1.2 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1009ms
发现无法ping通,因为系统为bridge开启了iptables功能,导致所有经过br0的数据包都要受iptables里面规则的限制,将iptables里面filter表的FORWARD链的默认策略设置成了drop,于是所有不符合docker规则的数据包都不会被forward,导致这种情况ping不通。
解决1:关闭系统bridge的iptables功能
echo 0 > /proc/sys/net/bridge/bridge-nf-call-iptables
解决2:为br0添加一条iptables规则,让经过br0的包能被forward
iptables -A FORWARD -i br0 -j ACCEPT
再次测试:
ns1 ping ns2和ns3
[root@ namespace]# ip netns exec ns1 ping 10.0.1.2 -c 2
PING 10.0.1.2 (10.0.1.2) 56(84) bytes of data.
64 bytes from 10.0.1.2: icmp_seq=1 ttl=64 time=0.034 ms
64 bytes from 10.0.1.2: icmp_seq=2 ttl=64 time=0.039 ms
--- 10.0.1.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.034/0.036/0.039/0.006 ms
[root@ namespace]# ip netns exec ns1 ping 10.0.1.3 -c 2
PING 10.0.1.3 (10.0.1.3) 56(84) bytes of data.
64 bytes from 10.0.1.3: icmp_seq=1 ttl=64 time=0.066 ms
64 bytes from 10.0.1.3: icmp_seq=2 ttl=64 time=0.040 ms
--- 10.0.1.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.040/0.053/0.066/0.013 ms
通过ovs连接namespace
和bridge连接原理一样,只是bridge换成了openvswitch
cloud_dev_veth_pair_ovs.png
创建两个ns
ip netns add ns1
ip netns add ns2
创建ovs
ovs-vsctl add-br ovs_br
创建两对veth-pair
ip link add veth1 type veth peer name veth1_ovs
ip link add veth2 type veth peer name veth2_ovs
用veth-pair将ns和ovs相连,并配置ns中veth接口的ip地址
ip link set veth1 netns ns1
ip netns exec ns1 ip addr add 10.0.1.1/24 dev veth1
ip netns exec ns1 ip link set veth1 up
ip link set veth2 netns ns2
ip netns exec ns2 ip addr add 10.0.1.2/24 dev veth2
ip netns exec ns2 ip link set veth2 up
ovs-vsctl add-port ovs_br veth1_ovs
ip link set veth1_ovs up
ovs-vsctl add-port ovs_br veth2_ovs
ip link set veth2_ovs up
连通性测试
[root@ ~]# ip netns exec ns1 ping 10.0.1.2 -c 2
PING 10.0.1.2 (10.0.1.2) 56(84) bytes of data.
64 bytes from 10.0.1.2: icmp_seq=1 ttl=64 time=0.271 ms
64 bytes from 10.0.1.2: icmp_seq=2 ttl=64 time=0.054 ms
--- 10.0.1.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.054/0.162/0.271/0.109 ms