分布式 L2 网关下的 OVS 未知单播泛洪
大家读完觉得有意义和帮助记得关注和点赞!!!
目录
1 问题描述
2 基础设施和环境信息
3 故障排除
3.1 确认:单播泛洪
3.2 确认:所有泛洪流量都以 L2 GW 为目标
3.3 验证:容器 ARP 处于活动状态时,OVS fdb 条目过时
3.4 分布式 L2 GW 行为:取决于供应商
有关物理交换机 ARP 老化的更多信息
3.5 修复
4 总结
引用
在分布式 L2 网关环境(例如 Spine-Leaf)中,ARP 老化时间配置错误可能会导致 OVS 单播泛洪。而且,的行为 分布式 L2 网关产品因供应商而异。
1 问题描述
一位内部用户报告说,他们注意到了一些实例 (docker containers)定期获得相对较大的怀疑入口流量 - 甚至 如果他们的实例没有提供服务,如下所示:
图 1.1 对实例的周期性入口流量持怀疑态度
2 基础设施和环境信息
本节提供了一些基本的基础设施信息,以帮助理解 问题。更多详细信息,请参考我之前的文章 携程 云计算时代的网络架构演进。
数据中心网络采用 Spine-Leaf 架构,具有 Leaf 节点 用作分布式 L2 和 L3 网关。
图 2.1 数据中心网络拓扑
在每个计算主机内部,所有连接到 OVS 网桥的实例以及 容器内的默认路由指向其自己的(分布式)网关。
图 2.2 主机内部的虚拟网络拓扑
别人:
- OVS 版本: ,
2.3.1
2.5.6
- Linux 内核:
4.14
3 故障排除
3.1 确认:单播泛洪
调用,并且不费吹灰之力,我们确认了这些流量 不是容器的目标,即这些定期数据包的 和 都不是实例的 IP/MAC。所以我们得到了第一个结论:OVS 正在进行单播泛洪 [1]。tcpdump
dst_ip
dst_mac
单播泛洪意味着 OVS 不知道数据包的位置,因此 它复制了此数据包,并将此数据包的副本发送到所有接口 具有相同的 VLAN 标记。例如,在图 2.2 中,的出口流量将 复制到 ,但不是 和 。dst_mac
inst1
inst2
inst3
inst4
3.2 确认:所有泛洪流量都以 L2 GW 为目标
接下来的问题是,为什么 OVS 不知道 .dst_mac
这些泛洪数据包的日志各不相同,它们来自不同的 IP 地址,并且 也选择了不同的 IP 地址。
但进一步研究捕获的数据包,我们发现所有这些数据包都泛滥了 共享同一dst_mac
的数据包,假设 .我们花了 过了一会儿,才弄清楚这是我们的 Spine-Leaf 网络(此 MAC 是手动编码的,由另一个团队负责, 这就是为什么我们一开始没有确定它)。00:11:22:33:44:55
3.3 验证:容器 ARP 处于活动状态时,OVS fdb 条目过时
OVS fdb 是什么样子的:
<span style="color:#333333"><span style="background-color:#f8f8f8"><span style="background-color:#f6f8fa"><code><span style="color:#008080">$ </span>ovs-appctl fdb/show br-int
port VLAN MAC Age
1 0 c2:dd:d2:40:7c:15 1
2 0 04:40:a9:db:6f:df 1
2 4 00:11:22:33:44:55 16
2 9 00:11:22:33:44:55 6
</code></span></span></span>
接下来,我们想验证我们的假设:L2 GW 在 OVS fdb 中的条目将是 此问题发生时已过时。
幸运的是,问题每 20 分钟发生一次(结果发现有一些 产生流量的周期性作业),因此我们很容易捕获 我们想要的任何东西。我们使用以下命令来检查该条目是否存在。在 在本例中,实例具有 VLAN 标记 ,因此我们 grep pattern 。4
" 4 00:11:22:33:44:55"
<span style="color:#333333"><span style="background-color:#f8f8f8"><span style="background-color:#f6f8fa"><code><span style="color:#000000"><strong>for </strong></span>i <span style="color:#000000"><strong>in</strong></span> <span style="color:#000000"><strong>{</strong></span>1..1800<span style="color:#000000"><strong>}</strong></span>; <span style="color:#000000"><strong>do
</strong></span><span style="color:#0086b3">echo</span> <span style="color:#dd1144">$(</span><span style="color:#0086b3">date</span><span style="color:#dd1144">)</span> <span style="color:#dd1144">" "</span> <span style="color:#dd1144">$(</span>ovs-appctl fdb/show br-int | <span style="color:#0086b3">grep</span> <span style="color:#dd1144">" 4 00:11:22:33:44:55"</span><span style="color:#dd1144">)</span> <span style="color:#000000"><strong>>></strong></span> fdb.txt;
<span style="color:#0086b3">sleep </span>1;
<span style="color:#000000"><strong>done</strong></span>
</code></span></span></span>
通常,打印是这样的:
<span style="color:#333333"><span style="background-color:#f8f8f8"><span style="background-color:#f6f8fa"><code>2 4 00:11:22:33:44:55 16
2 4 00:11:22:33:44:55 17
2 4 00:11:22:33:44:55 18
2 4 00:11:22:33:44:55 19
2 4 00:11:22:33:44:55 0
...
</code></span></span></span>
在测试过程中,我们发现打印消失了几分钟,并且这个 period 与有问题的 period 完全匹配。所以第二个结论: fdb 条目确实在容器内的 ARP 条目之前失效(因为 容器使用此 ARP 条目传输这些数据包)。
但仍然存在一个问题:容器的流量不是 在泛洪期间中断,这意味着从网关到 Container 已经成功地被 Container 接收,所以从 Container 的角度来看, 它不受此泛洪行为的影响(但如果泛洪流量 非常大,容器可能会受到影响,因为 这个案例)。
简而言之:gateway 已经回复了它从容器收到的每一个请求,为什么 OVS 没有刷新网关的 fdb 条目?理论上,OVS 会这样做,因为 回复是源自 Gateway 的单播数据包。我们错过了什么吗?
3.4 分布式 L2 GW 行为:取决于供应商
云中,来自网关的单播回复可能是 与在容器中看到的不同?src_mac
GW_MAC
为了验证,我调用了一个非常简单的流量,从容器 ping GW,打印每个数据包的 和 MAC 地址:src
dst
<span style="color:#333333"><span style="background-color:#f8f8f8"><span style="background-color:#f6f8fa"><code><span style="color:#008080">$ </span>tcpdump <span style="color:#000080">-n</span> <span style="color:#000080">-e</span> <span style="color:#000080">-i</span> eth1 host 10.60.6.1 and icmp
fa:16:3e:96:5e:3e <span style="color:#000000"><strong>></strong></span> 00:11:22:33:44:55, 10.6.6.9 <span style="color:#000000"><strong>></strong></span> 10.60.6.1: ICMP <span style="color:#0086b3">echo </span>request, <span style="color:#0086b3">id </span>7123, <span style="color:#0086b3">seq </span>1, length 64
70:ea:1a:aa:bb:cc <span style="color:#000000"><strong>></strong></span> fa:16:3e:96:5e:3e, 10.6.6.1 <span style="color:#000000"><strong>></strong></span> 10.60.6.9: ICMP <span style="color:#0086b3">echo </span>reply, <span style="color:#0086b3">id </span>7123, <span style="color:#0086b3">seq </span>1, length 64
fa:16:3e:96:5e:3e <span style="color:#000000"><strong>></strong></span> 00:11:22:33:44:55, 10.6.6.9 <span style="color:#000000"><strong>></strong></span> 10.60.6.1: ICMP <span style="color:#0086b3">echo </span>request, <span style="color:#0086b3">id </span>7123, <span style="color:#0086b3">seq </span>2, length 64
70:ea:1a:aa:bb:cc <span style="color:#000000"><strong>></strong></span> fa:16:3e:96:5e:3e, 10.6.6.1 <span style="color:#000000"><strong>></strong></span> 10.60.6.9: ICMP <span style="color:#0086b3">echo </span>reply, <span style="color:#0086b3">id </span>7123, <span style="color:#0086b3">seq </span>2, length 64
</code></span></span></span>
就是这样!为什么应答数据包具有 MAC 地址而不是 ?谁是 ?我们收到通知 这是分布式 L2 GW 的真实 MAC 之一,而后者 是虚拟 MAC。这就是问题所在!GW 使用与 00:11:22:33:44:55
不同的 MAC 进行回复,因此 OVS fdb 永远不会刷新此条目,因此 洪水仍在继续。70:ea:1a:aa:bb:cc
00:11:22:33:44:55
70:ea:1a:aa:bb:cc
这是 Cisco 设备的行为,我们进一步检查了我们的 H3C 设备, 令人惊讶的是,在相同条件下,H3C 的回复是一致的: 它始终用于发送和接收。 到目前为止,我还没有关于什么是分布式 L2(和 L3)的明确答案 应该表现得好。00:11:22:33:44:55
有关物理交换机 ARP 老化的更多信息
Cisco 交换机为每个 IP 维护一个 ARP 计时器,默认为 ( 分钟) [4]。1500s
25
<span style="color:#333333"><span style="background-color:#f8f8f8"><span style="background-color:#f6f8fa"><code>LEAF <span style="color:#999988"><em># show ip arp vrf test | in 2001</em></span>
10.6.2.227 00:01:12 fa16.xxxx.97c7 Vlan2001
10.6.2.228 00:01:15 fa16.xxxx.97c8 Vlan2001
10.6.2.229 00:01:33 fa16.xxxx.97c9 Vlan2001
</code></span></span></span>
如果几分钟内没有来自此 ARP 的帧,它将向此 IP(主机)发送免费 ARP。19
<span style="color:#333333"><span style="background-color:#f8f8f8"><span style="background-color:#f6f8fa"><code>Host <span style="color:#008080">$ </span>tcpdump <span style="color:#000080">-en</span> <span style="color:#000080">-i</span> eth0 ether src 00:11:22:33:44:55
15:26:31.650401 00:11:22:33:44:55 <span style="color:#000000"><strong>></strong></span> fa:16:xx:67, vlan 2001, ARP, Request who-has 10.6.2.241 <span style="color:#000000"><strong>(</strong></span>fa:16:xx:67<span style="color:#000000"><strong>)</strong></span> tell 10.6.2.1
15:27:06.023959 00:11:22:33:44:55 <span style="color:#000000"><strong>></strong></span> fa:16:xx:c5, vlan 2001, ARP, Request who-has 10.6.2.73 <span style="color:#000000"><strong>(</strong></span>fa:16:xx:c5<span style="color:#000000"><strong>)</strong></span> tell 10.6.2.1
15:27:07.594005 00:11:22:33:44:55 <span style="color:#000000"><strong>></strong></span> fa:16:xx:aa, vlan 2001, ARP, Request who-has 10.6.2.7 <span style="color:#000000"><strong>(</strong></span>fa:16:xx:aa<span style="color:#000000"><strong>)</strong></span> tell 10.6.2.1
</code></span></span></span>
3.5 修复
这个问题是由分布式 L2 GW 行为引发的,但实际上它是一个 host 内部的配置错误:我们应该始终确保 intermediate 转发设备(在本例中为 OVS 网桥)的老化时间比 实例本身和物理交换机 ARP 老化时间。
Linux 内核的 ARP 老化机制真的很复杂,而不是一个或 多个参数,它由参数和状态的组合控制 机器,请参考这篇文章 [3] 如果你是 感兴趣。将 OVS fdb aging 设置为 对我们来说足够安全:1800s
<span style="color:#333333"><span style="background-color:#f8f8f8"><span style="background-color:#f6f8fa"><code><span style="color:#008080">$ </span>ovs-vsctl <span style="color:#0086b3">set </span>bridge br-int other_config:mac-aging-time<span style="color:#000000"><strong>=</strong></span>1800
<span style="color:#008080">$ </span>ovs-vsctl <span style="color:#0086b3">set </span>bridge br-bond other_config:mac-aging-time<span style="color:#000000"><strong>=</strong></span>1800
</code></span></span></span>
(上述配置在 OVS 和系统重启后仍然存在。
配置完成后,问题消失了:
图 3.1 问题消失
4 总结
内核通常有一个 ARP 老化时间比 OVS fdb 长(默认为 300 秒),因此在某些情况下,当 网关的 MAC 条目在 ARP 表中仍然有效,它在 OVS fdb 中已过时。 因此,网关的下一个出口数据包 (with ) 将触发 OVS 单播泛洪。dst_mac=GW_MAC
当从网关收到正确响应的数据包时,OVS fdb 将刷新 网关的 MAC 条目,则后续的单播泛洪将停止(转换为 正常的 L2 转发,因为 OVS 知道 其中 is)。GW_MAC
确切地说,真正的灾难是 gateway 响应错误:
- 网关是一个分布式 L2 网关,具有一个虚拟 MAC 和许多实例 MAC(与负载均衡器中的 VIP 和实例 IP 的概念相同)
- 从容器到网关的出口流量使用网关的虚拟 MAC
- 从网关到容器的响应流量使用其真实 MAC 之一 (实例 MAC)
在这种情况下,OVS fdb 不会被刷新,因此 OVS 将每 egress 数据包,直到 网关主动将其虚拟 MAC 通告给容器或容器 向网关发起主动 ARP 请求 - 此泛洪期可能会持续 几分钟,并且同一 VLAN 中的所有流量(如果 VLAN 未使用)将累积/复制到连接到 OVS 的每个实例。
如果您将 QoS 设置为 容器正在使用的 OVS 接口。
引用
- Cisco Doc:单播泛洪
- 云计算时代的携程网络架构演进
- Linux 实现的 ARP 老化时间原理分析
- Cisco Doc:ip arp 超时设置