Linux 中的虚拟网络接口 (3)

其主要作用就是连接不同的网络,比如在容器网络中,用于将容器的 namespace 与 root namespace 的网桥 br0 相连。
容器网络中,容器侧的 veth 自身设置了 ip/mac 地址并被重命名为 eth0,作为容器的网络接口使用,而主机侧的 veth 则直接连接在 docker0/br0 上面。

使用 veth 的容器网络的详细示例图,在下一节有提供。

三、bridge

Linux Bridge 是工作在链路层的网络交换机,由 Linux 内核模块 brige 提供,它负责在所有连接到它的接口之间转发链路层数据包。

添加到 Bridge 上的设备被设置为只接受二层数据帧并且转发所有收到的数据包到 Bridge 中。
在 Bridge 中会进行一个类似物理交换机的查MAC端口映射表、转发、更新MAC端口映射表这样的处理逻辑,从而数据包可以被转发到另一个接口/丢弃/广播/发往上层协议栈,由此 Bridge 实现了数据转发的功能。

如果使用 tcpdump 在 Bridge 接口上抓包,可以抓到网桥上所有接口进出的包,因为这些数据包都要通过网桥进行转发。

与物理交换机不同的是,Bridge 本身可以设置 IP 地址,可以认为当使用 brctl addbr br0 新建一个 br0 网桥时,系统自动创建了一个同名的隐藏 br0 网络接口。br0 一旦设置 IP 地址,就意味着这个隐藏的 br0 接口可以作为路由接口设备,参与 IP 层的路由选择(可以使用 route -n 查看最后一列 Iface)。因此只有当 br0 设置 IP 地址时,Bridge 才有可能将数据包发往上层协议栈。

但被添加到 Bridge 上的网卡是不能配置 IP 地址的,他们工作在数据链路层,对路由系统不可见。

它常被用于在虚拟机、主机上不同的 namepsaces 之间转发数据。

虚拟机场景(桥接模式)

以 qemu-kvm 为例,在虚拟机的桥接模式下,qemu-kvm 会为每个虚拟机创建一个 tun/tap 虚拟网卡并连接到 br0 网桥。
虚拟机内部的网络接口 eth0 是 qemu-kvm 软件模拟的,实际上虚拟机内网络数据的收发都会被 qemu-kvm 转换成对 /dev/net/tun 的读写。

以发送数据为例,整个流程如下:

虚拟机发出去的数据包先到达 qemu-kvm 程序

数据被用户层程序 qemu-kvm 写入到 /dev/net/tun,到达 tap 设备

tap 设备把数据传送到 br0 网桥

br0 把数据交给 eth0 发送出去

整个流程跑完,数据包都不需要经过宿主机的协议栈,效率高。

+------------------------------------------------+-----------------------------------+-----------------------------------+ | Host | VirtualMachine1 | VirtualMachine2 | | | | | | +--------------------------------------+ | +-------------------------+ | +-------------------------+ | | | Network Protocol Stack | | | Network Protocol Stack | | | Network Protocol Stack | | | +--------------------------------------+ | +-------------------------+ | +-------------------------+ | | ↑ | ↑ | ↑ | |.......................|........................|................|..................|.................|.................| | ↓ | ↓ | ↓ | | +--------+ | +-------+ | +-------+ | | | .3.101 | | | .3.102| | | .3.103| | | +------+ +--------+ +-------+ | +-------+ | +-------+ | | | eth0 |<--->| br0 |<--->|tun/tap| | | eth0 | | | eth0 | | | +------+ +--------+ +-------+ | +-------+ | +-------+ | | ↑ ↑ ↑ +--------+ ↑ | ↑ | | | | +------|qemu-kvm|-----------+ | | | | | ↓ +--------+ | | | | | +-------+ | | | | | | |tun/tap| | | | | | | +-------+ | | | | | | ↑ | +--------+ | | | | | +-------------------------------------|qemu-kvm|-------------|-----------------+ | | | | +--------+ | | | | | | | +---------|--------------------------------------+-----------------------------------+-----------------------------------+ ↓ Physical Network (192.168.3.0/24) 跨 namespace 通信场景(容器网络,NAT 模式)

由于容器运行在自己单独的 network namespace 里面,所以和虚拟机一样,它们也都有自己单独的协议栈。

容器网络的结构和虚拟机差不多,但是它改用了 NAT 网络,并把 tun/tap 换成了 veth,导致 docker0 过来的数据,要先经过宿主机协议栈,然后才进入 veth 接口。

多了一层 NAT,以及多走了一层宿主机协议栈,都会导致性能下降。

示意图如下:

+-----------------------------------------------+-----------------------------------+-----------------------------------+ | Host | Container 1 | Container 2 | | | | | | +---------------------------------------+ | +-------------------------+ | +-------------------------+ | | | Network Protocol Stack | | | Network Protocol Stack | | | Network Protocol Stack | | | +----+-------------+--------------------+ | +-----------+-------------+ | +------------+------------+ | | ^ ^ | ^ | ^ | |........|.............|........................|................|..................|.................|.................| | v v ↓ | v | v | | +----+----+ +-----+------+ | +-----+-------+ | +-----+-------+ | | | .31.101 | | 172.17.0.1 | +------+ | | 172.17.0.2 | | | 172.17.0.3 | | | +---------+ +-------------<---->+ veth | | +-------------+ | +-------------+ | | | eth0 | | docker0 | +--+---+ | | eth0(veth) | | | eth0(veth) | | | +----+----+ +-----+------+ ^ | +-----+-------+ | +-----+-------+ | | ^ ^ | | ^ | ^ | | | | +------------------------+ | | | | | v | | | | | | +--+---+ | | | | | | | veth | | | | | | | +--+---+ | | | | | | ^ | | | | | | +------------------------------------------------------------------------------+ | | | | | | | | | | | +-----------------------------------------------+-----------------------------------+-----------------------------------+ v Physical Network (192.168.31.0/24)

每创建一个新容器,都会在容器的 namespace 里新建一个 veth 接口并命令为 eth0,同时在主 namespace 创建一个 veth,将容器的 eth0 与 docker0 连接。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwxzxy.html