总览
Linux 的虚拟化技术之一,就是 Namespace,其中 Net Namespace 是网络命名空间,这个在 Docker 里用的比较多,这篇文章主要想做的是,如何模拟的一个跨 Namespace 的通信过程。
提一点:跨Namespace,可以是多个 Net Namespace 之间,也可以是 宿主机和某一个 Net Namespace。我们要模拟的是:
①:只有一个自定义的网络命名空间(名为 blue )。
②:在宿主机网络和 blue 命名空间网络 两者上,分别建立虚拟网卡,并设置不同IP,进行通信(比如 ping,比如 curl)
③:尝试在名为 blue 的网络命名空间里启动 http 服务,在宿主机上网络上,访问 blue 空间里的这个 http 服务。
所以,我们需要完成以下几个步骤:
一、创建新命名空间
二、为新命名空间 blue ,添加网卡
三、打通宿主机命名空间和新命名空间之间的通信
四、在 blue 网络命名空间下,创建 http 服务,宿主机访问。
实施步骤
创建名为 blue 的网络命名空间
1 | ip netns add blue |
ip 工具集非常强大,即可处理网络命名空间,也可以处理网络设备。
为新命名空间,添加网卡
创建 veth pair
veth pair,主要就是用来处理不同命名空间通信用的(确切的说,是 Linux 虚拟化技术的产物之一,目前在容器化上用的比较多),veth 其实是 virtual ethernet 的缩写(虚拟以太网卡)。而 veth pair,就是一次性创建 一对 虚拟网卡,它们成对出现,向 veth pair 的一端发送的数据,经过操作系统内核后,可以通过另外一端读取到数据。
veth pair 在不同的命名空间使用如下:
1、创建 veth pair
1 | ip link add vethtest01 type veth peer name vethest002 |
2、查看 veth pair
1 | ip link list |
1 | // 输出大概如下: |
注意:
1、ip link list 里,这个 link 指的就是网络设备,感觉叫 link 不太理解,可以通过 man ip 手册,找到 link 部分的说明。
2、其实我们通过 ifconfig 也可以看到,不过需要加 -a,即:ifconfig -a。ifconfig 默认只能看到已up的网络设备。
将 veh pair 的一端,添加命名空间,并处理好网卡设置
1、添加网卡到 blue 网络命名空间
1 | ip link set vethest002 netns blue |
添加完成后,宿主机的环境中,已经无法通过 ip link list 看到 vethest002 这个网卡设备了,因为它已经到 blue 网络命名空间里去了。
2、去到查看 blue 网络命名空间内,查看网卡设备列表:
1 | ip netns exec blue ip link list |
1 | // 输出: |
3、为 blue 里的网卡,配置网卡接口
现在,blue 网络空间下,有 vethest002 设备,但这个设备第一,它没启动,第二,它没有设置网络IP信息,我们做一下这个处理:
1 | ip netns exec blue ifconfig vethest002 10.1.1.2/16 up |
注意:我这里设置的是 10.1.1.2/16,这里设置为16,而不是24,是因为,一会儿我要为宿主机网络的 veth pair 另一端 vethest001 设置另外一个网络段 10.1.2.2/16,这样,他俩才是在同一个网段。
再次查看 blue 网络命名空间内的网卡接口:
1 | ip netns exec blue ifconfig |
1 | vethest002: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 |
通过上面的命令,可以看到,我们可以在某个命名空间内执行某个命令,比如添加网卡接口、查看网卡列表,都是通过 ip netns exec 来做的,所以,我们也可以在某个网络命名空间下开启一个 shell,此 shell 中执行的所有操作,都会在这个网络命名空间下。
1 | // 比如在某个命名空间下,开启一个 shell,去执行其他命令。 |
打通宿主机命名空间和新命名空间之间的通信
bridge 概述:
我们已经为新的网络命名空间 blue 做了配置,但现在这个命名空间无法连通宿主机的网络。
我们需将通宿主机网络和 blue 网络命名的网络打通,就需要引入一个新的工具:bridge。
①:bridge,是虚拟网络设备,可以为 bridge 配置网络设备的特征,比如:IP、MAC等。
②:bridge 也是虚拟交换机,具备和物理交换机的类似功能。
bridge的特殊性:普通网络设备,一般有2个端,发送端和接收端。比如网卡,从外网接收数据,转到内核,或者从内核接收数据,再转发出去。但是,bridge 不同,它可以有很多的端口,数据可以从任意的一端进来,至于进来之后,要从哪里出去,就和物理交换机差不多,看目的地址了,bridge 可以正确的进行路由。
在开始配置 bridge 之前,我们可以看一下,在 K8S flannel(backend为overlay网络vxlan)这种网络模型下的 bridge 示例:
1 | [root@sja22 /] |
如上,可以看到,有一个名为 cni0 的 bridge,下面挂了一堆的 veth pair。
用 bridge 打通不同网络命名空间的原来图(图是摘的),大致如下:
总得来说有几个关键点:
①:得有一个网桥。
②:创建一对(或者多对)veth pair,取决于你想让几个 Namespace 网络进行通信。
③:veth pair 的一端,要接入 Namespace里,另外一端,接到 bridge 上。
④:为 Namespace 里的 veth pair 设备设置 IP ,并启动。
⑤:为 网桥配置 IP(这个 IP 必须和 Namespace 那头的 IP 在同一个网段),并启动。
创建 bridge 并连接 veth pair 的一端
1、创建一个 bridge(网桥)
创建 bridge 有2种方式,用到的命令也不同,最基本的,就是 ip 命令
方式1:ip 命令创建和操作 bridge
1 | ip link add name test-bridge type bridge |
这个命令执行后,无法通过 ifconfig 看到这个设备,因为这个设备没有启动,所以需要启动 bridge 设备:
1 | ip link set test-bridge up |
还是用的 ip link 操作,所以,其实 bridge 也是一个网络设备,和 veth pair 是同一个层级的东西。
此命令执行后,可以通过 ifconfig 看到设备
1 | [root@192-168-20-143 ~] |
方式2:brctl
1 | yum -y install bridge-utils |
1 | brctl addbr test-bridge up |
同样,上面的操作后,无法通过 ifconfig 看到此网桥设备,因为此设备还没有启动,还是需要手动启动
注意:新创建的 bridge 除了一端连接了网络协议栈外,啥都没有,所以,我们需要将 bridge 和 veth pair 连接起来。
2、将 bridge 和 veth pair 连接
我们之前,已经将创建的 veth pair 的一端(vethest002),连接到 blue 网络命名空间内,并配置好 IP 了,宿主机上还有 veh pair 另外一端(vethest001),我们要把它接入刚才创建的网桥上。
1 | ip link set dev vethtest01 master test-bridge |
3、为网桥配置IP地址并做连通测试
1 | ifconfig test-bridge 10.1.2.2/16 up |
经过上面的操作,其实我们已经可以连通这2个网络了。我们在宿主机网络,ping blue 命名空间的网络空间的 IP
明确一点:宿主机网桥IP是 10.1.2.2,网络命名空间blue内的是 10.1.1.2
1 | [root@test ~] |
如上,网络已经连通。
在 blue 网络命名空间下,创建 http 服务,宿主机访问
先创建一个简单的HTTP服务
我们直接编译一个非常简单的,基于 C 语言的 HTTP 服务就行,所以需要准备下
1 | yum -y install gcc |
1、创建 http_server.c 文件,写入如下内容:
1 |
|
2、创建 Makefile 文件,写入如下内容
1 | .PHONY:all clean |
编译出二进制文件
1 | make |
可以看到,编译出一个可执行文件:http_server
3、在 blue 网络命名空间下,启动这个 server
1 | ip netns exec blue /bin/bash |
在这个网络下启动的这个 server 监听 8080 端口,也意味着,我们在宿主机,理论上可以通过 curl 访问这个服务。
4、新开一个窗口,访问 blue 网络内的 8080 HTTP 服务
1 | [root@test ~] |