亚马逊AWS官方博客

SD-WAN 和专线混合组网中的高可用设计

在上一篇文章《利用 SD-WAN 和专线混合组网,加速境内外企业 IDC和多云数据中心》中,笔者介绍了如何使用纯 SD-WAN 和 SD-WAN加专线混合组网来加速境内外企业 IDC 和多云数据中心的方案。我们如果在运营跨境电商、游戏、社交、区块链,希望打通不同地区的本地机房,IDC,AWS 区域的话,是非常适合用这个方案的。在今天这个文章中,主要会讲解针对之前的架构,如何实施高可用。

架构解读

在一些情况下,比如 Direct Connect 线路维护、厂家 BGP 设备故障(这里也是默认一台设备,有单点故障的可能性)、专线线路不稳定等,服务的连接性会受影响。为了保护业务的连续性,很多时候再架设一条备用线路就显得非常有必要。从图中可以看出来,我们可以将 Direct Connect 专线设置为主线路,然后在主线路出现故障的时候切换到备用的SDWAN 线路上面去。

本文主要介绍两种不同的方法:

  1. 通过 AWS CLI 抓取 Direct Connect 专线的状态,根据状态切换子网路由表
  2. 在路由表上打开路由传播功能,传播 Direct Connect 的明细路由,并且加入 SDWAN 的泛路由

方法1:AWS CLI 获取 DX 状态

具体的操作,是在 AWS 区域内监控 Direct Connect上 的设备的 BGP 状态,正常情况下是 up 状态,如果状态异常,则启动路由表的切换,将子网的流量引导到 vCPE 上。这样整个子网就能通过 vCPE,通过 Internet 网关访问到其他站点或者本地数据中心。当 Direct Connect 的线路状态恢复正常后,线路又能自动切换回来,充分利用专线的稳定性优势,并且整个切换过程全程不需要人工介入

此架构图依然是基于云网通提供的SDWAN网络进行的测试,并且以下脚本主要在 AWS 北京区域进行测试,其他区域操作也类似。

创建IAM策略和角色

IAM 是负责 AWS 上的权限和用户管理的,我们需要先创建一个 IAM 策略,以便让 EC2 实例有后续执行脚本的一些权限。

  1. 进入 AWS 管理控制台,搜索 IAM 服务,点击策略选项,并点击创建策略按钮。
  2. 点击 JSON 按钮,贴入如下的 JSON 代码,并且点击查看策略
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ec2:ReplaceRouteTableAssociation",
                "ec2:DescribeInstances",
                "ec2:DescribeTags",
                "ec2:DeleteRoute",
                "ec2:CreateRouteTable",
                "ec2:DisassociateRouteTable",
                "ec2:ReplaceRoute",
                "ec2:DeleteRouteTable",
                "ec2:AssociateRouteTable",
                "directconnect:DescribeVirtualInterfaces",
                "ec2:DescribeVpcs",
                "ec2:CreateRoute",
                "ec2:DescribeRouteTables"
            ],
            "Resource": "*"
        }
    ]
}

 

  1. 输入一个策略名字,然后点击创建策略
  2. 回到 IAM 控制台,点击角色,点击创建角色按钮。
  3. 选择将使用此角色的服务处,选择 EC2,然后点击下一步
  4. 搜索刚刚创建的策略名,打上勾,选择下一步。
  5. 为该角色填写一个名称,然后点击创建角色

到EC2中关联该角色

您可以创建一个小型的实例,关联该角色,来做监控,也可以将 vCPE 关联该角色来做监控(但一般厂家不会开放 vCPE 的 Root 权限给用户)。如下图所示,选择实例后,点击操作 -> 实例设置 -> 附加/替换 IAM 角色,并且选取之前在 IAM 中创建的角色即可。

两个路由表

我们需要在主线路和备用线路两种状态创建不同的路由表,这样我们在做路由切换的时候不需要在同一张路由表上频繁更改路由,我们只需要将子网切换一下路由表的关联关系即可。

如下图所示,分别创建了两个路由表 sdwan-rt-client-through-dx 和 sdwan-rt-client-through-vcpe,分别代表在主线路可用情况下走专线,在备线路启动的情况下走SDWAN网络。

走 SDWAN 的路由表

 

走 Direct Connect 专线的路由表

修改EC2实例的标签

我们需要在 EC2 实例上面添加如下的标签,脚本会读取这些标签的信息来做监控和故障转移。我们随时可以更改这些标签上的数值,类似环境变量,而无需去更改代码本身。

其中 DXVIF_ID 是Direct Connect Private Vif的ID信息,也是我们需要监控的线路。

RTIDDX 是在上一步创建的路由表 sdwan-rt-client-through-dx 所拥有的ID值。

RTIDSDWAN 是在上一步创建的路由表 sdwan-rt-client-through-vcpe 所拥有的ID值。

SUBNET_ID 是我们需要切换的业务的子网。

 

监控脚本代码

以下代码主要是基于 AWS CLI 来获取 AWS 的资源信息和状态信息,并且通过 –filters–query 参数进行内容过滤和筛选。

将如下代码保存到 EC2 中,命名为 sdwan-ha.sh

#!/bin/bash
#This is a script to failover between DX connection and SDWAN
#Make sure you have already create 2 routing tables and name the tags on the vCPE
#
#Author: Teague Xiao
#Modification Date: 2019-11-19
#
######################################
# Define the region
REGION=cn-north-1
#REGION=`aws ec2 describe-instances --query 'Reservations[*].{REGION:Instances[0].Placement.AvailabilityZone}' --output text | sed 's/.$//'| head -n 1`

# Define other variables by reading the tag info 
DXVIF_ID=`aws ec2 describe-tags --region $REGION --filters Name=key,Values=DXVIF_ID --query 'Tags[*].{ID:Value}' --output text`
RT_ID_DX=`aws ec2 describe-tags --region $REGION --filters Name=key,Values=RT_ID_DX --query 'Tags[*].{ID:Value}' --output text`
RT_ID_SDWAN=`aws ec2 describe-tags --region $REGION --filters Name=key,Values=RT_ID_SDWAN --query 'Tags[*].{ID:Value}' --output text`
SUBNET_ID=`aws ec2 describe-tags --region $REGION --filters Name=key,Values=SUBNET_ID --query 'Tags[*].{ID:Value}' --output text`

#Fixed Variable
RT_ASSOCIATE_ID=INIT
HA_STATUS=DX

echo `date` "-- Starting HA Monitor"

while [ . ]; do

  BGPSTATUS=`aws directconnect describe-virtual-interfaces --virtual-interface-id $DXVIF_ID --region $REGION --query 'virtualInterfaces[*].{STATUS:bgpPeers[0].bgpStatus}' --output text`
  if [ "$BGPSTATUS" == "up" ] && [ "$HA_STATUS" == "SDWAN" ]; then
  echo `date` "-- Direct Conect Back online, switching to DX"
  RT_ASSOCIATE_ID=`aws ec2 describe-route-tables --region cn-north-1 \
  --filters "Name= association.subnet-id,Values=$SUBNET_ID" \
  --query 'RouteTables[*].{RTBASSOID:Associations[0].RouteTableAssociationId}' \
  --output text`
  
  sleep 5
  #Replcaing Route Table
  /usr/bin/aws ec2 replace-route-table-association --route-table-id $RT_ID_DX --association-id $RT_ASSOCIATE_ID --region $REGION
  
  HA_STATUS=DX
  continue
  fi
  
  if [ "$BGPSTATUS" == "down" ] && [ "$HA_STATUS" == "DX" ]; then
  echo `date` "-- Direct Conect failure, switching to SD-WAN"
  
  #Replcaing Route Table
  RT_ASSOCIATE_ID=`aws ec2 describe-route-tables --region cn-north-1 \
  --filters "Name= association.subnet-id,Values=$SUBNET_ID" \
  --query 'RouteTables[*].{RTBASSOID:Associations[0].RouteTableAssociationId}' \
  --output text`

  sleep 5
  /usr/bin/aws ec2 replace-route-table-association --route-table-id $RT_ID_SDWAN --association-id $RT_ASSOCIATE_ID --region $REGION
  
  HA_STATUS=SDWAN
  
  fi
  
  echo `date` "-- Nothing goes wrong, keep monitoring"
  sleep 2
 
sleep 10
done

 

赋予脚本可执行权限

sudo chmod +x sdwan-ha.sh

执行该脚本

./sdwan-ha.sh

后续也可以将脚本加入到 /etc/rc.local 中开机自动执行。

高可用测试

下面,我们会来模拟一下 Direct Connect 专线出现故障的时候,如何进行线路的自动切换的。

我们打开脚本,正常情况下,脚本会自动监控专线的 BGP 状态。

接着,我们到 SDWAN 控制器上关闭专线。

控制器会切段 BGP 的路由器,并且让其下线。稍等片刻,我们可以到控制台上看到专线的状态。

同一时间,我们观察脚本的运行状态,也会发现,线路自动切换了。我们到子网中也能看到,现在子网会关联一个新的路由表,将子网的所有流量都转发到 vCPE 中去,不走专线的网络。

此时,我们回到 SDWAN 控制器,恢复 Direct Connect 专线的状态。

几分钟后,控制台的专线状态会变回 UP 的状态,并且脚本也实时自动进行切换。


优劣分析

在上面实验所涉及的环境,是将脚本部署在 EC2 上,其实最理想的情况是将脚本部署在厂家的 SDWAN vCPE 上做无缝的集成,这样对用户是透明的。另外的话,也可以尝试使用 AWS 的无服务计算 Lambda 函数来做这个监控脚本。我们可以创建一个基于 Python 的函数,每一分钟运行一次,来监控 BGP 状态,并且决定是否切换线路。

另外,我们也可以在脚本中添加 SNS 组件,如果出现线路切换就发送邮件或者短信告知管理员,这样管理员能第一时间知道线路的健康状态。

本次线路的切换过程中,从线路物理状态更新到 BGP 状态更新需要几分钟(一般是3-5分钟左右),如果想修改这个时间,可以通过修改 BGP 设备 CE 端的 BFD (Bidirectional Forwarding Detection) 参数来修改。默认情况下,BGP 每30秒会发送一个 Keepalive 包,如果有连续3个 Keepalive 包没有送达的话,BGP 状态才会更改。我们可以将默认的30秒改为300毫秒,来进行路由更快地切换。但是如果值设置太小,很容易在线路抖动的情况下频繁进行路由切换。具体如何设置 BFD,可以查看这个链接

方法2: 通过路由传播功能,控制明细路由

在 AWS VPC 网络中有一个特性,即如果存在到达路径的多个不同路由条目,则会选取最明细的一条路径。

举个例子,如果我们需要到达10.0.0.1的机器,目前路由表中有条目A(10.0.0.0/8,下一跳VGW-A),有条目B(10.1.0.0/24,下一跳是VGW-B),两个路由条目都包含了去目标机器的路由,但是 VPC 此时会选择条目 B,因为它更精细。

基于这个特性,我们也可以设计出在 Direct Connect 专线和 SDWAN 线路之间的动态路由切换机制。

打开路由传播功能

首先到所有的 VPC 的相应路由表中,打开路由传播的功能,此功能默认是关闭的。

勾选传播这个选项,然后保存。

开启了路由传播功能之后,我们可以看到这个路由表已经收到了来自 Customer Gateway 的动态路由条目了。这里也是所有 SDWAN 网络里面包含的路由条目。

编辑路由表,将 SDWAN 的路由设置得更范围更大一些,让它不优先起作用。

高可用测试

我们到 SDWAN 控制台将 Direct Connect 线路手动断掉,并且我们保持 AWS 北京的一台客户端长期 ping 一个新加坡客户端的地址。

可以看到,在断开线路的一瞬间,我们可以看到路由表的 ”Propagated“ 路由条目中 ”Yes“ 的路由已经消失了,只剩下一些手动创建的路由条目。并且这些路由条目也能指引客户端找到访问对端的路径,并且这些路径是经过 SDWAN 网络过去的。

在整个切换过程中,持续的 Ping 只丢了3个包,切换时间还是非常迅速的。

同样,我们如果将 Direct Connect 线路恢复,这些动态路由也会在几分钟之内完全恢复。

 

优劣分析

第二种方法的切换时间更快,而且在出现专线故障的情况下,我们希望切换的这个过程越快越好,而如果专线恢复,我们对切换回来的时间要求相对就没那么高了。所以这个方法还是很符合实际的使用要求的。

但如果路由条目比较复杂,我们在编写泛路由的时候需要比较小心,而且也需要注意 VPC 中路由表条目的硬限制(100个路由条目)。

总结

在业务连续性和 RTO (Recovery Time Objective) 要求比较高的情况下,非常建议在网络的设计中考虑到双设备,双线路的冗余。并且需要整个切换的过程自动化,对业务的影响最小。

本文提供的两种方法,各有优缺点:

  1. AWS CLI 方法:能够集成更多功能,比如 VPC 路由表切换,SNS等,能为切换带来更多的操作可能性;但切换时间在3-5分钟不等。
  2. 路由传播方法:从 DX 切换到 SDWAN 的切换时间在3秒左右,反过来的切换时间在几分钟的时间内,并且操作更加简单,不涉及 IAM 设置和两套路由表以及监控脚本。

参考文档

https://www.cisco.com/c/en/us/support/docs/cloud-systems-management/prime-access-registrar/213601-csr1000v-ha-redundancy-deployment-guide.html

本篇作者

肖培庆

亚马逊AWS解决方案架构师,负责基于AWS的云计算方案架构的咨询和设计,同时致力于AWS云服务在国内的应用和推广。现主要负责初创企业行业解决方案,曾任职于IBM,联想,Avnet,多年大型企业网络架构和运维经验。