腾讯云网络自研路由平台—FCR
云网络厂商在用户接入侧一般采用传统网络设备如路由器、交换机,传统网络设备虽然功能稳定,但是开发周期较长,支持功能无法快速匹配互联网厂商日新月异的应用场景。为了解决上述问题,腾讯云网络在接入时使用了FCR(Fast Cloud Router)作为自己的路由控制平台。
FCR自研路由平台不仅支持BGP、静态路由、BFD等各类路由相关协议,同时还可以提供丰富的路由策略以及百万级的路由管理功能。
- 平台开放:完全基于开源组件构建,打破了传统设备厂商封闭的产品生态,开发新功能快捷,迭代速度更快;
- 部署灵活:能够部署在不同厂商的x86服务器上,也可以作为一个组件运行在其他产品中,便于灵活定制和系统扩展;
- 价格低廉:专为腾讯网络量身定做,裁剪了一些开源组件中和路由无关的冗余功能,能够在各类场景中替代商业路由器,节省采购费用。
仍然以云网络接入组网为例介绍下FCR在腾讯云网络中的角色,如下图所示:
FCR主要负责如下工作:
- 与用户网络建立BGP邻居,负责从客户和VPC学习路由;
- FCR通过GRPC,Netconf等方式将学习到的路由上报控制器,由控制器调优并指导转发;
- FCR从控制器接收路由,并向客户和VPC发布BGP路由;
- FCR将对学习到的路由进行策略控制和优选发布到云网络。
FCR在腾讯云网络中提供的路由服务对整个网络路由学习起到重要作用,因此在进行部署时,为了保证路由控制层面的可靠性,经常采用双邻居模式。但是这种双邻居架构在实际搭建网络时遇到了比较多的问题和挑战。首先是目前比较流行的只通过建立一个BGP邻居进行网络接入;其次FCR本身作为自研产品特性更新是很频繁的,当需要上线新功能切换版本时会导致其中一个BGP邻居断开重建,在切换版本过程中的邻居中断会让客户产生误解,从而耗费大量运维资源,提高了维护成本。
基于上述原因,需要考虑解决FCR在云网络接入中的配置问题,同时也要提高系统的稳定性,要求可以做到在切换版本或者发生设备异常时对外无感知。
要解决上述问题,FCR作为一款自研路由控制平台,自然应该要具备数通设备的NSR功能。
NSR技术
NSR(Non-stop-routing)不间断路由,是数通设备高可靠性的一种解决方案。在主设备出现异常重启的情况下,备设备可以及时接管主设备的运行状态,继续进行路由和转发过程。
由此可见,NSR技术不仅可以解决之前腾讯云网络AA架构的问题,同时也可以提升整个FCR平台系统的稳定性,那么实现NSR有哪些技术难点呢?
云网络接入时采用BGP协议,而BGP协议是基于TCP连接的,首先要考虑如何保证TCP连接一致性:
- TCP连接连接状态复杂,需要BGP应用协议与TCP/IP协议栈配合修改,这样就涉及用户态和内核的联动;
- 接收的报文从内核到用户态协议处理,整改过程都需要进行备份还原,涉及内核TCP、用户态BGP协议且都是异步过程,实现技术难度很高;
- 对于本端发送的协议报文,需要保证先备份成功后才能再进行发送。
其次是各种路由协议间的数据平滑
- 路由和交换设备支持协议庞杂,如BGP、IGP(OSPF、ISIS等)、MPLS等多个协议,各个协议间很容易形成相互依赖。以BGP协议为例:不仅需要平滑接收的路由信息和RIB信息,NSR倒换前后路由发送信息也需要备份和平滑。
三是主备间备份数据的高可靠性传输
- 主备设备间数据备份通道需要有很高的稳定性;
- 备份的关键数据必须保证正确,同时还有时序和性能要求。
四是如何进行正确的主备决策
- 需要有一套完善的系统能够快速进行主备决策;
- 同时还要避免误判,否则可能导致各种异常问题。
目前主流的设备厂商基本都已经实现了NSR,大致方案包括以下几种:
方案一:
方案概述:
- 基于linux内核实现,路由协议以独立进程运行在用户态,通过修改内核协议栈方式支持TCP NSR处理;
- 由TCP模块完成TCP状态信息的备份;
- 接口收到TCP报文后,会先将报文透传到备板内核协议栈,备板内核协议栈恢复TCP信息后,再将报文透传到主上内核协议栈,由主上的TCP协议栈上送给对应协议socket进行处理;
- 支持NSR的协议备进程不需要依靠外部事件触发协议状态机运行,而是通过主同步来的数据进行状态和数据的恢复。
存在如下问题:
- 首先通过报文先上备处理的方式进行TCP数据的恢复,减少了一次主备的交互,但整体连接的路径实际上增加了一个故障点,当备故障或进行升降级时,都会影响主的TCP状态。从而降低了NSR的可靠性;
- 其次是脑裂问题,NSR主备状态检查依靠的是主备板之间的心态报文检查模块,在堆叠情况下分裂后很容易出现双主情况。一但上层协议邻居在双主的情况下发生了交互就很容易导致邻居断开,从而导致NSR失败;
- 本方案对内核linux协议栈进行了特殊修改,很难进行虚拟化;
- 由于协议数据保存到备板,因而无法支持单机的NSR功能。
方案二:
方案概述:
- 基于Linux完全在用户态实现NSR功能,业务不修改内核协议栈;
- 在用户态提供协议栈垫层的方式配合应用协议完成TCP NSR功能,垫层本身需要完成TCP数据的从主到备的备份和恢复;
- 倒换时通过linux内核提供的TCP repair机制修复TCP连接的状态;
- 协议层面备板完全不运行,运行数据依赖于协议主的同步,但是协议层面需要记录TCP序列号等信息,倒换时辅助完成TCP repair过程。
存在如下问题:
- 仍旧存在脑裂问题;
- NSR数据需要实时备份备进程,同时在备进程进行恢复,因此无法完成单机NSR,只能通过模拟双机的方式实现进程级NSR,即需要在支持NSR功能时运用linux的容器化功能启动备容器,主实时同步数据给备进程,当主异常时,将备容器升级为主,因此单机NSR功能只可以在支持容器功能的产品上支持,同时支持NSR功能需要占用双倍的资源。
总的来看,虽然不同厂商采用多种方式实现了BGP协议的NSR功能,但是依然存在如下主要问题:
- 实现复杂:私有实现较多,需要TCP模块、BGP协议、RIB等多个模块配合实现,出问题后较难定位,运维困难;
- 脑裂问题:主备决策完全依赖于主备间的心跳探测,当主备间传输通道不稳定时,特别在盒式交换机堆叠的情况下,如果堆叠线不够稳定经常出现误判的情况,一旦出错,就很可能出现双主的情况,这类问题很难复现和定位;
- 较难支持单机ISSU:上述几种方案,必须还是NSR数据还是需要备份到备进程保存,因此需要实时运行一个存储运行数据的备进程来满足NSR切换的需要,对系统CPU和内存有较高要求。
FCR的主动NSR方案
主动NSR即由用户或者控制器主动通知FCR设备进行NSR的升降级处理,主要解决了升级软件版本场景和双邻居场景的问题,可以在保证业务不中断情况下快速迭代升级版本。
基本架构图如上,其中各个角色工作职责如下:
- 控制器: 根据设备状态和配置约束进行主备决策,下发NSR升降级等事件,决定FCR设备执行NSR操作过程;
- 分布式数据库:数据库服务集群,支持与FCR一同部署或者分离部署,负责保存FCR在NSR过程中存储的数据;
- FCR:FCR路由软件功能模块,支持主动NSR特性,与客户建立BGP邻居;
- FCR.XX:安装自研FCR的服务器设备,可以同时集成FCR路由软件功能和数据库服务;
- 客户:用户网络,与FCR建立BGP邻居并传递路由。
上述架构通过引入控制器作为第三方进行决策主备,解决传统设备经常出现的脑裂问题;通过引入分布式数据库具备了提供单机NSR能力;同时简化了协议内部的数据备份机制,降低了实现和维护复杂度。
TCP连接的备份和还原
倒换前后TCP的连接一致性设计逻辑,主要是由控制器统一管理设备的升降级动作,在主FCR收到降级事件时,借助Linux内核的socket repair机制到内核获取TCP对应的连接数据,同时与用户态协议数据一起备份数据库。备份完成后,再由控制器通知备FCR处理升级事件,备FCR收到升级事件再从数据库获取到这些信息,同样利用socket repair机制恢复TCP连接,同时协议数据再与TCP数据完成平滑,完成整个TCP连接的恢复。
TCP的关键数据包括:
- 五元组信息:要保证倒换后能恢复TCP连接,需要保证TCP五元组信息能够备份和还原,主要包括:源IP、目的IP、源端口、目的端口;
- 接收报文序列号:对端TCP连接发送来的接收报文确认序列号;
- 接收报文队列:未被用户态协议读取的内核协议栈TCP报文;
- 发送报文序列号:本端TCP连接发送报文的序列号;
- 发送报文缓冲区:内核未发送出去的TCP缓冲区数据。
为保证TCP连接恢复后,BGP协议报文能够处理正常,保证报文还原正确,协议也需要备份与TCP相关的数据。
升降级过程中从内核获取数据并写入数据库,简化了实现;同时用户态BGP协议帮助TCP了完成数据的备份和还原工作,不需要TCP协议栈单独再进行信息同步。同时也可以看到整个过程中备份的数据量是比较大的:单个BGP邻居至少需要备份3种不同的数据。因此对备份数据过程的性能和可靠性都有着比较高的要求。
数据库的选择
支持NSR功能时,需要备份和还原的主要数据及性能要求主要有:
- 路由数据:百万级BGP路由信息的读写数据库,性能要达到50K/秒;
- 会话信息:BGP会话信息和TCP相关数据在倒换过程中备份和还原,支持万级以上邻居时整体时间不能高于5秒。
因此支持NSR功能在选择分布式数据库时,需要有以下优点:
- 读写性能高:单线程情况下可以达到10万条数据/秒,可以满足NSR数据设计要求;
- 高可靠性:有成熟的高可靠性方案,可以实时监控数据库异常情况;
- 开源可控,集成简单:开源数据库实现,只需对开源代码进行简单封装就可以满足FCR应用,集成和维护方便。
目前比较流行的开源数据库软件如MongoDB、Redis、PostgreSQL等都基本满足要求,可以根据需要选择。
被动NSR探讨
主动NSR实现后能很好地满足FCR版本频繁升级的场景,而被动NSR则可以极大地提高整个路由控制系统的稳定性,但是实现被动NSR需要解决的问题要更多更复杂:
- 设备要支持随时进行主备切换的情况,如何能及时并准确判断并对设备下发切换指令;
- TCP报文和状态需要完全实时备份以满足任意时刻切换的要求,而大量数据写入数据库对TCP报文处理性能影响很大;
- 路由协议支持超大规模邻居和表项情况下备份数据的性能问题如何解决。
传统设备厂商为了解决上述NSR问题,在自己的通用数通平台上都设计了复杂的处理逻辑,主要包括:
- 增加单独组件进行主备间心跳检测来决策是否进行NSR切换;
- 实现统一的HA通道解决备份数据的性能和时序问题;
- 各NSR组件都采用多线程方案,同时备只进行数据恢复而不实际运行,从而提高处理性能。
从上述实现方案可以看出,传统设备厂商NSR的复杂度是非常高的,在软件开发和后期功能维护时都需要投入大量的人力,同时由于NSR涉及组件很多,出问题后又较难复现和定位。
显然,FCR作为互联网厂商自研的专用路由器是无法直接采用传统设备厂商方案的,而是需要另辟蹊径,设计适合自身应用场景的NSR方案。下面我们就来简单探讨下被动NSR的方案,主要有以下关键点:
- 支持NSR的应用协议可以采用当下比较流行的容器化和微服务化提高并发,将各个组件的异步处理变为同步处理,这样可以打破传统网络设备的scale UP限制,主备节点可以很方便的进行横向scale OUT扩展;
- 简化应用协议与TCP之间的平滑处理,在应用协议和linux内核协议栈中间增加缓存,流程简化可以对后续运维和软件迭代提供可靠保障;
- 完全去掉备角色,在主异常时新启动一个新的主来完成NSR升级过程,这样可以摒弃传统设备厂商的NSR主备行为,在不需要备的情况下进行NSR,完全避免主备决策错误等相关问题。
总之,互联网自研路由协议如果要实现一个简单地、能够快速迭代的NSR方案,就需要跳出传统NSR的设计思路,避免再次回到复杂化的老路上。
最后
本文讨论了云网络中路由协议的可靠性问题,以及互联网厂商与传统厂商实现NSR的差异;同时以腾讯云网络接入路由控制平台FCR为例讲解了在实践中的应用,也为后续持续演进提供了一些参考。
FCR作为一款互联网厂商自研的路由平台,在具备传统路由协议的功能的同时拥有互联网基因:
- 功能完备&高可靠性:适用于多种云网络场景,能够在快速开发迭代时保证高可靠性;
- 形态多样化:适应各种服务器,不仅可以单独发布FCR产品,还能作为容器运行在各种虚拟环境中;
- 微服务化:FCR产品中各个服务能够独立运行,不同的服务可以单独部署,在其中一个服务发生故障时不影响其他服务。
FCR在最初设计和开发的过程中就不断跟踪业界最新技术,并逐步将相关功能融入到平台中,已经发展为云网络场景中必不可少的重要组件。目前FCR已经在腾讯的专线接入、运营商接入、SDWAN接入、自研交换机、骨干网调度等场景落地生根,未来将在更多高可靠路由场景发挥作用。
道阻且长,行则将至,相信只要勇于实践,就一定可以打造出属于自己的最佳产品。
欢迎关注公众帐号“鹅厂网事”,我们给你提供最新的行业动态信息、腾讯网络最接地气的干货分享。
注1:凡注明来自“鹅厂网事”的文字和图片等作品,版权均属于“深圳市腾讯计算机系统有限公司”所有,未经官方授权,不得使用,如有违反,一经查实,将保留追究权利;
注2:本文图片部分来自互联网,如涉及相关版权问题,请联系v_meizhuang@tencent.com
鹅厂网事
分享鹅厂网络的那些事
扫码关注!解锁更多~