《Cloud Native Data Center Networking》(云原生数据中心网络设计)读书笔记 -- 11部署BGP

本章应有助于回答以下问题:

  • 核心的配置概念是什么?
  • 如何为 Clos 网络配置 BGP ?
  • 无编号的 BGP 如何工作?
  • 如何配置 BGP 与主机上的 BGP 发言者 (例如 Kube-router) 建立对等关系?
  • 如何配置 BGP 以对网络进行计划维护?

核心的 BGP 配置概念

全局BGP 配置,包含:

  • router-id (路由器 id) 配置。
  • Neighbor (邻居) ,或称为 peer (对等方) 配置
  • Routing policy (路由策略)定义。
  • Timer (计时器)配置。

Neighbor 相关的配置,包含:

  • 非全局计时器配置。
  • 和地址族无关的配置。

地址族相关的配置,包含:

  • 为 neighbor 启用 AFI/SAFI

    在BGP(Border Gateway Protocol)中,AFI(Address Family Identifier)和 SAFI(Subsequent Address Family Identifier)是用于标识和处理不同类型的地址族的概念。它们的结合允许BGP扩展其功能,以支持多种类型的网络地址,如IPv4、IPv6、VPN等。

    1. AFI(Address Family Identifier)

    AFI标识了地址的类别,即地址族。常见的AFI值包括:

    • 1:IPv4
    • 2:IPv6
    • 25:L2VPN(Layer 2 VPN)

    2. SAFI(Subsequent Address Family Identifier)

    SAFI进一步细化了AFI,指示地址的具体类型或用途。常见的SAFI值包括:

    • 1:Unicast
    • 2:Multicast
    • 4:Labeled Unicast(用于MPLS)
    • 128:MPLS-labeled VPN address
    • 129:Multicast VPN address

    3. AFI/SAFI组合

    AFI和SAFI的组合定义了BGP所处理的具体地址类型和应用场景。以下是一些常见的AFI/SAFI组合:

    • AFI 1, SAFI 1:IPv4 Unicast
    • AFI 1, SAFI 2:IPv4 Multicast
    • AFI 2, SAFI 1:IPv6 Unicast
    • AFI 2, SAFI 2:IPv6 Multicast
    • AFI 1, SAFI 128:VPNv4(用于MPLS VPN)
    • AFI 2, SAFI 128:VPNv6(用于MPLS VPN)

    4. 功能与应用

    通过使用AFI和SAFI,BGP能够灵活地支持多种不同类型的网络架构和服务。例如:

    • 多协议BGP(MP-BGP):通过扩展BGP以支持多个协议族(不仅仅是IPv4 Unicast),使BGP能够在MPLS VPN、IPv6、L2VPN等多种网络环境中工作。
    • VPNs:通过使用AFI/SAFI组合,BGP能够处理和通告多种类型的VPN地址,这在服务提供商网络中非常常见。
    • 多播路由:通过适当的AFI/SAFI组合,BGP可以用于通告和管理多播路由。

    实际配置示例

    一个典型的配置示例如下:

    bash 复制代码
    router bgp 65000
    neighbor 192.0.2.1 remote-as 65001
    address-family ipv4 unicast
      neighbor 192.0.2.1 activate
    address-family ipv6 unicast
      neighbor 192.0.2.1 activate

    在上述配置中:

    • address-family ipv4 unicast 对应 AFI 1 和 SAFI 1(IPv4 Unicast)。
    • address-family ipv6 unicast 对应 AFI 2 和 SAFI 1(IPv6 Unicast)。
  • 路由通告。

  • 在 neighbor 上应用 routing policy。

图15-1:用于演示BGP配置的Clos拓扑

二层 Clos 拓扑的传统配置: IPv4

像 OSPF一样,我们首先查看使用已编号接口分发 IPv4 路由的传统 BGP 配置。我们使用图 15-2 中所示的二层 Clos 来对此进行说明。

如第 14 章所述,我们在这使用了eBGP。每个路由器的 ASN 是一个从 65000 开始的数字,显示在该路由器图标的左上方。两个 spine的 ASN 相同,都是 65000,而每个leaf有一个不同的ASN,从 leaf01 的 65101 开始,到 leaf04 的 65104 为止。与之前一样,图中每个路由器内部显示的 IP 地址是该路由器的回环IP地址。服务器通过桥接网络连接到其关联的 leaf 路由器上。

Example 15-1. spine01和leaf01的传统BGP配置

1)spine01配置

bash 复制代码
! Configuration for spine01
!
interface lo
 ip address 10.0.0.21/32
!
interface swp1
  ip address 169.254.1.0/31
!
interface swp2
  ip address 169.254.1.2/31
!
interface swp3
  ip address 169.254.1.4/31
!
interface swp4
  ip address 169.254.1.6/31
!
router bgp 65000
  bgp router-id 10.0.0.21
  bgp log-neighbor-changes
  # BGP 计时器的默认值不适用数据中心,因此需要进行调整
  timers bgp 3 9   
  # BGP 对IPv4 单播地址族有一些默认行为,其中最关键的是缺省情况下自动启用 IPv4 路由的发布。但是许多运营商都喜欢显式激活该配置。
  # 通过该行关闭了IPv4 单播地址组的默认激活。
  no bgp default ipv4 unicast
  neighbor 169.254.1.1 remote-as 65101
  neighbor 169.254.1.3 remote-as 65102
  neighbor 169.254.1.5 remote-as 65103
  neighbor 169.254.1.7 remote-as 65104
  # 设置BGP邻居(IP地址为169.254.1.1)的路由更新广告间隔为0秒
  # 将广告间隔设置为0秒意味着BGP路由器将尝试立即向邻居发送路由更新,而不进行延迟。这可以在网络拓扑发生变化时更快地传播更新信息。
  neighbor 169.254.1.1 advertisement-interval 0 
  neighbor 169.254.1.3 advertisement-interval 0
  neighbor 169.254.1.5 advertisement-interval 0
  neighbor 169.254.1.7 advertisement-interval 0
  neighbor 169.254.1.1 bfd
  neighbor 169.254.1.3 bfd
  neighbor 169.254.1.5 bfd
  neighbor 169.254.1.7 bfd
  # 放宽BGP多路径选择的标准。
  bgp bestpath as-path multipath-relax
  address-family ipv4 unicast
  	 # 为了将一个地址族的路由通告给其邻居,BGP 必须为每个邻居激活该地址族activate 命令用于让 BGP 在 BGP OPEN 消息中通告该地址族的能力。
  	 # 只有当对方也支持该地址族时,才会发布该地址族的路由。
      neighbor 169.254.1.1 activate 
      neighbor 169.254.1.3 activate
      neighbor 169.254.1.5 activate
      neighbor 169.254.1.7 activate
      # redistribute 命令被放在一个特定的地址族下。BGP 是一种多协议路由协议,在特定地址族下使用 redistribute 命令只会重新分发该地址族的信息。如果需要为多个地址族重新分发直连路由,则需要在每个地址族下都指定 redistribute 命令
      # 由于接口具有IP地址,因此redistribute connected命令除了通告回环地址和服务器子网的IP地址外,还会通告接口的IP地址。
      # 接口IP地址增加了一些开销,包括多出的 BGP 消息,扩大了RIB和FIB大小等
      redistribute connected 
      # 与OSPF不同的是,BGP 并不会自动启用 ECMP (等价多路径) ,而是需要通过 maximum_paths 命令明确告知 BGP 这样做。像 redistribute 命令一样,可以配置只为指定的 AFI/SAFI 启用 ECMP
      maximum-paths 64       
  exit-address-family

2)leaf01配置

bash 复制代码
! Configuration for leaf01
!
interface lo
 ip address 10.0.0.11/32
!
interface swp1
  ip address 169.254.1.1/31
!
interface swp2
  ip address 169.254.2.1/31
!
! This next statement is for the servers subnet
!
interface vlan10
  ip address 172.16.1.1/24
!
router bgp 65011
  bgp router-id 10.0.0.11
  bgp log-neighbor-changes
  timers bgp 3 9             
  no bgp default ipv4 unicast 
  neighbor 169.254.1.0/31 remote-as 65000
  neighbor 169.254.2.0/31 remote-as 65000
  neighbor 169.254.1.0/31 advertisement-interval 0 
  neighbor 169.254.2.0/31 advertisement-interval 0
  neighbor 169.254.1.0/31 bfd
  neighbor 169.254.2.0/31 bfd
  address-family ipv4 unicast
      neighbor 169.254.1.0/31 activate 
      neighbor 169.254.2.0/31 activate
      redistribute connected 
      maximum-paths 64       
  exit-address-family

多路径选择

bgp bestpath as-path multipath-relax 是一个在BGP配置中使用的命令,用于放宽BGP多路径选择的标准。具体来说,它允许BGP在选择多路径时忽略AS路径的完全匹配要求,从而实现多路径选择的功能。

在默认情况下,BGP的最佳路径选择算法在进行多路径选择时要求AS_PATH(自治系统路径)必须完全匹配。这意味着,仅当两条路径的AS_PATH完全相同且其他度量值(如本地优先级、MED等)也相同时,BGP才会将这些路径视为等价并使用多路径。

当启用 bgp bestpath as-path multipath-relax 时,BGP将放宽多路径选择的AS路径匹配要求。这意味着BGP不再需要AS_PATH完全匹配,只要路径长度相同且其他度量值也相同,就可以认为这些路径是等价的,从而允许多路径选择。

假设有两条到同一目的地的路径:

  • 路径1:AS_PATH = {AS100, AS200, AS300}
  • 路径2:AS_PATH = {AS101, AS201, AS300}

在没有启用 bgp bestpath as-path multipath-relax 的情况下,BGP不会将这两条路径视为等价路径,因为它们的AS_PATH不完全匹配。

但是,启用 bgp bestpath as-path multipath-relax 后,只要这两条路径的长度相同且其他度量值(例如本地优先级、MED等)也相同,BGP将允许这两条路径作为多路径进行选择和使用。

实际配置示例

bash 复制代码
router bgp 65000
  bgp bestpath as-path multipath-relax
 address-family ipv4 unicast
    neighbor 192.0.2.1 remote-as 65001
    neighbor 192.0.2.1 activate
    maximum-paths 4
  !
  address-family ipv6 unicast
    neighbor 2001:db8::1 remote-as 65001
    neighbor 2001:db8::1 activate
    maximum-paths 4
  !

在上述配置中:

  • bgp bestpath as-path multipath-relax 启用了放宽AS_PATH匹配要求的多路径选择。
  • maximum-paths 4 指定了最多使用4条等价路径。

配置示例的问题

配置不容易实现自动化,因为每个节点的配置看起来都不同。spine01 的配置看起来与其他 spine 不同,leaf01的配置看起来与所有其他 leaf 也不相同,其他节

点也是如此。

该配置要求我们在配置 neighbor时使用每个远程对等方的IP 地址,BGP 进程会尝试与该地址建立连接或从其接受连接。需要对端IP 地址信息使 BGP 配置在

自动化和故障定位方面比 OSPP 稍微复杂一些。

该配置还要求使用远程对等方的 ASN。从leaf的角度来看,这很容易,因为所有 spinc的ASN都相同。但是对于 spine 就必须小心将ASN与正确的IP地址相关联。

很难发现配置中的错误 (例如,难以通过目测发现),因为错误可能源于多行之间的相互作用,因此需要验证多条信息。

必须重复 neighbor命今以配置各种参数,例如advertisement intervalactivation

由于接口具有IP 地址,因此redistribute connected命令除了通告回环地址和服务器子网的IP地址外,还会通告接口的IP地址。接口IP地址增加了一些开销,包括多出的BGP 消息,扩大了 RIB和FIB 大小等,这些开销是不必要的。

BGP 还支持用于指定需要通告的地址前级的配置命令。我们可以使用该命令来设置BGP 只通告回环地址和服务器子网,而不是使用redistribute connected

重分发所有直连路由。但这样做会使我们无法在路由器之间获得尽可能相同的配置。

Peer Group

为了简化对多个 neighbor的重复配置,大多数的路由套件都支持一种称为 peer group 的模板。用户创建一个 peer group 来配置所需的邻居连接属性 (例如remote-as,连接计时器和BFD的使用等),然后将每个邻居加入创建的 peer group中在后面的配置中,可以直接引用该 peer group,从而避免了一次又一次地键入相同的内容。很多的路由实现,包括 FRR,Cisco,Juniper和 Arista,都支持某种形式的 peer group。

示例 15-2: 使用了 peer group 的传统 BGP 配置

bash 复制代码
router bgp 65000
  bgp router-id 10.0.0.21
  bgp log-neighbor-changes
  timers bgp 3 9
  no bgp default ipv4 unicast
  # 这里定义了一个名为ISL的 peer-group
  neighbor peer-group ISL                                             
  # 设置 ISL peer-group 中所有成员共享的属性
  neighbor ISL bfd                                                    
  neighbor ISL advertisement-interval 0                               
  # remote-as 的值对于每一个对等方来说是不同的,因此我们不能设置一个公共的值
  neighbor 169.254.1.1 remote-as 65101                                
  # 将一个neighbor加入已定义的 peer-group 中,加的 neighbor会继承该 peer group 中所有相关的属性
  neighbor 169.254.1.1 peer-group ISL                                 
  neighbor 169.254.1.3 remote-as 65102
  neighbor 169.254.1.3 peer-group ISL
  neighbor 169.254.1.5 remote-as 65103
  neighbor 169.254.1.5 peer-group ISL
  neighbor 169.254.1.7 remote-as 65104
  neighbor 169.254.1.7 peer-group ISL
  bgp bestpath as-path multipath-relax
  address-family ipv4 unicast
      neighbor ISL activate
      redistribute connected
      maximum-paths 64
  exit-address-family

路由策略

**路由策略最简单的用法是用于指定何时接受或拒绝路由通告。**基于路由策略的使用位置,接受或拒绝的动作可以作用于从对等方接收的路由,发布给对等方的路由以及重新分发的路由。路由策略的更复杂的应用包括修改影响最佳路径选择的度量标准,以及为一个前缀或一组前缀添加或删除属性或团体。鉴于 BGP 主要用于连接不同的管理域,因此 BGP 具有所有路由协议中最复杂的路由策略。

路由策略由一系列 if-then-else 语句组成,当匹配条件符合时,会执行相应的动作。例如我们可以定义下面的路由策略,以避免上一节提到的通告接口IP 地址的问题(这里用伪代码表示,在本节末尾,我们将会展示该伪代码对应的实际配置)

shell 复制代码
if prefix equals '169.254.0.0/16' then 
	reject 
else 
	accept

在重新发布直连路由的配置中,一种安全的策略是接受属于该数据中心的路由,并拒绝任何其他路由。

到目前为止,我们看到的配置包含两种子网前缀:172.16.0.0/16 (假设网络中有很多个连接到主机的子网),以及路由器的回环IP 地址,例如 10.0.0.11/32。此外还有一个接口地址子网169.254.0.0/16,该子网不应该对外发布。

由于可以有多个这种路由策略,因此我们需要给这个策略命名。

几乎所有网络配置中的 route-map 和 prefix-list 名称都使用全大写形式

shell 复制代码
ACCEPT_DC_LOCAL(prefix)
{
    if prefix belongs to 172.16.0.0/16 then accept
    else if (10.0.254.0/24 contains prefix and
             subnet equals 32) then
    accept
    else reject
}

route map: 路由策略的实现

route map 是用于实现路由策略的常用方法。FRR,Cisco的IOS,NX-OS,Arist和其他许多路由栈都支持 route map。

每个 route-map 的格式如下:

shell 复制代码
route-map NAME (permit|deny) [sequence_number]
  match classifier
  set action

route-map 的定义为策略设置了一个名称并指明匹配的路由将被允许还是被拒绝,然后将输入与条件进行匹配。

  • 如果 match 子句成功匹配条件,则 set 子句将被作用于该路由。
  • sequence_number 是一个可选字段,当有多个相同名称的 route-map时,sequence_number 用于指定执行的顺序
  • permit 关键字表示当匹配成功时将执行指定的操作
  • deny 关键字表示当匹配失败时会执行指定的操作。换句话说,deny 相当于一个"非"运算符,如果一条路由匹配条件,则该路由会被该 route map 拒绝。

route-map 的末尾有一个隐含的"deny"条件分支,即如果没有条目匹配,则结果是拒绝该输入。

route map中的分类器

route map 有很多可用的匹配条件。你可以使用各种各样的特征作为匹配条件,不同的BGP 实现支持这些匹配条件的不同子集 (有些实现支持所有标准的匹配条件,以及一些扩展的条件)。

表15-1 中是在数据中心中最有用的一些匹配条件

Classifier name Description
as-path Match value from BGP's AS_PATH
ip Match IPv4 information such as IP address, next hop, or source
ipv6 Match IPv6 information such as IP address, next hop, or source
interface Match name of interface
peer Match session peer's information

如何定义两个 IP 前缀,将其作为路由策略的匹配条件:

bash 复制代码
ip prefix-list DC_LOCAL_SUBNET seq 5 permit 172.16.0.0/16 ge 24
ip prefix-list DC_LOCAL_SUBNET seq 10 permit 10.0.0.0/24 ge 32

这两条命令一起定义了一个名为 DC_LOCAL_SUBNET的列表,该列表中包含两个前缀: 172.16.0.0/16和 10.0.0.0/24。在将任何前缀与此列表进行匹配时,会检查待匹配的前缀是否和列表中的前缀完全匹配或包含在前缀中。在该示例中,10.0.0.0/24 ge 32特别声明任何匹配项都必须位于 /32 的子网上。/32是 IPv4 中编号最大的掩码,它表示了最小的子网,该子网中只有一个主机。因此,即使该匹配条件写的是"大于或等于",也仅与/32 前缀完全匹配。

seq<数字>用于指定匹配顺序。如果你想拒绝 10.1.1.1/32,但允许 10.1.1.0/24 中的所有其他地址,则可以 seq 对前缀列表进行排序,以达到该目的:

bash 复制代码
ip prefix-list EXAMPLE_SEQ seq 5 deny 10.1.1.1/32
ip prefix-list EXAMPLE_SEQ seq 10 permit 10.1.1.0/24

现在我们可以定义一个 route-map去匹配这两个前缀。

下面配置中的route-map 和之前"路由策略"中的 if-then-else 路由策略伪代码是等价的,后面的redistribute 命令使用了该 route-map 定义的路由策略。

bash 复制代码
ip prefix-list DC_LOCAL_SUBNET seq 5 permit 172.16.0.0/16 ge 26
ip prefix-list DC_LOCAL_SUBNET seq 10 permit 10.0.0.0/24 ge 32
route-map ACCEPT_DC_LOCAL permit 10
  match ip address DC_LOCAL_SUBNET

redistribute connected route-map DC_LOCAL_SUBNET

ip prefix-list DC_LOCAL_SUBNET seq 5 permit 172.16.0.0/16 ge 26的解析如下:

  • ip prefix-list DC_LOCAL_SUBNET :定义一个名为 DC_LOCAL_SUBNET 的前缀列表。
  • seq 5:指定序列号为5的条目,序列号用于确定前缀列表中的匹配顺序。
  • permit 172.16.0.0/16 ge 26:
    • 172.16.0.0/16:起始前缀。
    • ge 26 :表示匹配前缀 172.16.0.0/16 中的子网掩码长度大于或等于26的所有子网。这意味着匹配 172.16.0.0/16 范围内的所有子网,子网掩码长度在26到32之间。

route-map ACCEPT_DC_LOCAL permit 10

  • route-map ACCEPT_DC_LOCAL :定义一个名为 ACCEPT_DC_LOCAL 的路由映射。
  • permit 10:指定序列号为10的条目,允许匹配的路由通过。

match ip address DC_LOCAL_SUBNET

  • match ip-address DC_LOCAL_SUBNET :在路由映射条目中,匹配前缀列表 DC_LOCAL_SUBNET 中的IP地址。ip address 指的是路由条目的目的地址字段。

redistribute connected route-map ACCEPT_DC_LOCAL

  • redistribute connected:将本地连接的路由重新分发到当前路由协议(例如OSPF、BGP等)。
  • route-map ACCEPT_DC_LOCAL :应用 ACCEPT_DC_LOCAL 路由映射来过滤和选择哪些连接的路由将被重新分发。

在这里还可以使用接口名称来代替IP前缀。 假如只需要通告路由器的主回环IP地址,则可以像下面这样配置:

route-map ADV_LO permit 10
   match interface lo

redistribute connected route-map ADV_LO

该配置只会通告回环接口上全局可达的 IP 地址,而不会通告与回环接口关联的主机本地IP地址127.x.x.x。这种方法的好处是,它允许你自由更改接口,并可以为接口使用非连续的IP地址,而无需更改 route-map 或修改 BGP 配置。

FRR 支持 match interface 命令,特别是在和 redistribute connected一起起使用时,但并不是所有的路由软件都支持该语法。

编写安全的route map

编写route map 有两种方法。

  • 第一种是明确写出允许的内容,而其他所有内容都被隐式拒绝。
  • 第二种则恰好相反,明确写出拒绝的内容,然后允许其他所有内容。

这两种方法中,推荐使用第一种,因此这种方法更为安全。在前面的例子中,我们编写了ADV_LO route map 来明确允许回环接口和服务器子网接口,其他的地址都被拒绝/忽略。如果我们采用添加显式 deny 子句并允许其他所有内容的方法来重写该route map,可以得到随后的 EXCEPT_ISL_ETHO route map。swp1 和 swp2 是交换机之间的链接,eth0 是管理接口,这些接口都被显示设置为拒绝。该配置假设剩下的其他接口都是回环接口和连接服务器子网的接口:

bash 复制代码
route-map EXCEPT_ISL_ETH0 deny 10
   match interface swp1
route-map EXCEPT_ISL_ETH0 deny 20
   match interface swp2
route-map EXCEPT_ISL_ETH0 deny 30
   match interface eth0
route-map EXCEPT_ISL_ETH0 permit 40

redistribute connected route-map EXCEPT_ISL_ETH0

最终得到的配置允许通过任何不在 deny route map 中的接口

这种方法有一个问题:当出现任何一个新的网络接口时,该接口上的合法 IP 地址都会立即被通告,无论管理员是否打算这样做。因此这被认为是一种不安全的方法,你绝不能在配置路由策略时使用这种方式。

BGP中的route map

除了路由重发布之外,route map 还可以用于 BGP处理的其他很多地方。下面是一些例子:

bash 复制代码
# 过滤从邻居节点收到的路由广播
neighbor 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

**BGP是一种路径矢量路由协议,因此只会在运行最佳路径算法时才会对外通告路由更新。**BGP 在发送和接收数据包时使用 Route-map。如果一个 BGP 发言者有上百个带有 route map 的邻居节点,在发送路由通告前为每一个邻居应用 route map 将会耗费 CPU 资源,这会降低更新的发送速度,并导致收敛时间过长。

因此在 BGP中经常将peer group和route map一起使用,这样可以大大减少 BGP在向邻居发布路由之前需要做的处理工作。路由实现通常会动态地创建这些 peer group,而不仅仅依靠用户来进行配置。 这是因为即使在单个 peer group 中,不同的邻居节点也可能支持不同的能力 (例如,有些支持 MPLS,有些不支持 MPLS),而这些信息只能在会话建立期间才能确定。如果依赖用户进行配置,用户需要确保peer gourp 中所有的邻居节点支持同样的能力,这给用户造成了不必要的负担。

一些路由实现支持对具有相同出向路由策略和相同能力的对等节点进行动态分组和取消分组,以增强存在路由策略时的路由处理性能。BGP 对包含整个 peer group 的前缀运行一次策略,然后将结果自动应用于该 peer group 的每个成员。这允许路由实现扩展到支持数百甚至数千个邻居。此功能称为动态更新组或动态对等组。

为数据中心提供合理的默认配置

FRR 支持根据用例定义要使用的默认值。选项 frr defaults datacenter 用于设置在数据中心中使用 BGP 的默认值。

作者推荐的frr defaults datacente 的默认设置:

  • 为eBGP 和iBGP 启用多路径。
  • 将通告时间间隔设置为 0。
  • 将 Keepalive和Hold 计时器分别设置为3秒和9秒。
  • 启用邻接关系变化的日志记录。

在使用了 peer group、route map,并设置了合理的缺省值后,示例 15-2 中 spine节点的配置可以被简化为示例 15-3 所示。

bash 复制代码
router bgp 65000
  bgp router-id 10.0.0.21
  no bgp default ipv4 unicast
  neighbor peer-group ISL
  neighbor ISL bfd
  neighbor 169.254.1.1 remote-as 65011
  neighbor 169.254.1.1 peer-group ISL
  neighbor 169.254.1.3 remote-as 65012
  neighbor 169.254.1.3 peer-group ISL
  neighbor 169.254.1.5 remote-as 65013
  neighbor 169.254.1.5 peer-group ISL
  neighbor 169.254.1.7 remote-as 65014
  neighbor 169.254.1.7 peer-group ISL
  bgp bestpath as-path multipath-relax
  address-family ipv4 unicast
      neighbor ISL activate
      # 使用route-map ADV_LO将连接的路由重分发到BGP
      redistribute connected route-map ADV_LO
  exit-address-family
  # 创建一个名为ADV_LO的route-map,序号是10,允许匹配的路由
  route-map ADV_LO permit 10
     # 该route-map匹配lo接口的路由
     match interface lo

route-map ADV_LO的作用是在重分发连接的路由到BGP时,仅匹配和允许lo(loopback)接口上的路由 。也就是说,通过redistribute connected route-map ADV_LO配置,只有来自回环接口的连接路由才会被重分发到BGP。这就限制了BGP的路由通告范围,使其只通告从回环接口派生的路由,而不会通告其他连接的路由。

无编号 BGP:消除麻烦的接口IP地址

为了使 BGP真正易于自动化,我们还需要消除剩下的两个使 BGP配置和特定路由器相关的源头。示例 15-4 展示了我们最终要完成的配置。

Example 15-4. Unnumbered BGP configuration in FRR

bash 复制代码
! Configuration for spine01
!
interface lo
 # router-id definition is the only difference across all BGP configurations.
 ip address 10.0.0.21/32 
!
router bgp 65000
  bgp router-id 10.0.0.21 
  no bgp default ipv4 unicast
  neighbor peer-group ISL
  neighbor ISL remote-as external
  neighbor ISL bfd
  neighbor swp1 interface peer-group ISL
  neighbor swp2 interface peer-group ISL
  neighbor swp3 interface peer-group ISL
  neighbor swp4 interface peer-group ISL
  bgp bestpath as-path multipath-relax
  address-family ipv4 unicast
      neighbor ISL activate
      redistribute connected route-map ADV_LO
  exit-address-family

  route-map ADV_LO permit 10
     match interface lo
bash 复制代码
! configuration for leaf01
!
interface lo
 ip address 10.0.0.11/32 
!
! This next statement is for the servers subnet
!
# The server subnet definitions will be different per leaf.
interface vlan10
  ip address 172.16.1.1/24 
!
router bgp 65011
  bgp router-id 10.0.0.11
  no bgp default ipv4 unicast
  neighbor peer-group ISL
  neighbor ISL remote-as external
  neighbor ISL bfd
  neighbor swp1 interface peer-group ISL
  neighbor swp2 interface peer-group ISL
  address-family ipv4 unicast
      neighbor ISL activate
      redistribute connected route-map ADV_LO_SRVRS
  exit-address-family

  route-map ADV_LO_SRVRS permit 10
     match interface lo
  route-map ADV_LO_SRVRS permit 20
     match interface vlan10

如示例 15-4 所示,BGP配置中唯一不同之处是 router-id 的值。任何需要对等方IP地址和 ASN 的配置都被消除了。

A remote-as by Any Name

当使用 remote-as external 配置时,BGP会自动将所有与之建立会话的邻居视为eBGP邻居,而不需要手动指定每个邻居的AS号。这可以简化某些场景下的配置。

在 BGP 配置的 neighbor 部分声明对等方的 ASN 的目的主要有两个:

  • 在跨管理域进行连接时,要明确指出要连接到哪个 ASN,因为如果意外连接到错误的管理域,可能会导致较大的财务损失和全球范围的故障
  • 指明 BGP 对等方是由 iBGP 规则还是由 eBGP 规则管理

在数据中心,使用ASN的唯一真实原因是通过AS_PATH进行BGP的环路检测(iBGP通过自动生成的 cluster-id 来执行此操作,但iBGP的处理更为复杂。因此在数据中心中并未把 iBGP 作为 Clos 网络的主要路由协议),因此我们可以忽略指定对等方 ASN的要求。

数据中心中 ASN 的主要目的就是判断 iBGP 还是 eBGP 控制着 session。

基于此原因,FRR在remote-as关键字中添加了两个新的选项: externalinternal

  • "external"表示你希望与此邻居建立 eBGP连接(对等方的 ASN必须和我的不同)
  • "internal"表示你希望建立 iBGP 连接 (对等方的 ASN 必须与我的一致)。

BGP 发言者可以通过收到的 BGP OPEN 消息中的 ASN 来识别应该建立iBGP 还是 eBGP 连接。

remote-as external:用于配置eBGP对等体,会自动假定对等体在不同的AS中。

bash 复制代码
router bgp 100
 neighbor 192.168.1.2 remote-as external

remote-as internal:用于配置iBGP对等体,会自动假定对等体在同一个AS中。

bash 复制代码
router bgp 100
 neighbor 192.168.1.3 remote-as internal

如何在 BGP 中使用无编号接口

  • Numbered Interface:配置了IP地址的接口
  • Unnumbered Interface:没有配置IP地址的接口

注意,Unnumbered Interface情况下,接口并不是没有 IP 地址,而是从 node 的其他接口借 IP 地址来用 。 但是,如果被借的那个接口挂了,这个 IP 自然也就不可用了。为了保证借来的IP永远可用,被借的接口便永远不能挂,这个接口就是:loopback interface

路由器能够在 unnumbered interface 上应答 ARP,因为接口可以借 IP。ICMP 和 traceroute 也能正常工作。那么,这样不就无法区分出一个包是从哪个接口进入 路由器的吗

Clos 网络的任意两个 node 之间只有一条链路任何两个 node 之间都只有唯一的一对接口。因此不会出现上面提到的问题

那么,路由协议是怎么处理 unnumbered interface 的呢?

OSPF(运行在 IP 协议之上)可以正常工作,其 RFC 里面描述了这方面的设计。大部分厂商的实现可能不支持,但FRR支持。Unnumbered OSPF 已经在很多生产环境部署。IS-IS不依赖 IP 协议, 也可以在 unnumbered interface 场景下正常工作。

BGP 到底是如何在接口没有 IP 的情况下正常工作的呢?

在路由协议的世界里,有一个类似"鸡生蛋,蛋生鸡"的问题。如果路由协议是用来通告路由可达信息的,那么它本身是如何知道对端的可达信息的呢?一些协议通过引入一个链路特定的组播地址(link-specific multicast address)来解决这个问题,因为组播会限制在链路层。然而,BGP不能这样做,因为它依赖TCP,而TCP需要的是单播而不是组播包。BGP通常需要在两个BGP对等体之间建立一个直接或间接的TCP连接。要实现这一点,BGP对等体通常需要在一个共享的子网内(或通过静态路由或IGP可达)。

要BGP中使用没有明确分配 IP 地址的接口,需要依赖四个明确定义的特性:

  • 在接口上使用 IPv6 的链路本地地址
  • 使用IPv6 的路由器广播协议来学习对等方的链路本地地址
  • 使用 RFC 5549 来通告一个以其 IPv6 链路本地地址作为下一跳的 IPV4 地址
  • 使用通过 RFC 5549 地址通告获得的信息来填充路由表。

IPv6 链路本地地址

现在所有的操作系统都已经支持 IPv6 协议,无论是 Linux 还是传统的供应商操作系统。在一个链路上启用IPv6 后,会自动生成一个仅在该链路上有效的IPv6 地址,即 LLA (link-local address,链路本地地址) 。大多数情况下,该地址是使用接口MAC地址生成的。IPv6 LLA 具有明确定义的格式:以 fe80 开头。一个IPV6 LLA的示例信息 fe80::5054:ff:fe6d:4cbe

无编号 BGP使用LLA 来建立TCP 连接。FRR 并不要求用户指定该 LLA,只需要用接口名称来表示用户希望使用IPV6 LLA 来建立 BGP对等会话。如果fe80::5054:ff:fe6d:4cbe 是接口的 IPV6 LLA,则 FRR 会在该地址上接收对该方的连接请求,也会使用该地址将连接请求发送到对等方。

但是,要与远程实体处立连接,BGP 需要链路对端接口的IPV6 LLA。节点是如何自动获取到该地址的呢? 这是通过 IPv6 路由器通告得到的。

IPv6 路由器通告

为了让主机和路由器能够自动发现和其相邻的路由器,设计人员在 IPv6 中添加了RA(router advertisement,路由器通告)功能。RA 是IPv6的NDP 消息之一 (IPv6的 NDP 相当于 IPv4 的 ARP) 。在接口上启用 IPv6 后,RA 会定对外通告该接口的IPv6 地址,包括 LLA。因此,链路一端可以自动获取到另一端的IPV6 地址。如今在主机和路由器上普遍都实现了 RA。

需要指明的是,使用IPv6 LLA 并不需要运营商在网络中部署 IPV6 网络地址。IPv6 LLA 只用于建立BGP会话的TCP连接。除了在链路上启用IPv6(通常是自动启用的)和IPv6 路由器通告之外,运营商不需要任何其他关于 IPV6 的设置。

RFC 5549

IPv6链路本地地址(LLA)可以用于在两个路由器之间建立BGP对等体关系。然而,仅仅通过IPv6 LLA建立BGP TCP连接并不意味着可以直接交换IPv4路由。为了交换IPv4路由信息,需要有一个IPv4的下一跳地址。

但是已建立 BGP 对等关系的接口上并没有 IPv4 地址,并且路由器上也没有其他可以用于通告的外部可达的 IPv4 地址。那么这是如何工作的呢? 这包含两个部分:控制平面部分和数据包转发(或数据平面) 部分。控制平面部分需要实现一个标准的,定义明确的扩展,以对 BGP的下一跳进行编码。该标准在RFC 5549 中定义,标题是"Network Layer Reachability Information with an IPv6 Next Hop"(使用IPv6 下一跳通告 IPv4 网络层可达性信息)。

IPv4 NLRI就是路由。因此,该RFC定义了如何使用一个IPV6下一跳地址来发布 IPv4 路由

MP_REACH_NLRI属性中的 AFI / SAFI 字段定义了路由的网络地址族。一般情况下,下一跳网络地址属于同一AFI / SAFI,但下一跳地址的网络地址族**也可以和路由的网络地址族不同。**RFC 4760定义了 MP_REACH_NLRI的格式和功能,该标准要求如果下一跳网络地址有不同于路由的网络地址族,则必须能够通过该字段的编码轻易识别出来。

RFC 5549 的内容如下:

  • 也可以用 MP_REACH_NLRI来表示 IPv4 (和VPN-IPv4)路由。
  • 可以使用 Nexthop Network Addr 属性的长度字段来标识该字段是否同时包含了本地链路和全局 IPv6 地址,或者只包含一个地址。

换句话说,将图 14-3 (a) 用于具有IPv4 下一跳的IPv4 路由,并将图 14-3 (b)用于具有 IPv6 下一跳的 IPv4 路由。

图14-3见 《Cloud Native Data Center Networking》(云原生数据中心网络设计)读书笔记 -- 10数据中心中的BGP

支持RFC 5549的BGP 能力被称为"extended next hop"(扩展下一跳)。

RFC 5549的数据转发

在解决了控制平面问题后,数据包转发是如何工作的呢?是否必须扩展路由表以支持将IPv6 地址作为IPv4 路由的下一跳?分组交换硬件是否也需要支持此功能?我

们将对此进行进一步研究,以了解为什么不需要更改数据转发芯片就可以支持 RFC 5549

下一跳路由器的IP地址被用于确定下一跳路由器接口的MAC 地址。该MAC 地址被用作被路由转发的数据包的目的MAC 地址,这样该数据包可以被下一跳路由器接受。我们可以看到,被路由转发的数据包中的任何地方都未直接使用下一跳路由器的IP地址

IPv6 RA 不仅为我们提供了对等路由器的IPv6链路本地址,还为我们提供了该路由器上对等接口的MAC 地址。 对于任何给定的IPV6 链接本地地址,我们都有其对应的MAC地址。交换芯片中通常有指向一组下一跳的路由,并且下一跳中的每个条目仅包含 MAC地址 (和VLAN),可以使用该下一跳MAC 地址和IPV4 路由填充交换芯片的路由表。因此,可以使用来自 RFC 5549 编码格式的信息来填充分组交换芯片,就像我们收到的是带有 IPv4 下一跳地址的 IPv4 路由一样。

对于交换芯片来说,处理带有IPv6下一跳的IPv4路由与处理带有IPv4下一跳的IPv4路由几乎相同,因为在底层,路由转发依赖的是MAC地址(和VLAN ID),而不是IP地址本身。

小结:

  • 路由表中的目的地址仍然是IPv4地址
  • 下一跳字段可以是IPv6链路本地地址(LLA),这是通过RFC 5549定义的机制来支持的。
  • 转发数据时,使用的是通过IPv6 LLA解析出来的MAC地址来进行数据包的二层转发。

FRR和RFC 5549

可以通过使用一个假的IPv4地址来作为下一跳路由器的 IP 地址。FRR 使用 169.254.0.1 作为假的 IPv4 地址 (在撰写本书时,你无法通过配置对其进行更改) 。按照惯例,尽管不会像 IPV6 LLA 那样自动将IPV4 LLA分配给接口,还是会将 169.254.0.0/16 定义为IPV4 LLA 的子网。请看 FRR的show ip route 命令的输出:

bash 复制代码
$ sudo vtysh -c 'show ip route'
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
       F - PBR,
       > - selected route, * - FIB route

C>* 10.0.0.11/32 is directly connected, lo, 20:04:01
B>* 10.0.0.12/32 [20/0] via fe80::5054:ff:fe92:a7dd, swp4, 20:03:52
  *                     via fe80::5054:ff:fef5:ca97, swp2, 20:03:52
  *                     via fe80::5054:ff:feb6:d927, swp1, 20:03:52
B>* 10.0.0.13/32 [20/0] via fe80::5054:ff:fe92:a7dd, swp4, 20:03:52
  *                     via fe80::5054:ff:fef5:ca97, swp2, 20:03:52
  *                     via fe80::5054:ff:feb6:d927, swp1, 20:03:52

可以看到每个IPv4 路由都有一个IPv6 LLA 下一跳 (地址以 fe80:: 开头)。我们还看到该路由是通过 BGP 学习的。

当从 Linux 内核中查看同一路由时,你会看到示例15-5 中展示的代码。

示例 15-5:Linux FIB 输出的使用 RFC5549 通告的路由

bash 复制代码
$ ip ro show
10.0.0.12  proto bgp  metric 20
        nexthop via 169.254.0.1  dev swp4 weight 1 onlink
        nexthop via 169.254.0.1  dev swp2 weight 1 onlink
        nexthop via 169.254.0.1  dev swp1 weight 1 onlink
10.0.0.13  proto bgp  metric 20
        nexthop via 169.254.0.1  dev swp4 weight 1 onlink
        nexthop via 169.254.0.1  dev swp2 weight 1 onlink
        nexthop via 169.254.0.1  dev swp1 weight 1 onlink

ip neighbor 表项的输入如下:

bash 复制代码
$ ip neighbor
169.254.0.1 dev swp2 lladdr 52:54:00:f5:ca:97 PERMANENT
169.254.0.1 dev swp1 lladdr 52:54:00:b6:d9:27 PERMANENT
169.254.0.1 dev swp4 lladdr 52:54:00:92:a7:dd PERMANENT
fe80::5054:ff:fe92:a7dd dev swp4 lladdr 52:54:00:92:a7:dd router REACHABLE
fe80::5054:ff:fef5:ca97 dev swp2 lladdr 52:54:00:f5:ca:97 router REACHABLE
fe80::5054:ff:feb6:d927 dev swp1 lladdr 52:54:00:b6:d9:27 router REACHABLE

你可以看到每个接口上的 169.254.0.1 条目具有与该接口对应的IPv6 条目相同的MAC 地址(例如 52:54:00:f5:ca:97) 。此外,该条目被标记为 PERMANENT,这向内核表明该条目是一条静态条目。换话说,内核不会尝试刷新此 ARP 条目。

FRR如何实现无编号的 BGP

1)FRR本地实现了IPv6 RA。在接口上启用了 FRR 的RA 后,RA 会通告其自己的LLA 和MAC 地址。RA 数据包的目的地址是链路本地多播地址,因此永远不会被转发。

2)在从一个接口上收到对等路由器的 RA 数据包后,FRR 将从中提取对方的 MAC地址和相关的 IPv6 LLA。

3)学习到接口对端的 IPv6 LLA 地址后,FRR 开始使用该地址建立 BGP 连接

4)成功建立 BGP 连接后,BGP 使用能力协商来确保对等会话的双方都支持 RFC 5549。

5)BGP 从对等方接收一条路由的路由通告,例如 10.0.0.11/32。该路由的下一跳为其对等方的 IPv6 LLA 地址 (以及全局 IPv6 地址,如果配置了的话)。

6)如果 BGP 选择此路径作为到达 10.0.0.11/32 的最佳路径,它将此路径传递到RIB 进程 (在 FRR 中称为 zebra) ,并将下一跳设置为 BGP UPDATE 消息中接收到的IPv6 LLA。

7)假设 RIB 选择此 BGP 路由作为填充 FIB 的最佳路由。RIB 进程会在其数据库中查找与此 IPv6 LLA 关联的 MAC 地址,它在数据库中找到了该地址

8)RIB 进程使用该 MAC 地址添加一个 169.254.0.1 的静态ARP条目,条目中的出接口设置为路由对等接口。

9)然后 RIB 进程将路由推送到内核路由表中,其下一跳为 169.254.0.1,并且将出接口设置为路由对等接口,此时 FIB 中的最终状态如示例 15-5 所示。到此为止,一切都准备就绪,包转发可以正常工作。可以看到,采用无编号接口的数据包转发逻辑保持不变。

如果链路断开或远端停止发送 RA 消息,则本地 RA 进程会从 RIB 中删除对端接口LLA 及其关联的 MAC。这使 RIB 进程认为下一跳不再可达,并会通知 BGP 进程该对等方不再可达。RIB 还会拆除它之前创建的和该对端接口相关的静态 ARP 条目。会话中断会使 BGP 删除其指向该会话对等接口的那些路由。

在无编号 BGP 中,BGP 路由交换的数据包时序如图 15-3 所示。

图 15-3 : FRR中无编号BGP的数据包时序

互操作性

那么,使用 RFC 5549 是否意味着网络中的每个路由器都必须支持它才能正常工作呢?我们是否可以与支持 RFC 5549 功能的路由器建立一个 BGP 对等会话,而与不支持 RFC 5549 功能的路由器建立另一个 BGP 对等会话,以交换双方都能看到的路由?这是可以的。

每个 eBGP 对等方在发送路由通告之前都会将路由的 NEXTHOP 设置为自己的IP地址。图 15-4 展示了一个假想的网络,其中路由器B和D支持 RFC 5549,而路由器A和C不支持。因此为 B与A 之间以及 B 与C之间的链路明确配置了接口IP地址。当A向B通告 10.1.1.0/24 的可达性时,它将自己的对等接口上的 IPv4 地址作为路由的下一跳。当B将10.1.1.0/24的路由发送到D时,将其IPV6 LLA 设置为下一跳,而将该路由发送给 C时,将其接口的 IPv4 地址设置为下一跳。

在反方向上,当 D通告前缀 10.1.2.0/24 的路由时,D 会使用其接口的IPV6 LLA将该路由发送给 B。当B将该路由通告发送给 A 和C时,它将下一跳设置为其对等接口的IPv4地址。

图15-4:展示与 RFC 5549 互操作性的示例拓扑

FRR 中BGP 配置的最终观察

如前所述,无编号 BGP 要求我们启用 IPv6 RA 并支持 RFC 5549。在 FRR 中,默认情况下并未启用这两项功能。在接口上启用它们的代码如下所示:

bash 复制代码
! Enable RA on an interface and advertise it every 5 seconds
interface swp1
  # 启用 RA
  no ipv6 nd suppress-ra 
  # 设置 RA 的广播间隔,缺省为1小时
  ipv6 nd ra-interval 5  
!
...
router bgp 65011
  bgp router-id 10.0.0.11
  neighbor ISL peer-group
  neighbor ISL remote-as external
  neighbor ISL bfd
  # 对外的能力通告中声明支持 RFC 5549
  neighbor ISL capability extended-nexthop 
  neighbor swp1 interface peer-group ISL
  neighbor swp2 interface peer-group ISL
...

FRR 中其实并不需要显式启用 extended-nexthop 和 RA。当你在 neighbor 命令中使用接口名称而不是IP地址时 (例如 neighbor swpl interface ...) ,FRR 会认为你在使用无编号 BGP,因此会在该接口上自动启用 RA,并在该接口上的 BGP 对等会话中通告extended-nexthop 能力。如果你愿意,可以使用上面的命令显式地进行设置,但是在通常情况下这并不需要。这是 FRR通过合理的默认设置来减少复杂的用户配置的设计理念的另一个例子。这就是我们如何得到示例 15-4 中的 BGP 配置的。

路由协议栈对无编号 BGP的支持

FRR 率先实现了无编号 BGP,随后许多其他的路由栈也纷纷开始支持。另外两个开源路由软件 goBGP和BIRD 支持了无编号 BGP。

在本章的其余部分和下一章中,我们假定在所有出现的配置中都使用了无编号 BGP。

配置IPv6

只需要激活 IPv6 的地址族并发布相关路由,就可以在 BGP 中添加对 IPV6 的支持。

使用下面的简单代码片段就可以在示例 15-4 的配置中添加IPV6 支持

bash 复制代码
address-family ipv6 unicast
     neighbor ISL activate
     redistribute connected route-map ADV_LO

此段代码应用于配置的 BGP 部分 (router bgp 下的那一部分) 。这里使用的 route-map 表明这是针对 spine 的配置。类似地,我们也可以为 leaf添加IPV6 支持。leaf 必须通告回环地址和本地连接的服务器子网,因此需要使用一个和 spine 不同的route-map。除此之外,支持IPv6 的 leaf 配置和 spine 的配置相似

在BGP 支持多协议的初期,由于实现中存在 bug,导致人们为IPV4和IPV6 各自配置单独的 BGP 会话。这样可以确保当 BGP 会话由于 Pv6 支持中的错误而发生问题时,不至于丢失 IPv4 连接。如今大多数实现都已经能够很好地处理 IPV6,因此完会可以在单个会话中同时处理 IPv4 和IPv6 路由。

如表 14-2 所述,IPv6 路由通过 MP_REACH_NLRI属性进行通告。IPv6 路由可以只带有一个LLA 地址,也可以同时带有一个 LLA 和一个全局IPv6 地址。IPv6 被明确设计为使用 LLA 进行路由,因此,仅使用 LLA 进行路由通告就足够了。全局IPv6地址通常用于跨越多跳(即双方未直接连接)的 BGP 对等连接中,但这种情况在数据中心内部并不常见。

BGP和VRF

在一个非VPN环境中,在不和MPLS 或VXLAN一起使用的情况下,使用BGP通告 VRF相关的路由只需要配置多个 BGP 实例 (每个 VRF一个)。假设在图15-1的经典两层拓扑中有私有和公共两个 VRF,每个路由器间链路上有用于分隔这两个 VRF的两个 VLAN,分别为10和20。尽管 VLAN的编号无关紧要,只在本地链路范围内有意义,但 VRF 却涉及所有 leaf和spine。假设私有 VRF 中的服务器位于 172.16.10.0/24子网,并关联到 VLAN10,而公共 VRF中的服务器位于172.16.20.0/24 子网中并关联到 VLAN20。考虑 leaf01和 spine01 之间的 BGP对等连接,使用了 VRF 的配置如下所示

示例15-6: FRR中的BGP VRF 配置代码片段

1)spine01的配置

bash 复制代码
! BGP configuration for spine01
router bgp 65000 vrf private
   bgp router-id 10.0.0.21
   neighbor peer-group ISL
   neighbor ISL remote-as external
   neighbor ISL bfd
   neighbor swp1.100 interface peer-group ISL
   neighbor swp2.100 interface peer-group ISL
   neighbor swp3.100 interface peer-group ISL
   neighbor swp4.100 interface peer-group ISL
   bgp bestpath as-path multipath-relax
   address-family ipv4 unicast
      neighbor ISL activate
      redistribute connected route-map ADV_VRF_PVT
   exit-address-family
!
!
router bgp 65000 vrf public
   bgp router-id 10.0.0.21
   neighbor peer-group ISL
   neighbor ISL remote-as external
   neighbor ISL bfd
   neighbor swp1.200 interface peer-group ISL
   neighbor swp2.200 interface peer-group ISL
   neighbor swp3.200 interface peer-group ISL
   neighbor swp4.200 interface peer-group ISL
   bgp bestpath as-path multipath-relax
   address-family ipv4 unicast
      neighbor ISL activate
      redistribute connected route-map ADV_VRF_PUB
   exit-address-family
!
!
route-map ADV_VRF_PVT permit 10
   match interface private
!
route-map ADV_VRF_PUB permit 10
   match interface public
!

2)leaf01的配置

bash 复制代码
! BGP configuration for leaf01
router bgp 65011 vrf private
   bgp router-id 10.0.0.11
   neighbor peer-group ISL
   neighbor ISL remote-as external
   neighbor ISL bfd
   neighbor swp1.100 interface peer-group ISL
   neighbor swp2.100 interface peer-group ISL
   address-family ipv4 unicast
      neighbor ISL activate
      redistribute connected route-map ADV_VRF_PVT
   exit-address-family
!
!
router bgp 65011 vrf public
   bgp router-id 10.0.0.11
   neighbor peer-group ISL
   neighbor ISL remote-as external
   neighbor ISL bfd
   neighbor swp1.200 interface peer-group ISL
   neighbor swp2.200 interface peer-group ISL
   address-family ipv4 unicast
      neighbor ISL activate
      redistribute connected route-map ADV_VRF_PUB
   exit-address-family
!
route-map ADV_VRF_PVT permit 10
   match interface private
route-map ADV_VRF_PVT permit 20
   match interface vlan10
!
route-map ADV_VRF_PUB permit 10
   match interface public
route-map ADV_VRF_PUB permit 20
   match interface vlan20

示例中有两部分 BGP 配置,每个 VRF一个。这种配置样式在大多数路由栈中都很常见。在撰写本书时,VRF 自身的创建必须在 FRR 之外完成。你可以使用 Linux ip命令,或使用 netplan或ifupdown2 之类的工具来创建 VRF 接口。接口与 VRP的关联也在 FRR 之外进行。

1)我应该使用什么作为路由器 ID ?

非VRF的 BGP 使用回环IP地址作为路由器ID。每个 VRP都有一个类似回环地址的接口,这也是 VRF 自身的名称。该接口被分配了一个IP 地址,可用作VRF的路由器ID。

2)我应该使用什么作为 ASN ?

尽管大多数实现都支持不同的 VRF 使用不同的 ASN,但是使用相同的 ASN更简单。ASN 不像 IP 地址那样受 VRF 限制,因此没有理由为每个 VRF 使用不同的ASN。

3)如果我有 32个 VRF,是否需要 32 个不同的 BGP 配置?

很不幸,是的。

4)可以在VRF之间重用peer-group吗?

FRR并不支持,但思科的NX-OS模板允许。

与主机上的 BGP 发言者建立对等连接

随着 Kube-router 和 Calico 之类的解决方案的流行,leaf 和服务器之间的 BGP 对等连接日益受到关注。本节将重点介绍 Kube-router。Kubernetes pod 和网络的设置如图 15-5 所示。这只是图 15-2 中展示的常规二层 Clos 拓扑的一部分。我们假设使用无编号 BGP,因此图中没有任何接口IP地址。另外为了展示更多细节,图中只展示了 leaf (leaf01 和leaf02) 和服务器 (server11 和server21) 。实际上在leaf01 和leaf02 后面都有不止一个服务器。

图 15-5:说明Kube-router 和leaf 之间 BGP 对等连接的示例拓扑

如图15-5 所示,每个服务器中都有两个连接到 Kubernetes 网桥 cbr0 的容器。server11 中 cbr0 的子网为 10.172.1.0/24,server21 中 cbr0的子网为 10.172.2.0/24

图中展示了各个容器的IP地址。服务器自身的IP地址分配自他们各自连接的leaf的子网。为 server11 分配的IP地址为 172.16.1.2,而为 server21 分配的地址为172.16.2.2,并为 leaf 自身分配了相应的.1 地址。服务器的第一跳路由器是 leaf,其网关地址是 leaf 上相应的.1 地址(例如,leaf01 的地址172.16.1.1)

在服务器上运行 Kube-router时,BGP 要求为节点分配一个 ASN。Kubernetes 集群中的所有节点都被分配了一个相同的 ASN,就像数据中心内的所有其他东西一样,该ASN是一个私有 ASN。这里我们分配一个私有 ASN 64512 给 Kube-router 使用。首先,Kube-router 之间会建立 iBGP 连接,以相互学习 pod 子网的 IP 地址。通过server11和server21 之间的iBGP会话,server11 学习得到 server21 上的 pod 子网10.172.2.0/24,而 server21学习得到 server11 上的 pod 子网 10.172.1.0/24。查看server11 上的路由表,将发现以下内容:

bash 复制代码
$ ip route show
default via 172.16.1.1 dev eth0
10.172.2.0/24 via 172.16.1.1 dev eth0

通过配置 Kube-router 与 leaf 进行 BGP对等,还可以从外部访问这些 pod。

在leaf配置与 Kube-router 的 BGP 对等的方法如下面的代码片段所示 (以leaf01为例):

bash 复制代码
router bgp 65011
   bgp router-id 10.0.0.11
   neighbor peer-group SERVERS
   neighbor SERVERS remote-as external
   neighbor 172.16.1.2 peer-group SERVERS
   ...
   neighbor 172.16.1.40 peer-group SERVERS
   address-family ipv4 unicast
      neighbor SERVERS activate
      redistribute connected route-map ADV_LO_SRVRS
   exit-address-family

上面的配置假设 leaf01 连接了 39 台服务器。这样直接列出 39 台服务器导致配置显得冗长。此外,并非所有服务器都处于联机状态。如果某些邻居节点不在线,在配置中简单地指定这些邻居节点会导致和这些邻居的 BGP 会话处于未建立的状态,从而导致输出混乱和误报的 BGP错误。如果需要对主机的IP地址重新编号,这种配置也会导致 IP 地址重编号更复杂。

BGP 为处理这种情况提供了一个更简单的方法,称为动态邻居。

动态邻居

因为 BGP在TCP 上运行,所以只需要对等方中的一端发起连接,另一端可以保持被动状态,等待对方的连接即可,就像 Web 服务器等待来自客户端 (例如浏览器)

的连接一样。某些 BGP 实现支持 BGP 动态邻居功能,这些实现的其中一端(监听端)是被动的,只需要告诉监听端接收来自哪个 IP 子网的连接,并关联一个控制等会话特性的peer group 即可。

同一机架上的所有服务器通常共享一个子网。因此本示例中的 leaf 可以作为监听端leaf 上的 BGP 动态邻居的典型配置如下所示:

bash 复制代码
router bgp 65011
  bgp router-id 10.0.0.11
  ...
  neighbor SERVERS peer-group
  neighbor SERVERS remote-as 64512
  bgp listen range 172.16.1.0/24 peer-group SERVERS
  ...

配置中的 listen 命令告诉 BGP 接受任何从 172.16.1.0/24 子网中接收到的 BGP连接请求,并对该对等会话应用 peer-group 模板 SERVERS。由于服务器和网络通常属于数据中心内的不同组织,因此我们明确定义了要使用的 ASN,这将使 BGP 只接受指定ASN的连接。通过命令 neighbor listen limit limit-number,可以限制动态邻居模式支持的对等方数量。例如,配置为 neighbor listen limit 20 将只允许和 20 个动态邻居建立连接。通常我们通过设置该限制值来防止路由器的负载大于计划值。

交换机的对等IP地址通常被设置为服务器的默认网关。在 leaf01 的情况下为172.16.1.1,在 leaf02 的情况下为172.16.2.1

Kube-router 路由器还可以在服务可用时发布服务的IP 地址。Kube-router 内部使用了不支持 BFD (双向转发检测)的 goBGP,Calico 则选择了支持 BFD的 BIRD作为其路由协议软件。

BGP 和升级

在升级路由器时,使路由器正常地退出转发路径的功能非常有用。换句话说,在升级路由器之前,必须先清空该路由器中的所有存量流量。OSPF提供了 max-metric 命令来使路由器脱离经过它的路由路径(只与该路由器连接的节点除外)。同样地,BGP 也使用了几种不同的方法来支持相同的功能。我们先看一下最常见的方法。

AS_PATH Prepend

在数据中心中,AS_PATH是影响 BGP 最佳路径计算中路径选择的主要参数。因此,为了使将被升级的路由器不再被选为最佳路径,我们可以增加 AS_PATH的长度。这是通过 as-path prepend 选项完成的。该选项会在将路由发布给邻居前在其AS_PATH 属性中添加指定的 ASN。推荐使用的 ASN 是该路由器自己的 ASN。就像OSPF的 max-metric 一样,这可以让有多条到达目的地的路径时,经过该路由器的路径不被选为最佳路径,但同时保证在没有其他到达目的地的路径时,数据包还可以流经该路由器。

下面的代码片段展示了 as-parth prepend 的用法

bash 复制代码
router bgp 65011
  ...
  neighbor ISL route-map MAINT out
  ...

route-map MAINT
  set as-path prepend 65011

此命令会把 ASN 65011 添加到 AS_PATH上,然后再通告给 peer-group ISL 定义的所有邻居。

GRACEFUL_SHUTDOWN community

在BGP标准列表中有一个加入不久,但非常著名的 BGP community: GRACEFUL_SHUTDOWN ,该community 允许路由器优雅地退出转发路径。在RFC 8326中定义了该community 在优雅退出时的行为。当路由器收到的 BGP UPDATE消息中未定义 LOCAL_PREF时,FRR 和其他路由实现会为 LOCAL_PREF 属性分配一个默认值 100。而在收到设置了 GRACEFUL_SHUTDOWN community 的路由后,BGP 发言者会将 LOCAL_PREF 属性的值设置为 0。由于设置的 LOCAL_PREF属性值0小于默认值 100,通过发布 community GRACEFUL_SHUTDOWN的路由器的路径不会被选中为最佳路径。除了优雅关闭以外,作者还没有看到数据中心内部将LOCAL PREF 属性用于其他目的。

FRR 无需除 GRACEFUL_SHUTDOWN之外的任何其他配置,就可以自动更改LOCAL_PREF的值。而其他路由实现则要求使用 route map 或对等的路由策略来实现此更改。

通过 bgp graceful shutdown 命令可以使路由器节点在路由通告时带上该community字符串。

Max-MED

第三种对外通告自己要退出路由路径的方法是更改路由中的 MED 属性,但是一种不太常用的方法。MED 是一个没有在数据中心内使用的属性,但它是 BGP 最佳路径计算的一部分。FRR 支持 max-med (类似OSFP 中的 max-metric) BGP 配置命令,可以将 MED 的值改得更大。所有路由器都必须启用一个附加命令才能使用该参数。在计算最佳路径时,LOCAL_PREFAS_PATH 优先于 MED,只有两个路径的 LOCAL_PREF 相同,并且 AS_PATH 长度相等时,才会考虑 MED。以下代码片段显示了如何在 FRR 中启用此配置:

bash 复制代码
router bgp 65000
  bgp router-id 10.0.0.21
  ...
  bgp max-med administrative
  ...

最佳实践

  • 遵循本书介绍的 ASN 编号模型
  • 如果可以,尽量使用无编号 BGP。现在很多开源和专有路由软件都已经支持了无编号 BGP。
  • 确保本地回环接口有一个合法的 IP 地址(除了127.0.0.0/8地址之外的IP地址),并确保对外通告了该地址。
  • 在非 FRR 路由软件上启用多路径,FRR 上已经缺省启用。
  • 启用 bgp bestpath as-path multipath-relax 命令。
  • 在非 FRR 路由软件上启用对等会话改变的详细日志。FRR 上已经缺省启用
  • 使用单个 eBGP 会话来通告多个地址族。
  • 使用 BFD 来检测故障,BFD 除了可以快速发现其他类型的连接错误之外,还可发现线缆的问题,例如单向链接。
  • 与服务器连接时,请使用 route-map,以确保你永远不会收到错误前缀的路由。
  • 使用动态邻居来简化和服务器的对等连接。
  • 除了 leaf以外,不要进行路由汇总。
  • 尽量保持最小化的配置。这使得网络更健壮,易于理解,管理和故障定位。

小结

在本章中,我们深入探讨了如何为 Underlay 网络 (即基础的 Clos 拓扑) 配置BGP。我们研究了无编号 BGP 的工作方式以及它给配置带来的简化。我们还研究了peer group 和路由策略配置等概念。我们看到了 Kube-router 如何使用 BGP来通告pod 子网和服务的IP地址,以及如何配置leaf路由器和服务器的 BGP 对等连接。我们还检查了 BGP 故障定位的方法,以及第 11 章出现的 show 命令。

相关推荐
黑客Ash1 小时前
【D01】网络安全概论
网络·安全·web安全·php
->yjy1 小时前
计算机网络(第一章)
网络·计算机网络·php
摘星星ʕ•̫͡•ʔ2 小时前
计算机网络 第三章:数据链路层(关于争用期的超详细内容)
网络·计算机网络
wuxingge3 小时前
k8s1.30.0高可用集群部署
云原生·容器·kubernetes
.Ayang3 小时前
SSRF漏洞利用
网络·安全·web安全·网络安全·系统安全·网络攻击模型·安全架构
好想打kuo碎3 小时前
1、HCIP之RSTP协议与STP相关安全配置
网络·安全
志凌海纳SmartX4 小时前
趋势洞察|AI 能否带动裸金属 K8s 强势崛起?
云原生·容器·kubernetes
锅总4 小时前
nacos与k8s service健康检查详解
云原生·容器·kubernetes
BUG弄潮儿4 小时前
k8s 集群安装
云原生·容器·kubernetes