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

数据中心里面是一个个的机架(Rack),机架里面放着服务器,怎么把这些服务器连接起来呢?如果是 ToR (Top of Rack)的架构,就是在每一个机架上放一个机架交换机,这个机架的所有机器都连接顶部的交换机,然后再用聚合交换机把机架顶部的交换机连接起来。

ToR Switch, 来源

服务器和交换机是怎么连接的呢?最简单的方式是,服务器上有一个网卡,用网线把服务器和交换机连接起来。但这样做的话,我们就有了很多「单点」:网卡,网线,和交换机。高可用设计的目标就是排除掉单点,方法是添加冗余。

网卡通过 PCI 或者 PCIe 接口插在主板上,可以插多个网卡。有的网卡能够提供多个 Ethernet 接口或者多个光口

于是我们在服务器上再插上一根网卡,然后我们再用一根线连接服务器和交换机。

服务器上面有两个网卡,使用两条线连接到交换机的两个端口

现在在服务器上,我们就有了两个物理卡,对应地,我们在操作系统上可以看到两个 interface。

我们怎么配置这两个网卡呢?

首先,假设我们给两个 interface 分别配置一个 IP 地址,这样的话,在交换机和其他设备看来,这个服务器其实是两个机器,因为它是两个不同的 IP,已经失去了高可用的意义了。因为软件是需要基于 IP 来部署和交互的,拿 Etcd 来讲,假设我们部署 Etcd 在这个机器上,它就只能 listen 其中的一个 IP。如果部署两个实例分别 listen 一个 IP,那在其他实例看起来,好像是有两个不同的实例,但其实是部署在一个物理机上,这样,反而降低了可用性。因为物理机一挂就会导致两个 Etcd 实例一起失败。综上,我们要让服务器对外看起来还是一个 IP 才行。

我们在考虑:假设给这两个网卡配置成一样的 MAC 地址行不行?这样,对外看起来只有一个 IP 和一个 MAC 地址,发送数据的时候可以用两条线,接收数据的时候,无论哪一条线收到都可以。看起来完美,但是忽略了一个重要的角色——交换机。

还记得交换机是怎么工作的吗?它从每一个收到的包学习 MAC 地址。两条线接到交换机上,对于交换机来说,这就是两个客户端。假设这两个网卡(客户端)的 MAC 地址一样,都是 MAC AA,那么当网卡 A 从交换机端口 1 发送数据出去的时候,交换机学习到:「MAC AA 对应端口1,发往 MAC AA 的数据都转发给端口 1」;但是当网卡 B 从端口 2 发送出去的时候,来源 MAC 地址也是 AA,交换机就学习到:「OK,现在 MAC AA 是在端口 2 了,让我修改我的 MAC 地址表,之后如果发给 MAC AA 我就往端口 B转发就好了」。过了一会,交换机的端口 1 又收到了 MAC AA 发来的数据,交换机迷惑了——「怎么这个 MAC AA 一会插在端口 1 上,一会插在端口 2 上,切换如此频繁,到底是谁的手速这么快?」。

这就是 MAC flapping 问题,指的就是同一个 MAC 地址在不同的交换机端口之间来回切换。

它的坏处有几个:

  1. 显而易见它会给交换机带来困扰,交换机来回修改 MAC 地址表,性能会下降;
  2. 对目标地址为 MAC AA 的,交换机会时而发给端口 1,时而发给端口 2,可能会造成同一个 TCP 连接的乱序问题,从而造成性能下降。

综上,我们不能对两个网卡使用相同的 MAC 地址。

但是我们可以把两张卡配置成一样的 MAC 地址,却不同时使用呀。

最简单的方案是:我们总是使用一张物理卡,当这个网卡不可用的时候,我们转而无缝切换到另一张网卡。这就是 Linux bonding 的 active-backup 模式。

配置 bonding active-backup 模式(mode 1)

从命令行配置 bonding 模式非常直观,大体的步骤是,把要配置的网卡先 down 掉,然后创建一个 bond 模式的 interface,将物理网卡设置为 bond 的 slave,最后把 bond 设置为 up,完事。(不需要手动设置物理网卡为 up,会自动 up。)

命令如下:

其中,ip link add bond0 type bond mode active-backup 命令又可以写成 ip link add bond0 type bond mode 0。每一个 bond mode 都有一个编号。(我们在接下来的文章中会循序渐进地介绍这些 mode)。

实验用的拓扑图

在这个拓扑图中,我们对 ubuntu-5 机器配置好了 bonding。使用 prof fs 的接口可以查看当前 bonding 的配置:

可见当前的 slave 是 eth0

Failover 过程

我们已经配置好了 active-backup 模式,希望在主接口 down 之后,自动切换到 backup 接口。

但是现在的配置下,是不能自动切换的,因为 bond 不知道应该何时切换。高可用的部署中,我们加了冗余之后,还需要思考两个问题:

  1. 什么时候会触发切换;
  2. 以及如何切换。

Failover 触发

Failover 触发方案的本质是监控——要监控两条线路的状态,在一条线路 down 的时候,执行切换动作。主要的监控方式有两种:MII Monitoring 和 ARP Monitoring。

MII Monitoring

MII 的全称是 Media-independent interface,是 MAC 硬件层和传输媒介 PHY 硬件之间的接口。

MII 在 PHY 和 MAC 之间,来源

它是干什么的呢?还记得理解网络的分层模型中我们提到的「沙漏模型」吗?假设没有 MII,网卡中的 MAC 硬件直接连接物理媒介,那么每出现一种新的物理媒介,比如千兆以太网,万兆以太网,各种光纤,都要去适配所有的 MAC 硬件,是 M x N 的工作量。如果有 MII,MAC 硬件对接 MII,然后每出现一种新的媒介,只需要开发一次新的 MII 接口即可。

MII Monitoring 就是通过 MII 来检查物理物理网卡的状态。如果物理网卡挂了,通过 MII 就可以检测到。但是 MII 检查通过不能代表网络是通的

(之前我有一个误解,我觉得 MII 只能检测网卡自身问题,无法检测像是网线不良,对端是否插线,对端设备挂了,对端设备端口挂了等问题,但是后来发现 PHY 芯片是可以检测到这些问题的,这里稍微展开一下。)

use_carrier 如果打开的话(默认就是 1, 打开的),就使用 netif_carrier_ok 来获取链路状态,底层依赖的是网卡驱动程序。大部分的网卡驱动程序都支持 netif_carrier_on/off 功能,如果不支持的话,那么链路检测永远是 up 的,即使挂了也不会触发 bonding 的切换。所以网卡如果不支持,就得把 use_carrier 改成 0

use_carrier 能够检查出来更多的问题,原理是通过 PHY 芯片来检查以太网物理层上的电信号(载波检测、信号强度、波形和信噪比),在以太网线路上,即使线路是 idle 的,只要线路健康,也会有一些信号在线路上发送,这些信号就可以用来做健康检测。在一些高阶的以太网标准上,比如 IEEE 802.3 1000BASE-T,能够检测的故障更多。可以检测出对端交换机挂了,交换机的端口挂了等问题。

MII Monitoring 无法检测的问题是:交换机正常运行但是配置错误,或者通过了 Linux 网卡驱动的检测但是发送数据会有问题等等。

下面会演示 MII Monitoring 触发的切换。

MII Monitoring 下的 Failover 测试

我们在上面的配置中,并没有配置 miimon ,所以默认是关闭的。这里再配置下检测频率为 102ms.

再看一下 bonding 状态,确认 miimon 已经生效,并且当前 active 端口是 eth0.

我们现在 ping 交换机另一端的一个主机,并且在 ping 的过程中手动 down 掉现在的 active eth0 端口。

ping 程序也显示,在切换的过程中一个包都没有丢。我们来分析一下这个切换过程。

Failover 过程分析

对于对端的主机来说,什么都没发生改变,因为这个 IP 对应的 MAC 地址没变,对端主机依然按照这个目标 IP 和 MAC 地址发送包过来。

出流量对于本机来说,切换也很简单,原先成 eth0 发送出去,现在从 eth1 发送出去即可。

入流量就麻烦了,我们的端口 down 了,交换机可不知道,入流量是交换机来决定从哪条线路发送过来的,所以流量还是会从端口 1 源源不断地进来。

发出流量已经切换,可是怎么切换接收的流量呢?

我们想要的是:让交换机现在通过端口 2 来发给我们流量,而不是端口 1.

如何做到呢?还记得交换机的工作方式吗?交换机从每一个收到的包学习 MAC 地址和端口的对应关系。利用这个,我们让交换机学习到,此时 MAC AA 对应的是端口 2,而不是端口 1。

即,我们使用 MAC AA 作为 Src MAC 从端口 2 发送点数据出去,交换机就知道了。

在 Failover 的时候用 tcpdump 来抓包,我们可以观察到在 backup 的端口发送出去的内容。

哈,eth1 发送出去了一个 ARP 请求,它问:「谁有 192.168.1.10 的地址?请告诉 192.168.1.10。」可是这个 IP 明明是它自己呀。它这是明知故问,没有人会回复给他,它也不需要答案,发送这个 ARP 请求的目标是让交换机知道现在 MAC AA 对应端口 2。

从交换机的视角,就如同 MAC AA 原先插在端口 1 上,现在移动到了端口 2 上一样,交换机会立即把发往这个 MAC 地址的流量切换到端口 2.

这种 ARP 的用法叫做 Gratuitous ARP(不必要的ARP),有的时候是不要的 ARP 请求,有的时候是不必要的 ARP 响应(我们会在后面见到)。在 RFC 5227 中定义。

实验:交换机端口 down

我们继续用 MII Monitoring 的方式,来测试一下模拟交换机 down,看能否触发切换。

确认当前的 active 端口:

然后我们 ping 其中的一个主机,同时去交换机 down 掉 eth0 连接的端口。

可以看到现在无法完成切换,此时的 active interface 还是 eth0。因为 MII Monitoring 依然认为服务器的物理链路是好的(这个实验是在没有上文说的 use_carrier 功能下做的,所以 MII 无法检测对端的端口 down)。

ARP Monitoring

ARP Monitoring 的原理就是用 ARP 协议一直对某一个 IP 询问 MAC 地址,如果能够得到回复,说明网络没问题,如果得不到回复,就执行切换。

我们首先设置 miimon 为 0 来关闭 MII Monitoring,然后开启 ARP Monitoring,主要设置两个选项:ARP 检测的地址和检测的频率,这里使用 1s。

然后开始测试切换,查看现在 active 的端口是 eth1

然后开始 ping,在 ping 的时候在交换机把 eth1 端口 down 掉。

可以看到第 11-13 个包丢了,一共丢了三个包。因为我们设置的频率是 1s,所以切换有些慢的。ARP Monitoring 比 MII Monitoring 能检测的网络范围更广泛。

ARP 也有问题,就是如果我们使用的 192.168.1.12 有问题,有时候回复 ARP 有时候不回复,就会导致端口来回 flapping。一个解决方法是,ARP Monitoring 支持多个 IP 检查目标,就可以避免 false alarm。

另一个坏处是会给网络带来额外的 ARP 流量。但现在网络都是万兆起步,这点流量可以忽略。

分析和总结

本文讨论了 Linux bonding 模式中的一种:active-backup。这个模式的特点是:

  • 不需要交换机特殊配置,在交换机看来就是两个独立的端口;
  • 由于交换机视角是独立的,所以我们可以把两根线接到两个不同的交换机上,可以实现多交换机的 Failover,避免交换机的单点故障;
  • 一次只能利用一条线路,假设两条1G线路,总速率还是 1G,有一条线总是浪费的;

本质上这是个冷备方案,我们不喜欢冷备方案,因为它浪费资源。下一篇文章我们讨论如何将两条线路都利用起来。

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

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


数据中心网络高可用技术之从服务器到交换机:active-backup”已经有16条评论

  1. mode 0 (balance-rr) 是不是既提供高性能(负载均衡)又提供极端情况下面的可用性?
    那岂不是比 active-backup 更使用?

    • 是的,balance-rr 是需要交换机支持链路聚合的,而这篇介绍的active-backup 可以和任何交换机工作。后面会介绍的。这篇是先介绍简单的。

      不过机房用的交换机都是支持链路聚合的,要说链路聚合的话,mode4 802.3ad 是用的最多的。

  2. “MII Monitoring 就是检测链路状态,只能检查物理链路的连通性,不能代表网络是通的。比如,交换机挂了,或交换机的端口挂了的情况下,服务器网卡没问题,就不会触发切换”
    MII Monitoring是服务器内的吧,不对外发送包,交换机也感知不到,MII Monitoring只是网卡驱动程序对网卡的一种检测。

    • 不好意思,这个地方貌似是我错了。我在原文中更新了,这一段:

      > 之前我有一个误解,我觉得 MII 只能检测网卡自身问题,无法检测像是网线不良,对端是否插线,对端设备挂了,对端设备端口挂了等问题,但是后来发现 PHY 芯片是可以检测到这些问题的…

      • 学习了,linux bonding 参数和 ovs 的不太一样

        > bond-detect-mode, optional string, either carrier or miimon

      • 请教一下,如果说MII可以检测到对端设备端口挂了,那么为什么后面的实验中关闭交换机的端口,没有能进行自动切换呢

          • 前面的实验中,关闭ubuntu-5的网卡是可以通过MII检测切换的,但是后面关闭物理交换机端口就不行,我理解虚拟机是支持的,虚拟系统里面是否有虚拟交换机,所以MII检测不到物理交换机的端口状态?

          • MII 是支持的,但是检测对端链路,要求网卡驱动支持 netif_carrier, 这个在虚拟机中是不支持的。

            如文中所说:

            大部分的网卡驱动程序都支持 netif_carrier_on/off 功能,如果不支持的话,那么链路检测永远是 up 的,即使挂了也不会触发 bonding 的切换。

  3. 2.数据中心网络高可用技术之从服务器到交换机:active-backup
    这个链接貌似没有链接成功,没法点击

Leave a comment

您的电子邮箱地址不会被公开。 必填项已用 * 标注