本文首发于我的公众号 「Linux云计算网络」(id: cloud_dev) ,专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可免费领取,欢迎大家关注,二维码文末可以扫。

01 从物理网络到虚拟网络

著名的「六度分隔定理」说到,世界上任何两个互不相识的人,只需要最多六个人就能够建立起联系。这个定理成立的前提就是依托于庞大的网络结构。

在虚拟化技术没出现之前,构成网络的元素都是实体的物理设备,比如交换机、路由器、网线等等,人们想要构建一个小型的局域网自己玩玩,都要买各种设备,成本高还不灵活。虚拟化技术普及之后,云计算开始大行其道,我们在自己的单机上就可以建各种虚拟机,想怎么玩就怎么玩。

本文首发于我的公众号 「Linux云计算网络」(id: cloud_dev) ,专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可免费领取,欢迎大家关注,二维码文末可以扫。

前面几篇文章介绍了 tap/tun、veth-pair,今天这篇来看看 Bridge。

Bridge 是什么

同 tap/tun、veth-pair 一样,Bridge 也是一种虚拟网络设备,所以具备虚拟网络设备的所有特性,比如可以配置 IP、MAC 等。

除此之外,Bridge 还是一个交换机,具有交换机所有的功能。

文章首发于我的公众号「Linux云计算网络」,欢迎关注,第一时间掌握技术干货!

当容器逐步向容器集群,容器云技术演进的时候,一个不得不面对的问题就是各个容器的管理问题,有些容器需要交互,有些容器需要隔离,如何保证这些操作能够顺利地进行,这个时候,很多容器管理和编排的平台就应运而生了。首先,当然是 Docker 社区自己开发的 Swarm+Machine+Compose 的集群管理套件,然后还有 Twitter 主推 Apache 的 Mesos,最有名的应该为 Google 开源的 Kubernetes。

这些平台综合了容器集群资源管理,服务发现和扩容缩融等问题,是一个集大成的解决方案,但其实这些问题本质上都离不开网络,资源在各容器之间调度需要网络,服务发现需要网络,所以,可以说网络是容器集群环境下最基础的一环。

Docker 容器网络根据容器的部署位置,可以分为单主机网络(host)和多主机网络(multi-host),本文先看 Docker host 网络。

Docker host 网络分为 none,host,joined container 和 bridge 网络。

none 网络模式下,Docker 容器拥有自己的 network namespace,但是并不为容器进行任何的网络配置,也就是说容器除了 network namespace 本身自带的 localback 网卡外什么都没有,包括网卡、IP、路由等信息。用户如何要使用 none 网络,就需要自己添加特定的网卡,并配置 IP、路由等信息,但一般不会这么干,none 网络很好地做到了隔离,一般是用来跑那些对安全性要求极高且不需要联网的应用。

比如某个容器的唯一用途是生成随机密码,就可以放到 none 网络中避免密码被窃取。

想要使 Docker 使用 none 网络,只需要在创建容器的时候附带 –network = none 即可。

host 网络,顾名思义就是 Docker 容器使用宿主机的网络,相当于和 host 共用了同一个 network namespace,Docker 容器使用 host 的网卡、IP 和路由等功能对外通信。

虽然这种模式下 Docker 没有创建独立的 network namespace,但其他 namespace 仍然是隔离的,如文件系统、进程列表等。host 网络最大的好处就是使得 Docker 容器对外通信变得简单,直接使用 host 的 IP 进行通信即可,但缺点也很明显,就是降低了隔离性,同时还会存在和其他容器对网络资源的竞争与冲突的问题。

同样要使用 host 网络,只需创建容器时附带 –network = host 即可。

joined container 网络和 host 网络不同的是,它是和其他的 container 共享一个 network namespace,一个 network namespace 可以被一个或者多个 Docker 容器共享。在这种模式下,两个容器之间可以通过 localback 回环网卡通信,增加了容器间通信的便利性。

同样可以在创建容器时,使用参数 –network = container:another_container_name 来和另外容器共享网络。

bridge 网络是最常用的网络模式,它兼顾了安全性和功能的完备性,但其与外部通信要通过 NAT 转换,在复杂的网络场景下会存在诸多不便。

bridge 网络在创建的时候通过 –network = bridge 指定,Docker daemon 会为创建的容器自动创建一个 Docker 网桥——docker0(也可以人为指定名称 –driver bridge my_net),这个 docker0 就用来联结 Docker 容器和 host 的桥梁。

然后,Docker daemon 会创建一对虚拟网卡 veth pair,一块网卡留在宿主机的 root network namespace 中,并绑定到 docker0 上,另一块放在新创建的 network namespace 中,命名为 eth0,并为其配置 IP 和路由,将其网关设为 docker0,如下,这样整个容器的 bridge 网络通信环境就建立起来了,其他容器的建立方式也是如此,最终各容器之间就通过 docker0 这个桥梁互联互通了。

下文将讨论更为复杂的 multi-host 网络。

PS:文章未经我允许,不得转载,否则后果自负。

–END–

欢迎扫👇的二维码关注我的微信公众号,后台回复「m」,可以获取往期所有技术博文推送,更多资料回复下列关键字获取。

文章首发我的公众号「Linux云计算网络」,欢迎关注,第一时间掌握技术干货!

和物理网络一样,虚拟网络要通信,必须借助一些交换设备来转发数据。因此,对于网络虚拟化来说,交换设备的虚拟化是很关键的一环。

上文「网络虚拟化」已经大致介绍了 Linux 内核为了满足网络虚拟化的要求,实现了一套虚拟交换设备——Bridge。本文重点介绍下 Bridge 的加强版——Open vSwitch(OVS),并从 Bridge 过渡到 OVS 的缘由讲起,让大家有个全面的认识。

借助 Linux Bridge 功能,同主机或跨主机的虚拟机之间能够轻松实现通信,也能够让虚拟机访问到外网,这就是我们所熟知的桥接模式,一般在装 VMware 虚拟机或者 VirtualBox 虚拟机的时候,都会提示我们要选择哪种模式,常用的两种模式是桥接和 NAT。

NAT 也很好理解,可以简单理解为当虚拟机启用了 NAT 模式之后,宿主机便通过 DHCP 为其生成可以访问外网的 IP,当 VM 访问外网的时候,就可以用该 IP 访问,其实就是宿主机为其做了地址转换。更详细的内容请自行搜索了解。

物理交换机有个重要的功能,就是虚拟局域网(VLAN),是对局域网(LAN)的软件化升级。一般,两台计算机通过一台交换机连接在一起就构成了一个 LAN。

一个 LAN 表示一个广播域,这意味着这个 LAN 中的任何节点发的数据包,其他节点都能收到,这有两个问题,一个是容易形成广播风暴,造成网络拥塞,另一个是广播包无法隔离,比如节点 B 不想接收节点 A 的包,但节点 A 强行要发,这就有点说不过去了。

解决这个问题的方案就是 VLAN,VLAN 能够对广播包进行有效隔离,它的做法是从软件上将交换机的端口虚拟出多个子端口,用 tag 来标记,相当于将交换机的端口划分多个 LAN,同一个 LAN 中的节点发出的数据包打上本 LAN 的 tag,这样,其他 LAN 中的节点就无法收到包,达到隔离的目的。

Bridge 本身是支持 VLAN 功能的,如下图所示,通过配置,Bridge 可以将一个物理网卡设备 eth0 划分成两个子设备 eth0.10,eth0.20,分别挂到 Bridge 虚拟出的两个 VLAN 上,VLAN id 分别为 VLAN 10 和 VLAN 20。同样,两个 VM 的虚拟网卡设备 vnet0 和 vnet 1 也分别挂到相应的 VLAN 上。这样配好的最终效果就是 VM1 不能和 VM2 通信了,达到了隔离。

Linux Bridge + VLAN 便可以构成一个和物理交换机具备相同功能的虚拟交换机了。对于网络虚拟化来说,Bridge 已经能够很好地充当交换设备的角色了。

但是为什么还有很多厂商都在做自己的虚拟交换机,比如比较流行的有 VMware virtual switch、Cisco Nexus 1000V,以及 Open vSwitch。究其原因,主要有以下几点(我们重点关注 OVS):

1) 方便网络管理与监控。OVS 的引入,可以方便管理员对整套云环境中的网络状态和数据流量进行监控,比如可以分析网络中流淌的数据包是来自哪个 VM、哪个 OS 及哪个用户,这些都可以借助 OVS 提供的工具来达到。

2) 加速数据包的寻路与转发。相比 Bridge 单纯的基于 MAC 地址学习的转发规则,OVS 引入流缓存的机制,可以加快数据包的转发效率。

3) 基于 SDN 控制面与数据面分离的思想。上面两点其实都跟这一点有关,OVS 控制面负责流表的学习与下发,具体的转发动作则有数据面来完成。可扩展性强。

4) 隧道协议支持。Bridge 只支持 VxLAN,OVS 支持 gre/vxlan/IPsec 等。

5) 适用于 Xen、KVM、VirtualBox、VMware 等多种 Hypervisors。

……

除此之外,OVS 还有很多高级特性,详情可以查阅官网自行了解。

下面简单看下 OVS 的整体架构,如下图所示,OVS 在 Linux 用户态和内核态都实现了相应的模块,用户态主要组件有数据库服务 ovsdb-server 和守护进程 ovs-vswitchd。内核态中实现了 datapath 模块。

其中, ovs-vswitchd 和 datapath 共同构成了 OVS 的数据面,控制面由 controller 模块来完成,controller 一般表示的是 OpenFlow 控制器,在 OVS 中,它可以借由第三方来完成,只要支持 OpenFlow 协议即可。

这里额外提一点,很多的一些产品级的虚拟交换机都是自身集成了控制器,比如 Cisco 1000V 的 Virtual Supervisor Manager(VSM),VMware 的分布式交换机中的 vCenter,而 OVS 是把这个事交由第三方去做,这么做的意义还是比较大的,可以让自己的产品很好地融入到各种解决方案中。

OpenFlow


OpenFlow 是控制面和数据面通信的一套协议,我们常常把支持 OpenFlow 协议的交换机称为 OpenFlow 交换机,控制器称为 OpenFlow 控制器,业界比较知名的 OpenFlow 控制器有 OpenDaylight、ONOS 等。

OpenFlow 是一个独立的完整的流表协议,不依赖于 OVS,OVS 只是支持 OpenFlow 协议,有了支持,就可以使用 OpenFlow 控制器来管理 OVS 中的流表。OpenFlow 不仅仅支持虚拟交换机,某些硬件交换机也支持 OpenFlow 协议。

ovs-vswitchd


ovs-vswitchd 是 OVS 的核心组件,它和内核模块 datapath 共同构成了 OVS 的数据面。它使用 OpenFlow 协议与 OpenFlow 控制器通信,使用 OVSDB 协议与 ovsdb-server 通信,使用 netlink 和 datapath 内核模块通信。

ovsdb-server


ovsdb-server 是 OVS 轻量级的数据库服务,用于整个 OVS 的配置信息,包括接口、交换内容、VLAN 等,ovs-vswitchd 根据这些配置信息工作。

OpenFlow 控制器


OpenFlow 控制器可以通过 OpenFlow 协议连接到任何支持 OpenFlow 的交换机,比如 OVS 。控制器通过向交换机下发流表规则来控制数据流向。

Kernel Datapath


datapath 内核模块和 ovs-vswitchd 是相互协作工作的,datapath 负责具体的收发包,而 ovs-vswitchd 通过 controller 下发的流表规则指导 datapath 如何转发包。

举个例子,datapath 从主机物理网卡 NIC 或者 VM 的 虚拟网卡 vNIC 收到包,如果是第一次收到包,datapath 不知道怎么处理这个包,于是将其丢给 ovs-vswitchd , ovs-vswitchd 决定该如何处理这个包之后又丢给 datapath,datapath 根据 ovs-vswitchd 的指示执行相应的动作,是丢弃还是从哪个口传出去。同时,ovs-vswitchd 会让 datapath 缓存好这个包的动作,下次再来就可以直接执行动作。

如果不是第一次收到包,就是按照之前缓存好的动作执行,这样极大地提高了数据处理的速度。

本文先对 OVS 有个初步印象,下文再详细介绍 OVS 的其他组件。

PS:文章未经我允许,不得转载,否则后果自负。

–END–

欢迎扫👇的二维码关注我的微信公众号,后台回复「m」,可以获取往期所有技术博文推送,更多资料回复下列关键字获取。

文章首发我的公众号「Linux云计算网络」,欢迎关注,第一时间掌握技术干货!

网络虚拟化相对计算、存储虚拟化来说是比较抽象的,以我们在学校书本上学的那点网络知识来理解网络虚拟化可能是不够的。

在我们的印象中,网络就是由各种网络设备(如交换机、路由器)相连组成的一个网状结构,世界上的任何两个人都可以通过网络建立起连接。

带着这样一种思路去理解网络虚拟化可能会感觉云里雾里——这样一个庞大的网络如何实现虚拟化?

其实,网络虚拟化更多关注的是数据中心网络、主机网络这样比较「细粒度」的网络,所谓细粒度,是相对来说的,是深入到某一台物理主机之上的网络结构来谈的。

如果把传统的网络看作「宏观网络」的话,那网络虚拟化关注的就是「微观网络」。网络虚拟化的目的,是要节省物理主机的网卡设备资源。从资源这个角度去理解,可能会比较好理解一点。

传统网络架构


在传统网络环境中,一台物理主机包含一个或多个网卡(NIC),要实现与其他物理主机之间的通信,需要通过自身的 NIC 连接到外部的网络设施,如交换机上,如下图所示。


传统网络(图片来源于网络,侵权必删)

这种架构下,为了对应用进行隔离,往往是将一个应用部署在一台物理设备上,这样会存在两个问题,1)是某些应用大部分情况可能处于空闲状态,2)是当应用增多的时候,只能通过增加物理设备来解决扩展性问题。不管怎么样,这种架构都会对物理资源造成极大的浪费。

虚拟化网络架构


为了解决这个问题,可以借助虚拟化技术对一台物理资源进行抽象,将一张物理网卡虚拟成多张虚拟网卡(vNIC),通过虚拟机来隔离不同的应用。

这样对于上面的问题 1),可以利用虚拟化层 Hypervisor 的调度技术,将资源从空闲的应用上调度到繁忙的应用上,达到资源的合理利用;针对问题 2),可以根据物理设备的资源使用情况进行横向扩容,除非设备资源已经用尽,否则没有必要新增设备。这种架构如下所示。


虚拟化网络(图片来源于网络,侵权必删)

其中虚拟机与虚拟机之间的通信,由虚拟交换机完成,虚拟网卡和虚拟交换机之间的链路也是虚拟的链路,整个主机内部构成了一个虚拟的网络,如果虚拟机之间涉及到三层的网络包转发,则又由另外一个角色——虚拟路由器来完成。

一般,这一整套虚拟网络的模块都可以独立出去,由第三方来完成,如其中比较出名的一个解决方案就是 Open vSwitch(OVS)。

OVS 的优势在于它基于 SDN 的设计原则,方便虚拟机集群的控制与管理,另外就是它分布式的特性,可以「透明」地实现跨主机之间的虚拟机通信,如下是跨主机启用 OVS 通信的图示。


分布式虚拟交换机(图片来源于网络,侵权必删)

总结下来,网络虚拟化主要解决的是虚拟机构成的网络通信问题,完成的是各种网络设备的虚拟化,如网卡、交换设备、路由设备等。

Linux 下网络设备虚拟化的几种形式


为了完成虚拟机在同主机和跨主机之间的通信,需要借助某种“桥梁”来完成用户态到内核态(Guest 到 Host)的数据传输,这种桥梁的角色就是由虚拟的网络设备来完成,上面介绍了一个第三方的开源方案——OVS,它其实是一个融合了各种虚拟网络设备的集大成者,是一个产品级的解决方案。

但 Linux 本身由于虚拟化技术的演进,也集成了一些虚拟网络设备的解决方案,主要有以下几种:

(1)TAP/TUN/VETH


TAP/TUN 是 Linux 内核实现的一对虚拟网络设备,TAP 工作在二层,TUN 工作在三层。Linux 内核通过 TAP/TUN 设备向绑定该设备的用户空间程序发送数据,反之,用户空间程序也可以像操作物理网络设备那样,向 TAP/TUN 设备发送数据。

基于 TAP 驱动,即可实现虚拟机 vNIC 的功能,虚拟机的每个 vNIC 都与一个 TAP 设备相连,vNIC 之于 TAP 就如同 NIC 之于 eth。

当一个 TAP 设备被创建时,在 Linux 设备文件目录下会生成一个对应的字符设备文件,用户程序可以像打开一个普通文件一样对这个文件进行读写。

比如,当对这个 TAP 文件执行 write 操作时,相当于 TAP 设备收到了数据,并请求内核接受它,内核收到数据后将根据网络配置进行后续处理,处理过程类似于普通物理网卡从外界收到数据。当用户程序执行 read 请求时,相当于向内核查询 TAP 设备是否有数据要发送,有的话则发送,从而完成 TAP 设备的数据发送。

TUN 则属于网络中三层的概念,数据收发过程和 TAP 是类似的,只不过它要指定一段 IPv4 地址或 IPv6 地址,并描述其相关的配置信息,其数据处理过程也是类似于普通物理网卡收到三层 IP 报文数据。

VETH 设备总是成对出现,一端连着内核协议栈,另一端连着另一个设备,一个设备收到内核发送的数据后,会发送到另一个设备上去,这种设备通常用于容器中两个 namespace 之间的通信。

(2)Bridge


Bridge 也是 Linux 内核实现的一个工作在二层的虚拟网络设备,但不同于 TAP/TUN 这种单端口的设备,Bridge 实现为多端口,本质上是一个虚拟交换机,具备和物理交换机类似的功能。

Bridge 可以绑定其他 Linux 网络设备作为从设备,并将这些从设备虚拟化为端口,当一个从设备被绑定到 Bridge 上时,就相当于真实网络中的交换机端口上插入了一根连有终端的网线。

如下图所示,Bridge 设备 br0 绑定了实际设备 eth0 和 虚拟设备设备 tap0/tap1,当这些从设备接收到数据时,会发送给 br0 ,br0 会根据 MAC 地址与端口的映射关系进行转发。


Bridge 与 TAP/TUN 的关系

因为 Bridge 工作在二层,所以绑定到它上面的从设备 eth0、tap0、tap1 均不需要设 IP,但是需要为 br0 设置 IP,因为对于上层路由器来说,这些设备位于同一个子网,需要一个统一的 IP 将其加入路由表中。

这里有人可能会有疑问,Bridge 不是工作在二层吗,为什么会有 IP 的说法?其实 Bridge 虽然工作在二层,但它只是 Linux 网络设备抽象的一种,能设 IP 也不足为奇。

对于实际设备 eth0 来说,本来它是有自己的 IP 的,但是绑定到 br0 之后,其 IP 就生效了,就和 br0 共享一个 IP 网段了,在设路由表的时候,就需要将 br0 设为目标网段的地址。

总结


传统网络架构到虚拟化的网络架构,可以看作是宏观网络到微观网络的过渡

TAP/TUN/VETH、Bridge 这些虚拟的网络设备是 Linux 为了实现网络虚拟化而实现的网络设备模块,很多的云开源项目的网络功能都是基于这些技术做的,比如 Neutron、Docker network 等。

OVS 是一个开源的成熟的产品级分布式虚拟交换机,基于 SDN 的思想,被大量应用在生产环境中。

PS:文章未经我允许,不得转载,否则后果自负。

–END–

欢迎扫👇的二维码关注我的微信公众号,后台回复「m」,可以获取往期所有技术博文推送,更多资料回复下列关键字获取。