1. 方案背景与方案设计
客户初期上云过程中为了确保通信安全性兼顾成本原因,通常会采用IPSec隧道(VPN)满足需求,随着业务发展对网络稳定性要求提高,开始建设专线。可参考AWS专线高弹性方案通过双专线提供高可用及冗余,链接 https://docs.aws.amazon.com/zh_cn/directconnect/latest/UserGuide/high_resiliency.html。
本文将介绍在单专线情况下,利用已有VPN形成高弹性架构的可选方案,并介绍亚马逊云科技一个客户的高可用架构和具体步骤。
2.可选的VPN加专线架构
共有三种可选架构,三种架构专线均接入Transit Gateway,区别在于VPN的实现方式。
架构1 Transit Gateway(TGW)一体化接入架构
架构利用TGW作为统一接入点,并结合BGP协议,实现云端的主备线路自动切换。
方案参见链接 https://docs.aws.amazon.com/whitepapers/latest/hybrid-connectivity/vpn-connection-as-a-backup-to-aws-dx-connection-example.html
架构2 Transit Gateway Connect+ VPN设备架构
部分客户为了方便统一管理,在云端及本地采用相同第三方厂商的网络设备,构建VPN隧道。此架构中,需要新建专用VPC,并在云端第三方厂商设备与TGW间构建GRE隧道,利用BGP协议,可以实现主备线路自动切换。注TGW connect有支持的第三方厂商列表。
方案参见链接 https://aws.amazon.com/blogs/networking-and-content-delivery/simplify-sd-wan-connectivity-with-aws-transit-gateway-connect/
兼容厂商列表:https://aws.amazon.com/transit-gateway/partners/
路由优先级说明参见链接 https://docs.aws.amazon.com/vpc/latest/tgw/how-transit-gateways-work.html 参见Route evaluation order一节。
架构3 Transit Gateway + 开源/其他VPN设备架构
多数客户初始采用开源软件构建VPN,并且采用静态路由简化管理和配置,架构3中采用独立VPC部署VPN,方便未来云端多VPC扩展以及统一管理主备链路切换。此种架构与专线之间实现主备链路自动切换存在一定困难,要么需要对VPN路由协议进行改造并增加一条云端VPN到TGW的隧道,实现类似TGW Connect功能;要么利用主机或Lambda的监控脚本,根据探测结果,实现主备链路的自动切换。
架构对比与选择
方案 |
优点 |
缺点 |
Transit Gateway 一体化接入 |
实施简单 |
北京和宁夏区域不支持 |
Transit Gateway Connect + VPN |
通过端到端BGP,自动切换路由 |
VPN兼容设备有要求 |
Transit Gateway + 开源VPN |
成本低 复用主机节点或Lambda作为监控 无需修改原有VPN配置 |
需要开发脚本并进行调试 |
本文将主要介绍我的客户利用架构3结合监控切换脚本实现主备链路自动切换,客户专线采用BGP路由协议,VPN采用静态路由协议。客户因使用习惯,要求通过在主机层面使用脚本而非Lambda实现。
3. 脚本检测方案设计说明
- 检测脚本部署在云上主机,使用ping作为健康检测机制,连续10个失败数据包作为切换条件;
- 选用专线两端路由器的地址作为云端和本地健康检测目标端
- 创建Managed prefix list,包含所有需要通信的本地IP地址段(3.0.0/18);
- 默认使用专线通信,当满足切换条件后,检测脚本自动切换TGW路由,添加Managed prefix list路由指向VPN VPC attatchment。当专线恢复后,检测脚本自动切回专线,在TGW路由删除Managed prefilx list路由。
- 客户机房侧,客户利用第三方防火墙实现机房到云上的链路检测设计,根据检测的结果进行VPN与专线的路由切换。
4.脚本检测实施步骤
实施前提条件:VPN,专线分别已经部署成功,并且点对点路由测试通过,生产VPC已经切换为Direct Connect专线。
1、EC2主机(10.0.0.7)安装aws cli,确认automatic recovery已启用。
2、给EC2主机(10.0.0.7)绑定IAM Role,授权EC2允许修改TGW的prefix路由
1)创建IAM 策略 TGW_prefix_policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:CreateTransitGatewayRoutePrefixListReference",
"ec2:DeleteTransitGatewayRoutePrefixListReference"
],
"Resource": [
"*"
]
}
]
}
2)创建IAM角色 EC2_TGW_Prefix_Role,绑定新建的策略 TGW_prefix_policy
3)在EC2上绑定新建的角色EC2_TGW_Prefix_Role
3、路由设置
1)检查生产VPC(10.0.0.0/18)的子网路由中,目的地是客户机房IP地址段(10.3.0.0/18),下一跳路由指向Transit Gateway
2)VPC中设置 Managed prefix list, VPC->Managed prefix lists -> Create prefix list ,设置客户机房的IP地址段(10.3.0.0/18)。
再新建一个测试的managed prefix list,用于调试验证,prefix的IP地址设置一个不使用的IP地址段,例如173.0.0.5/32
3)Transit Gateway设置一条32位掩码的点对点静态路由,目的地是Ping检测的客户机房的IP(10.109.2.1),下一跳指向DirectConnectGateway。配置位置VPC->Transit Gateway route tables -> [transitGateway的ID] -> Create static route
Attachment选择DirectConnectGateway
4)VPN所在的VPC(10.1.0.0/18),目的地是客户机房IP地址段(10.3.0.0/18),下一跳路由指向VPN(10.1.0.5所在主机的ENI)。目的地是生产VPC的IP地址段(10.0.0.0/18),下一跳路由指向Transit Gateway。默认路由走公网,目的地地址是全0,指向IGW。
5)客户机房的Fortinet切换和路由设置,由客户机房的IT工程是配置完成。
4、维护脚本
1)脚本三个shell脚本组成。
a、监控切换脚本HAmonitor.sh,可以灵活设置目标测的IP地址,Ping的累积失败的个数,Ping的检测周期等。脚本内容如下:
#!/bin/bash
dxTargetIP=127.0.0.1
tgwRT=tgw-rtb-0d86bcd71877f6d88
idcPrId=pl-0d81338f99b4770b6
vpnAttId=tgw-attach-0f21402e36c7c65ed
period=1
failCount=10
connectionStatus=0
dxFail=0
dxFailCount=0
pingTimeout=1
switchTGWRouteTableToVPN(){
echo "add vpn prefix preference in tgw route table "
/usr/bin/aws ec2 create-transit-gateway-prefix-list-reference \
--transit-gateway-route-table-id $tgwRT \
--prefix-list-id $idcPrId \
--transit-gateway-attachment-id $vpnAttId
}
switchTGWRouteTableToDx(){
echo "delete vpn prefix preference in tgw route table"
/usr/bin/aws ec2 delete-transit-gateway-prefix-list-reference \
--transit-gateway-route-table-id $tgwRT \
--prefix-list-id=$idcPrId
}
echo "default we use dx when this script begin, this is reset to default"
connectionStatus=0
switchTGWRouteTableToDx
while :; do
#dx monitoring
if ping -c 1 -w $pingTimeout $dxTargetIP &> /dev/null
then
echo "dx test success"
if [ $dxFailCount -lt 2 ]
then
dxFailCount=0
dxFail=0
else
dxFailCount=$[$dxFailCount-1]
fi
else
echo "dx ping test fail "
dxFailCount=$[$dxFailCount+1]
fi
#dx status set
if [ $dxFailCount -gt $failCount ]
then
echo "dx status is fail "
dxFailCount=$[$failCount+1]
dxFail=1
fi
if [ $connectionStatus -eq 0 ]
then
echo "dxFail = $dxFail"
if [ $dxFail -eq 1 ]
then
echo "trigger switch from dx to vpn a"
connectionStatus=0
switchTGWRouteTableToVPN
echo "trigger switch from dx to vpn b"
fi
# $connectionStatus=1 so route is vpn
elif [ $connectionStatus -eq 1 ]
then
if [ $dxFail -eq 0 ]
then
echo "trigger switch from vpn to dx a"
connectionStatus=0
switchTGWRouteTableToDx
echo "trigger switch from vpn to dx b"
fi
fi
sleep $period
done
b、守护脚本HAwatch.sh,当发现检测脚本异常退出之后,会重新启动检测。脚本内容如下:
#! /bin/sh
#nohup /home/ec2-user/monitor/HAwatcher.sh > /home/ec2-user/monitor/log/HAwatcher`date '+%Y%m%d%H%M'`.log 2>&1 &
#进程名字可修改
PRO_NAME=HAmonitor.sh
basePath=/home/ec2-user/monitor
chmod +x ${basePath}/HAmonitor.sh
#find /home/ec2-user/monitor/log/ -mmin +120 -name "*.log" -exec rm -rf {} \;
find ${basePath}/log/ -mtime +4 -name "*.log" -exec rm -rf {} \;
while true ; do
#用ps获取$PRO_NAME进程数量
NUM=`ps aux | grep -w ${PRO_NAME} | grep -v grep |wc -l`
#echo $NUM
#少于1,重启进程
if [ "${NUM}" -lt "1" ];then
echo "${PRO_NAME} was killed"
LogNameDATE=`date '+%Y%m%d%H%M'`
nohup ${basePath}/${PRO_NAME} > ${basePath}/log/${PRO_NAME}${LogNameDATE}.log 2>&1 &
#大于1,杀掉所有进程,重启
elif [ "${NUM}" -gt "1" ];then
echo "more than 1 ${PRO_NAME},killall ${PRO_NAME}"
killall -9 -I $PRO_NAME
${PRO_NAME} -d
fi
#kill僵尸进程
NUM_STAT=`ps aux | grep -w ${PRO_NAME} | grep T | grep -v grep | wc -l`
if [ "${NUM_STAT}" -gt "0" ];then
echo "kill zombie ${PRO_NAME}"
killall -9 -I ${PRO_NAME}
${PRO_NAME} -d
fi
sleep 5s
done
exit 0
c、Cron脚本HAcron.sh, 利用CronJob来做二次保护,默认每周一早晨8点运行一次,清理日志,重置状态。脚本会固定清除4天前的日志,在HAwatch.sh中,可以根据需要调整。脚本内容如下:
#! /bin/sh
basePath=/home/ec2-user/monitor
PRO_NAME=HAwatch.sh
PRO_NAME2=HAmonitor.sh
# 每周重启一次
killall -9 -I $PRO_NAME
killall -9 -I $PRO_NAME2
while true ; do
#用ps获取$PRO_NAME进程数量
NUM=`ps aux | grep -w ${PRO_NAME} | grep -v grep |wc -l`
#echo $NUM
#少于1,重启进程
if [ "${NUM}" -lt "1" ];then
echo "${PRO_NAME} was killed"
LogNameDATE=`date '+%Y%m%d%H%M'`
echo "$LogNameDATE restart ${PRO_NAME} ${PRO_NAME}"
nohup ${basePath}/${PRO_NAME} > ${basePath}/log/${PRO_NAME}${LogNameDATE}.log 2>&1 &
break
#大于1,杀掉所有进程,重启
elif [ "${NUM}" -gt "1" ];then
echo "more than 1 ${PRO_NAME},killall ${PRO_NAME}"
killall -9 $PRO_NAME
${PRO_NAME} -d
fi
#kill僵尸进程
NUM_STAT=`ps aux | grep -w ${PRO_NAME} | grep T | grep -v grep | wc -l`
if [ "${NUM_STAT}" -gt "0" ];then
killall -9 ${PRO_NAME}
${PRO_NAME} -d
fi
done
exit 0
2)将三个脚本放入monitor目录,放入/home/ec2-user/monitor/, 注意如果放在别的目录,需要修改脚本中的路径。
3)添加脚本的执行权限
chmod +x HAcron.sh
chmod +x HAwatch.sh
chmod +x HAmonitor.sh
mkdir log
4)修改HAmonitor.sh脚本中和环境相关的关键字段,包括以下字段
注意先把testTemp的PrefixID填入到脚本中,先用于调试,避免调试时影响生产环境的业务。
#用于检测的,客户机房IP地址
dxTargetIP=10.109.2.1
#transitGateway的路由表
tgwRT=tgw-rtb-0d86*****77f6d88
#添加的客户机房的Managed Prefix List
idcPrId=pl-0d813*****4770b6
#transitGateway上VPN的VPC的Attachment
vpnAttId=tgw-attach-0f21*****6c7c65ed
注意
脚本默认路径为 /home/user2
5、部署脚本
执行Crontab命令,添加Cron表达式
crontab -e -u root
#添加如下内容
10 8 * * 1 /bin/bash /home/ec2-user/monitor/HAcron.sh > /home/ec2-user/monitor/log/HAcron`date '+\%Y\%m\%d\%H\%M'`.log 2>&1 &
重启Crond服务
sudo service crond restart
查看日志
/home/ec2-user/monitor/log
6、脚本部署完成之后,对修改参数后的脚本进行备份,并对EC2进行SnapShot备份
7、调试测试:脚本此时使用的是临时的模拟的ManagedPrefixList(ManagedPrefixList 包含不影响生产的IP地址端,例如173.0.0.0/18),使用它做测试。验证当专线正常时,TransitGateway 上的prefix路由是没有的。手工修改10.0.0.5的安全组,出方向禁止Ping后,专线ping检测失败,这时会发生切换,观察TransitGateway上的prefix路由,如果成功创建出prefix路由,则测试成功。
8、正式测试,修改HAmonitor.sh中prefixID为机房IDC(10.3.0.0/18地址段的Prefix),kill HAmonitor.sh的进程,HAwatch.sh守护程序会自动拉起新的HAmonitor.sh,之后与业务预约时间,进行生产环境的故障转移测试。
生产测试,可以测两个用例。
第一个测试,手工在AWS上的directConnect界面上虚接口上触发test,将BGP down掉,观察切换效果。触发操作参考链接 https://docs.aws.amazon.com/directconnect/latest/UserGuide/resiliency_failover.html
效果检查
1)查看HAMonitor.sh日志,观察切换日志。
2)在TransitGateway上观察到,Prefix Reference路由正常加上
3) 观察Ping的Trace Route查看走了VPN。BGPUp后,专线切换回到专线上。
第二个测试,将IDC的router(10.109.2.1)路由器端口Down掉做测试,一样会正常切换。
方案总结
该方案通过切换脚本实现专线和VPN的切换方案,是一个成本低廉且架构简单的方案。
本篇作者