本页课程原文(点开阅读)

EVPN 控制面

课程(6 节,按顺序学)

第 1 课 · EVPN 到底解决什么问题

入门 · 约 10 分钟

本课目标:先把「VXLAN 单独用为什么撑不住」说清楚,再引出 EVPN 是控制平面——数据平面和控制平面各管一件事。

回顾:VXLAN 单独用只能靠泛洪学习

「VXLAN」模块(本类目下的另一个 tab)讲完的是封装:一个二层帧怎么被塞进 UDP 4789,怎么带着外层 IP 头穿过一张纯三层的 fabric。但封装解决不了一个问题——leaf-1 凭什么知道某个 MAC 挂在 leaf-3 后面? VXLAN 头里没有这个信息,VXLAN 协议本身也没规定谁来告诉它。

没有人告诉它,VTEP 只剩一个办法:泛洪学习。目的 MAC 查不到就当作未知单播,连同 ARP、DHCP 这些广播一起复制给这个 VNI 里的每一个远端 VTEP(underlay 组播,或者头端复制成 N-1 份单播);谁后面挂着这个主机,谁就回包;VTEP 再从回包的外层源 IP 里反推出「这个 MAC 在那个 VTEP 后面」,写进表里。

泛洪的代价,以及真正的问题在哪

这套机制能跑,问题在代价。一是放大:fabric 里 40 台 leaf,一个未知单播就是 39 份拷贝,而 ARP 在一个大二层域里是持续不断的。二是表项来自数据面:MAC 表是用户流量的副产品,所以它只和「最后一个包」一样准——一台从不主动说话的主机(只应答的集群 VIP 是典型例子)在别人 ARP 到它之前根本不可达。三是变更收敛靠老化:虚机从 leaf-1 迁到 leaf-3,其他 leaf 还会继续往 leaf-1 发,一直发到表项老化超时,中间那几分钟就是黑洞。

★ 所以真正的问题不是「泛洪不能用」,而是正确性的代价随 leaf 数量和变更频率一起涨,而且 fabric 的控制状态是用户流量的副作用——规模上来之后这两件事都不可接受。

EVPN 是控制平面:先知道,再转发

EVPN 的做法是把「谁在哪」这件事交给一个路由协议。它是 MP-BGP 的一个地址族(AFI 25 L2VPN / SAFI 70 EVPN),沿用 BGP 已经有的一切:TCP 会话、增量更新、路由反射器、策略、认证。每台 leaf 把自己本地学到的 MAC 当作 BGP 路由通告出去,其他 leaf 收到之后直接装进转发表。

这是一次方向上的反转:泛洪学习是从数据面反推控制信息,EVPN 是从控制面拿到信息再转发。结果是 MAC 表在第一个包之前就已经填好了——未知单播变成罕见事件,很多现网干脆把未知单播泛洪整个关掉。

★ 同一次反转顺手解决了上一步列的三个代价:不用再复制给所有人(N-1 份拷贝变成一次 BGP 更新);表项不再依赖用户是否说话(沉默主机也能被通告出来);变更不再等老化(主机走了就是一条 withdraw,显式撤销)。

顺带还有一件工程上很值钱的事:underlay 和 overlay 用同一个协议。你已经为了 fabric 的路由部署了 BGP、已经有了 RR、已经有了监控和排障手册,overlay 只是在同一批会话上多开一个地址族。

把数据平面和控制平面明确分开

这一课最该记住的是一句话:VXLAN 是数据平面,EVPN 是控制平面,两者是正交的。 VXLAN 只定义「一个帧长什么样、怎么封、怎么解」;EVPN 只定义「可达性怎么分发」。VXLAN 不知道任何远端主机的存在,EVPN 一个包也不转发。

正交的意思是两边都能单独换掉。VXLAN 可以不配 EVPN,退回组播泛洪学习(很多老部署就是这样);EVPN 也可以不用 VXLAN——它最早是给 MPLS 定义的(RFC 7432),VXLAN 封装是后来补的(RFC 8365),今天同一套 EVPN 控制平面还可以驮在 MPLS 或者 SRv6 上。所以「EVPN/VXLAN」这个写法里的斜杠,读作控制平面/数据平面。

★ 出故障的时候这句话直接决定你从哪儿查:丢包、MTU、ECMP 不均、封装错是数据平面的问题,去看 VXLAN 和 underlay;某台主机不可达、某个 VNI 不通、迁移后黑洞是控制平面的问题,去看 BGP EVPN 的路由有没有收到、有没有被导入。把这两类混在一起查是最浪费时间的做法。

去「② Fabric 组网」页看一眼这张 fabric:spine 上只有 underlay 路由和 EVPN 的路由反射,spine 不是 VTEP、不封装也不解封装;所有 VTEP、所有 EVI 都在 leaf 上。

实验重点

  • VXLAN 只定义封装;单独用只能靠泛洪学习,代价随 leaf 数量和变更频率一起涨
  • EVPN 是 MP-BGP 的一个地址族,在第一个包之前就把 MAC 分发给每一台 leaf
  • 数据平面(VXLAN)和控制平面(EVPN)正交:VXLAN 可以不配 EVPN,EVPN 也可以跑在 MPLS 或 SRv6 上

第 2 课 · ★★★ 五种路由类型

入门 · 约 16 分钟

本课目标:这是整个模块最需要反复回来看的一课——五种路由类型各自带什么、谁发、谁收、少了会怎样。

为什么要分成五种类型

EVPN 的 NLRI 第一个字段就是路由类型。一个地址族里塞五种完全不同的信息,不是历史包袱,而是刻意的:二层可达性、三层可达性、BUM 怎么复制、多归属怎么协调,本来就是四个互不相干的问题,混成一种路由会让每台设备都被迫解析自己根本不关心的内容。

先建立一张对照表,后面每次回来看的都是它:

· RT-1 Ethernet Auto-Discovery:我接在哪个以太段上(多归属自动发现)
· RT-2 MAC/IP Advertisement:某个 MAC(可带 IP)在我后面(主力)
· RT-3 Inclusive Multicast:这个 VNI 的 BUM 请发给我
· RT-4 Ethernet Segment:我和谁共享同一个以太段(DF 选举的输入)
· RT-5 IP Prefix:某个 IP 前缀在我后面

★ 数量上完全不成比例:一张正常 fabric 的 EVPN 表里 RT-2 通常占 95% 以上,RT-3 是每 leaf 每 VNI 一条,RT-1/RT-4 只有配了多归属才会出现,RT-5 只有需要通告前缀(而不是主机)时才有。但故障率和数量是反过来的——最难查的问题往往就出在那几条少得可怜的路由上。

RT-2:一条顶三条

RT-2 MAC/IP Advertisement——主力。 谁发:本地学到主机的那台 leaf。带什么:MAC、可选的 IP(也就是 ARP/ND 绑定)、L2VNI、可选的 L3VNI 和 Router MAC、ESI、以及 MAC 迁移序号。谁收:所有导入了对应 RT 的 leaf。少了会怎样:单播可达性直接没有,退回泛洪学习;而且因为没有 IP-MAC 绑定,ARP 抑制的缓存是空的,连 ARP 也得泛洪。一条 RT-2 同时喂了二层转发表、三层主机路由和 ARP 缓存——这也是为什么它一条顶三条。

RT-3:BUM 复制列表靠它拼出来

RT-3 Inclusive Multicast Ethernet Tag。 谁发:本地存在这个 VNI 的每一台 leaf(每 leaf 每 VNI 一条)。带什么:VNI、我的隧道端点地址、以及隧道类型(头端复制,还是 underlay 组播)。谁收:这个 VNI 里所有的 leaf——它们用这批路由拼出BUM 复制列表。少了会怎样:复制列表是空的,于是 BUM(广播、未知单播、组播)被丢掉而不是被泛洪。症状最容易骗人:单播全通,但 DHCP 拿不到地址、没被抑制的 ARP 不通、组播收不到——看起来像「只有一部分流量有问题」。

这里有人会问:既然 EVPN 把 MAC 都分发了,为什么还需要泛洪?因为总有 EVPN 管不到的流量:主机第一次 ARP(如果没开抑制)、DHCP discover、非 IP 的协议、真正的组播、以及任何还没被通告出来的 MAC。EVPN 把泛洪从常态降级成例外,但没有取消它。★ 所以 RT-3 是每个 VNI 都必须有的基础设施,而不是一个可选特性。

RT-4 与 RT-1:多归属靠这两条

RT-4 Ethernet Segment。 谁发:接在这个以太段上的每台 leaf 各发一条,带 ESI 和自己的源 IP,并且用一个专门的 ES-import RT 把它只送给同段的邻居。谁收:同一段上的其他 leaf。为什么存在:它是 DF 选举唯一的输入。少了会怎样:每台 leaf 都以为自己独占这一段,于是都把自己选成 DF,多归属主机收到的每一份 BUM 都会收两遍——这就是第 6 课的陷阱。

RT-1 Ethernet Auto-Discovery 有两种粒度。per-ES 那条带 ESI 标签和 single-active/all-active 标志,用于 split-horizon 和快速收敛——接入链路一断,一条 per-ES 撤销就顶掉了成千上万条 per-MAC 撤销。per-EVI 那条实现 aliasing:告诉远端「这个 ESI 也能从我这儿走」。没有它,主机的 MAC 只在服务器哈希到的那一台 leaf 上学到,远端就把 100% 流量压给那一台,你花钱配的 LAG 有一半在空转。

RT-5:前缀路由,以及五种类型的分工

RT-5 IP Prefix。 谁发:需要通告前缀而不是主机的 leaf 或者边界设备。什么时候需要:外部路由和默认路由(指向防火墙或者出口方向)、汇总后的子网、fabric 之外的网段、以及那种根本学不到主机路由的静默网段。谁收:对应的 L3VNI / IP-VRF。少了会怎样:fabric 内部靠 RT-2 携带的主机路由还能通,但凡是「不是本地 ARP 学来的主机」的目的地——汇总、外部前缀、默认路由——一律进不来。

★ 一句话把五种类型串起来:RT-2 提供可达性,RT-3 让泛洪成为可能,RT-1 和 RT-4 只因为多归属而存在,RT-5 存在是因为不是每个目的地都是你 ARP 到的主机。

动手:按类型把路由表数一遍

去「③ EVPN 路由表」页,把过滤器按路由类型切一遍:先数一下 RT-2 有多少条,再确认 RT-3 是不是恰好每 leaf 每 VNI 一条,然后看 RT-1 和 RT-4 是不是只出现在配了 ESI 的那两台 leaf 上。

接着挑一条 RT-2 展开,把字段和这一课的对照表一项一项对起来:MAC、IP、L2VNI、L3VNI、Router MAC、ESI、序号。尤其要把同一条路由同时服务了二层转发和三层主机路由这件事看实——它是第 5 课对称 IRB 的前提。

实验重点

  • RT-2 是主力:MAC、可选 IP、L2VNI/L3VNI、ESI、迁移序号——一条同时喂二层转发表、三层主机路由和 ARP 缓存
  • RT-3 决定 BUM 复制列表;缺了它 BUM 是被丢掉而不是被泛洪,症状像「只有一部分流量不通」
  • RT-1 和 RT-4 只为多归属存在(RT-4 是 DF 选举的输入,RT-1 提供 split-horizon 和 aliasing),RT-5 用来通告前缀而不是主机

第 3 课 · RD 与 RT:一个管唯一,一个管归属

进阶 · 约 14 分钟

本课目标:把 RD 和 RT 的分工彻底分清,然后看那个最阴的陷阱:RT 配错,会话全正常、路由看得见,流量照样黑洞。

RD:让路由在 BGP 里能共存

先说 RD 解决的问题。BGP 的决策过程是对同一条 NLRI 的多条路径挑一条最优,其余的要么当备份、要么根本不装。而 EVPN 里有两种情况会让「同一条 NLRI」变得很危险:一是不同租户的 MAC/IP 完全可能重复(两个客户都用 10.0.0.1,两台虚机克隆出同一个 MAC);二是虚机迁移的那一瞬间,leaf-1 和 leaf-3 会同时通告同一个 MAC。

RD(Route Distinguisher,8 字节)的作用就是给每条路由加一段前缀,让它们在 BGP 眼里是不同的 NLRI。现网几乎都让设备自动派生:本机 Router-ID 加 EVI 编号,于是每台 leaf 的每个 EVI 都有一个独一无二的 RD。leaf-1 通告的 MAC-X 和 leaf-3 通告的同一个 MAC-X,因为 RD 不同,是两条能同时存在于表里的路由。

这带来两个很实际的好处:路由反射器能把所有路径都留住(而不是只留一条最优的),排障时你能同时看见「这个 MAC 现在被两台 leaf 声称」;MAC 迁移也因此能表现成「两条路径、序号不同」,第 6 课的仲裁才有东西可比。★ 但要记住 RD 不是策略——它只负责唯一性,从不决定任何一条路由该被谁导入。

RT:决定被谁导入到哪里

RT(Route Target)是一个扩展团体属性,它做的事只有一件:决定这条路由该被导入到哪个 EVI(二层的 MAC-VRF)或者哪个 IP-VRF。每个 EVI 有两组配置:export RT 是我发出去的路由要盖的章,import RT 是我愿意接受的章。收到一条路由时,leaf 逐条比对:路由携带的 RT 里只要有一个落在这个 EVI 的 import 列表里,就导入;一个都不落在,就留在 BGP 表里不动。

自动派生的 RT 通常是 ASN 加 VNI,这里藏着一个坑:它只在全 fabric 同一个 AS(比如 iBGP 加路由反射器的设计)时才自然对齐。如果你按 RFC 7938 做 eBGP per leaf——每台 leaf 一个私有 ASN——那么每台自动派生出来的 RT 都不一样,谁也导入不了谁。所以 eBGP fabric 要么手工写死 RT,要么打开厂商那个「RT 里忽略或改写 AS 号」的开关。这是新建 fabric 最常见的一类初期故障。

RT 还是多租户和路由泄漏唯一的工具:想让两个 VRF 互访,就互相导入对方的 RT;想做 hub-and-spoke,就让 spoke 只导入 hub 的 export RT。★ 记住分工就够了:RD 告诉 BGP「这些是不同的路由」,RT 告诉收到它的 leaf「这条路由属于哪儿」——而只有 RT 会让你静默黑洞。

★★★ 陷阱:RT 配错,所有检查都是绿的

当前预置的场景是这样的:fabric 扩容加了一台 leaf-3,VNI 10010 在别的 leaf 上用的 RT 是 65000:10(约定按 EVI 编号),而 leaf-3 上被写成了 65000:10010——有人顺手把 VNI 号当成了 EVI 号。这个配置不会报任何错,语法完全合法。

于是你按平时的顺序检查,每一项都是绿的:underlay ping 通;show bgp l2vpn evpn summary 里会话是 Established、收发计数在涨;show bgp l2vpn evpn 里那个远端 MAC 明明白白就在表里;VNI 是 Up;VTEP 是 Up。可主机之间就是不通。

原因就在「表里有」和「装进去了」之间那一步:路由确实被收下、也确实存在 BGP 的 EVPN 表里(Adj-RIB-In / 全局 EVPN 表),但它必须通过 RT 匹配才会被导入 MAC-VRF,而只有被导入的路由才会变成转发表项。RT 不匹配的路由状态就是:看得见,没导入。这种错通常还是双向的——leaf-3 自己发出去的路由在对端也同样看得见、同样没被导入。

★ 最能骗人的地方在于它的范围:出错的往往只有一个 VNI,同一条 BGP 会话上其他 VNI 全都好好的。于是所有人的注意力都被引向「这一台主机」「这个 hypervisor」「这个应用」,因为「网络明显是好的」。只影响一个 VNI、而会话健康——这个组合基本上就是 RT,或者某一侧漏配了 L2VNI。

怎么把它查出来

排障时问错了问题,就永远查不到。别问「会话起来了吗」,要问「这条路由被导入了吗」。命令层面就是不要停在 show bgp l2vpn evpn(那只证明收到了),而要去看这条路由携带的 RT 扩展团体,和目标 EVI 的 import RT 列表逐项对。

去「③ EVPN 路由表」页:页面对每一条路由都直接标了已导入 / 被忽略(RT 不匹配)以及被忽略的原因,还会把路由携带的 RT 和本地 import 列表并排列出来。先找到那条 MAC,看它在 leaf-3 上的状态;再去「④ 转发过程」页发一个包,看它在哪一跳因为查不到表项而失败。

修好之后回头再对比一次两张表。★ 这一课真正要留在你脑子里的不是命令,而是一个形状:一条路由的生命周期有两段——被通告/被收到,和被导入。 EVPN 里大多数「看起来一切正常,但就是不通」的故障,都发生在第二段。

实验重点

  • RD 只管唯一性(让同一个 MAC 被两台 leaf 通告时能共存),从不决定导入
  • RT 决定一条路由被导入到哪个 EVI/VRF;不匹配的路由在 BGP 表里看得见,但永远进不了转发表
  • 「会话 Established、路由看得见、只有一个 VNI 不通」——先怀疑 RT;eBGP per leaf 的自动 RT 尤其危险

第 4 课 · ARP 抑制与分布式任播网关

进阶 · 约 12 分钟

本课目标:把「网关永远在本地」和「ARP 不再泛洪」这两件事讲透——它们都是 EVPN 控制平面顺手给的。

集中式网关的代价:hairpin

传统设计里 SVI(网关)只在一对设备上——汇聚交换机,或者 fabric 的边界 leaf。于是同一台 leaf 下面两个不同子网的主机互访,路径是 leaf-1 → 边界 → leaf-1;跨 leaf 的跨子网访问是 leaf-1 → 边界 → leaf-3。这个绕路有个专门的名字:hairpin(发卡弯),也叫 traffic tromboning。

代价有三层。延迟上,本来一跳的事变成三跳;容量上,整个 fabric 的东西向三层流量全部压在那一对设备上,而 spine-leaf 好不容易换来的横向扩展在这里被打回原形;可靠性上,这对设备成了所有租户所有子网的共同故障域。

还有一件更隐蔽的:主机的 ARP 缓存里记的是网关的 MAC。网关只存在于某一对设备上时,虚机迁到另一个机架后,这个 MAC 依然要靠二层泛洪穿过整张 fabric 才能被找到——你的三层网关变成了对大二层的依赖,这跟做 fabric 的初衷正好相反。

分布式任播网关:每台 leaf 都是同一个网关

分布式任播网关的做法很直接:每一台 leaf 都为这个子网配置完全相同的 SVI IP(比如 10.10.10.1/24)和完全相同的虚拟 MAC。 从主机看,它的默认网关永远就在本地那一跳;从 fabric 看,跨子网流量在入口 leaf 就被路由,直接进 L3VNI 送给出口 leaf,没有任何绕路。

为什么必须是同一个 MAC,而不只是同一个 IP?因为主机缓存的是 MAC。★ 虚机热迁移到另一个机架之后,它不会重新 ARP——它继续往缓存里那个网关 MAC 发帧;而因为每一台 leaf 都用这个 MAC 应答网关,新机架的 leaf 直接就把它路由走了:零丢包,也不需要发免费 ARP。只统一 IP 不统一 MAC,缓存一复用就断。

代价是这个网关 MAC 在 fabric 里故意不唯一——同一个 MAC 出现在几十台 leaf 上。所以它不能被当成普通 RT-2 到处通告,否则 leaf 之间会互相指来指去。EVPN 对它做特殊处理(设备上就是 anycast-gateway 或者 sticky/静态 MAC 那套配置)。对学习者要记住的是:任播网关能成立,是因为控制平面知道这个 MAC 是被刻意复制的,不是冲突。

ARP 抑制:用 EVPN 缓存代答,而不是泛洪

ARP 抑制搭的是第 2 课那条便车:RT-2 可以同时带 MAC 和 IP,也就是 leaf 本地学到的 ARP 绑定被一起通告出去了。结果是每台 leaf 手里都有整个 VNI 的 IP → MAC 表,而它从来没见过那些 ARP 报文。

于是本地主机 ARP 一个远端主机时,leaf 直接用这张缓存本地代答,这个广播根本不进 fabric。在一个大二层域里,ARP/ND 是 BUM 流量最大的来源——把它压掉,第 1 课里泛洪学习那些代价大部分就跟着消失了。这也是「EVPN 把泛洪从常态降级成例外」最具体的一次体现。

但抑制不是免费的,两个边界要清楚:缓存未命中还是要泛洪(一台从没说过话、或者表项已经老化的主机);如果你同时把未知单播泛洪也关了,那这类流量是被丢掉而不是被泛洪。典型受害者就是第 1 课提过的静默主机——只应答不主动说话的集群 VIP,以及某些安全设备。所谓「ARP 抑制要小心」,具体指的就是这件事。

去「④ 转发过程」页做两件事:先把 ARP 抑制开关来回切一次,看同一次 ARP 请求是「本地代答」还是「复制给 N-1 个 VTEP」;再走一遍跨子网的包,确认它在入口 leaf 就被路由了,路径上没有任何一跳绕到边界。

实验重点

  • 集中式网关会造成 hairpin:所有东西向的跨子网流量绕到那一对边界设备,把横向扩展打回原形
  • 分布式任播网关每台 leaf 用同一个 SVI IP 加同一个虚拟 MAC,所以迁移后的虚机不用重新 ARP 也不丢包
  • ARP 抑制靠 RT-2 里的 MAC+IP 绑定在本地代答;但缓存未命中仍要泛洪,静默主机是典型受害者

第 5 课 · L2VNI 与 L3VNI,以及对称 / 非对称 IRB

进阶 · 约 12 分钟

本课目标:分清两种 VNI 各管什么,然后搞明白对称 IRB 为什么成了默认方案——出口 leaf 不需要远端子网的 ARP 状态。

两种 VNI,两件事

VNI 这个 24 位的数字在 VXLAN 头里只有一个字段,但 EVPN 用它表达两种完全不同的东西,配置里通常明确分开写:

· L2VNI = 一个广播域(也就是一个 MAC-VRF / bridge domain)。同子网内互访走它:封装保留原始的以太头,VNI 指明是哪个广播域,出口 leaf 用自己的 MAC 表查一下就桥接出去。
· L3VNI = 一个路由域(也就是一个租户的 IP-VRF)。只有跨子网的流量走它:入口 leaf 会重写以太头(目的 MAC 换成出口 leaf 的 Router MAC),VNI 填 L3VNI,出口 leaf 拿到之后在对应 VRF 里做一次 IP 查表。

★ 一句话记法:L2VNI 回答「哪个广播域」,L3VNI 回答「哪张路由表」。 编号规律也很好记:每个子网一个 L2VNI,每个租户一个 L3VNI——所以一个几百个子网的租户,通常是几百个 L2VNI 加一个 L3VNI。

非对称 IRB:状态随子网总数增长

跨子网怎么走,历史上有两种做法。非对称 IRB 的路径是 route-and-bridge:入口 leaf 在本地就把包从源子网路由进目的子网,然后用目的子网的 L2VNI 封装发出去;出口 leaf 什么都不用想,纯桥接。

听起来很省事,账单以状态的形式送来:要在本地路由进目的子网,入口 leaf 必须有那个子网的 SVI,而且必须有目的主机的 ARP/ND 表项。而 fabric 里任何一台 leaf 都可能是某个包的入口,所以结论是每台 leaf 都得持有所有子网的 SVI 和 ARP 状态——哪怕这台 leaf 下面一个该子网的主机都没有。状态量变成「子网数 × 主机数」,在多租户大 fabric 上很快就撞天花板。

还有个排障上的麻烦:A → B 和 B → A 用的是不同的 VNI(各自目的子网的 L2VNI),所以路径不对称,抓包和计数器要分两套看。

对称 IRB:为什么它成了默认

对称 IRB 的路径是 route-bridge-route:入口 leaf 在租户的 IP-VRF 里查一次路由,用 L3VNI(一个纯中转的 VNI)封装;出口 leaf 解封装,在同一个 VRF 里再查一次路由,然后桥接进它本地的 L2VNI 交给主机。两个方向用的是同一个 L3VNI,所以叫对称。

★ 它赢在哪儿:出口 leaf 只需要持有自己本地真实承载的那些子网的状态。 一台 leaf 永远不需要为远端子网配 SVI,也不需要远端主机的 ARP 表项——它只要 VRF 里有那条路由(来自带 IP 的 RT-2,或者 RT-5)加上下一跳 VTEP 就够了。这把「每台 leaf 的状态」和「租户里子网的总数」解耦开,这就是全部的扩展性故事。

对称 IRB 也带来一些新的一致性要求:同一个租户里每台 leaf 必须用同一个 L3VNI 编号,每台都要有这个租户的 IP-VRF,而且每台需要一个 Router MAC——这个 MAC 随 RT-2 的 Router MAC 扩展团体一起发过去,入口 leaf 就是靠它重写以太头。少配或者配错任何一个,症状非常固定:同子网内互通完全正常,跨子网完全不通。第 3 课那句「先问路由有没有被导入」在这里同样适用,只不过要看的是 IP-VRF 而不是 MAC-VRF。

去「④ 转发过程」页走一遍跨子网的包,重点看三处:入口 leaf 查的是哪张表、封装里的 VNI 是 L2VNI 还是 L3VNI、出口 leaf 又查了一次什么。

实验重点

  • L2VNI 回答「哪个广播域」,L3VNI 回答「哪张 VRF 路由表」;每子网一个 L2VNI,每租户一个 L3VNI
  • 非对称 IRB 要求每台 leaf 都持有所有目的子网的 SVI 和 ARP 状态,状态量随子网总数增长
  • 对称 IRB 用 L3VNI 中转、两端各查一次路由,出口 leaf 只需要本地子网的状态——所以它成了默认

第 6 课 · 排障:多归属(ESI / DF / split-horizon / aliasing)与 MAC 迁移

排障 · 约 16 分钟

本课目标:多归属的四个机制各修什么,然后看那个只在应用层暴露的陷阱:没选出 DF(或者两个 DF),主机收到重复的 BUM。

ESI:不用 peer-link 的双归属

一台服务器为了不被单台 leaf 的故障影响,会把两块网卡做成一个 bond,分别接到 leaf-1 和 leaf-2。从服务器看这就是一个普通的 LAG;问题在网络侧:leaf-1 和 leaf-2 怎么知道它们接的是同一台主机,而不是两台?

传统答案是厂商私有的 MLAG/堆叠:两台设备之间拉一条 peer-link,互相同步状态,对外假装成一台。EVPN 的答案完全不同——两台 leaf 在这个 bundle 上配置同一个 10 字节的 ESI(Ethernet Segment Identifier),然后各自用 RT-4 通告「我接在 ESI X 上」,从而互相发现自己是同一段上的邻居。没有 peer-link,没有厂商配对,而且不限于两台:同一个 ESI 可以有三台、四台 leaf。

多归属有两种模式:single-active(同一时刻只有一台 leaf 转发,另一台纯备份)和 all-active(两台同时转发,服务器侧按 LAG 哈希分流)。大家真正想要的是 all-active——但一旦允许「同一个主机同时从两个地方可达」,下面三个机制就从可选变成必需。

DF 与 split-horizon:先解决重复和回灌

DF(Designated Forwarder,指定转发者)解决重复。 BUM 流量从 fabric 泛洪过来时,leaf-1 和 leaf-2 都连着这段以太网,如果都往下送,主机会收到两份。所以两台 leaf 要用 RT-4 收集到的候选列表,按 ES、按 VNI 选出恰好一台来负责往这一段送 BUM(经典算法是把候选按源 IP 排序,用 VNI 取模选一个)。注意粒度是每 VNI 一次选举——所以不同 VNI 的 DF 可以落在不同 leaf 上,这本身也是一种负载分担。

split-horizon 解决回灌。 主机发出的一个广播从 leaf-1 进来、被泛洪到整张 fabric,那么 leaf-2 也会收到一份;而 leaf-2 也接在这同一段上,它绝对不能把这份再送回主机。做法是给流量打上源以太段的标记(per-ES 的 RT-1 里带的 ESI 标签;VXLAN 部署里常用 local-bias 实现),leaf-2 一看是自己所在段来的,直接丢弃。

aliasing:再解决负载分担

aliasing 解决负载分担。 主机的 MAC 只会在两台 leaf 中的一台上被学到(取决于服务器侧的哈希把流量送给了谁),于是只有那一台会发 RT-2。远端 leaf 如果严格按 RT-2 转发,就会把 100% 的流量压给那一台——你花钱配的 LAG 有一半在空转。per-EVI 的 RT-1 就是来补这个缺口的:它告诉远端「这个 ESI 也能从我这里走」,远端于是可以对两台做 ECMP。

★ 这样分组就很好记:这三件事都只是在修同一个事实带来的后果——这个 MAC 是真的能从两个地方到达。 DF 修「送重了」,split-horizon 修「送回去了」,aliasing 修「只送一边」。

★★★ 陷阱:没有 DF 或者两个 DF

当前预置的故障是这样的:leaf-1 和 leaf-2 之间的 RT-4 没有真正交换成功——可能是 ES-import RT 不匹配(第 3 课那个坑的变体)、可能是 ESI 有一位敲错了导致两台认不出对方是同段、也可能是某条策略把 ES 路由过滤掉了。后果是两台 leaf 各自认为自己独占这一段,于是各自把自己选成 DF。现在每一份送到这一段的 BUM 都会被送两次。

这个故障最难查的地方在于单播完全正常。ping 通、业务大部分正常、监控一片绿。真正暴露出来的症状全都在应用层,而且长得完全不像网络问题:DHCP 客户端收到两个 offer;ARP 应答重复;组播/IGMP 的接收端看到成倍的流;集群心跳收到自己发出去的包因而误判脑裂;服务器的 bond 驱动开始报那种莫名其妙的「收到自己的帧」计数。没有人会想到去看 DF 选举。

为什么这个故障特别难查

还有一种镜像的错法,值得一起记住:两台 leaf 配了同一个 ESI,但配在了错的口上(ESI 被复制粘贴到了另一台服务器的 bundle 上)。这时一台 leaf 会成为一段它其实并没有接入的以太段的 DF,于是发往真实主机的 BUM 被黑洞掉。同一类配置错误,症状正好相反:一个是收重了,一个是收不到。

★ 记一条经验:多归属主机上出现重复帧,先查 ESI / RT-4 / DF,不要先怀疑主机。 去「⑤ 多归属」页看 DF 选举结果——正常情况下每个 ES 每个 VNI 只有一个 DF,页面会直接把「两个都是 DF」标出来,再把它和 RT-4 的收敛情况对起来看。

MAC 迁移:序号仲裁与重复 MAC 检测

最后一块是 MAC 迁移。虚机从 leaf-1 热迁移到 leaf-3,leaf-3 在本地学到它之后通告一条同 MAC 的 RT-2,并带上 MAC Mobility 扩展团体,里面的序号比它见过的值大 1。规则很简单:序号大的赢。 leaf-1 收到一条「自己以为是本地」的 MAC 的更优路由,就停止通告、撤销自己那条,并把本地表项清掉。

★ 这一块正好补上了第 1 课泛洪学习的那个洞:迁移是被显式信号通知的,一次 BGP 更新就收敛完,而不是等 MAC 老化定时器慢慢超时、期间一直往老 leaf 发。 同一个动作从「几分钟黑洞」变成「亚秒级」。

序号还有第二个用途:重复 MAC 检测。如果同一个 MAC 的序号在短时间内不停递增(常见默认阈值是 180 秒内 5 次),那就不是迁移了——同一个 MAC 真的同时存在于两个地方,或者有个环路在来回搬这些帧。这时 leaf 会把它判定为 duplicate MAC,冻结、停止通告,而不是让整张 fabric 的表跟着抖。这个取向值得注意:宁可让一个 MAC 停摆,也不让控制平面被一个坏主机拖着震荡。

常见根因就三类:克隆虚机时没改 MAC;两个接入口被一根线背靠背连上形成二层环路;以及 ESI 配错,让同一台主机在控制平面上看起来像两台。去「⑤ 多归属」页先触发一次迁移,看序号怎么加一、老 leaf 怎么撤销;再触发反复漂移,看它在第几次被判成 duplicate。

实验重点

  • ESI 是「这几台 leaf 接的是同一段以太网」的共同标识:不需要 peer-link,也不限于两台
  • all-active 多归属必须同时有 DF(BUM 只送一份)、split-horizon(不回灌源段)、aliasing(两边都能收流量)
  • MAC 迁移靠序号仲裁;序号在短时间内反复递增就是重复 MAC 或者环路,不是迁移
冀ICP备2026021556号-2|冀公网安备13068302000206号