笔记 趣谈网络协议(下)

想成为技术牛人,先搞定网络协议。

数据中心:我是开发商,自己拿地盖别墅

数据中心用到了前面学过的所有知识,数据中心里面是一堆服务器。服务器被放在一个个叫作机架(Rack)的架子上面,出入口也是漏油器,在数据中心的边界,
所以叫做边界路由器,为了高可用,边界路由器有多个,而且会连接多个运营商网络,防止一个运营商网络出问题。

交换机往往是放在机架顶端的,所以经常称为TOR(Top Of Rack)交换机。这一层的交换机常常称为接入层(Access Layer)

当一个机架放不下的时候,就需要多个机架,还需要有交换机将多个机架连接在一起。这些交换机对性能的要求更高,带宽也更大。这些交换机称为汇聚层交换机(AggregationLayer)

数据中心里面的每一个连接都是需要考虑高可用的。这里首先要考虑的是,如果一台机器只有一个网卡,上面连着一个网线,接入到TOR交换机上。如果网卡坏了,或者不小心网线掉了,机器就上不去了。
所以,需要至少两个网卡、两个网线插到TOR交换机上,但是两个网卡要工作得像一张网卡一样,这就是常说的网卡绑定(bond)

这就需要服务器和交换机都支持一种协议LACP(Link Aggregation Control Protocol)。它们互相通信,将多个网卡聚合称为一个网卡,多个网线聚合成一个网线,在网线之间可以进行负载均衡,
也可以为了高可用作准备。

TOR交换机也需要高可用,同理接入层和汇聚层的连接也需要高可用性,也不能单线连着。

最传统的方法是,部署两个接入交换机、两个汇聚交换机。服务器和两个接入交换机都连接,接入交换机和两个汇聚都连接,当然这样会形成环,所以需要启用STP协议,去除环,但是这样两个汇聚就只能一主一备了。
STP协议里我们学过,只有一条路会起作用。

交换机有一种技术叫作堆叠,所以另一种方法是,将多个交换机形成一个逻辑的交换机,服务器通过多根线分配连到多个接入层交换机上,而接入层交换机多根线分别连接到多个交换机上,并且通过堆叠的私有协议,
形成双活的连接方式。

汇聚层将大量的计算节点相互连接在一起,形成一个集群。在这个集群里面,服务器之间通过二层互通,这个区域常称为一个POD(Point Of Delivery),有时候也称为一个可用区(Available Zone)

当节点数目再多的时候,一个可用区放不下,需要将多个可用区连在一起,连接多个可用区的交换机称为核心交换机

核心交换机吞吐量更大,高可用要求更高,肯定需要堆叠,但是往往仅仅堆叠,不足以满足吞吐量,因而还是需要部署多组核心交换机。核心和汇聚交换机之间为了高可用,也是全互连模式的。

VPN:朝中有人好做官

数据中心,里面很复杂,但是有的公司有多个数据中心,需要将多个数据中心连接起来,或者需要办公室和数据中心连接起来。怎么办?
走公网不安全,租用专线成本高,使用VPN,安全有不贵。

VPN,全名Virtual Private Network,虚拟专用网,就是利用开放的公众网络,建立专用数据传输通道,将远程的分支机构、移动办公人员等连接起来。

VPN是如何工作的

VPN通过隧道技术在公众网络上仿真一条点到点的专线,是通过利用一种协议来传输另外一种协议的技术,这里面涉及三种协议:乘客协议、隧道协议承载协议

以IPsec协议为例:

IPsec VPN。这是基于IP协议的安全隧道协议,为了保证在公网上面信息的安全,因而采取了一定的机制保证安全性。

  • 机制一:私密性,防止信息泄漏给未经授权的个人,通过加密把数据从明文变成无法读懂的密文,从而确保数据的私密性。前面讲HTTPS的时候,说过加密可以分为对称加密和非对称加密。对称加密速度快一些。
    而VPN一旦建立,需要传输大量数据,因而我们采取对称加密。但是同样,对称加密还是存在加密秘钥如何传输的问题,这里需要用到因特网密钥交换(IKE,Internet Key Exchange)协议。
  • 机制二:完整性,数据没有被非法篡改,通过对数据进行hash运算,产生类似于指纹的数据摘要,以保证数据的完整性。
  • 机制三:真实性,数据确实是由特定的对端发出,通过身份认证可以保证数据的真实性。

如何保证对方就是真正的那个人呢?

  • 第一种方法就是预共享密钥,也就是双方事先商量好一个暗号,比如“天王盖地虎,宝塔镇河妖”,对上了,就说明是对的。
  • 另外一种方法就是用数字签名来验证

基于以上三个特性,组成了IPsec VPN的协议簇

  • AH(Authentication Header),只能进行数据摘要,不能实现数据加密。
  • ESP(Encapsulating Security Payload),能够进行数据加密和数据摘要。
  • IKE组件,用于VPN的双方要进行对称密钥的交换。
  • SA(Security Association)组件,用于VPN的双方对连接进行维护

IPsec VPN的建立过程

分两个阶段。

第一个阶段,建立IKE自己的SA。这个SA用来维护一个通过身份认证和安全保护的通道,为第二个阶段提供服务。通过DH(Diffie-Hellman)算法计算出一个对称密钥K。

DH算法是一个比较巧妙的算法。客户端和服务端约定两个公开的质数p和q,然后客户端随机产生一个数a作为自己的私钥,服务端随机产生一个b作为自己的私钥,客户端可以根据p、q和a计算出公钥A,服务端根据p、q和b计算出公钥B,
然后双方交换公钥A和B。

到此客户端和服务端可以根据已有的信息,各自独立算出相同的结果K,就是对称密钥。但是这个过程,对称密钥从来没有在通道上传输过,只传输了生成密钥的材料,通过这些材料,截获的人是无法算出的。

第二个阶段,建立IPsec SA。在这个SA里面,双方会生成一个随机的对称密钥M,由K加密传给对方,然后使用M进行双方接下来通信的数据。对称密钥M是有过期时间的,会过一段时间,重新生成一次,从而防止被破解。

IPsec SA里面有以下内容:

  • SPI(Security Parameter Index),用于标识不同的连接
  • 双方商量好的加密算法、哈希算法和封装模式
  • 生存周期,超过这个周期,就需要重新生成一个IPsec SA,重新生成对称密钥

当IPsec建立好,接下来就可以开始打包封装传输了。

左面是原始的IP包,在IP头里面,会指定上一层的协议为TCP。ESP要对IP包进行封装,因而IP头里面的上一层协议为ESP。在ESP的正文里面,ESP的头部有双方商讨好的SPI,以及这次传输的序列号。

接下来全部是加密的内容。可以通过对称密钥进行解密,解密后在正文的最后,指明了里面的协议是什么。如果是IP,则需要先解析IP头,然后解析TCP头,这是从隧道出来后解封装的过程。

有了IPsec VPN之后,客户端发送的明文的IP包,都会被加上ESP头和IP头,在公网上传输,由于加密,可以保证不被窃取,到了对端后,去掉ESP的头,进行解密。

这种点对点的基于IP的VPN,能满足互通的要求,但是速度往往比较慢,这是由底层IP协议的特性决定的。IP不是面向连接的,是尽力而为的协议,每个IP包自由选择路径,到每一个路由器,都自己去找下一跳,丢了就丢了,
是靠上一层TCP的重发来保证可靠性。

因为IP网络从设计的时候,就认为是不可靠的,所以即使同一个连接,也可能选择不同的道路,这样的好处是,一条道路崩溃的时候,总有其他的路可以走。当然,带来的代价就是,不断的路由查找,效率比较差。

和IP对应的另一种技术称为ATM。这种协议和IP协议的不同在于,它是面向连接的。你可以说TCP也是面向连接的啊。这两个不同,ATM和IP是一个层次的,和TCP不是一个层次的。

另外,TCP所谓的面向连接,是不停地重试来保证成功,其实下层的IP还是不面向连接的,丢了就丢了。ATM是传输之前先建立一个连接,形成一个虚拟的通路,一旦连接建立了,所有的包都按照相同的路径走,不会分头行事。

好处是不需要每次都查路由表的,虚拟路径已经建立,每个包都按相同的路径走,这样效率会高很多。但是一旦虚拟路径上的某个路由器坏了,则这个连接就断了,什么也发不过去了,因为其他的包还会按照原来的路径走,
都掉坑里了,它们不会选择其他的路径走。

多协议标签交换(MPLS,Multi-Protocol Label Switching),将两者的优点结合起来。

移动网络:去巴塞罗那,手机也上不了脸书

移动网络的发展历程

你一定知道手机上网有2G、3G、4G的说法,究竟这都是什么意思呢?有一个通俗的说法就是:用2G看txt,用3G看jpg,用4G看avi。

2G网络

在2G时代,上网使用的不是IP网络,而是电话网络,走模拟信号,专业名称为公共交换电话网(PSTN,Public Switched TelephoneNetwork)。

那手机不连网线,也不连电话线,它是怎么上网?

手机是通过收发无线信号来通信的,专业名称是Mobile Station,简称MS,需要嵌入SIM。手机是客户端,而无线信号的服务端,就是基站子系统(BSS,Base Station SubsystemBSS)。

无论无线通信如何无线,最终还是要连接到有线的网络里

基站子系统分两部分,一部分对外提供无线通信,叫作基站收发信台(BTS,Base Transceiver Station),另一部分对内连接有线网络,叫作基站控制器(BSC,Base StationController)。
基站收发信台通过无线收到数据后,转发给基站控制器。

这部分属于无线的部分,统称为无线接入网(RAN,Radio Access Network)。

基站控制器通过有线网络,连接到提供手机业务的运营商的数据中心,这部分称为核心网(CN,Core Network)。核心网还没有真的进入互联网,这部分还是主要提供手机业务,是手机业务的有线部分。

首先接待基站来的数据的是移动业务交换中心(MSC,Mobile Service Switching Center),它是进入核心网的入口,但是它不会让你直接连接到互联网上。

因为在让你的手机真正进入互联网之前,提供手机业务的运营商,需要认证是不是合法的手机接入。别你自己造了一张手机卡,就连接上来。鉴权中心(AUC,Authentication Center)和设备识别寄存器
(EIR,Equipment Identity Register)主要是负责安全性的。

另外,需要看你是本地的号,还是外地的号,这个牵扯到计费的问题,异地收费还是很贵的。访问位置寄存器(VLR,Visit Location Register)是看你目前在的地方,归属位置寄存器
(HLR,Home Location Register)是看你的号码归属地。

当你的手机卡既合法又有钱的时候,才允许你上网,这个时候需要一个网关,连接核心网和真正的互联网。网关移动交换中心(GMSC ,Gateway Mobile Switching Center)就是干这个的,然后是真正的互连网。
在2G时代,还是电话网络PSTN。

数据中心里面的这些模块统称为网络子系统(NSS,Network and Switching Subsystem)。

  • 手机通过无线信号连接基站
  • 基站一面朝前接无线,一面朝后接核心网
  • 核心网一面朝前接到基站请求,一是判断你是否合法,二是判断你是不是本地号,还有没有钱,一面通过网关连接电话网络

2.5G网络

在原来电路交换的基础上,加入了分组交换业务,支持Packet的转发,从而支持IP网络。多了一个分组控制单元(PCU,Packet Control Unit),用以提供分组交换通道。

在核心网里面,有个朝前的接待员(SGSN,Service GPRS Supported Node)和朝后连接IP网络的网关型GPRS支持节点(GGSN,Gateway GPRS Supported Node)。

3G网络

线通信技术有了改进,大大增加了无线的带宽。

以W-CDMA为例,理论最高2M的下行速度,因而基站改变了,一面朝外的是Node B,一面朝内连接核心网的是无线网络控制器(RNC,Radio Network Controller)。核心网以及连接的IP网络没有什么变化。

4G网络

基站为eNodeB,包含了原来Node B和RNC的功能,下行速度向百兆级别迈进。另外,核心网实现了控制面和数据面的分离,这个怎么理解呢?

在前面的核心网里面,有接待员MSC或者SGSN,你会发现检查是否合法是它负责,转发数据也是它负责,也即控制面和数据面是合二为一的,这样灵活性比较差,因为控制面主要是指令,多是小包,往往需要高的及时性;
数据面主要是流量,多是大包,往往需要吞吐量。

HSS用于存储用户签约信息的数据库,其实就是你这个号码归属地是哪里的,以及一些认证信息。

MME是核心控制网元,是控制面的核心,当手机通过eNodeB连上的时候,MME会根据HSS的信息,判断你是否合法。如果允许连上来,MME不负责具体的数据的流量,而是MME会选择数据面的SGW和PGW,然后告诉eNodeB,
我允许你连上来了,你连接它们吧。

于是手机直接通过eNodeB连接SGW,连上核心网,SGW相当于数据面的接待员,并通过PGW连到IP网络。PGW就是出口网关。在出口网关,有一个组件PCRF,称为策略和计费控制单元,用来控制上网策略和流量的计费。

手机上网流程

手机开机之后上网的流程,这个过程称为Attach。可以看出来,移动网络还是很复杂的。因为这个过程要建立很多的隧道,分配很多的隧道ID:

  1. 手机开机以后,在附近寻找基站eNodeB,找到后给eNodeB发送Attach Request,说“我来啦,我要上网”。
  2. eNodeB将请求发给MME,说“有个手机要上网”。
  3. MME去请求手机,一是认证,二是鉴权,还会请求HSS看看有没有钱,看看是在哪里上网。
  4. 当MME通过了手机的认证之后,开始分配隧道,先告诉SGW,说要创建一个会话(Create Session)。在这里面,会给SGW分配一个隧道ID t1,并且请求SGW给自己也分配一个隧道ID。
  5. SGW转头向PGW请求建立一个会话,为PGW的控制面分配一个隧道ID t2,也给PGW的数据面分配一个隧道ID t3,并且请求PGW给自己的控制面和数据面分配隧道ID。
  6. PGW回复SGW说“创建会话成功”,使用自己的控制面隧道ID t2,回复里面携带着给SGW控制面分配的隧道ID t4和控制面的隧道ID t5,至此SGW和PGW直接的隧道建设完成。
    双方请求对方,都要带着对方给自己分配的隧道ID,从而标志是这个手机的请求。
  7. 接下来SGW回复MME说“创建会话成功”,使用自己的隧道ID t1访问MME,回复里面有给MME分配隧道ID t6,也有SGW给eNodeB分配的隧道ID t7。
  8. 当MME发现后面的隧道都建设成功之后,就告诉eNodeB,“后面的隧道已经建设完毕,SGW给你分配的隧道ID是t7,你可以开始连上来了,但是你也要给SGW分配一个隧道ID”。
  9. eNodeB告诉MME自己给SGW分配一个隧道,ID为t8。
  10. MME将eNodeB给SGW分配的隧道ID t8告知SGW,从而前面的隧道也建设完毕。

异地上网问题

为什么要分SGW和PGW呢,一个GW不可以吗?SGW是你本地的运营商的设备,而PGW是你所属的运营商的设备。

如果你在巴塞罗那,一下飞机,手机开机,周围搜寻到的肯定是巴塞罗那的eNodeB。通过MME去查寻国内运营商的HSS,看你是否合法,是否还有钱。如果允许上网,你的手机和巴塞罗那的SGW会建立一个隧道,
然后巴塞罗那的SGW和国内运营商的PGW建立一个隧道,然后通过国内运营商的PGW上网。

这样判断你是否能上网的在国内运营商的HSS,控制你上网策略的是国内运营商的PCRF,给手机分配的IP地址也是国内运营商的PGW负责的,给手机分配的IP地址也是国内运营商里统计的。运营商由于是在PGW里面统计的,
这样你的上网流量全部通过国内运营商即可,只不过巴塞罗那运营商也要和国内运营商进行流量结算。由于你的上网策略是由国内运营商在PCRF中控制的,因而你还是上不了脸书。

云中网络:自己拿地成本高,购买公寓更灵活

数据中心里面堆着一大片一大片的机器,但是维护起来很麻烦。

从物理机到虚拟机

为了解决这些问题,人们发明了一种叫虚拟机的东西,并基于它产生了云计算技术。

我们常把物理机比喻为自己拿地盖房子,而虚拟机则相当于购买公寓,更加灵活方面,随时可买可卖。

它用的是软件模拟硬件的方式。刚才说了,数据中心里面用的qemu-kvm。从名字上来讲,emu就是Emulator(模拟器)的意思,主要会模拟CPU、内存、网络、硬盘,使得虚拟机感觉自己在使用独立的设备,
但是真正使用的时候,当然还是使用物理的设备。

简单比喻,虚拟化软件就像一个“骗子”,向上“骗”虚拟机里面的应用,让它们感觉独享资源,其实自己啥都没有,全部向下从物理机里面弄。

虚拟网卡的原理

首先,虚拟机要有一张网卡。对于qemu-kvm来说,这是通过Linux上的一种TUN/TAP技术来实现的。

虚拟机是物理机上跑着的一个软件。这个软件可以像其他应用打开文件一样,打开一个称为TUN/TAP的Char Dev(字符设备文件)。打开了这个字符设备文件之后,在物理机上就能看到一张虚拟TAP网卡。
虚拟化软件作为“骗子”,会将打开的这个文件,在虚拟机里面虚拟出一张网卡,让虚拟机里面的应用觉得它们真有一张网卡。于是,所有的网络包都往这里发。

当然,网络包会到虚拟化软件这里。它会将网络包转换成为文件流,写入字符设备,就像写一个文件一样。内核中TUN/TAP字符设备驱动会收到这个写入的文件流,交给TUN/TAP的虚拟网卡驱动。
这个驱动将文件流再次转成网络包,交给TCP/IP协议栈,最终从虚拟TAP网卡发出来,成为标准的网络包

就这样,几经转手,数据终于从虚拟机里面,发到了虚拟机外面。

虚拟网卡连接到云中

虚拟TAP网卡怎么接入庞大的数据中心网络中。

云计算中的网络需要注意的点:

  • 共享:尽管每个虚拟机都会有一个或者多个虚拟网卡,但是物理机上可能只有有限的网卡。那这么多虚拟网卡如何共享同一个出口?
  • 隔离:分两个方面,一个是安全隔离,两个虚拟机可能属于两个用户,那怎么保证一个用户的数据不被另一个用户窃听?一个是流量隔离,两个虚拟机,如果有一个疯狂下片,会不会导致另外一个上不了网?
  • 互通:分两个方面,一个是如果同一台机器上的两个虚拟机,属于同一个用户的话,这两个如何相互通信?另一个是如果不同物理机上的两个虚拟机,属于同一个用户的话,这两个如何相互通信?
  • 灵活:虚拟机和物理不同,会经常创建删除,从一个机器漂移到另一台机器,有的互通,有的不通,灵活性比物理网络要好的多,需要能够灵活配置。

共享与互通问题

首先,一台物理机上有多个虚拟网卡,这些虚拟网卡如何连在一起,进行相互访问,并且可以访问外网?

你可以想象物理机就是你的宿舍,虚拟机就是你的个人电脑,这些电脑怎么连接起来,需要一个交换机。

在物理机上,应该有一个虚拟的交换机,在Linux上有个命令brctl,可以常见虚拟网桥brctl addbr br0。创建出来之后,将虚拟网卡连接到虚拟网桥上brctl addif br0 tap0,将两个虚拟机配置相同的
子网网段,两台虚拟机就可以互相通信了。

虚拟机如何连外网呢?

这里面,host-only的网络对应的,其实就是上面两个虚拟机连到一个br0虚拟网桥上,而且不考虑访问外部的场景,只要虚拟机之间能够相互访问就可以了。

如果要访问外部,往往有两种方式。

  1. 一种方式称为桥接。如果在桌面虚拟化软件上选择桥接网络,则在你的笔记本电脑上,就会形成下面的结构。

每个虚拟机都会有虚拟网卡,在你的笔记本电脑上,会发现多了几个网卡,其实是虚拟交换机。这个虚拟交换机将虚拟机连接在一起。在桥接模式下,物理网卡也连接到这个虚拟交换机上,
物理网卡在桌面虚拟化软件上,在“界面名称”那里选定。

如果使用桥接网络,当你登录虚拟机里看IP地址的时候会发现,你的虚拟机的地址和你的笔记本电脑的,以及你旁边的同事的电脑的网段是一个网段。这是为什么呢?这其实相当于将物理机和虚拟机放在同一个网桥上,
相当于这个网桥上有三台机器,是一个网段的,全部打平了。我将图画成下面的样子你就好理解了。

在数据中心里面,采取的也是类似的技术,只不过都是Linux,在每台机器上都创建网桥br0,虚拟机的网卡都连到br0上,物理网卡也连到br0上,所有的br0都通过物理网卡出来连接到物理交换机上。

在这种方式下,不但解决了同一台机器的互通问题,也解决了跨物理机的互通问题,因为都在一个二层网络里面,彼此用相同的网段访问就可以了。但是当规模很大的时候,会存在问题。

在一个二层网络里面,最大的问题是广播。一个数据中心的物理机已经很多了,广播已经非常严重,需要通过VLAN进行划分。如果使用了虚拟机,假设一台物理机里面创建10台虚拟机,
全部在一个二层网络里面,那广播就会很严重,所以除非是你的桌面虚拟机或者数据中心规模非常小,才可以使用这种相对简单的方式。

  1. 另外一种方式称为NAT。如果在桌面虚拟化软件中使用NAT模式,在你的笔记本电脑上会出现如下的网络结构。

在这种方式下,你登录到虚拟机里面查看IP地址,会发现虚拟机的网络是虚拟机的,物理机的网络是物理机的,两个不相同。虚拟机要想访问物理机的时候,需要将地址NAT成为物理机的地址。

除此之外,它还会在你的笔记本电脑里内置一个DHCP服务器,为笔记本电脑上的虚拟机动态分配IP地址。因为虚拟机的网络自成体系,需要进行IP管理。为什么桥接方式不需要呢?
因为桥接将网络打平了,虚拟机的IP地址应该由物理网络的DHCP服务器分配。

在数据中心里面,也是使用类似的方式。这种方式更像是真的将你宿舍里面的情况,搬到一台物理机上来。

虚拟机是你的电脑,路由器和DHCP Server相当于家用路由器或者寝室长的电脑,物理网卡相当于你们宿舍的外网网口,用于访问互联网。所有电脑都通过内网网口连接到一个网桥br0上,
虚拟机要想访问互联网,需要通过br0连到路由器上,然后通过路由器将请求NAT成为物理网络的地址,转发到物理网络。

隔离问题

如果一台机器上的两个虚拟机不属于同一个用户,怎么办?brctl创建的网桥也是支持VLAN功能的,可以设置两个虚拟机的tag,这样在这个虚拟网桥上,两个虚拟机是不互通的。

但是如何跨物理机互通,并且实现VLAN的隔离?由于brctl创建的网桥上面的tag是没办法在网桥之外的范围内起作用的,于是我们需要寻找其他的方式。

有一个命令vconfig,可以基于物理网卡eth0创建带VLAN的虚拟网卡,所有从这个虚拟网卡出去的包,都带这个VLAN,如果这样,跨物理机的互通和隔离就可以通过这个网卡来实现。

云计算的关键技术是虚拟化,这里我们重点关注的是,虚拟网卡通过打开TUN/TAP字符设备的方式,将虚拟机内外连接起来

云中的网络重点关注四个方面,共享、隔离、互通、灵活。其中共享和互通有两种常用的方式,分别是桥接和NAT,隔离可以通过VLAN的方式

软件定义网络:共享基础设施的小区物业管理办法

可以这样比喻,云计算就像大家一起住公寓,要共享小区里面的基础设施,其中网络就相当于小区里面的电梯、楼道、路、大门等,大家都走,往往会常出现问题,尤其在上班高峰期,出门的人太多,对小区的物业管理
就带来了挑战。

如果物业管理人员有一套智能的控制系统,在物业监控室里就能看到小区里每个单元、每个电梯的人流情况,然后在监控室里面,只要通过远程控制的方式,拨弄一个手柄,电梯的速度就调整了,栅栏门就打开了,
某个入口就改出口了。

这就是软件定义网络(SDN)。它主要有以下三个特点。

  • 控制与转发分离:转发平面就是一个个虚拟或者物理的网络设备,就像小区里面的一条条路。控制平面就是统一的控制中心,就像小区物业的监控室。它们原来是一起的,物业管理员要从监控室出来,
    到路上去管理设备,现在是分离的,路就是走人的,控制都在监控室。
  • 控制平面与转发平面之间的开放接口:控制器向上提供接口,被应用层调用,就像总控室提供按钮,让物业管理员使用。控制器向下调用接口,来控制网络设备,就像总控室会远程控制电梯的速度。
    这里经常使用两个名词,前面这个接口称为北向接口,后面这个接口称为南向接口,上北下南嘛。
  • 逻辑上的集中控制:逻辑上集中的控制平面可以控制多个转发面设备,也就是控制整个物理网络,因而可以获得全局的网络状态视图,并根据该全局网络状态视图实现对网络的优化控制,就像物业管理员在监
    控室能够看到整个小区的情况,并根据情况优化出入方案。

OpenFlow和OpenvSwitch

一种开源的SDN实现方式。

OpenFlow是SDN控制器和网络设备之间互通的南向接口协议,OpenvSwitch用于创建软件的虚拟交换机。OpenvSwitch是支持OpenFlow协议的,当然也有一些硬件交换机也支持OpenFlow协议。
它们都可以被统一的SDN控制器管理,从而实现物理机和虚拟机的网络连通。

SDN控制器是如何通过OpenFlow协议控制网络的?

在OpenvSwitch里面,有一个流表规则,任何通过这个交换机的包,都会经过这些规则进行处理,从而接收、转发、放弃。

云中的网络安全:虽然不是土豪,也需要基本安全和保障

对于公有云上的虚拟机,建议是仅仅开放需要的端口,而将其他的端口一概关闭。这个时候,你只要通过安全措施守护好这个唯一的入口就可以了。采用的方式常常是用ACL(Access Control List,访问控制列表)来
控制IP和端口。

设置好了这些规则,只有指定的IP段能够访问指定的开放接口,就算有个有漏洞的后台进程在那里,也会被屏蔽,黑客进不来。在云平台上,这些规则的集合常称为安全组。那安全组怎么实现呢?

首先拿下MAC头看看,是不是我的。如果是,则拿下IP头来。得到目标IP之后呢,就开始进行路由判断。在路由判断之前,这个节点我们称为PREROUTING。如果发现IP是我的,包就应该是我的,就发给上面的传输层,
这个节点叫作INPUT。如果发现IP不是我的,就需要转发出去,这个节点称为FORWARD。如果是我的,上层处理完毕完毕后,一般会返回一个处理结果,这个处理结果会发出去,这个节点称为OUTPUT
无论是FORWARD还是OUTPUT,都是路由判断之后发生的,最后一个节点是POSTROUTING

整个包的处理过程还是原来的过程,只不过为什么要格外关注这五个节点呢?

因为在Linux内核中,有一个框架叫Netfilter。它可以在这些节点插入hook函数。这些函数可以截获数据包,对数据包进行干预。例如做一定的修改,然后决策是否接着交给TCP/IP协议栈处理;或者可以交回给协议栈,
那就是ACCEPT;或者过滤掉,不再传输,就是DROP;还有就是QUEUE,发送给某个用户态进程处理。

有了这个Netfilter框架就太好了,你可以在IP转发的过程中,随时干预这个过程,只要你能实现这些hook函数。

一个著名的实现,就是内核模块ip_tables。它在这五个节点上埋下函数,从而可以根据规则进行包的处理。按功能可分为四大类:连接跟踪(conntrack)、数据包的过滤(filter)、网络地址转换(nat)和数据包的
修改(mangle)。其中连接跟踪是基础功能,被其他功能所依赖。其他三个可以实现包的过滤、修改和网络地址转换。

在用户态,还有一个你肯定知道的客户端程序iptables,用命令行来干预内核的规则。内核的功能对应iptables的命令行来讲,就是表和链的概念。

iptables的表分为四种:raw–>mangle–>nat–>filter。这四个优先级依次降低,raw不常用,所以主要功能都在其他三种表里实现。每个表可以设置多个链。

filter表处理过滤功能,主要包含三个链:

  • INPUT链:过滤所有目标地址是本机的数据包
  • FORWARD链:过滤所有路过本机的数据包
  • OUTPUT链:过滤所有由本机产生的数据包

nat表主要是处理网络地址转换,可以进行Snat(改变数据包的源地址)、Dnat(改变数据包的目标地址),包含三个链:

  • PREROUTING链:可以在数据包到达防火墙时改变目标地址
  • OUTPUT链:可以改变本地产生的数据包的目标地址
  • POSTROUTING链:在数据包离开防火墙时改变数据包的源地址

mangle表主要是修改数据包,包含:

  • PREROUTING链
  • INPUT链
  • FORWARD链
  • OUTPUT链
  • POSTROUTING链

将iptables的表和链加入到上面的过程图中,就形成了下面的图和过程。

  1. 数据包进入的时候,先进mangle表的PREROUTING链。在这里可以根据需要,改变数据包头内容之后,进入nat表的PREROUTING链,在这里可以根据需要做Dnat,也就是目标地址转换。
  2. 进入路由判断,要判断是进入本地的还是转发的。
  3. 如果是进入本地的,就进入INPUT链,之后按条件过滤限制进入。
  4. 之后进入本机,再进入OUTPUT链,按条件过滤限制出去,离开本地。
  5. 如果是转发就进入FORWARD链,根据条件过滤限制转发。
  6. 之后进入POSTROUTING链,这里可以做Snat,离开网络接口。

有了iptables命令,我们就可以在云中实现一定的安全策略。例如我们可以处理前面的偷窥事件。首先我们将所有的门都关闭。

1
iptables -t filter -A INPUT -s 0.0.0.0/0.0.0.0 -d X.X.X.X -j DROP

-s表示源IP地址段,-d表示目标地址段,DROP表示丢弃,也即无论从哪里来的,要想访问我这台机器,全部拒绝,谁也黑不进来。

但是你发现坏了,ssh也进不来了,都不能远程运维了,可以打开一下。

1
iptables -I INPUT -s 0.0.0.0/0.0.0.0 -d X.X.X.X -p tcp --dport 22 -j ACCEPT

如果这台机器是提供的是web服务,80端口也应该打开,当然一旦打开,这个80端口就需要很好的防护,但是从规则角度还是要打开。

1
iptables -A INPUT -s 0.0.0.0/0.0.0.0 -d X.X.X.X -p tcp --dport 80 -j ACCEPT

这些规则都可以在虚拟机里,自己安装iptables自己配置。但是如果虚拟机数目非常多,都要配置,对于用户来讲就太麻烦了,能不能让云平台把这部分工作做掉呢?

当然可以了。在云平台上,一般允许一个或者多个虚拟机属于某个安全组,而属于不同安全组的虚拟机之间的访问以及外网访问虚拟机,都需要通过安全组进行过滤。

例如图中,我们会创建一系列的网站,都是前端在Tomcat里面,对外开放8080端口。数据库使用MySQL,开放3306端口。

为了方便运维,我们创建两个安全组,将Tomcat所在的虚拟机放在安全组A里面。在安全组A里面,允许任意IP地址0.0.0.0/0访问8080端口,但是对于ssh的22端口,仅仅允许管理员网段203.0.113.0/24访问。

我们将MySQL所在的虚拟机在安全组B里面。在安全组B里面,仅仅允许来自安全组A的机器访问3306端口,但是对于ssh的22端口,同样允许管理员网段203.0.113.0/24访问。

前面的章节我们说过,在设计云平台的时候,我们想让虚拟机之间的网络和物理网络进行隔离,但是虚拟机毕竟还是要通过物理网和外界通信的,因而需要在出物理网的时候,做一次网络地址转换,也即nat,这
个就可以用iptables来做。

我们学过,IP头里面包含源IP地址和目标IP地址,这两种IP地址都可以转换成其他地址。转换源IP地址的,我们称为Snat;转换目标IP地址的,我们称为Dnat

你有没有思考过这个问题,TCP的访问都是一去一回的,而你在你家里连接WIFI的IP地址是一个私网IP,192.168.1.x。当你通过你们家的路由器访问163网站之后,网站的返回结果如何能够到达你的笔记本电脑呢?
肯定不能通过192.168.1.x,这是个私网IP,不具有公网上的定位能力,而且用这个网段的人很多,茫茫人海,怎么能够找到你呢?

所以当你从你家里访问163网站的时候,在你路由器的出口,会做Snat的,运营商的出口也可能做Snat,将你的私网IP地址,最终转换为公网IP地址,然后163网站就可以通过这个公网IP地址返回结果,然后再nat回来,
直到到达你的笔记本电脑。

云平台里面的虚拟机也是这样子的,它只有私网IP地址,到达外网网口要做一次Snat,转换成为机房网IP,然后出数据中心的时候,再转换为公网IP。

这里有一个问题是,在外网网口上做Snat的时候,是全部转换成一个机房网IP呢,还是每个虚拟机都对应一个机房网IP,最终对应一个公网IP呢?前面也说过了,公网IP非常贵,虚拟机也很多,当然不能每个都有单独的
机房网和公网IP了,于是这种Snat是一种特殊的Snat,MASQUERADE(地址伪装)

这种方式下,所有的虚拟机共享一个机房网和公网的IP地址,所有从外网网口出去的,都转换成为这个IP地址。那又一个问题来了,都变成一个公网IP了,当163网站返回结果的时候,给谁呢,再nat成为哪个私网的IP呢?

这就是Netfilter的连接跟踪(conntrack)功能了。对于TCP协议来讲,肯定是上来先建立一个连接,可以用“源/目的IP+源/目的端口”唯一标识一条连接,这个连接会放在conntrack表里面。当时是这台机
器去请求163网站的,虽然源地址已经Snat成公网IP地址了,但是conntrack表里面还是有这个连接的记录的。当163网站返回数据的时候,会找到记录,从而找到正确的私网IP地址。

如果虚拟机做服务器呢?也就是说,如果虚拟机里面部署的就是163网站呢?

这个时候就需要给这个网站配置固定的物理网的IP地址和公网IP地址了。这时候就需要显示的配置Snat规则和Dnat规则了

当外部访问进来的时候,外网网口会通过Dnat规则将公网IP地址转换为私网IP地址,到达虚拟机,虚拟机里面是163网站,返回结果,外网网口会通过Snat规则,将私网IP地址转换为那个分配给它的固定的公网IP地址。

  • 源地址转换(Snat):iptables -t nat -A -s 私网IP -j Snat --to-source 外网IP
  • 目的地址转换(Dnat):iptables -t nat -A -PREROUTING -d 外网IP -j Dnat --to-destination 私网IP

云中的网络QoS:邻居疯狂下电影,我该怎么办?

你租房子的时候,有没有碰到这样的情况:本来合租共享WIFI,一个人狂下小电影,从而你网都上不去,是不是很懊恼?

在云平台上,也有这种现象,好在有一种流量控制的技术,可以实现QoS(Quality of Service),从而保障大多数用户的服务质量。

对于控制一台机器的网络的QoS,分两个方向,一个是入方向,一个是出方向。

其实我们能控制的只有出方向,通过Shaping,将出的流量控制成自己想要的模样。而进入的方向是无法控制的,只能通过Policy将包丢弃。

控制网络的QoS有哪些方式?

在Linux下,可以通过TC控制网络的QoS,主要就是通过队列的方式。

无类别排队规则

  1. pfifo_fast
    这是一种不把网络包分类的技术。

pfifo_fast分为三个先入先出的队列,称为三个Band。根据网络包里面TOS,看这个包到底应该进入哪个队列。TOS总共四位,每一位表示的意思不同,总共十六种类型。

通过命令行tc qdisc show dev eth0,可以输出结果priomap,也是十六个数字。在0到2之间,和TOS的十六种类型对应起来,表示不同的TOS对应的不同的队列。其中Band 0优先级最高,
发送完毕后才轮到Band 1发送,最后才是Band 2。

  1. 随机公平队列
    会建立很多的FIFO的队列,TCP Session会计算hash值,通过hash值分配到某个队列。在队列的另一端,网络包会通过轮询策略从各个队列中取出发送。这样不会有一个Session占据所有的流量。

  2. 令牌桶规则

所有的网络包排成队列进行发送,但不是到了队头就能发送,而是需要拿到令牌才能发送。令

牌根据设定的速度生成,所以即便队列很长,也是按照一定的速度进行发送的。

当没有包在队列中的时候,令牌还是以既定的速度生成,但是不是无限累积的,而是放满了桶为止。设置桶的大小为了避免下面的情况:当长时间没有网络包发送的时候,积累了大量的令牌,突然来了大量的网络包,
每个都能得到令牌,造成瞬间流量大增。

基于类别的队列规则

  1. 分层令牌桶规则(HTB,Hierarchical Token Bucket)

HTB往往是一棵树,接下来我举个具体的例子,通过TC如何构建一棵HTB树来带你理解。

使用TC可以为某个网卡eth0创建一个HTB的队列规则,需要付给它一个句柄为(1:)。

这是整棵树的根节点,接下来会有分支。例如图中有三个分支,句柄分别为(:10)、(:11)、(:12)。最后的参数default 12,表示默认发送给1:12,也即发送给第三个分支。

1
tc qdisc add dev eth0 root handle 1: htb default 12

对于这个网卡,需要规定发送的速度。一般有两个速度可以配置,一个是rate,表示一般情况下的速度;一个是ceil,表示最高情况下的速度。对于根节点来讲,这两个速度是一样的,
于是创建一个root class,速度为(rate=100kbps,ceil=100kbps)。

1
tc class add dev eth0 parent 1: classid 1:1 htb rate 100kbps ceil 100kbps

接下来要创建分支,也即创建几个子class。每个子class统一有两个速度。三个分支分别为(rate=30kbps,ceil=100kbps)、(rate=10kbps,ceil=100kbps)、(rate=60kbps,ceil=100kbps)。

1
2
3
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 30kbps ceil 100kbps
tc class add dev eth0 parent 1:1 classid 1:11 htb rate 10kbps ceil 100kbps
tc class add dev eth0 parent 1:1 classid 1:12 htb rate 60kbps ceil 100kbps

发现三个rate加起来,是整个网卡允许的最大速度。

HTB有个很好的特性,同一个root class下的子类可以相互借流量,如果不直接在队列规则下面创建一个root class,而是直接创建三个class,它们之间是不能相互借流量的。借流量的策略,
可以使得当前不使用这个分支的流量的时候,可以借给另一个分支,从而不浪费带宽,使带宽发挥最大的作用。

创建叶子队列规则,分别为fifosfq

1
2
3
tc qdisc add dev eth0 parent 1:10 handle 20: pfifo limit 5
tc qdisc add dev eth0 parent 1:11 handle 30: pfifo limit 5
tc qdisc add dev eth0 parent 1:12 handle 40: sfq perturb 10

基于这个队列规则,我们还可以通过TC设定发送规则:从1.2.3.4来的,发送给port 80的包,从第一个分支1:10走;其他从1.2.3.4发送来的包从第二个分支1:11走;其他的走默认分支。

1
2
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip src 1.2.3.4 match ip dport 80 0xffff flowid 1:10
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip src 1.2.3.4 flowid 1:11

如何控制QoS?

使用OpenvSwitch将云中的网卡连通在一起,那如何控制QoS?
OpenvSwitch支持两种:

  1. 对于进入的流量,可以设置策略Ingress policy
  2. 对于发出的流量,可以设置QoS规则Egress shaping,支持HTB

云中网络的隔离GRE、VXLAN:虽然住一个小区,也要保护隐私

云平台中的隔离问题,前面咱们用的策略一直都是VLAN,但是我们也说过这种策略的问题,VLAN只有12位,共4096个。当时设计的时候,看起来是够了,但是现在绝对不够用,怎么办呢?

扩展,在原来包的格式的基础上扩展出一个头,里面包含足够用于区分租户的ID,外层的包的格式尽量和传统的一样,依然兼容原来的格式。一旦遇到需要区分用户的地方,我们就用这个特殊的程序,
来处理这个特殊的包的格式。

这个概念很像隧道理论,之前讲的VPN协议,扩展的包头主要是用于加密的,而我们现在需要的包头是要能够区分用户的。

底层的物理网络设备组成的网络我们称为Underlay网络,而用于虚拟机和云中的这些技术组成的网络称为Overlay网络,这是一种基于物理网络的虚拟化网络实现。

GRE

GRE,全称Generic Routing Encapsulation,它是一种IP-over-IP的隧道技术。它将IP包封装在GRE包里,外面加上IP头,在隧道的一端封装数据包,并在通路上进行传输,到另外一端的时候解封装。
你可以认为Tunnel是一个虚拟的、点对点的连接。

GRE还需要有一个地方来封装和解封装GRE的包,这个地方往往是路由器或者有路由功能的Linux机器。

GRE的问题:

  • Tunnel的数量问题。GRE是一种点对点隧道,如果有三个网络,就需要在每两个网络之间建立一个隧道。如果网络数目增多,这样隧道的数目会呈指数性增长。
  • GRE不支持组播,因此一个网络中的一个虚机发出一个广播帧后,GRE会将其广播到所有与该节点有隧道连接的节点。
  • 目前还是有很多防火墙和三层网络设备无法解析GRE,因此它们无法对GRE封装包做合适地过滤和负载均衡。

VXLAN

第二种Overlay的技术称为VXLAN。和三层外面再套三层的GRE不同,VXLAN则是从二层外面就套了一个VXLAN的头,这里面包含的VXLAN ID为24位,也够用了。在VXLAN头外面还封装了UDP、IP,以及外层的MAC头。

VXLAN作为扩展性协议,也需要一个地方对VXLAN的包进行封装和解封装,实现这个功能的点称为VTEP(VXLAN Tunnel Endpoint)。

VTEP相当于虚拟机网络的管家。每台物理机上都可以有一个VTEP。每个虚拟机启动的时候,都需要向这个VTEP管家注册,每个VTEP都知道自己上面注册了多少个虚拟机。当虚拟机要跨VTEP进
行通信的时候,需要通过VTEP代理进行,由VTEP进行包的封装和解封装。

VXLAN不是点对点的,而是支持通过组播的来定位目标机器的,而非一定是这一端发出,另一端接收。

当一个VTEP启动的时候,它们都需要通过IGMP协议。加入一个组播组,就像加入一个邮件列表,或者加入一个微信群一样,所有发到这个邮件列表里面的邮件,或者发送到微信群里面的消息,
大家都能收到。而当每个物理机上的虚拟机启动之后,VTEP就知道,有一个新的VM上线了,它归我管。

如图,虚拟机1、2、3属于云中同一个用户的虚拟机,因而需要分配相同的VXLAN ID=101。在云的界面上,就可以知道它们的IP地址,于是可以在虚拟机1上ping虚拟机2。
虚拟机1发现,它不知道虚拟机2的MAC地址,因而包没办法发出去,于是要发送ARP广播。

ARP请求到达VTEP1的时候,VTEP1知道,我这里有一台虚拟机,要访问一台不归我管的虚拟机,需要知道MAC地址,可是我不知道啊,这该咋办呢?
VTEP1想,我不是加入了一个微信群么?可以在里面@all 一下,问问虚拟机2归谁管。于是VTEP1将ARP请求封装在VXLAN里面,组播出去。
当然在群里面,VTEP2和VTEP3都收到了消息,因而都会解开VXLAN包看,里面是一个ARP。
VTEP3在本地广播了半天,没人回,都说虚拟机2不归自己管。
VTEP2在本地广播,虚拟机2回了,说虚拟机2归我管,MAC地址是这个。通过这次通信,VTEP2也学到了,虚拟机1归VTEP1管,以后要找虚拟机1,去找VTEP1就可以了。

VTEP2将ARP的回复封装在VXLAN里面,这次不用组播了,直接发回给VTEP1。
VTEP1解开VXLAN的包,发现是ARP的回复,于是发给虚拟机1。通过这次通信,VTEP1也学到了,虚拟机2归VTEP2管,以后找虚拟机2,去找VTEP2就可以了。
虚拟机1的ARP得到了回复,知道了虚拟机2的MAC地址,于是就可以发送包了。

虚拟机1发给虚拟机2的包到达VTEP1,它当然记得刚才学的东西,要找虚拟机2,就去VTEP2,于是将包封装在VXLAN里面,外层加上VTEP1和VTEP2的IP地址,发送出去。
网络包到达VTEP2之后,VTEP2解开VXLAN封装,将包转发给虚拟机2。

虚拟机2回复的包,到达VTEP2的时候,它当然也记得刚才学的东西,要找虚拟机1,就去VTEP1,于是将包封装在VXLAN里面,外层加上VTEP1和VTEP2的IP地址,也发送出去。
网络包到达VTEP1之后,VTEP1解开VXLAN封装,将包转发给虚拟机1。

容器网络:来去自由的日子,不买公寓去合租

如果说虚拟机是买公寓,容器则相当于合租,有一定的隔离,但是隔离性没有那么好。

云计算解决了基础资源层的弹性伸缩,却没有解决PaaS层应用随基础资源层弹性伸缩而带来的批量、快速部署问题。于是,容器应运而生。

容器的思想就是要变成软件交付的集装箱。集装箱的特点,一是打包,二是标准。比如在把货从一个码头运到另一个码头,使用集装箱把货物打包,就可以一整箱搬上船,在整箱搬到另一个码头。如果没有
集装箱,就要先一件件搬上船码好,在一件件搬到另一个码头。

容器如何对应用打包

容器实现隔离主要用了两种技术,一种是看起来是隔离的技术,称为namespace,即每个namespace中的应用看到的是不同的IP地址、用户空间、程号等。
一种是用起来是隔离的技术,称为cgroup,也即明明整台机器有很多的CPU、内存,而一个应用只能用其中的一部分。

所谓镜像,就是将你焊好集装箱的那一刻,将集装箱的状态保存下来,然后将这一刻的状态保存成一系列文件。无论从哪里运行这个镜像,都能完整地还原当时的情况。

namespace

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

cgroup

cgroup全称control groups,是Linux内核提供的一种可以限制、隔离进程使用的资源机制。

cgroup能控制哪些资源呢?它有很多子系统:

  • CPU子系统使用调度程序为进程控制CPU的访问
  • cpuset,如果是多核心的CPU,这个子系统会为进程分配单独的CPU和内存
  • memory子系统,设置进程的内存限制以及产生内存资源报告
  • blkio子系统,设置限制每个块设备的输入输出控制
  • net_cls,这个子系统使用等级识别符(classid)标记网络数据包,可允许Linux 流量控制程序(tc)识别从具体cgroup中生成的数据包

cgroup提供了一个虚拟文件系统,作为进行分组管理和各子系统设置的用户接口。要使用cgroup,必须挂载cgroup文件系统,一般情况下都是挂载到/sys/fs/cgroup目录下。

容器网络中如何融入物理网络?

如果你使用docker run运行一个容器,你应该能看到这样一个拓扑结构。

是不是和虚拟机很像?容器里面有张网卡,容器外有张网卡,容器外的网卡连到docker0网桥,通过这个网桥,容器直接实现相互访问。如果你用brctl查看docker0网桥,你会发现它上面连着一些网卡。
其实这个网桥和用brctl创建的网桥没什么两样。

那连接容器和网桥的那个网卡和虚拟机一样吗?在虚拟机场景下,有一个虚拟化软件,通过TUN/TAP设备虚拟一个网卡给虚拟机,但是容器场景下并没有虚拟化软件,这该怎么办呢?在Linux下,
可以创建一对veth pair的网卡,从一边发送包,另一边就能收到。

一台机器内部容器的如何访问外网?
就是虚拟机里面的桥接模式和NAT模式。Docker默认使用NAT模式。NAT模式分为SNAT和DNAT,如果是容器内部访问外部,就需要通过SNAT。
在宿主机上,有这么一条iptables规则:

1
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE

所有从容器内部发出来的包,都要做地址伪装,将源IP地址,转换为物理网卡的IP地址。如果有多个容器,所有的容器共享一个外网的IP地址,但是在conntrack表中,记录下这个出去的连接。当服务器返回结果的时候,
到达物理机,会根据conntrack表中的规则,取出原来的私网IP,通过DNAT将地址转换为私网IP地址,通过网桥docker0实现对内的访问。

Docker有两种方式,一种是通过一个进程docker-proxy的方式,监听10080,转换为80端口。

1
/usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 10080 -container-ip 172.17.0.2 -container-port 80

另外一种方式是通过DNAT方式,在-A PREROUTING阶段加一个规则,将到端口10080的DNAT称为容器的私有网络。

1
-A DOCKER -p tcp -m tcp --dport 10080 -j DNAT --to-destination 172.17.0.2:80

容器网络之Flannel:每人一亩三分地

容器作为集装箱,可以保证应用在不同的环境中快速迁移,提高迭代的效率。但是如果要形成容器集团军,还需要一个集团军作战的调度平台,这就是Kubernetes。它可以灵活地将一个容器调度到任何一台机器上,并且当某个应
用扛不住的时候,只要在Kubernetes上修改容器的副本数,一个应用马上就能变八个,而且都能提供服务。

集团军作战有个重要的问题,就是通信。这里面包含两个问题,第一个是集团军的A部队如何实时地知道B部队的位置变化,第二个是两个部队之间如何相互通信。

第一个问题位置变化,往往是通过一个称为注册中心的地方统一管理的。这个是应用自己做的。当一个应用启动的时候,将自己所在环境的IP地址和端口,注册到注册中心指挥部,这样其他的应用请求它的时候,
到指挥部问一下它在哪里就好了

接下来是如何相互通信的问题。NAT这种模式,在多个主机的场景下,是存在很大问题的。在物理机A上的应用A看到的IP地址是容器A的,是172.17.0.2,在物理机B上的应用B看到的IP地址是容器B的,
不巧也是172.17.0.2,当它们都注册到注册中心的时候,注册中心就是这个图里这样子。

应用A要访问应用B,当应用A从注册中心将应用B的IP地址读出来的时候,就彻底困惑了,这不是自己访问自己吗?

怎么解决这个问题呢?一种办法是不去注册容器内的IP地址,而是注册所在物理机的IP地址,端口也要是物理机上映射的端口。但是一方面,大部分分布式框架都是容器诞生之前就有了,它们不会适配这种场景;另一方面,
让容器内的应用意识到容器外的环境,本来就是非常不好的设计。

于是业界就涌现了大量的方案,Flannel就是其中之一。