注:
- 本文根据《BGP in the Datacenter》整理,有兴趣和英文阅读能力的朋友可以直接看原文:https://www.oreilly.com/library/view/bgp-in-the/9781491983416/
- 上一部分笔记请参考:https://blog.csdn.net/tushanpeipei/article/details/128526841
一、自动化配置基础
在数据中心规模的网络下,自动化是必须的。否则我们只会因为太低的效率而无法实现目标。当然,实现自动化的方式有很多,例如最基础的使用Python脚本多线程配置设备,或者是通过一些开源自动化工具例如Nornir、Ansible对设备进行运维,乃至可以利用基于意图的网络(IBN)等方式实现自动化。总的来说,自动化的方式很多,在这里不会过多的去解释,我们需要将重点集中在BGP本身。
进一步说,任何自动化都需要具体的配置模版,对BGP来说也不例外。我们需要找到BGP的模版,并且该模版需要满足如下需求:
- 健壮性(robust):足够的健壮性才能减少变动带来的危险;
- 避免重复:长期的实践证明,重复的配置容易导致错误。
二、数据中心架构举例
后续的知识点涉及到配合拓扑进行说明,在这里我们使用的拓扑如图1所示:
在我们的网络中,我们配置了以下内容:
- Leaf,Leaf01到Leaf04;
- Spine,Spine01到Spine02;
- Exit01,Exit01到Exit02;
- Server,Server01到Server04除服务器;
- 设备之间统一运行eBGP。
三、BGP自动化中存在的痛点
首先我们来看一下一个常见的BGP配置。这里以图1中的Leaf01的BGP配置为例子
router bgp 65000 //该Speaker的ASN
bgp router-id 10.0.254.1 //通告Router-id来唯一标识一台Speaker
bgp log-neighbor-changes //自动log邻居状况的改变
bgp no default ipv4-unicast //默认不在ipv4-unicast地址簇中建立邻居
timers bgp 3 9 //设置的keepalive和hold定时器
neighbor peer-group ISL //定义具有相同策略的对等体组
neighbor ISL remote-as 65500 //该对等体组的ASN
neighbor ISL advertisement-interval 0 //设置Update消息的通告时间
neighbor ISL timers connect 5 //设置connect定时器的时间
neighbor 169.254.1.0 peer-group ISL //将目标地址加入对等体组
neighbor 169.254.1.64 peer-group ISL //同上
address-family ipv4 unicast //进入ipv4-unicast地址簇中
neighbor ISL activate //在该地址簇中与所有ISL对等体的成员建立邻居关系
network 10.0.254.1/32 //通告网关网络进入BGP
network 10.1.1.0/26 //通告下连服务器的子网地址进入BGP
aximum-paths 64 //设置最大的mutipath数量
exit-address-family
根据上述的配置我们可以看到首先其中出现了重复(duplication)。例如,例如,10.1.254.1被指定两次,一次有/32(网络通告),一次没有(router-id)。如果代码经验丰富的话,我们能可以很清楚在编写代码时需要避免重复的代码。这是因为如果重复点出现问题,我们需要同时修改多处。但是通常,我们容易忽略一些其他的重复点。例如,在上面点BGP配置中,如果我们节点配置的网关IP地址10.0.254.1已经被分配给了其他设备,但是我们仅仅修改了network部分,却忽略了修改router-id,这当导致一些邻居建立的故障(在peering iBGP邻居时)。
进一步说,这种配置还假设每个Leaf下行只有一个VLAN或子网。如果有多个子网,将它们全部列出的个将是不可扩展的,并且无法读取。接下来再来看看Spine01上的配置:
router bgp 65534
bgp router-id 10.0.254.254
bgp log-neighbor-changes
bgp no default ipv4-unicast
timers bgp 3 9
neighbor peer-group ISL
neighbor ISL advertisement-interval 0
neighbor ISL timers connect 5
neighbor 169.254.1.1 remote-as 65000
neighbor 169.254.1.1 peer-group ISL
neighbor 169.254.1.3 remote-as 65001
neighbor 169.254.1.3 peer-group ISL
neighbor 169.254.1.5 remote-as 65002
neighbor 169.254.1.5 peer-group ISL
neighbor 169.254.1.5 remote-as 65003
neighbor 169.254.1.7 peer-group ISL
bgp bestpath as-path multipath-relax
address-family ipv4 unicast
neighbor ISL activate
network 10.0.254.254/32
maximum-paths 64
exit-address-family
可以看到,在Leaf节点上出现的问题也存在于Spine节点的配置中。当然,结合Leaf和Spine的配置,我们也可以看到一些配置正确的点:
- 每一条链路使用/31位的网络号,能节约IP地址;
- 网关地址以32位路由的形式被单独通告了出来,和服务器所在子网不同;
- 假设每一个机架有40台服务器,我们需要给每个机架分配的子网为/26,其覆盖64-2个IP地址,可以满足现状和拓展需求。
总结一下BGP配置中遇到的困难。配置中存在了太多的IP地址,这意味着我们在多个地方有重复信息。因此随着新IP地址的添加和删除,配置变得脆弱和不可扩展。
四、重分发路由
我们可以看到IP地址主要出现在标识邻居以及network路由条目的配置中。首先我们来解决network路由时出现的IP路由信息。我们知道,BGP“发现路由”目前主要通告两种方式,一是通告network命令将本地已经存在的路由通告进入BGP中,还有一种则是通告重分发(redistribute)的方式将路由通告进入BGP。重发布命令如下所示(不同厂商可能会不同):redistribute protocol route-map route-map-name。
其中的协议(protocol)关键字段指的是静态(static)、直连(connected)、ospf、isis、bgp等不同种类的路由。例如,我们想要将直连路由重分发进入到BGP可以在节点上输入:使用redistribute connected命令即可。这种情况下,我们在BGP的配置中就代替了network+IP网段。然而,这种不加修饰的重分发通常会将额外的一些路由发布到BGP,所以这里我们需要通告路由策略(routing policy)来限制重分发的路由,仅仅允许我们需要的路由进入BGP中。
五、路由策略
路由策略(routing policy)可以最直接的功能就是帮助我们允许和拒绝路由。此外,它还可以匹配对应的路由,并调整路由的属性。进一步说,Route-maps是路由策略的一个普遍的实现方式,当然不同厂商的命令可能不同,但是大体都是按照如下的格式进行配置的:
route-map NAME (permit|deny) [sequence_number]
match classifier
set action
其中,NAME关键字这为策略分配了一个名称,permit|deny关键字则指示匹配的路由是被允许还是拒绝,sequence_number则是该规则的执行顺序(同一个route-map下可以有多个策略)。接下来进入match子句,如果匹配子句成功匹配分类器(classifer),则该集合子句对路由起作用。这时,当我们在该语句使用的是permit关键字时,则执行set子句后的动作(action)并放行,如果没有动作,则默认放行。但当我们使用deny关键字时,match失败时会应用set后的动作。换句话说,拒绝函数作为“非(not)”运算符:如果有匹配,请拒绝路由;没有匹配,则执行动作并放行。最后,所有route-map的末尾有一个隐式的“拒绝”。因此,如果没有匹配的条目,结果就是拒绝输入。
此外,支持BGP协议的Classifiers十分丰富,如下所示:
- as-path:匹配BGP的AS_PATH属性;
- community:匹配BGP路由的团体属性;
- ext- community:匹配BGP路由的拓展团体属性;
- interface:匹配路由下一跳的接口的名称;
- ip/ipv6:匹配人任意的IP地址,下一跳以及原地址(前缀列表);
- local- preference:匹配BGP路由的本地优先级;
- metric:匹配路由的metric;
- origin:匹配路由的ORIGIN属性;
- peer:匹配对等体。
在这里我们给出一个route map的配置案例,如下所示:
route-map EXCEPT_ISL_ETH0 deny 10
match interface swp51
route-map EXCEPT_ISL_ETH0 deny 20
match interface swp52
route-map EXCEPT_ISL_ETH0 deny 30
match interface eth0
route-map EXCEPT_ISL_ETH0 permit 40
redistribute connected route-map EXCEPT_ISL_ETH0
可以看到,该route-map允许其他所有的直连路由重分发进入BGP,但是拒绝来上行swp51,swp52接口以及管理接口eth0的网段被通告进入BGP。但是这是不安全的,因为在最后一步允许了所有的路由进入BGP,违反了安全route map的设计方式:永远拒绝那些不是明确允许的路由。因此我们需要使用的route-map是明确允许可以放行的路由,然后拒绝其他不是明确允许的路由。也就是在多个permit节点后拒绝所有其他的路由,这与上述演示正好相反。当然如果需要允许的节点太多,我们可以通过一些聚合的方式批量匹配路由。
接下来,我们继续探索一些route-map的使用点。不仅仅在重发布的时候我们可以调用route-map,我们还可以在指定对等体时,在出方向和入方向过滤路由、改变路由属性,如下所示:
eighbor 169.254.1.1 route-map NBR_RT_ACCEPT in
neighbor 169.254.1.1 route-map NBR_RT_ADV out
或者在network时对其进行调用:
network 10.1.1.1/24 route-map ADV_NET
最后,我们需要注意的是使用route-policy时候的性能调优。BGP是一种路径向量(path-vector)路由协议,因此在运行最佳路径算法之前,它不会宣布路由更新。route-map通常应用于数据包接收和数据包发送。如果一个BGP Speaker有数十个或数百个邻居,并且这些邻居都附有route-map,那么他会在通告路由之前之前为每个邻居运行route-map,将会在很大程度上降低设备CPU处理转发流量的性能。
因此,我们通常使用peer-groups技术来解决这个问题。peer-group中的所有成员(必须具有统一的功能)具有一个统一的route map。因此,对于整个peer-group的所有成员执行路由通告或者撤销的时,我们仅仅只需要执行一次route-map。
六、使用接口名字作为邻居标识
在上述两个小节中,我们探索了使用重分发+路由策略的方式减少了BGP配置中由于network命令引入的IP网段信息。接下来,我们可以使用接口名字作为邻居标识,进一步的减少在BGP配置中指定对端设备地址时配置的IP地址信息。
可以看到在Clos网络架构中,每一层设备之间建立了大量的连接,但是这些连接都是点到点(P2P)的形式。因此我们可以使用/31位掩码来覆盖每条链路的2个IP地址。同时,一台设备肯定是知道自己接口上的IP地址,那么就能快速推导出对端的IP地址为该网段的另外一个。在这种情况下,我们可以不指定对等体IP地址,而通过指定本地接口的形式与对端建立BGP邻居关系。(注:这种方式仅仅能使用在/30或者/31掩码的情况下)。
例如,我们可以将Leaf01的BGP配置进行如下的修改:
neighbor 169.254.1.0 peer-group ISL
neighbor 169.254.1.64 peer-group ISL
上面是使用IP地址指定对等体的情况,接下来我们可以将IP地址替换为本地的接口名称:
neighbor swp51 interface peer-group ISL
neighbor swp52 interface peer-group ISL
最终,通过上述优化后,Leaf01和Spine01的配置分别变为了下面这种形式:
Leaf01:
ip prefix-list DC_LOCAL_SUBNET 5 permit 10.1.0.0/16 le 26
ip prefix-list DC_LOCAL_SUBNET 10 permit 10.0.254.0/24 le 32
route-map ACCEPT_DC_LOCAL permit 10
match ip-address DC_LOCAL_SUBNET
router bgp 65000
bgp router-id 10.0.254.1
bgp log-neighbor-changes
bgp no default ipv4-unicast
timers bgp 3 9
neighbor peer-group ISL
neighbor ISL remote-as 65500
neighbor ISL advertisement-interval 0
neighbor ISL timers connect 5
neighbor swp51 peer-group ISL
neighbor swp52 peer-group ISL
address-family ipv4 unicast
neighbor ISL activate
redistribute connected route-map DC_LOCAL
maximum-paths 64
exit-address-family
Spine01:
ip prefix-list ACCRT 5 permit 10.1.0.0/16 le 26
ip prefix-list ACCRT 10 permit 10.0.254.0/24 le 32
route-map DC_LOCAL permit 10
match ip-address ACCRT
router bgp 65500
bgp router-id 10.0.254.254
bgp log-neighbor-changes
bgp no default ipv4-unicast
timers bgp 3 9
neighbor peer-group ISL
neighbor ISL advertisement-interval 0
neighbor ISL timers connect 5
neighbor swp1 remote-as 65000
neighbor swp1 peer-group ISL
neighbor swp2 remote-as 65001
neighbor swp2 peer-group ISL
neighbor swp3 remote-as 65002
neighbor swp3 peer-group ISL
neighbor swp4 remote-as 65003
neighbor swp4 peer-group ISL
bgp bestpath as-path multipath-relax
address-family ipv4 unicast
neighbor ISL activate
redistribute connected route-map DC_LOCAL
maximum-paths 64
exit-address-family
到此,我们已经可以通过route-map加上重分发,以及接口代替IP地址的方式让整个BGP配置模版更加的通用和减少了重复点。但是,我们还是可以看到,在BGP的配置中依然存在大量的ASN,以及在链路的两端依然配置了IP地址。那么,我们能否用一些方法去替代ASN和接口IP地址的配置?这将是我们下一个笔记中探讨的内容。