被反复讲述的说法是:EC2 VPN 设备上的路由守护进程会在 BGP 建立之后,把远端前缀教给 VPC。这话只说对了一半。会话确实建立了,但 VPC 的路由表并不会因此发生任何变化,所以最先出现的症状通常是某个子网悄悄把流量丢进黑洞。

这里混在了一起的是两件不同的事:与路由服务器建立对等,以及把路由安装进路由表。

误区:只要 BGP 起来,VPC 就会学到前缀

BGP 是两个发言者之间的对话,而在这个设计里,发言者是您设备上的路由守护进程,以及 AWS 放在您自己的子网里的 VPC Route Server 端点。这段对话携带前缀,但它不会触碰工作负载子网的路由表,因为那些路由表只能通过传播来学习,而传播必须在每一张表上单独启用。在启用之前,VPC 的网络结构对设备所知道的东西一无所知。

配置步骤之所以分开,是有原因的:先关联,再创建端点,然后建立对等,最后启用传播。

Route Server 是控制平面,不是隧道

Route Server 不加密、不转发、也不检查任何一个数据包。它存在的目的是与设备交换 BGP,并把得到的前缀交给配置为接收这些前缀的路由表。数据平面没有任何改变:数据包仍然从设备的网络接口发出,经过它的 VPN,再按原路返回。

这意味着转发实例上的源目检查依然重要,因为这个实例现在转发的是发往别人的流量。

安全组和子网层面的控制同样适用于被转发的流量。Route Server 不会让一个丢弃流量的设备开始转发,也不会修复远端缺失的回程路由。

传播是按路由表生效的,不是按整个 VPC

把路由服务器关联到 VPC,和在某个路由表上启用传播,是两个决定,而只有第二个会改变子网的行为。一个有六张路由表的 VPC 可以在其中一张收到传播来的前缀,而另外五张收不到,这对中心子网来说恰好正确,也正是产生「只工作一半」这种费解结果的原因。即使传播已经开启,竞争路由仍可能胜出,因为 VPC 的路由选择偏好最长前缀,长度相同时则偏好静态路由而不是传播路由。这个偏好是静默应用的。

要检查具体子网的实际生效路由表,而不是设备宣告的前缀列表。API 可以直接回答这个问题:aws ec2 associate-route-server 和 aws ec2 enable-route-server-propagation --route-table-id <id> 是大家最常忘记的两步,而 aws ec2 describe-route-tables --route-table-ids <id> 则显示前缀究竟有没有作为 route server 条目出现。

设备依然承载每一个数据包

宣告可达性并不等于真正拥有可达性。BGP 会话可以在设备 VPN 断开时仍然保持建立,而一个永远不变的静态宣告会持续把流量拉向一条死路。Route Server 支持 BFD 之类的故障检测,但那检验的是对端的存活,而不是对端背后所有东西的健康。

把宣告和真实的远端路由绑定起来:隧道和远端网络都在时宣告该前缀,不在时就撤销。

撤销一个前缀,看看会发生什么

分阶段测试,并把最后一步做成撤销。确认宣告能够到达、前缀出现在每张预期的表里、设备是下一跳、转发确实穿过活动隧道、远端能够响应。然后撤销一个测试前缀,或者关闭一条已批准的隧道,观察流量是否移动到设计所说的位置。在测试仍然开放时记录操作前后的路由表。

把一条路由迁移到第二台设备,并不会迁移它原本承载的会话,因为 NAT 和防火墙状态留在第一台设备上。

对于十来个前缀这种固定规模,VPC 路由表里的静态路由仍然是更便宜的答案。只有当前缀列表真的会变化,并且撤销策略是您能向值班同事解释清楚的东西时,Route Server 才值得占一席之地。

相关文章