影响半径
一次性测试每一条链路和每一台路由器,以及为什么图论让它只花 13 毫秒
Michel Wijnberg
“如果我把这个弄坏会怎样?“是一个关于单个对象的问题。而架构师真正需要答案的那个问题是它的 反面,而且难得多:
在这张网络里的所有东西当中,哪些是重要的?
靠一条一条点链路是到不了那儿的。我实验室里的 AS 200 有 275 条链路和 64 台路由器。手工测试 每一次故障就是 339 次实验,而且每次拓扑一变就得重来。
所以 Osprey 一次性把它们全做了。这买来的是一份短名单:在 339 件可能出事的东西里,真正会让您付出代价的那几件。这就是排到下个 季度的冗余评审和批准变更之前顺手跑一遍之间的差别。
每条链路、每台路由器,十三毫秒
看标题:“1 with impact in 13ms”,下面还写着测试的是什么:“Links whose failure causes device isolation. Redundant links omitted.”
这个租户里的每一条链路都被评估过了。其中恰好只有一条,mia1-cr1 ↔ mia1-gw1,会孤立掉什么
东西,而它孤立的是一台路由器:mia1-gw1。把开关切到 Node Failures,答案是镜像的:64 台路
由器里,恰好一台(mia1-cr1)会让恰好另一台失联。
那才是架构师想要的结果:不是 275 行等着读的清单,而是一句”其中 274 行可被证明毫无看头”。
同一个弱点,被三次发现,穿过三种协议
同一事实的结构视角,住在它自己那份报告里:
64 台设备,分析了 275 条链路,1 个割点(mia1-cr1,172.16.4.31)和 1 条桥链路。割点
是这样一个顶点:把它去掉会让连通分量的数量增加。这就是”如果这台路由器死了,网络就会裂开”在图
论里的说法。
下面是我没有计划过、而且最喜欢的部分。我把同一份报告对另外两个租户也跑了一遍:
| 租户 | IGP | 割点 | 桥链路 |
|---|---|---|---|
| Harrier-Broadband | OSPFv2 | mia1-cr1 | mia1-cr1 ↔ mia1-gw1 |
| Kestrel-Dynamics | EIGRP | e-mia1-cr1 | e-mia1-cr1 ↔ e-mia1-gw1 |
| Merlin-Carrier | IS-IS | i-mia1-cr1 | i-mia1-cr1 ↔ i-mia1-gw1 |
三家运营商。三种不同的 IGP。三条完全独立的发现路径:OSPF 的 LSDB 遍历、CISCO-EIGRP-MIB 的
邻居表、IS-IS 的 LSP。每一个里都有同一个结构性弱点,而且在同一个位置。
诚实的解释是:我是照着模板搭的实验室,把迈阿密的网关单归属地建了三遍。但这恰恰让它成为一次有
用的核对:同一个物理错误,通过三套互不相干的协议模型描述给 Osprey,产出了同样的三个答案。如果
IS-IS 的拓扑提取里有缺陷,i-mia1-cr1 就是那个分歧会冒出来的地方。
在工具告诉我之前,我根本不知道实验室里有这么一处。它在那儿摆了好几周,而这个实验室,正是我专门 为了抓出问题才搭的。
这一部分值得和图论分开来看,因为图论才是不出奇的那一半。割点和桥都写在教科书里,任何工具都能 在任何一张图上把它们算出来。决定这个答案有没有意义的,是那些顶点和边究竟是什么。Osprey 的 图不是谁手工维护的示意图:它是从路由器自己泛洪出来的东西重建的,所以图里的一条桥,说的是转 发,而不是一张画。把同一个算法跑在一份过期的 Visio 文件上,您会得到一模一样的形状,和一点都 不剩的真相。
为什么答案在您松开鼠标之前就到了
275 个故障场景只用十三毫秒,靠的不是什么精巧的并行,而是根本不去做那些活。
一条移除后会让图断开的链路,就是一条桥:不在任何环上的边。Tarjan 的桥查找算法用一次深度 优先遍历就能把它们全部找出来,O(V+E),一次性覆盖整张图。而一条不是桥的链路根本不可能孤立 任何东西:按定义它在一个环上,所以一定存在另一条绕行的路。
于是评估先找出桥,只对这些做仿真:
// Precompute bridges in O(V+E). These are the only links that can
// cause unreachable devices when removed.
bridgeLinks := spf.FindBridges(baselineMerged)
接着它再剔掉一类。如果两台路由器之间有多条并行链路,那么其中任何一条都不可能是那种要紧意义上 的桥,因为断掉一条还剩下别的:
// Parallel links: if a device pair has multiple links, failing any one
// cannot disconnect them. Remove such links from the bridge set.
274 条链路是被一条定理排除掉的,而不是靠一次可达性检查。只有一条链路真的被仿真了。整个把戏就 是这样,也正是为什么答案在你还没松开鼠标之前就已经出来了。在一张一百倍规模的网络上,它依然是 一次遍历加上少数几次检查。
图论在这里不是装饰。它是”一份你要跑的报告”和”一份你顺眼一扫的报告”之间的差别。
当没有东西是关键的时候,“关键”意味着什么
Critical Pairs 页签回答的是再往外一步的问题:哪两条链路,单看谁都不是单点故障,合在一起却 是致命的?
那是一类真正讨厌的风险。这两条链路都不会出现在任何单点故障报告里。它们单独拿掉都什么事也没有。 把两条一起拿掉(同一条管道、同一块板卡、同一个维护窗口),网络就裂了。
要找到它们,就得对每一条非桥边,把它移除,然后在剩下的图上重跑一次桥检测。复杂度是 O(L·(V+E)),也是这份报告里最贵的部分。
在三个租户里,答案都是零,而面板会用文字说出来:
No critical link pairs detected — your topology has good redundancy.
一个真的花了功夫算出来的零,比一份长长的清单更有价值。这个零说的是:这张网络里不存在任何一对链 路,其同时失效会把它切开,而这是被穷举检查过的,不是被假定的。
影响半径不只是拓扑
结构是一种依赖。另一种依赖是可达性,而它的度量单位是地址空间:
| 对等 AS | 对等体数 | 前缀数 | IP 空间 | 等效 CIDR |
|---|---|---|---|---|
| 100 | 2 | 3 | 131,328 | /15 |
| 300 | 2 | 3 | 131,074 | /15 |
三个前缀听起来没什么,直到它被表达成131,328 个地址,相当于一个 /15,而且只能经由 AS 100 到 达。前缀数量是衡量暴露面的糟糕代理指标(一个 /15 和一个 /32 都算作”1”),所以这份报告会把它 换算成地址空间,再换算回一个等效 CIDR,而那才是架构师真正在其中推理的单位。
在它旁边,报告还会把每一对关键链路与其成员所属的 SRLG 组求交集,这样两条在地图上看起来彼此 独立、实际却共用一条管道的链路,就会被报告为相关联的,而不是分散的。
这就把我带到了那个我宁可自己说出来、也不愿被你发现的缺口。
诚实而未完成的那一部分
Osprey 的 SRLG 支持在除一个方向之外的每个方向上都是完整的。你可以定义组、把链路挂上去、把整个组 作为一次仿真变更一起打掉,并在依赖报告里看到共享风险的相关性。你做不到的,是去发现它们。
**没有任何东西在给 SRLG 表供数。**每一个组都是手工录入的。Osprey 会把它在 IS-IS 里看到的 RFC 5305 流量工程子 TLV 以原始字节形式存下来,但还没有解码 SRLG 子 TLV,所以一张已经在自己的 IGP 里 通告共享风险组的网络,得不到任何好处。
消费者比数据源先被造出来了。那是错误的顺序,它在路线图上,而在它做完之前,这个功能诚实的描述是 “SRLG 仿真,基于你告诉它的那些组”,而不是”SRLG 发现”。
我宁可写下这句话,也不愿让某个人在评估过程中自己发现。
为什么这是我会最先跑的那份报告
如果明天我接手一张网络,我想要的第一样东西不是地图。是三个问题的答案:
- 哪些单点故障真的会孤立掉什么?(一条链路。一台路由器。)
- 哪些成对的故障会,而任何单故障报告都不会显示?(没有:是验证过的,不是假定的。)
- 每一个外部依赖背后压着多少地址空间?(每个对等 AS 一个 /15。)
这三个问题都能从一个本来就正确的模型里算出来,远不到一秒,而且完全不用碰路由器。这就是”先花四篇 文章把模型做对”的全部理由:一个准确的模型不是产品,它是那些有用问题赖以运行的基底。
下一篇:这一篇悄悄绕开的那个数字。那条链路断掉时到底有多少流量在移动,以及为什么我的实验室没法 告诉我。估计你测不到的东西。