数据中心网络高可用技术之从交换机到交换机:MLAG, 堆叠技术

上一篇文章结束对链路聚合的讨论之后,我们发现一个问题——我们只能用多条线连接到同一个 switch 上面,这样万一这个交换机挂了,连接这个这个交换机的机器(通常是一个 Rack)就一起消失了。

MLAG 技术

MLAG(Multi-Chassis Link Aggregation) 可以提供跨设备的链路聚合功能。

思科模块化交换机

Multi-Chassis 这个词很有意思,为什么叫做 Chassis (机箱)而不叫座 Multi-Switch LAG 呢?因为这个功能不仅仅是运行在 Switch 上,还记得在理解网络的分层模型中说的吗?二层和三层设备的界限已经越来越模糊了,三层设备也可以有这个功能。

现在的网络设备都是模块化的,一个机箱上面可以根据自己的需求插不同的线卡,卡上面甚至还能装不同的模块,满足不同的需求。机箱可以认为是网络设备单元,以「机箱」来说,意思就是运行于不同网络设备之间的功能。

MLAG 是一个设备的 feature,而不是协议,所以在不同厂商的产品中,MLAG,Peer Link 等术语会有所不同。

多交换机 MLAG

对于客户端 Linux 来说,不知道对端是两个设备,在 Linux 的视角下,自己的多条线路连接的就是同一个设备。

在交换机侧,就需要跨设备完成 LACP 信息的同步,两个交换机设备之间需要协调好,A 的 3号端口 和 B 的 3号端口是同一个链路聚合组(LAG)。所以两个交换机之间需要一条线,来沟通控制面的信息。这条线就叫做 Peer Link。在 Peer Link 上如何传输控制信息,取决于不同厂商对于 MLAG 的实现。某些厂商的设备使用 ICCP (Inter-Control Center Communications Protocol) 来进行不同的机箱之间的连接。

这样,就可以完成从服务器到交换机的高可用了,服务器网卡、网线、交换机接口、交换机系统、交换机整机,任意一个地方出现问题,都有冗余路线,不会对服务造成太大影响。

数据中心广泛使用的就是 MLAG。

堆叠技术

在交换机之间的高可用,还有一种技术,就是交换机堆叠。这个功能在不同的厂商里也是不同的名字,比如华为的 istack,思科的 StackWise.

简单来说,这个功能可以让多个交换机虚拟成一个。只有一个主操作系统在运行,其他的交换机就像主交换机扩展出来的板卡一样。堆叠之后只有一个管理 IP 和 MAC 地址,只需要登录一个系统进行配置操作。

4个交换机完成堆叠之后,相当于一个交换机有了 4 倍的端口

堆叠之后逻辑上就是一个交换机,所以服务器可以直接连接到多个物理交换机,从逻辑上看,交换机侧也是同一个了。

交换机堆叠连接服务器

堆叠也能实现故障快速切换,在正常情况下也能充分利用线路的带宽,配置简单。但是和 MLAG 相比,稳定性上来说 MLAG 更高,因为堆叠交换机只有一个控制面,如果主交换机出现故障,比如堆叠失效,整个堆叠集群都会出错。MLAG 的故障域更小,交换机坏也就坏一台。这也带来很多维护便利,从升级维护上说,MLAG 可以让我们一台一台地操作交换机升级而不影响服务,堆叠就会更加麻烦一些。从部署上,MLAG 不受距离显示,堆叠的话,两个交换机距离越远,出错的概率越大。

说起来,思科还有一个 VDC 技术(Virtual Device Context), 支持把一个设备虚拟成多个。这些技术又是把一个物理设备拆成多个又是把多个合成一个的,可真有意思。

这个系列的二层技术介绍的差不多了,我们下一篇就开始聊三层技术。

Until next time!

数据中心网络高可用技术系列

  1. 数据中心网络高可用技术:序
  2. 数据中心网络高可用技术之从服务器到交换机:active-backup
  3. 数据中心网络高可用技术之从服务器到交换机:balance-tlb 和 balance-alb
  4. 数据中心网络高可用技术之从服务器到交换机:链路聚合 (balance-xor, balance-rr, broadcast)
  5. 数据中心网络高可用技术之从服务器到交换机:802.3 ad
  6. 数据中心网络高可用技术之从交换机到交换机:MLAG, 堆叠技术
  7. 数据中心网络高可用技术之从服务器到网关:VRRP
 

TCP 下载速度为什么这么慢?

最近,某团队在上线一个 AI 训练服务,运行在美国。AI 训练需要从另一个服务加载一些数据,数据因为欧洲国家的规定必须存储在欧洲,在美国的训练集群只能按需去加载欧洲的数据。

在训练的时候, 这个团队发现美国的客户端去读取欧洲的数据效率很低,美国欧洲购买的带宽是 10MiB/s,但是实际运行,数据的加载速度只有 KB 级别。导致训练时间都花在了数据加载上。AI 团队刚刚采购了昂贵的英伟达 A100 显卡,这数据加载这么慢,显卡都闲着,眼看着钱都打水漂了呀。

这个团队听说隔壁组有个新来的同事小张(就是你!)经常在一个叫卡瓦邦噶!的博客上学习网络知识,现在已经学成一个网络大神了,说不定他能解决这个问题呢!

这个团队找到小张,小张听说之后眉头一皱,觉得事情并不简单,要求这个团队在美国机房的客户端侧测试一下 TCP 的传输速率

测试方法是,使用 iperf 软件测试带宽速度(可以理解为就是模拟 TCP 传输,使用一个连接,传输一个大文件,测试传输速度),并且在客户端机器上进行抓包。传输方向是欧洲向美国传输,抓包是在欧洲(TCP 的发送端)。

不一会,AI 团队发来了抓包数据。

小张兴奋地打开了 Wireshark……

请下载如下的文件并分析网络下载达不到带宽瓶颈的原因。

如果没有头绪的话,可以打开这个提示

==计算机网络实用技术 目录==

这篇文章是计算机网络实用技术系列文章中的一篇,这个系列正在连载中,我计划用这个系列的文章来分享一些网络抓包分析的实用技术。这些文章都是总结了我的工作经历中遇到的问题,经过精心构造和编写,每个文件附带抓包文件,通过实战来学习网路分析。

如果本文对您有帮助,欢迎扫博客右侧二维码打赏支持,正是订阅者的支持,让我公开写这个系列成为可能,感谢!

没有链接的目录还没有写完,敬请期待……

  1. 序章
  2. 抓包技术以及技巧
  3. 理解网络的分层模型
  4. 数据是如何路由的
  5. 网络问题排查的思路和技巧
  6. 不可以用路由器?
  7. 网工闯了什么祸?
  8. 网络中的环路和防环技术
  9. 延迟增加了多少?
  10. TCP 延迟分析
  11. 重新认识 TCP 的握手和挥手
  12. 重新认识 TCP 的握手和挥手:答案和解析
  13. TCP 下载速度为什么这么慢?
  14. TCP 长肥管道性能分析
  15. 后记:学习网络的一点经验分享
与本博客的其他页面不同,本页面使用 署名-非商业性使用-禁止演绎 4.0 国际 协议。
 

数据中心网络高可用技术之从服务器到交换机:802.3 ad

我们距离双线双活的完美方案越来越近了。在上文的链路聚合方案中,服务器和交换机之间的多条线路可以虚拟成一条,唯一的不足是故障检测比较复杂,MII Monitoring 和 ARP Monitoring 都不够完美。有什么办法,可以在出现问题的时候,让无论是交换机还是服务器都能快速发现问题并进行切换呢?

目前的健康检查手段,MII Monitoring 太短,不足以检查到线路的问题;ARP Monitoring 太长,连对端服务器的问题也会触发。最好的检测距离就是服务器到交换机之间,这样不多也不少。

按照这个思路,可以让交换机和服务器之间实现类似 keepalive 的机制,当任意一方的任意一条线路发现对面不再存活,就不使用这条线继续发送数据,就可以做到更加准确的健康检查机制。

LACP (Link Aggregation Control Protocol) 就是这样一种协议。

IEEE 802.3ad 定义了链路聚合,但是链路聚合可以认为是一种实现而不是协议,它的兼容性很高,不同的厂商可以自己实现链路聚合功能。在上一篇文章中,我们没有使用 LACP 协议,也看到了链路聚合正常工作。802.3ad 一个是定义了链路聚合,另一个就是定义了 LACP 协议。LACP 协议做了两件事情:

  1. 健康检查,可以自动发现问题执行切换;
  2. 可以自己协商链路聚合,减少手动配置的内容;

健康检查是通过 LACP 协议参与的两端(交换机和服务器),互相发送 LACPDU,这是一个二层的数据帧,只会存在于网线的两端,不会被转发。如果能收到对方发送的 LACPDU,说明线路健康,如果连续3个 LACPDU 都没收到,就不从这条线路发送数据了。LACP 发送 LACPDU 的 rate 有两种,一种是 fast, 每 1s 发送一个,这样在线路挂的时候,需要 3 个包的时间,就是 3s 恢复。另一种是 slow,每 30s 发送一个,出现问题的时候需要 90s 时间恢复。

第二个功能更加实用。读者可能觉得,配置多一点没有什么问题呀,只要我们使用自动化来代替手动配置就可以。但是事实上,这个功能远不止节省了配置。

LACP 协议有两种模式,mode active 和 mode passive:

  • active 模式下,设备会通过线路发送 LACPDU(LACP 协议的包),不管对方有没有开启 LACP 协议;
  • passive 模式下,设备不会发送 LACPDU,除非收到了对方发过来的 LACPDU;

Active 不代表建立了链路聚合,要完成链路聚合,双方至少有一方得是 active 模式才行,如果两端都收到了对方的 LACPDU 就可以协商建立起来链路聚合。

建立链路聚合的过程,来源

这种自动协商的链路聚合第一个优点就是配置很少,要多加一根线的时候,插上线,LACP 协议就可以开始自动协商。

第二个优点就是可以阻止错误,这点非常重要。机房部署的时候,经常遇到线路接错的情况(不要惊讶,这太常见了)。

考虑下面这种情况,交换机 1 和 2 做了链路聚合,服务器网口 A 和 B 做了链路聚合,配置正确,但是机房人员在接线的时候接错了,服务器 B 口应该连接交换机端口 2,却连接了端口 5.

接错线的例子

如果是静态配置的链路聚合,交换机和服务器都不会知道线路接错的情况,服务器会通过 A 和 B 发送数据,交换机这边就会出现 MAC flapping 问题。交换机也可能通过 2 端口把应该发给这台服务器的数据发送到错误的地方去。

这是一个灾难性的问题,因为程序会表现异常而不是直接报网络错误,很难排查。可以类似我们在写程序的时候,我们喜欢程序直接出错挂掉,而不是没有错误但是逻辑有 BUG。又如,我们宁可数据库出问题,也不想数据库没问题但是数据全错了。

而如果使用 LACP 协议的话,交换机从 1 号端口和 5 号端口发送过来的 LACPDU 会有不一样的 system id,在服务器侧,就会发现对方的两个端口不属于同一个 Link Aggration Group (LAG), 于是协商失败,就无法完成链路聚合,在服务器侧就会只选择使用一条线进行发送。同理,交换机也不会认为自己的 1 号和 5 号能完成链路聚合,这时候会选择断开一条线。LACP 协商会让两端断开同一条线,所以最终这种情况是依然可以通信,但是只有一条线能工作。问题非常明确,我们直接去排查为什么带宽不正确,进而排查 LACP 链路聚合状态即可。

802.3ad 模式实验 (mode 4)

我们使用的拓扑结构如下,还是和之前的一样:

使用默认的配置很简单,还是和之前的配置一样,只不过 mode 使用 802.3ad 这个名字。

因为 LACP 协议是在 802.3ad 中定义的,所以 Linux 中的配置直接用了 802.3ad 作为 mode,意思就是完全使用 802.3ad 中定义的链路聚合,也意味着开启了 LACP 协议。

查看 ip link,和之前的静态链路聚合是一样的。

查看 bonding 信息:

可以看到默认的模式是 active. 即 Linux 总是尝试与对面进行 LACP 协商。这样的话,我们在交换机侧配置成 active 或者 passive 都是可以的。

交换机配置很简单,我们直接对这两个端口配置成一个 channel-group,模式是 active 或者 passive。

现在线路已经完成链路聚合了,我们抓包可以看到,两端都在定期发送 LACPDU,结构长这样子:

LACP 抓包

除了 LACP,还有一个协议支持自动协商链路聚合:PAgP(Port Aggregation Protocol)。这个是思科的专有协议。思科设计很多优秀的协议,很多开放网络协议就是参考了思科的协议而设计的。PAgP 在 1990s 就出现了,LACP 在 2000 才标准化。但是,像链路聚合这种事情,很多场景是运行在多个厂商的设备之间,私有协议很难普及。如今大部分几乎见不到 PAgP 了,思科设备之间运行的一般也是 LACP。

802.3ad 模式近乎完美,数据中心使用的 bonding 模式基本上都是 802.3ad 模式了。我们花了这么篇幅介绍了没有在使用的方案,好像是研究了一些没有用的东西,其实不是。后面我们在介绍 VRRP,HSRP 等更高级的内容的时候,读者会发现,原理还是 ARP,MAC 地址表这些东西,所以这个系列的内容是由简入难,对后面的内容理解是有帮助的。另外,像 MikroTik 这种基于 Linux 的路由器,其内置的链路聚合就是 Linux 的 bonding,所以配置这个路由器就是配置我们熟悉的 bonding,有时候可以灵活运用这些 bonding 模式。

到本文我们有能够自动协商的链路聚合,但是距离「完美」还差一步。我们发现,现在在服务器这儿是高可用了,但无论是链路聚合,还是 LACP 自动协商的链路聚合,都有一个限制——就是两条线必须连接到相同的交换机,这样一来交换机就成了一个单点。在没有链路聚合之前,我们的 bonding 方案 (active-backup, balance-tlb, balance-tlb) 还支持插到多个交换机上呢!需要交换机使用链路聚合的 bonding 模式 (balance-xor, balance-rr, 802.3ad) 只能接到一台交换机上。下篇文章我们来讨论如何解决交换机的单点问题。

Until next time!

参考资料:

数据中心网络高可用技术系列

  1. 数据中心网络高可用技术:序
  2. 数据中心网络高可用技术之从服务器到交换机:active-backup
  3. 数据中心网络高可用技术之从服务器到交换机:balance-tlb 和 balance-alb
  4. 数据中心网络高可用技术之从服务器到交换机:链路聚合 (balance-xor, balance-rr, broadcast)
  5. 数据中心网络高可用技术之从服务器到交换机:802.3 ad
  6. 数据中心网络高可用技术之从交换机到交换机:MLAG, 堆叠技术
  7. 数据中心网络高可用技术之从服务器到网关:VRRP
 

数据中心网络高可用技术之从服务器到交换机:链路聚合 (balance-xor, balance-rr, broadcast)

到现在我们讨论了 3 种 Linux bonding 模式:active-backup, balance-tlb, balance-alb. 这些方案都不够完美,各有利弊。那么有没有完美的方案呢?前面讨论的方案都没有需要交换机支持特殊功能,假设我们可以在交换机上做一些事情,交换机可以如何配合服务器来做到完美的双线双活?

我们重新思考一下我们的需求:

  • 我们有两条线,我们想充分利用两条线的带宽;
  • 当有一条线挂的时候,就只用另一条线,自动切换。

将这个需求转换到对交换机的要求,那具体就是:

  • 交换机将两条线路视为一条线路,即对于物理端口 1 和 2,在 MAC 地址表中,不再记录 MAC 地址 AA 对应的端口是 1 还是 2,而是记录为 虚拟1号端口,虚拟1号就是物理 1 和 2 的结合体,这样就没有 MAC flapping 的问题了。对于:
    • 发送数据,交换机对于发往 MAC 地址 AA 的 Frame,可以自由选择从 1 还是 2 来发送,但是要保证一个数据流总是发送到一条线路,来尽量保证顺序。对于广播数据,也只需要广播给两个端口中的一个即可;
    • 接收数据,无论从物理端口 1 还是 2 收到的数据,都视为从虚拟端口 1 收到的数据,如果修改 MAC 地址表,就将学习到的 Src MAC 地址记录为虚拟端口 1。如果从 1 或 2 收到广播数据,不需要再发给物理端口 1 或 2。
  • 当其中一条线路 down 的时候,只从另一条好的线路发送数据

实际上,交换机完全能做到这种事情,这个功能叫做链路聚合。简单,就是将两条线虚拟成一条线。

这里说个题外话,链路聚合技术,英文名字叫 Link Aggregation. 但是它还有很多其他的很多名字:

  • Ethernet bonding
  • Ethernet teaming
  • Link bonding
  • Link bundling
  • Link teaming
  • Network interface controller (NIC) bonding
  • NIC teaming
  • Port aggregation
  • Port channeling
  • Port trunking
  • Eth-Trunk
  • EtherChannel

不要被这些吓人的名字唬住了,其实说的都是上文链路聚合这点简单的东西……

其中,Trunking 一般是说交换机之间连接模式,用来让不同的交换机上的相同 Vlan 能够互通。不同厂商的设备都有自己的一套命名逻辑,这些名字要结合语境来理解,知道它们说的是什么。

为什么要起这么多有迷惑性的名字呢?简单来说就是为了卖设备。像笔者写的这么直白,怎么忽悠客户购买上万元的设备呢?EtherChannel,听着多牛逼。但是你 Cisco 起名叫 EtherChannel,我华为也叫这个名字未免就显得我抄了你的,我就叫个 Eth-Trunk,还用上个缩写,显得更牛逼。实际都是差不多的东西,咱可不能被忽悠瘸了。

公开的网络协议方面,命名是很统一的,但是涉及技术实现,就有很多高大上的名词和缩写了。

回到我们高可用的话题上,链路聚合具体做的事情就是将多个物理线路组合成一个逻辑线路,对于交换机系统,就如同只有一条带宽更高的线一样——虚拟线路的带宽是所有物理线路的总带宽。当某条线路挂掉,发送的流量可以自动切换到其他线路上。

链路聚合应用很广。我们的公司附近最近新盖了一个办公大楼,要部署网线,像这种工程,挖路布线,成本都在人工上,埋一根线和十根线成本差别不大。假设 5 年之后网络大发展,带宽不够用了,再挖开路面重新施工,成本就得再来一次。那就不如一开始埋上十根线,之后可以通过链路聚合来获得更多的带宽。

布线施工现场

有了这个技术,交换机能替我们办点事,服务器这边的事就好办多了。利用这个功能,我们再来看服务器这边如何做到高可用。

Balance-xor (mode 2)

链路聚合可以把多条线路「捆绑」在一起,对于同一个 flow,需要保持使用同一条线路来发送,如何选择线路呢?

链路聚合并没有规定线路选择算法(或者叫路由算法,负载均衡算法),原因是:

  • 没有必要,即使运行链路聚合的服务器和交换机使用不同的算法,在数据的两个方向上都不会有问题;
  • 如果要标准化,会花费很多精力去对这些算法标准化,来统一不同的厂商;
  • 具体使用什么算法最好,通常取决于拓扑结构和流量特征;
  • 不标准化算法可以留给厂商优化的空间(比如一些高端交换机支持动态负载均衡,根据线路使用率来调整);

所以:

  • 链路聚合中的负载均衡算法并不作标准化,只对算法提需求;
  • 需求就是对于同一个 flow 要始终选择同一个路线;
  • 对于流量的接收,需要兼容所有算法。即作为链路聚合的接收端无论发送端使用什么样的算法来发送,都能正确处理收到的包,无论从哪一条物理线路收到流量,都如同在虚拟线路上收到一样
不同的链路聚合算法可以一起工作

所以,发送端可以自己选择负载均衡算法。聚在均衡算法本质上就是根据包的 header 计算 hash,然后根据 hash 来决定走哪一条线。常用的 header 有:

  • Source MAC Address (SA)
  • Destination MAC Address (DA)
  • Layer 3 (IP)
  • Layer4 (Port)

balance-xor 模式就是在链路聚合的模式下,使用一种负载均衡算法来选路。默认的算法是:(src mac address XOR dest mac address XOR packet type ID) modulo slave account.

也支持使用 xmit_hash_policy 来选择其他算法。xmit_hash_policy 支持的算法有:

  • layer2
  • layer2+3
  • layer3+4
  • encap2+3
  • encap3+4

配置实验

我们还是使用前面一直在用的拓扑图做实验。

实验拓扑图

在 ubuntu-5 上,用如下的命令配置好 bonding:

查看 ip link ,发现这下 bond0 和两个 slave eth0, eth1 都是一样的 MAC 地址了:

在交换机上面将 Eth0/0 和 Eth0/1 配置成 Etherchannel 之后,再查看 MAC 地址表:

会发现 0a:56:27:5a:c9:13 这个 MAC 地址对应的既不是 Eth0/0 也不是 Eth0/1,而是 Port Channel 的虚拟接口 Po22

执行一个 ping 命令,我们甚至可以看到 ping request 从 eth1 发出去,reply 从 eth0 收到的奇观。这是因为 Linux 和交换机使用了不同的负载均衡算法。这也是没问题的,只要 request 始终走一张卡,reply 始终走另一张卡,就可以看作是 flow 没有乱序。

ping 的 request 和 response 分别使用了一张网卡

由于发送出去的选路是 Linux 和交换机双方自由决定的,所以故障切换就有一些难度。难点是双发各自不知道对方的状态。之前我们在 Linux 这边就可以完成切换,因为我们什么都不需要交换机来做。现在不行了,假设我们这边网卡挂了,交换机不知道,交换机还是会往这张卡发送,这些包就被丢弃了。

为了解决这个问题,在 Linux 侧,我们应该使用 ARP monitoring 而不是 MII monitoring,这样就可以检测整个链路的状态。在交换机侧也需要配置类似的检测切换机制。

还真是麻烦呢,先不说这些配置有多复杂,光是「是否应该切换」这个问题也无法检测准确,ARP monitoring 可能由于目标 IP 的问题导致误切换。

看来,我们距离完美方案还有一步之遥,下一期我们讨论更加智能的链路聚合。在开启下一期之前,我们再来讨论两个「神奇」的 bonding 模式。

Balance-rr (mode 0)

balance-rr 中 rr 的意思是 round robin,意思是轮询使用所有的 interface 来发送包。我把这个模式配置好,ping 一下,读者就了然了。

ping 发现,request 轮流被两张卡发送

右边上下两个面板分别是两张网卡的 tcpdump. ping 的 reply 可以忽略,因为这是交换机决定的走哪条线。我们专注看 request。这个 request 可就有意思了,它一会从 eth0 发出去,一会从 eth1 发出去,而且是准确的一个包换一次。

这就是 balance-rrbalance-rr 是唯一一个对于同一个 flow 可以使用所有网卡的 bonding 模式。什么意思呢?假设服务器有两张 10G 网卡,做好 bonding,非 balance-rr 的情况下,由于同一个 flow (同一个 TCP 连接)会走同一张卡,一个 TCP 连接最大速率是 10G,假设建立很多 TCP 连接,也许可以用上 20G 的速率。而 balance-rr 可以让同一个 TCP 连接能够用上 20G 的速率。实际上这样会造成乱序,所以 TCP 的例子不是很恰当,派上用场的场景很有限,对于某些基于 UDP 的不关心 flow 顺序的协议可能会有用。

Broadcast (mode 3)

这个就更有意思了,顾名思义,这个模式就是把要发送的包复制到所有的 interface 发送。

broadcast 模式通过两个网卡传送一样的包

这个模式有什么用处呢?也许可以用于流量复制。

在这个模式下光有交换机的链路聚合还不行,因为包从 Linux 这里就复制 2 次了,所以如上图,每一个 ping request 都发出去 2 次,收到 2 个 reply。特殊的拓扑结构才会用到这种模式。

这篇就写到这里,写了这么久,我们的一个包还没找到从服务器传到交换机的「万无一失」的方案呢。别急,希望读者还觉得有趣,我们距离完美方案已经很近了。Until next time!

参考资料:

数据中心网络高可用技术系列

  1. 数据中心网络高可用技术:序
  2. 数据中心网络高可用技术之从服务器到交换机:active-backup
  3. 数据中心网络高可用技术之从服务器到交换机:balance-tlb 和 balance-alb
  4. 数据中心网络高可用技术之从服务器到交换机:链路聚合 (balance-xor, balance-rr, broadcast)
  5. 数据中心网络高可用技术之从服务器到交换机:802.3 ad
  6. 数据中心网络高可用技术之从交换机到交换机:MLAG, 堆叠技术
  7. 数据中心网络高可用技术之从服务器到网关:VRRP
 

数据中心网络高可用技术之从服务器到交换机:balance-tlb 和 balance-alb

在上一篇文章中我们讨论了 active-backup 的模式,能够在一张线路出现故障的时候快速切换,配置也比较简单。但是这种方式有一个很大的缺点——就是明明我有两张卡,但是一次只能使用一张,只有在这张卡挂了的时候才使用另一张。

这样很浪费,我们花了两张卡的钱,希望能用两张卡。我们想要的是两张卡都在工作,当其中一张卡挂了的时候,退回到使用一张卡。

在高可用的设计中,双活优于主备,主备意味着浪费

这篇文章我们来讨论如何能让两张卡都工作。

Balance-tlb (Adaptive transmit load balancing, mode 5)

我们还是通过流量的入和出两个方向分开讨论。

假设想要两张卡都使用,对于出方向的流量,前文提到过 MAC flapping 问题:如果同一个 MAC 一会从端口 1 发出去流量,一会从端口 2 发出流量,交换机通过收到的包学习 MAC 地址会感到困惑。所以,如果两个 interface 都往外发送数据的话,不能使用相同的 MAC 地址

这样,问题就解决了:对于发出去的流量,我们可以用两个 interface 来发,两个 interface 使用不同的 MAC 地址,对于交换机来说,就像是两个不同的主机。

对于接收流量,我们还是只能用一个 interface 来接收。这一点怎么做到呢?还记得别人是怎么发送流量给我们的吗?需要先发送 ARP 通过 IP 获得 IP 对应的 MAC 地址,然后才能将这个 MAC 封装为二层帧的目标来发送。所以,在回应 ARP 请求的时候,我们总是使用其中一个 interface 的 MAC 地址来回复。

balance-tlb 模式:两张卡发送,一张卡接收

如此,我们就实现了 Transmit Load Balancing (balance-tlb):

  • 对于发出去的流量,我们使用两个 interface。但是我们需要某种 hash 的机制,保证同一个 TCP 流总是走同一个 interface,不然就可能带来 reorder 问题,影响性能;(实际上,balance-tlb 模式不是简单的 hash,而是会根据两张卡的负载动态调整使用哪张卡来发)
  • 对于接收流量,由于其他的客户端只知道 IP 对应一个网卡的 MAC 地址,所以入流量总是会走到其中一个 interface 上;
  • 在交换机看来,有一个主机的 MAC 地址只会发出去包,但是从来没有其他人发给这个 MAC,像是一个孤独的可怜人。

虽然这样只是发出去的流量可以充分用两张卡,还是没有完全利用上手里的两张卡,但是已经比较好了。因为对于面向客户的武服务器来说,进入服务器的流量很少(请求一般都比较小),从服务器出去的流量比较多(响应一般很大),像短视频服务器,流媒体,HTTP 服务器等,尤其如此。所以这种方案是可以解决一定的问题的。

Failover 流程

现在我们有两个 interface 在工作,接收流量的叫做主,不接受流量只发送的叫做备。

假设备挂了,那么很简单,接收端不受影响。发送端只要切换到只用主来发就可以了。

假设主卦了,那么发送端要切换到只使用备来发,并且接收端的流量也要切换到备上面。

接收端的流量如何切换呢?我们现在有两个 MAC 地址,切换接收端流量,就要让发送流量的地方来切换。一个很直观的解决思路是切换 ARP。即,让其他的发送者知道,现在应该发送给另一个 MAC 地址了。但是 ARP 太慢了,在 ARP 更新到发送者那里之前,流量都会因为发送到了挂掉的 MAC 地址而被丢弃掉。

那么有没有更快的切换方式呢?发送者的流量是发送给交换机,交换机再发送给我们的。所以一个更好的解决办法是让交换机来切换,交换机原来通过端口1发给我们,现在通过端口2发送我们。如果要实现快速切换,就要求不涉及去通知发送者,发送者还是使用原来的 MAC 地址进行发送。客户端的目标 MAC 地址不能变,但是交换机转发的端口改变,这不就和我们在 数据中心网络高可用技术之从服务器到交换机:active-backup 中讨论的 Gratuitous ARP 一样吗?不过这里需要额外做的事情是,我们的主 MAC 地址所在的 interface 已经挂了,这个 MAC 地址原来在 interface A 上,现在要转移到 interface B 上,需要交换两个 interface 的 MAC 地址。(所以,balance-tlb 模式需要硬件支持改写 MAC 地址才行。)

总结一下这个切换过程,我们要保持主 MAC 地址总是可用来做到不影响 ARP 缓存,快速切换,那么就要:

  1. 交换主和备的 MAC 地址,这样主 MAC 地址迁移到了备上,继续存活;
  2. 通过备 interface (现在的主)发送一个 GARP,让交换机来更新 Mac address table,对于目标 MAC 原先发送给端口1,现在发送给端口2.

演示

我们使用如下的拓扑图来演示,在 ubuntu-5 上面开启 balance-tlb bonding 模式,其他的 ubuntu 作为普通的客户端。

实验拓扑图

在 ubuntu5 上配置 bonding 的命令如下:

查看网卡的信息,可以看到 bond0 interface 的 MAC 地址是和其中的一个 slave eth0 一样,这个 MAC 地址是不能挂的。eth0 这个 interface 也是当前主要的 interface,它会接收 inbond 流量。

如果其他客户端查询 192.168.1.10 对应的 MAC 地址,也是拿到的这个主 MAC 地址 1a:50:9c:11:58:a3,不会知道另一个 MAC 地址。

我们在 ping 的同时,手动 down 掉 eth0. 会看到 1a:50:9c:11:58:a3 这个地址迁移到了 eth1 上来。

与此同时,ping 也没有失败。

这个方案可以在发送方向使用两张卡,也能做快速的自动切换。有没有办法能够在接收方向也能用上两张卡呢?

Balance-alb 模式 (adaptive load balancing, mode 6)

要想让收到的流量也负载均衡,就涉及到发送者了。因为我们作为流量的接收方,有两个 MAC 地址,对于让流量发送到哪一个 interface 来说无能为力。

发送者是怎么决定发给哪一个 MAC 的呢?又回到了 ARP。

那么我们现在有两个 interface,分别有两个 MAC 地址,我们希望这两张 interface 各收到 50% 的流量,可以该怎么做呢?对于两个 MAC 地址,可以让 50% 的发送者发给 MAC AA,另外的 50% 的发送者发送给 MAC BB。具体来说,就是在响应 ARP 的时候,我们有时对别人说,这个 IP 对应的 MAC 地址是 AA,有时说此 IP 对应的是 BB。这样就可以对流量做到一定程度的负载均衡。这种方法叫做 ARP negotiation。

ARP negotiation: 回复不同的 MAC 地址来让发送端进行负载均衡

是不是有点像使用 DNS 做负载均衡

这里面有几个技术难点。

首先,我们在回答 ARP 问题的时候,对于相同的 Client,要给出相同的答案。不能让人家一会发送到 MAC AA,一会又发送到 MAC BB,这样可能造成 TCP 乱序影响性能,对于负载均衡也不好,无法保证两个 interface 收到的流量是均衡的。这个问题的解决方法就是追踪我们回复给不同的客户端什么 MAC 地址,后续对于此客户端都回复一样的 MAC 地址。

第二个问题更难。主机得到 IP 和 MAC 之间的对应关系,不光是靠发出去 ARP 问题来询问,还会从收到的 ARP 问题中学习。当一个主机 Z 收到 ARP 问题:「谁有 xx 的地址,如果有的话,请告诉 192.168.1.10192.168.1.10 的 MAC 地址是 YY。」不管这个主机 Z 有没有 xx 的地址,它都会从这个问题中学习到:192.168.1.10 对应的 MAC 地址是 YY,并且缓存在自己的 ARP 缓存中。

这样做可以减少很多 ARP 查询,假设主机要发送给 192.168.1.10 内容,或者要发送 ARP reply 的时候,就不必再通过 ARP 协议来询问 192.168.1.10 的 MAC 地址了,可以直接根据自己的 ARP 缓存进行发送。

但是这对我们的 balance-alb 来说很糟糕,我们好不容易骗一半的客户端认为我们的 MAC 地址是 AA,一半认为是 BB,一旦我们要询问 ARP,好了,所有的人都知道我们的 MAC 地址是 AA(或者 BB)了,接收的流量又全部去了一条线路上。

ARP 问题刷新了所有的客户端 ARP 缓存

有什么方法能让我们在询问 ARP 的时候,不要让别人学习到同一个 MAC 地址呢?既然我们已经追踪了之前回复给所有客户端的 MAC 地址,能否在发送 ARP 问题的时候,对于一半的客户端使用 AA 来询问,另一半使用 BB 来询问?

这是不可行的,因为我们询问 ARP 的时候,不是发送 N 个请求出去询问 N 个客户端,而是发送一个广播包给交换机,交换机帮助我们广播给 N 个客户端。所以对于一个 ARP 问题,我们发出去的只有一个包而已,无法对于不同的客户端区别对待。

这样看来 ARP 问题刷新所有人的缓存是无法避免的了。我们能做的,只有是在刷新这些缓存之后,重新修正部分客户端的 ARP 缓存。即,我们在我们的 ARP 问题收到回复之后,再对所有人发送一个 Gratuitous ARP,使用自己不同的 MAC 地址告知这些客户端。

发送 GARP 重新对客户端分流

之前我们学到的 Gratuitous ARP 发送的是(不求答案的)问题,为的是更新交换机的 MAC – 端口对应关系。而在这里,我们需要更新的是客户端的 IP-MAC 地址对应关系,所以我们要发送的是(没有人问的) ARP reply。Gratuitous ARP 不仅可以是问题,也可以是 reply。当其他主机收到这个 ARP reply 的时候,会有些奇怪,但是他们也会更新自己的 ARP 缓存「我没有问你呀,为什么要告诉我你的 IP 对应的 MAC 是 xx,算了,我先记下吧。」

实验

还是上面的拓扑图,配置命令也几乎一样。唯有 mode 现在改成了 balance-alb

配置好之后,我们在 ubuntu-5 上面查看 link,结果和之前也是一样的。

但是我们去另外的两台机器分别查看 ARP 记录,有趣的就来了,不同的机器显示相同的 IP 有不同的 MAC 地址:

然后我们在 ubuntu-5 尝试发出去一个 ping 包,并且在这两台机器抓包,(只抓 in 方向的包,看看其他的客户端都会收到哪些 ARP 内容)。

可以看到,所有人都收到了一开始的 ARP 广播问题,随后又收到了一个自作多情的 ARP reply,但是 reply 中 IP 对应的 MAC 地址也是不同的。

但是,理论上发送一个包就够了,我在实验的时候,每次都会收到正好2个 GARP 的包,不知道为什么,在网络上提问也没人回答,看代码也没看懂。有知情的读者欢迎赐教。

Failover 过程

Failover 的过程和 balance-tlb 基本上一样,但是现在,无论是哪一个卡挂了,我们必须要更新所有人的 ARP 缓存,不能只让交换机换端口了。

Failover 流程如下:

  • 如果挂的是主,交换两张卡的 MAC 地址,如果是备,不需要;
  • 发送 GARP 给所有人(Unicast),告诉所有人自己的 IP 对应的 MAC(当然是没挂的那一个)。

将 link set down 并且在其他机器上抓包,就会看到有多个 GARP 包发过来。

总结和分析

到现在我们讨论了三种 bonding 模式:

  • active-backup:实现简单,快速切换,只能用单卡;
  • balance-tlb:实现简单,快速切换,发送能用双卡,需要硬件支持 MAC 地址修改;
  • balance-alb:实现简单,切换较慢,涉及 GARP 去刷新所有的客户端缓存,收发双卡,需要硬件支持 MAC 地址修改。

博客中讨论的这三种方案都是用了两张卡来讨论的,实际上这三种方案都可以加更多的卡,工作原理完全一样。(仔细想想看!)

实际上,这些都有缺点,都不是数据中心在用的方案,但是我们离「完美」的方案越来越近了,希望读者觉得这篇讨论的内容有趣,until next time!

参考资料:

数据中心网络高可用技术系列

  1. 数据中心网络高可用技术:序
  2. 数据中心网络高可用技术之从服务器到交换机:active-backup
  3. 数据中心网络高可用技术之从服务器到交换机:balance-tlb 和 balance-alb
  4. 数据中心网络高可用技术之从服务器到交换机:链路聚合 (balance-xor, balance-rr, broadcast)
  5. 数据中心网络高可用技术之从服务器到交换机:802.3 ad
  6. 数据中心网络高可用技术之从交换机到交换机:MLAG, 堆叠技术
  7. 数据中心网络高可用技术之从服务器到网关:VRRP