← 全部文章

如果我把这个弄坏会怎样?

一个你信任的模型,只有在你能向它提出从未被问过的问题时才值得拥有

Michel Wijnberg

这个系列的前八篇讲的是把模型做对:在不成为网络一部分的前提下发现网络、逐跳复现转发、拒绝 猜测,以及用最难受的方式发现我自己的工具一直在画虚构的东西。

那些全都是准备工作。一个仅仅准确的网络模型,是一张非常昂贵的照片。花掉那些力气的理由, 是为了能向它提出那个你没法向真实网络提出的问题:

如果我把这个弄坏会怎样?

这个问题决定了维护窗口。总得有人说清楚:凌晨三点拔掉那块板卡,网络扛不扛得住。通常他是靠脑子 里的模型和对上一次故障的记忆来回答的。接下来要讲的东西之所以有意思,不是因为 Osprey 有个仿真 器,而是因为故障不必先发生,您就已经能对它进行推理了。


你能改动的七件事

Osprey 的仿真模式会把在线模型取过来、克隆一份、施加变更,然后重新计算。它允许你改动的东西 清单很短,而这个”短”是刻意的:

变更作用
link_failure断掉一条链路
node_failure断掉一台路由器
cost_change给一条链路重新赋度量值,正反方向各自独立
hypothetical_link增加一条并不存在的链路,带开销和速率
hypothetical_node增加一台并不存在的路由器
srlg让一个共享风险组失效:一次操作,N 条相关联的链路同时断
peer_failure断掉一条 BGP 会话

其他任何东西都会被以 unknown mutation type 拒绝。没有区域重构变更,没有重分发变更,也没有 级联故障变更,因为这些我一个都没法在不编造数据的前提下实现。这一点我后面还会回来讲。


一根线缆,以及网络对它的反应

这是实验室里的真实一例。nrt1-cr1 ↔ sea1-cr1 是 AS 200 里一条跨太平洋的骨干链路,在 OSPFv2 下开销 10, 是 Osprey 在这个租户的两个 OSPF 实例上持有的 275 条链路之一。我右键点了它,选了 Simulate Failure

仿真的 Impact 页签:0 个被孤立,56 条路径变化,0 个新增单点故障
仿真的 Impact 页签:0 个被孤立,56 条路径变化,0 个新增单点故障

看顶上那三个数字。**没有任何东西变得不可达。56 条路径变了。没有出现新的单点故障。**整个评估 在服务端只花了 57 毫秒。

现在再看 Failed Links 那个标题,因为它在做一件很多人会漏掉的事:2 links。我点了一根线 缆,Osprey 断掉了两条链路,因为那根线缆把 OSPFv2 和 OSPFv3 当作 两个互相独立的协议实例来承载,各有各的开销。让这根线失效,就 是让它在两边都失效。一个按每根线缆建一条边的工具,必须决定要结束它两条命中的哪一条。

有意思的是那 56 条的拆分:

Paths 页签:15 条路径开销上升,41 条以相同开销改道
Paths 页签:15 条路径开销上升,41 条以相同开销改道
  • 15 条上升:路径变贵了。sea1-cr1 → nrt1-cr1 从开销 1 变成开销 11,直连链路被一条三跳的路径取代。
  • 41 条改道:路径换了跳数,而开销完全没动

第二个数字才是值得盯着看的。四十二个源/目的对在网络里走了另一条路,而且一分钱代价都没付,因为 一条等价路径本来就在那儿。当你把冗余表达成一次测量而不是一个形容词时,它看起来就是这样。“我们 有多样化的路径”是一个说法。“56 个受影响的对里有 41 个以相同开销改道”是一个数字,而且正是这个 数字告诉你维护窗口需不需要安排在凌晨 3 点。

这里没有任何东西被敲进过路由器。实验室没有真的断掉一条链路。我问的是模型。


屏幕顶上的那句拒绝

现在看第一张截图里那条琥珀色横幅,因为它是一次承认,也正是我信任面板其余部分的原因:

simulated paths are shown as an SPF projection (source-rooted least-cost tree) so before and after stay comparable; the live path panel shows the hop-by-hop forwarding chain, which can differ where an intermediate router’s own routing table disagrees with the source’s view

第三篇文章论证的是:以源为根的走廊是 IP 转发的错误模型,并且拿测量 数据撑腰:2,839 个跨区域路由器对里有 360 个,其走廊里含着一个任何报文都不会走的跳。我把那个引 擎换成了会遍历每台路由器自己路由表的引擎,并拿全部 4,032 对做了验证。

然后,在仿真里,我刻意不用它。

理由写在代码里,那也是这个产品里我最引以为傲的一句话:

// The panel shows the hop-by-hop forwarding chain (path_chain.go): every
// router's OWN routing table, read from the per-area LSDBs. A what-if topology
// has no such tables. The Type-3 summaries the surviving ABRs would
// re-originate after the mutation are exactly the thing that cannot be
// synthesised, and inventing them would make the simulation's numbers agree with
// nothing. So both simulation sides stay on the source-rooted SPF projection,
// consistently with each other, and say so. A labelled projection is honest; a
// baseline that disagrees with the baseline is not.

要遍历每台路由器自己的表,就需要知道变更之后每台路由器的表会是什么样。在 OSPF 里,这取决 于幸存的 ABR 会重新产生哪些 Type-3 summary-LSA:那些 LSA 并不存在,因为故障还没发生。我可以猜 它们。我没法猜对,而一条建立在猜出来的 summary 之上的逐跳链,会带着那个已验证引擎的全部权 威,却一点验证都没有。

所以比较的两侧都停留在那个明确标注过的投影上。“之前”那张图是被刻意做差的,好让它仍然和”之后” 那张图可比。一个”56 条路径变化”,如果实际上是”36 条真变化加上 20 条因为两侧用了不同引擎而产生 的假象”,那它就不是一份 diff。那是带着数字的噪声。


EIGRP:天花板是我的数据,不是协议

在 EIGRP 租户里弄坏点什么,Osprey 会停下来,而不是给你一个投影:

the simulated change affects the observed EIGRP chain (forward and reverse). Osprey cannot predict DUAL re-convergence: the topology tables it reads carry the DUAL distances, not the metric components (bandwidth, delay) a recomputation needs. After a real event the live view shows the new chain.

EIGRP 没有可供重新计算的链路状态数据库。Osprey 手里有的,是从 CISCO-EIGRP-MIB 读来的每台路 由器自己的拓扑表,而那十二列带的是 DUAL 的距离(feasible distance、computed distance、 reported distance),不是这些距离所依据的分量

要在变更之后重算 DUAL,你需要最小带宽、总时延、可靠性、负载、MTU 和跳数。这些在设备上是存在 的;我在 e-ams1-cr1 上用 show ip eigrp topology 10.64.0.0/15 确认过。它们只是不在 Osprey 所读的那张 MIB 表里。

这个区分是特意写进代码注释里的:

// Scoped to what Osprey READS, deliberately not to what SNMP can carry: … A future
// CLI enricher could lift part of this ceiling, so the sentence must not read as a
// permanent property of the protocol.

**“这个协议无法被仿真””我目前没有采集那些输入”**之间有实质区别,而一个把两者混为一谈的 产品,是在悄悄告诉你别再费心问了。这是一个数据采集层面的天花板,而且是可以掀掉的。等我掀掉它, 这条消息就会消失。

它底下还有一条更小、更锋利的规则。如果变更是纯粹的移除(一条链路或一个节点失效),而被移除的 东西可被证明不在观测到的那条链上,Osprey 会继续显示真实的链,并说明理由:“observed live EIGRP chain: the simulated failure does not touch it (EIGRP re-convergence itself is not modelled)”。 在别处拿掉容量,永远不可能改善一条本来就没用到它的距离矢量路径。但一次开销变更或一条新链路 可能从任何地方把路径吸引过去,所以那些一律算作”碰到了”。这个引擎恰在必须拒绝的时候拒绝, 而不是一刀切地拒绝。


变更清单里没有什么,以及为什么

这七种变更,是我能在不编造输入的前提下实现的那些。缺席的那些,都是有明确理由地缺席:

  • **区域重构。**挪动一个 ABR 或者重画一条区域边界,会改变”到底存在哪些 summary-LSA”。那不是对 拓扑的一次变更,那是另一张拓扑。
  • **重分发变更。**它们取决于 route-map 和 prefix-list,而 Osprey 对这些毫无可见性。我等于是在 给一份我读不到的策略建模。
  • **级联故障。**要预测第二次故障,需要队列和 TCP 的动力学,而一个拓扑工具没有资格声称自己能对 那些建模。标出风险;别去预测级联。

这几样每一个演示起来都会很漂亮。每一个都会是一个背后空无一物的数字。


要点

仿真是一个拓扑产品要么把建模的功夫兑现、要么把它暴露出来的地方。数据模型里抄过的每一条近路,都 会在这里以”自信的错误答案”的形式冒出来,因为一个假设场景没有任何基准真相可以对照。故障还没发 生,所以没有任何东西能反驳你。这恰恰是它成为最值得小心对待的功能的原因。

诚实的版本,单看截图不那么震撼,而在凌晨 3 点相当有用得多:七件你能改的事、四个出来的数字,以及 一条说明这些数字由哪个引擎产出的横幅。


下一篇:一条链路断了,但网络里到底哪些部分真的依赖它? 影响半径