云原生路由架构探索

今日给某个云技术交流的分享, 转发出来.

以部署场景为中心的网络架构

网络技术的发展一直以来是以部署场景为中心,很多设备厂商也很自然的分成运营商数据中心企业网终端 等各个事业部。很多网络技术也是为了解决某个特定场景的问题而提出的。当然在这个过程中也相互借鉴,例如将MPLS VPN技术应用于Ipsec VPN之上构成了现在的企业网SDWAN架构的最佳实践。而VXLAN等技术又伴随着BGP EVPN等运营商技术的发展构建了现代数据中心的基础架构。

云原生路由架构探索

但是这样的设计方式可能需要一系列变革了,因为云的出现带来了一系列变化,云原生应用有了, 而云原生网络应该如何设计呢?这就是今天的主要议题。

应用和网络的割裂

现在的架构中,应用和网络是完全割裂开的,很多时候当我们有一个双线路由器的时候,而我们的手机只能看到默认网关一条路。我们期待路由器能够识别应用并根据性能智能的调度路径,但是这些操作通常非常复杂。

云原生路由架构探索

但是在生活中,选择那条路绕开拥塞路段却是非常容易的一件事,我们经常会把“车路协同”这个词挂在嘴边,是否可以借鉴这样的思路来构造一个网络和应用协同的架构呢?这也是很多运营商提出云网融合的原因。

以应用为中心

而云网融合的核心是以应用和数据为中心的架构,如何将已有的多种技术组合在一起,更好的给云原生应用服务,这才是下一代网络发展的方向。

应用的云原生改造

我们先从应用出发, 来看看云原生架构,可以看到API-Gateway到后期的ServiceMesh所使用的Sidecar所涵盖的功能和很多网络设备支持的功能并无太多的差别, 无论是智能路由,分布式负载均衡,还是流量管理,限流熔断,或者超时重试,微服务间的可视化,安全等等,

应用侧几乎是完全的自己造了一遍轮子,这样也带来了额外的开销,而智能网卡替代Sidecar的逻辑就在此。与此同时,我们在云网融合的场景下,又在SDWAN上继续造同样的轮子。唯一的区别就在于一个以应用为中心,另一个以网络为中心。能否将这些新的技术以应用为中心重新组织在一起呢?

以网络为中心的Calico

Calico为了和原有的数据中心基础架构整合,采用了BGP协议和Underlay交换机通信,针对较大规模部署时还需要RR. 因此这样的部署对网络拓扑有很强的依赖性,在具有收敛比的常规数据中心架构中,很容易出现拥塞点,但这种以网络为中心的架构在策略灵活性上却无法给应用提供很好的支撑.

当然也有以应用为中心的架构, 例如早期的基于Iptables劫持的实现方式,但是性能非常差

因此后期也出现了Cilium这一类以eBPF实现的透明SideCar技术,但是似乎对底层网络并没有做到很好的融合.

以应用和数据为中心

我们是否可以把网络作为资源注册到应用中,让终端进行消费呢?这样就构成了一种服务化的网络,也就是Network as a Service(NaaS)的场景。这也就是我设计Ruta时的第一个初衷,让应用的人更加容易的调度网络资源。而且现阶段来看,数据中心网络交换机逐渐开放,特别是软件层面由Sonic替代后,修改一下路由协议也是一件非常容易的事情了,但是关键问题是:网络该如何抽象成资源呢?

网络资源抽象

整个网络由多个网络设备多种链路类型构成,那么我们就需要将每个设备后面挂的资源(网段、主机)提供一种寻址的方式。所以无论是思科还是华为在对于资源的描述上都采用类似的做法:Transport Locator(TLOC)。

通过链路端点进行编码,例如我们会给每个网络设备定义一个回环地址,并将其作为System-IP或者传统路由协议中配置的Router-ID,然后针对不同的链路资源分组为不同的Color,把底层IP地址等信息隐藏起来,最后定义一下传输方式VXLAN、Ipsec、MPLS、GRE等,这个三元组构成了一个资源符,然后我们可以根据这些信息主动的探测远端的资源符,从而获得链路状态信息。这样我们就可以构建出一个资源矩阵了。

任何一个应用或者终端都可以在资源矩阵中消费,并自定义最优路径,这也是我们在SDWAN部署中的最佳实践,路由计算一定要分布式的方式进行,集中式控制器计算路由的解决方案通常都会碰到Scale的问题或者信息不一致的问题,或者决策无法下放的问题。分布式决策可以伴随着FlexAlgo玩出很多东西来,而且也更符合云原生的想法。

Segment Routing

最后我们就需要在数据包上标记该如何转发路径了,这里我们借用了Segment Routing的思路。

例如某个应用需要绕行MEC后再到云端,可以将其转发路径加入MEC路由器标签和云端路由器标签,然后中继节点根据标签转发即可。当然与此同时您会想到, 能否在报文中也定义一下MEC上该调用哪个函数处理,这样不就把Serverless也串入整个架构了么?当然可以咯。

数据面可编程

谈到MEC,当然还有一个重要的议题就是,Serverless和边缘计算了,很多时候我们对数据包需要分类并调用特定的函数处理,这也是Serverless出现的原因,此处我们可以借鉴SRv6的数据面可编程的思路,利用不同的标签作为函数的Callback指针

为什么不是SRv6

但是为什么不全盘使用SRv6呢?一方面,SRv6由于源地址不更改还存在一些uRPF校验的问题,

另一方面是整个互联网还没有准备好,可能国内IPv6建设非常快,但其它一些国家基础架构受到疫情的影响,经济缓慢复苏势必会在一些国家拖缓IPv6建设的进程。所以我们采取搁置争议的方式,在Layer-4 UDP层上实现这样的处理方式,保证了IPv4和IPv6的兼容,同时还为未来互通和平滑割接做好了准备。当然还有一个以应用为中心的考虑,SRv6的Option Header并不能够很好的在Userspace修改,而UDP极大的丰富了应用的可编程的能力,

Ruta数据面协议SRoU

所以Ruta的数据面实现,选择了Segment Routing over UDP的方式,我们新定义了一个SRoU的头,直接放置于UDP载荷中,当然在它也可以嵌入到QUIC或者IPsec中为传输层或者VPN业务赋能

当然谈到这个话题,历史上还出现过一种MPLS、SR over UDP的解决方案,即RFC8663. Ruta使用的SRoU相对于它采用了类似于SRv6的可编程SRH的定义方式,并且考虑了一个非常重要的场景NAT穿越

Ruta架构

所以Ruta的架构如图所示,控制面以应用为中心选用ETCD,同时ETCD的LeaseWatch机制非常适合用于路由协议通告路由信息,同时也和各种云原生应用能够更好的整合:

传统的网络转发节点,例如数据中心核心交换机、SDWAN路由器等都可以作为Ruta的Fabric节点,而一些家用路由器或者服务器的智能网卡,或者已有的ServiceMesh的Sidecar,甚至应用本身,都可以扩展出来作为Linecard接入到整个Ruta转发架构中. 您可以看到这个架构完全构建在UDP层之上,底层使用IPv4、IPv6、IPsec、或者MPLS并不重要。

Ruta的网元分类如下:

  • STUN: 需要有公网地址或者1:1NAT静态映射的地址。主要用于帮助其它节点发现公网地址
  • Fabric: 用于SRoU的中继转发节点.  它默认会根据经纬度等一系列信息主动的发起和其它Fabric之间的TWAMP测量协议。
  • Linecard: SRoU的头端和尾端,可以以多种形态存在,移动端的VPN  软件或者代理,家用路由器,AP,服务器端的智能网卡,应用的Sidecar这些节点可以根据地理位置信息直接发起对目的节点Linecard的TWAMP延迟测量,也可也hunt就近的Fabric节点并注册到Fabric节点的链路上。
  • Analytic: 主要用于watch stats,分析网络故障,为AIOps提供数据支撑等,它也可以作为分布式智能控制器帮助区域内节点进行策略优化等。通常我会用一些类似于Nvidia Jetson Xavier或者带GPU的大型节点放置于园区中用于做一些模型的推理。|

部署场景1:Mobile SDWAN

传统架构中,用户接入云VPC需要VPN或者SDWAN网关,而借助Ruta在Userspace的可编程能力,我们可以直接通过定制化的UDP通信库访问云端,甚至可以对QUIC等传输协议进行整合,实现可靠传输、弱网优化和网络访问的一体化解决方案

部署场景2:智能网卡和容器网络路由

在公有云等超大规模数据中心的部署下,传统的BGP管理数千台TOR交换机已经有些力不从心了,那么当智能网卡和HostOverlay出现以及容器网络的部署,路由协议该如何设计?传统的路由协议也约束了网络拓扑必须为CLOS架构进行负载均衡,并且考虑到成本还设计了3:1或者2:1的收敛比,当东西向流量出现拥塞时难以调度。

Ruta基于云原生的方式构建,对底层拓扑无依赖, 已有的交换机也可以在SONIC上实现协议栈,并且交换机作为Fabric节点,转发规则简单,复杂逻辑完全交由智能网卡处理,这样很好的实现了数据中心基础架构和VPC的融合

部署场景3:HPC通信库

超算通常场景中虽然也可以使用CLOS的架构,但是必须要1:1的收敛比,通常这样的网络部署成本较高扩展性也不是很好,因此很多超算平台都采用*-D Torus Ring的结构,传统的基于目的地址的路由无法很好的适应这样的多环状网部署,而Ruta基于源路由非常容易的解决了这个问题

部署场景4:全球性的协作系统弱网优化

由于疫情的影响,全球性的协作平台需求增长也非常迅速,但是直接通过互联网连接音视频会议体验非常差,这类业务通常需要进行弱网优化,优化过程中有采用SBC进行信令和媒体转接的方式,通常为静态配置的路径,并且每路呼叫都需要维持状态,Scale会非常差,运营成本也非常高

我们利用Ruta在全球多个公有云上部署了Fabric节点,然后进行了路由测试,发现可以通过自适应的路由算法实现200ms、零丢包全球可达

详细路径日志可以访问:

https://github.com/zartbot/ruta_demo/blob/main/multicloud/log_opt

其背后的逻辑是利用公有云的全球覆盖资源,同时借助公有云内部的一些Dark Fiber或者跨数据中心的广域网带宽资源自动发现优质路径,

然后由于公有云和很多传统运营商都有Peering,可以让本地网络可以尽快的接到云上,这样就规避了传统的Internet路由使用BGP跨越多个运营商的缺陷,在不改变Internet架构的同时,构建了一个Overlay将部分云节点构成了Transit-AS

Ruta协议详解

部署环境

这里我们以一个典型的数据中心Spine-Leaf基础架构和HostOverlay融合的方式进行部署, Fabric1、Fabric2可以为基础架构中的P4交换机,Linecard1、Linecard2可以为智能网卡或者SideCar

节点注册

每个节点会按照如下方式注册节点和通告业务能力:

  • SystemName:相对于传统的RouterID,SystemName更加易读,您可以继续采用RouterID编码方式,也可以使用ASCII String命名节点
  • SiteID:这个类似于BGP的ASN,主要是用以做一些site level的策略使用的。
  • SystemLabel:用来压缩SID长度或者和MPLS网络对接时的标签,也可以用这个标签映射成VPN客户端的IP地址。它总长24bit,通过分布式锁机制由ETCD分配。完成后还会生成一个/systemIP/到SystemName的映射,便于后期中继节点通过监听/systemIP获取网络标签表
  • SRLOC:该字段编码方式参考下节

SRLOC

SRLOC以设备SystemName为Key,Value包含Color 上下行带宽 私网地址 公网地址等多个参数,

同时我们在节点注册时,还会通告节点的GPS信息、内存和CPU使用信息、以及密钥等,通告节点密钥还有一个好处,在广域网SDWAN部署时避免了点到点的IKE密钥交互流程,做到了无状态隧道的转发机制。而协议安全由基于TLS加密的ETCD通信保障

Fabric注册

Fabric注册时会首先Get /service/stun列表,获取STUN服务器信息,并通过STUN服务检测到其公网地址,然后再向ETCD发起节点注册。

链路状态测量及通告

默认情况下,Fabric节点间会进行Fullmesh的链路节点Probe,并将结果发送到ETCD供应用消费,

LineCard部署:路由模式

这种模式应用于一些TOR Overlay场景或者传统的BGP-EVPN+VLXAN的部署替代,路由前缀定义和BGP-EVPN类似

路由转发

Overlay路由查询采用VPN(type2/type5)路由查询获取Underlay SRLOC,然后根据Linkstate本机可以构建一个FlexAlgo计算到远端的SRLOC路径,并构建转发的SRH

这里路由协议的实现非常灵活,因为是源路由的方式不会出现环路,因此也没有分布式一致性的问题,源可以通过一系列算法构建最优转发路径. 您可以使用最简单的SPF计算,基于时延或者丢包率都行.

复杂一点的则是我在思科的另一个AIOps项目Nimble Engine就可以根据APM和NPM的结果进行基于ML模型的推理评分:

我们可以看到这些推理评分系统的在注入网络损伤后的结果, 这些HealthScore可以作为强化学习的Reward,基于决策树的故障根源分析可以为强化学习的Action搜索空间剪枝

而Ruta自带的Linkstate矩阵则构成了Environment,最终通过强化学习,可以自主优化路径。

LineCard as SideCar

当LineCard为SideCar模式时或者为应用终端时处理更加简单,业务本身是注册到ETCD的,只需要随机寻找Fabric节点(例如地理位置最近的Fabric),把连通Fabric节点的Linkstate和加密密钥上报即可,这样终端应用直接在ETCD中就可以获取可达路径了。

Ruta数据面报文格式

  • Magic Number: 报文头中的Magic Number,当用于QUIC传输时,它为0x0,这样正好区分开QUIC的Long/Short Packet Flags,而针对IPSec封装时取值为0xF,并规定IPsec SPI不分配0xFxxxxxx的SPI就好。通过这样的方式就可以在原有的IPsec隧道或者QUIC会话中添加SR能力了。

  • FlowID字段:协议定义是变长的,在报头也有一个Length字段帮助ASIC定位,但工程实现上可以定义为一个64bit或者128bit flowid,它的用途一方面是用于做基于流的监控和分析,类似于Google Dapper的TraceID,而SID-List则可以作为Parent-ID使用,另一方面也适合于DetNet的处理,可以进一步控制延迟。而当我们在IPv4公网上架设服务时,也需要一个token机制避免其它人使用您的带宽,或者注入攻击流量,这也是一个接入控制的ID,处理机制和互联网公司的Token机制类似,验证+黑名单数据库即可。

  • Source Address: 这个字段用于头端封装自己的公网地址,或者第一跳Fabric节点帮助将接收到的IP包的公网地址和端口压入这个字段。主要目的是让远端的隧道终点溯源同时执行逆向对称路由或者可优化的非对称路由。第一跳压入还有另一个考虑,在报文中间插入header会是一个非常麻烦的事情,中继Fabric节点如果需要插入源地址信息在UDP头中,如果用DPDK实现则需要把mbuf 拆开,然后insert,或者把很多bytes 前移后移空出一段。而第一跳需要LineCard识别公网也很麻烦,搞STUN代价也有点大,所以第一跳还可以什么都不干,allocate一段source address 空间置0就好,而Fabric节点的第一跳设备可以自动的把源地址源端口拷贝进入这个字段即可。

  • SRH & Function: 定义和操作方式和SRv6完全一致,只是针对IPv4的UDP overlay场景添加了一个48bit长度的SID支持, IPv6网络中可以采用UDP固定协议端口的方式沿用128bit SID即可。所有的字段要直接拷贝到SRv6 SRH中也非常容易。同时正如前文所述,考虑到IPv4支持可编程的能力,我们将SID中高位为255.0.0.0:xx的整个一段用于执行End.X的可编程处理能力,例如我们的线卡节点接收到一条Type-2EVPN路由,数据包的Segment-List[0]的封装即为<255:VNID:End.X>, 定义上End.X正好16bit,VNID也刚好24bit,而255.0.0.0/8的地址段正好又没人用,就这样我们在IPv4网络上也可以实现类似的可编程能力。

  • INT Rewrite: draft-version-01会添加的新功能,主要是SRH编码也有缺点,header不好删,那么我们可以采用ReWrite用过的SID来构建对该跳节点的In-Network Telemetry描述。

安全策略

通信上由于采用了TLS连接到ETCD,而且ETCD也有非常完善的RBAC控制, 控制面我们仅需要定义一些策略列表即可,但是转发面基于一些已有的研究,我们需要将报文标记分类三类, 一类是租户隔离信息,另一类是安全相关的Token或者微分段的身份信息,最后是用于最优路径转发的流量工程信息:

云原生路由架构探索》来自互联网,仅为收藏学习,如侵权请联系删除。本文URL:http://www.hashtobe.com/222.html