Linux 网络虚拟化(Docker 组网模型)

Linux 网络虚拟化(Docker 组网模型),第1张

在 Linux 中很多的资源都是全局的。比如进程有全局的进程 ID,网络也有全局的路由表。当一台 Linux 上跑多个进程的时候,如果我们要使用不同的路由策略,这些进程可能会冲突,那就需要将这个进程放在一个独立的 namespace 里面,这样就可以独立配置网络了。

Linux 中 namespace 的作用就是用来隔离内核资源,共有 6 种不同类型的 namespace:

network namespace 技术是实现网络虚拟化的重要功能,它可以创建多个隔离的网络空间,这些网络空间都有各自独立的私有的网络栈信息,包括:网卡(Network Interface)、回环设备(Loopback Device)、路由表(Routing Table)和 iptables 规则。

关于 network namespace 的增删改查功能已经集成到 Linux 工具的 netns 命令中,下面通过一个 demo 来演示一下 Linux Network Namespace 的功能。

创建了两个网络空间,默认情况下都只会有一个回环接口,处于 DOWN 状态。现在要解决一下四个问题:

仅有一个本地回环设备是无法与宿主机或外界通信的,如果想与外界通信,就需要有网卡,这里扮演网卡角色的就是 Linux 中的虚拟设备 veth pair 对。

Veth Pair 设备的特点是:它被创建出来后,总是以两张虚拟网卡(Veth Peer)的形式成对出现的。并且,从其中一个网卡发出的数据包,可以直接出现在与它对应的另一张“网卡”上,哪怕这两个“网卡”在不同的 Network Namespace 里。

当每个 veth 设备在不同的 Network Namespace 的时候,Namespace 之间就可以用这对 veth 设备来进行网络通讯了,这就使得 Veth Pair 常常被用作连接不同 Network Namespace 的“网线”。

下面通过命令创建 veth pair 对,创建成功后可以看到,他们在宿主机上就表现为两张网卡,然后分别把两端移动到两个 network namespace 中,并为虚拟网卡配置 IP。此时在两个 network namespace 中就可以互相 ping 通。

虽然现在这两块虚拟网卡可以互相通信了,但是仍然是不能连接外部网络的,并且和宿主机物理网卡也是不能通信的。要想通信有一下几种解决方式:

下面介绍第一种,这也就是容器的主机内组网模型:veth pair + bridge 的模式。

Linux Bridge 网桥是一种软件配置,用于连结两个或更多个不同网段。它的行为就像是一台虚拟的二层网络交换机,工作于透明模式(即其他机器不必关注网桥的存在与否)。任意的真实物理设备(例如 eth0)和虚拟设备(例如 veth tap0)都可以连接到网桥。

下面演示下 bridge 网桥的作用,命令用的是 bridge-utils 软件包里的 brctl 工具来管理网桥。首先创建两个 veth pair 对,并分别将各自的一段移动到 network namespace 中,另一端插入到网桥上。

当成功创建一个网桥 test-bridge 并为其配置好 IP 的时候(ip 要在同一个网段),会默认在宿主机上维护一条此网段的路由规则(直连规则,二层网络通信,ARP 广播)。可以看到任何目的地到这个网段 (192.168.1.0/24) 的请求都会经过网桥设备转发,也就是说在宿主机上可以 ping 通。

由于网络空间中的路由表没有默认网关,因此无法从 172.14 范围之外到达其他计算机。要解决这个问题,需要给网络名称空间一个默认的网关路由。

梳理下上面所形成的一个网络栈,将两个 network namespace 和 bridge 组成了一个子网,bridge 上的 IP 就是这个子网的网关 IP。network namespace 中的数据包通过 veth 设备到达 bridge,bridge 中的数据包要把数据包转发到 eth0 上,这里需要做两个网络设备接口之间的数据包转发,用到了 Linux 协议栈里的一个常用参数 ip_forward。

此时,通过一些虚拟网络设备:Veth Pair 虚拟网卡、Bridge 网桥、Routing Table 路由规则,解决了 network namespace 之间的通信,以及 network namespace 与 宿主机之间的通信。但是现在 network namespace 还无法与局域网、外部网络通信。

与外部网络通信,就需要用到 NAT 网络地址转换技术,由于网络空间的 IP 地址都是私有的,经过物理网络时是不能被识别的,这个时候就需要对出去的包做地址伪装,对回来的包再做目标地址转换。

所有从 namespace 内部发出来的包,都要做地址伪装,将源 IP 地址,转换为物理网卡的 IP 地址。如果有多个 namespace,所有的 namespace 共享一个宿主机的 IP 地址,但是在 conntrack 表中,记录下这个出去的连接。

当服务器返回结果到达宿主机时,会根据 conntrack 表中的规则,取出原来的私网 IP,通过 DNAT 将地址转换为私网 IP 地址,通过网桥 bridge 实现对 network namespace 的访问。

iptables 是最常用的一种配置工具。其在 Docker、Kubernetes、Istio 网络中应用甚广,像 Docker 容器的端口映射,Kubernetes Service 的工作模式,Istio 的流量接管等都是通过 iptables 来实现的。

1、早期的虚拟化模型被称为Type 1,或者叫本地虚拟化(native virtualization)。

2、后来出现了主机虚拟化(hosted virtualization)模式,被称为Type 2,hypervisor运行在操作系统之上,在同一平台上允许两个或更多的操作系统共存。

3、更加传统的虚拟化解决方案是平台虚拟化,或者叫做硬件虚拟化,具有两种主要的形式,完全虚拟化( full-virtualization)和半虚拟化(para-virtualization)。

4、平台虚拟化:如Citrix的Xen是一个流行的解决方案,可以同时执行Type1和Type2型hypervisor,Amazon的EC2就采用Xen来进行服务器的虚拟化。另一个重要的hypervisor是Linux Kernel Virtual Machine(KVM),同样都支持本地虚拟化和主机虚拟化模型。

5、操作系统虚拟化:操作系统虚拟化是另外一个重要的虚拟化技术,正如其名,是对操作系统本身进行虚拟化,而不是平台。在这种方式下,操作系统提供一组用户空间(User-Space)彼此隔离,而应用被限制在每个用户空间里面,就好像一个独立的主机。这种形式的虚拟化在虚拟主机环境中非常流行,让多个独立的用户可以共享一个操作系统。

6、其他Linux虚拟化技术:

CoLinux,或者叫做协作Linux,是一种利用协作虚拟机的虚拟化方式。

用户模式(User-Mode)Linux,即UML,和CoLinux有些类似,但是更加灵活。

Wine和Cygwin也是有趣的虚拟化解决方案。


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/308793.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-28
下一篇2023-04-28

发表评论

登录后才能评论

评论列表(0条)

    保存