0
点赞
收藏
分享

微信扫一扫

linux网络虚拟化 network namespace 【待解决】

唯米天空 2022-02-11 阅读 100


namespace(命名空间)和cgroup是软件容器化(想想Docker)趋势中的两个主要内核技术。简单来说,cgroup是一种对进程进行统一的资源监控和限制,它控制着你可以使用多少系统资源(CPU,内存等)。而namespace是对全局系统资源的一种封装隔离,它通过Linux内核对系统资源进行隔离和虚拟化的特性,限制了您可以看到的内容。

Linux 3.8内核提供了6种类型的命名空间:Process ID (pid)、Mount (mnt)、Network (net)、InterProcess Communication (ipc)、UTSUser ID (user)。例如,pid命名空间内的进程只能看到同一命名空间中的进程。mnt命名空间,可以将进程附加到自己的文件系统(如chroot)。在本文中,我只关注网络命名空间 Network (net)。

网络命名空间为命名空间内的所有进程提供了全新隔离的网络协议栈。这包括网络接口,路由表和iptables规则。通过使用网络命名空间就可以实现网络虚拟环境,实现彼此之间的网络隔离,这对于云计算中租户网络隔离非常重要,Docker中的网络隔离也是基于此实现的,如果你已经理解了上面所说的,那么我们进入正题,介绍如何使用网络命名空间。

准备工作以及环境:

系统:centos 7系统(因为namespace是linux 内核3.8开始支持的,所以要想进行本文的实验,请用linux内核3.8及以上版本)

安装iproute(yum install iproute2,其他平台请自行下载iproute2工具)

注意:本文作者使用ip命令,因为它已成为Linux中的首选网络工具,旧的ifconfig,route等命令也已经被淘汰了。请注意,ip命令需要root权限,因此ip命名要以root用户身份运行或预先添加sudo。

1.新增一个网络命名空间(名称netns1)

ip netns add netns0

解释:从系统的角度来看,当通过clone()系统调用创建一个新进程时,传递标志CLONE_NEWNET将在新进程中创建一个全新的网络命名空间。从用户的角度来看,我们只需使用工具ip(iproute2工具包)来创建一个新的持久网络命名空间:此命令将创建一个名为netns0的新网络命名空间。创建命名空间后,ip命令会在/var/run/netns目录下增加一个netns0文件(In Linux, Everything is a File)。

# ls /var/run/netns
netns0

2.使用命令 ip netns show或ip netns list,列出系统中可用的命名空间:

# ip netns show
netns0

3.如前所述,网络命名空间包含自己的网络资源:接口,路由表等。默认添加网络命名空间netns1后,在netns1命名空间中会自动添加一个loopback(回环)接口:

首先开启回环口lo网卡

ip netns exec netns0 ip link set lo up

查看网络lo回环口信息:

# ip netns exec netns0 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

ping 127.0.0.1

# ip netns exec netns0 ping 127.0.0.1 -c 3

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.016 ms

64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.033 ms

64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.033 ms

--- 127.0.0.1 ping statistics ---

3 packets transmitted, 3 received, 0% packet loss, time 1999ms

rtt min/avg/max/mdev = 0.016/0.027/0.033/0.009 ms

既然已经了解了网络命名空间后,那我们通过两个隔离的命名空间来实现互通(模拟两台主机直接的互通,作为网络开发人员,有时候需要很多台机器来测试网络,但是只有一台机器,那么有了网络命名空间这个特性,完全就可以在一台主机上模拟多台主机之间互通的网络测试),如下所示:


linux网络虚拟化 network namespace 【待解决】_网线

# ip netns add netns1
# ip netns show
netns0
netns1

这时候需要一根网线来连接,这根网线就是采用的veth pair技术。这根网线是双向的,而且当数据包来到某一端的时候,会无条件的传输到另一端。需要注意的是veth pair只能是成对存在的,只要创建就会成对的创建出来,一旦删除其中一端,那么另一端也会跟着消失。 我们先来创建一对veth pair

模拟创建一根网线:

# ip link add name vnet0 type veth peer name vnet1

# ip a

1: vnet1@vnet0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000

link/ether 52:42:c3:02:54:38 brd ff:ff:ff:ff:ff:ff

2: vnet0@vnet1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000

link/ether a6:20:57:dc:c6:dd brd ff:ff:ff:ff:ff:ff

可以看见创建了一个vnet1@vnet0和vnet0@vnet1两张虚拟网卡,现在要把一头插到netns0主机中,另外一套插在netns1主机中,命令如下:

# ip link set vnet0 netns netns0
# ip link set vnet1 netns netns1

给两个主机分别配置ip,192.168.0.2和192.168.0.3,然后互ping

# ip netns exec netns0 ip link set vnet0 up
# ip netns exec netns1 ip link set vnet1 up
# ip netns exec netns0 ip a add 192.168.0.2 dev vnet0
# ip netns exec netns1 ip a add 192.168.0.3 dev vnet1
# ip netns exec netns0 ping 192.168.0.3
connect: 网络不可达

网络不可达???what??为什么会这样?其实是因为没有路由

添加路由

# ip netns exec netns0 ip r add 192.168.0.3 dev vnet0
# ip netns exec netns1 ip r add 192.168.0.2 dev vnet1

在netns0中去ping netns1主机

# ip netns exec netns0 ping 192.168.0.3 -c 2

PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.

64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.021 ms

64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.047 ms

--- 192.168.0.3 ping statistics ---

2 packets transmitted, 2 received, 0% packet loss, time 999ms

rtt min/avg/max/mdev = 0.021/0.034/0.047/0.013 ms

上一个是仅仅两个虚拟网络的情况下,那么如果多了起来,再去两两进行配对就明显不太可行了。所以引入了网桥bridge这个技术。将网络全都与bridge连通,那么所有的两两之间的网络就都可以通信了。 

我们演示下,我们创建新的命名空间,分别是netns3,netns4,netns5

ip netns add netns3
ip netns add netns4
ip netns add netns5

然后创建网桥且开启它

ip link add br0 type bridge
ip link set dev br0 up

然后创建第一对veth pair,将veth pair的一端挂在netns3上,并且给配上ip地址,分配路由并启动。

#创建连接端口
ip link add name vnet3 type veth peer name br3
ip link add name vnet4 type veth peer name br4
ip link add name vnet5 type veth peer name br5

#连接不同的网络空间
ip link set vnet3 netns netns3
ip link set vnet4 netns netns4
ip link set vnet5 netns netns5

#启动
ip netns exec netns3 ip link set vnet3 up
ip netns exec netns4 ip link set vnet4 up
ip netns exec netns5 ip link set vnet5 up

#分配ip
ip netns exec netns3 ip a add 192.168.0.5 dev vnet3
ip netns exec netns4 ip a add 192.168.0.6 dev vnet4
ip netns exec netns5 ip a add 192.168.0.7 dev vnet5

#设置路由
ip netns exec netns3 ip r add 192.168.0.5 dev vnet3
ip netns exec netns4 ip r add 192.168.0.6 dev vnet4
ip netns exec netns5 ip r add 192.168.0.7 dev vnet5

再将另一端挂在bridge上

ip link set dev br3 master br0
ip link set dev br4 master br0
ip link set dev br5 master br0
ip link set dev br3 up
ip link set dev br4 up
ip link set dev br5 up

linux网络虚拟化 network namespace 【待解决】_网线_02

测试一下

ip netns exec netns3 ping -c 3 192.168.0.7

linux网络虚拟化 network namespace 【待解决】_命名空间_03

ping不通。。。

哎!!!谁能解决评论下,不胜感激!!!


举报

相关推荐

0 条评论