本篇博客将讲述一些常见的虚拟网络及其原理,如虚拟机网络、WSL网络、Linux网络命名空间、Docker网络。
网络互联设备本质上就是能对信息进行特定处理的设备。
网卡:发送与接收帧(纠错、成帧、流控)
中继器与集线器:恢复衰减信号,使信号不失真
网桥与二层交换机:分割冲突域,二层负载均衡
路由器与三层交换机:分割广播域以及解析IP报文,三层负载均衡
这些网络设备最核心的就是网卡。
传统的网络互联设备都是物理世界真实的机器,但是本质上这些物理设备都是对数据的处理(基于芯片而非CPU),而实际上,我们完全可以在一个终端里通过一个个程序来模拟这些物理互联设备,这就是虚拟网络互联设备(就像在MC里做个电脑一样,图灵完备性与编程语言的自举)。
首先来看一下网卡,网卡拥有三种工作模式,正常情况下,一个网卡是不会将除了广播帧和自身MAC地址对应的帧以外的帧继续往上层协议继续传递的,但是开启混杂模式便可以将非自身MAC地址的帧传递到上层协议了。这样便能解决虚拟网卡在一二层的传递。物理网卡开启混杂模式接收虚拟网卡MAC地址的帧,这样简单的二层虚拟网络就建立了,但出于冲突域的考虑,也许还需要虚拟的网桥对二层的流量进行隔离。
虚拟的网络有很多,在操作系统中,比如Windows的WSL网络,或者Linux的网络命名空间,或者虚拟机的网络、Docker网络、K8S网络。接下来,将详细讲一下虚拟机的三种网络模型。虚拟机的网络共有三种模型,分别是Host-Only、NAT、桥接(此桥接和Docker的bridge模型名字一样但不是一个东西)。
所谓的桥接模式就是物理的网卡开启混杂模式,将所有路过该网卡的帧都传到上层进行处理,这是会有一个虚拟的交换机(或者网桥)在内存中,然后都会传给这个虚拟的交换机上,虚拟的交换机通过自学习将对应的帧发到对应的虚拟网卡里。在桥接模式下,虚拟网卡的IP地址往往和物理主机在同一个子网内,这样当子网内其他主机访问虚拟机的IP时,广播ARP协议便能拿到虚拟主机的MAC地址然后进行互联。在桥接模式下,虚拟网卡和物理网卡处于同一个物理网络,虚拟机和物理机的网络环境基本相同。在桥接模式下,虚拟机的IP地址可以静态分配也可以通过局域网内的DHCP服务器动态获得IP地址。
第二种模式便是NAT模式,NAT模式会给物理主机建立两个网卡,使物理机同时存在于两个网络,一个真实的物理网络,另一个便是在主机内部建立的虚拟网络,其工作模式类似私网访问因特网,因特网的主机没法访问私网的主机,私网的主机能够访问因特网(物理机网络的主机无法访问虚拟机,虚拟机能访问物理机所在的网络(通过路由表代理到物理机))。
第三种便是Host-Only,Host-Only的特点就是NAT模式没有NAT设备,这样虚拟机便不能访问物理机所在的物理网络,但是和物理机在同一个虚拟网络,所以可以和物理机进行互联。这时候物理机其实打开网卡配置会发现两个IP地址,这两个IP地址分别对应物理机在物理网络和虚拟网络的IP地址。
WSL是一个在Windows 10上能够运行原生Linux二进制可执行文件(ELF格式)的兼容层。它是由微软与Canonical公司合作开发,其目标是使纯正的Ubuntu、Debian等映像能下载和解压到用户的本地计算机,并且映像内的工具和实用工具能在此子系统上原生运行。在这里我们将通过一些命令来研究WSL的网络拓扑结构。
首先,准备一台装有WSL的windows操作系统(比如公司的主机),通过ipconfig命令我们可以看到两个网卡配置,一个是以太网网卡(真实的连接在物理网络的网卡,10.209.144.1是主机在以太局域网的IP地址,这个局域网的子网掩码是255.255.254.0,这个局域网的默认网关是10.209.144.1),另一个是WSL的虚拟网卡信息(基于本地环境搭建了一个虚拟网络,我的物理机在虚拟网络中的IP是172.29.32.1,子网掩码是255.255.240.0)
然后通过wsl命令进入wsl内,使用ifconfig命令看到,虚拟的WSL的网卡有两个,一个是回环网卡lo,指的是每台主机的127.0.0.1的本地网络网卡,另一个是eth网卡0,IP地址是172.29.33.47,子网掩码是255.255.240.0,可以看到与windows的虚拟网卡位于同一个网络。
然后回到windows操作系统,使用route PRINT可以查看windows的路由信息,可以看到整个路由的默认网关是10.209.144.1(物理以太网的网关,应该是路由器的地址,可以看到10.209.144.1是一个私有地址,如果要访问因特网IP那么将会把帧发送到路由器,路由器解析帧分析IP报文,通过路由器的动态路由表跨越一个个局域网来到目标网络完成寻址)。同时可以看到172.29.32.0-255.255.240.0的报文将会转发给172.29.32.1(这应该是虚拟交换机的IP地址)。通过这个路由表大概能分析出本地主机为啥能访问虚拟以太网和以太网以及因特网。
回到WSL,通过route -n查看路由表信息,可以发现两个路由,在127.29.30.0-255.255.240.0的报文将发给0.0.0.0,在0.0.0.0-0.0.0.0的报文将发给172.29.32.1,也就是说WSL环境下,访问因特网是通过转发给虚拟交换机然后交换机通过NAT连上外网的。但是由于WSL的IP地址不在物理以太网的网段内,物理以太网内的IP报文将会被转发到交换机路由器最终丢失,物理以太网的主机将无法直接连通虚拟的WSL。通过上述的调查,其实可以发现WSL的网络是类似于虚拟机的NAT模式。
上面讲的是windows操作系统的虚拟网络,下面谈谈Linux操作系统的网络。Linux操作系统和网络相关的feature,比较重要的就是Netfilters与Iptables以及网络命名空间。其中Netfilters工作在内核空间,对网络报文进行过滤转发以及NAT,而iptables工作于用户空间,可以修改过滤转发以及NAT相关的配置。另一个比较重要的技术便是网络命名空间,网络命名空间的特点就是每个网络命名空间拥有独立的网卡信息,独立的路由表信息等,每个网络命名空间独享一个网络栈。而这个技术的实现其实主要基于两个技术,那就是虚拟网络技术与Linux的文件系统的抽象(基于抽象编程,Linux操作系统内核并不在于文件系统是bfs还是rfs还是vfs或者ufs或者aufs,通过挂载在不同fs上使网络相关的配置文件隔离,简单讲就是ThreadLocal)。
Docker的单机网络模型便基于Linux的网络命名空间实现,Docker单机的网络模式有host、container、none、bridge。其中host模式就是使用物理机的网络命名空间;none模式不会配置网卡和IP、路由等信息;bridge模式将类似虚拟机的NAT模式;container模式则是获得和某个container相同的网络命名空间。