刘劲男,架构师,微软云解决方案专家

最近为客户搭建一个 Azure 的测试环境,客户的用户一半在上海、一半在香港、台湾、印度、孟加拉等地,客户需要从价格、性能等方面确定其服务器部署在Azure的站点以及网络环境。随着中国企业出海、以及经济全球化的普及,这类总部在中国大陆、分部在亚洲各地甚至全球的情形已经非常普遍,现将测试环境的设计和结果与大家分享。

公有云的设计需要从价格、性能两方面考虑。价格方面,同等虚机在中国 Azure 的价格比香港 Azure(属于全球 Azure 一个站点)低,所以把生产服务器(使用 FTP Server 模拟)放在中国 Azure 站点在价格上是有优势的;性能方面,占据一半用户的上海用户如果访问上海 Azure 性能肯定是最优的,所以首先考虑把生产服务器放在上海 Azure 站点(简称 SH)。但是这样的部署,我们需要解决的是亚洲用户访问上海服务器的性能问题:如果直接通过 Internet 访问上海站点,除了香港的访问速度是理想的,其他台湾、印度、孟加拉的用户直接访问中国 Azure 的效果都不理想。鉴于如此 Internet 网络环境,同时中国 Azure 和全球 Azure 是两套隔离环境,如果不借助第三方运营商的专线只能通过 Internet 访问,所以在 Azure 上海和香港 Azure(简称 HK)搭建 Site to Site VPN;然后利用全球 Azure 各站点间的 backbone 光纤搭建 Azure HK 到 Azure 各站点的 VNet to VNet VPN,在 Azure 各站点搭建 proxy,让各地客户就近进入最近的 Proxy,最终通过 VPN 去到上海的 FTP Server。架构如下图:

因为上海到 IND 都需要 HK 作为中转节点,因此考虑 VPN Gateway 启用 BGP,这样可以方便地通过前缀来交换“路由”,使得多地网络可以方便互通。

虽然将来在正式生产环境中,客户 Office 将使用本地 VPN Gateway 和 Azure  各地的 VPN Gateway 相连,但是为了节省调试客户本地  VPN Gateway 的时间,提高测试效率,这里使用 Haproxy 作为就近测试节点,同样能模拟各地的网络访问速度。

感谢客户配合测试,最后 FTP 的 Client Filezilla 基本跑满了用户的 Internet 出口带宽。摘录了一部分测试结果:

说明:

  1. 本测试环境为避免混淆,并没有搭建 SH 的出口,因为从 Shanghai 到 SH 入口网速并不是本环境验证的要素;
  2. 因为在 HK/TW 没有测试人员,所以使用上海 Office 来模拟 HK 用户,到 HK 节点进行上传下载,速度能跑满用户的 Internet 出口带宽,这时路线是客户上海 office 通过 Internet Azure HK,然后 Azure HK VPN Azure SH
  3. 在测试时,由于孟加拉并不如事先想象访问印度速度好,所以我们又增加了新加坡 Azure 站点来比较。从测试结果看,以 Azure HK 节点为中转,印度从 Azure 印度、新加坡节点进入经过 HK 到 SH 的速度明显高于直接从 HK 节点进入到 SH 的速度。

当然从费用考虑多增加站点会增加 VPN Gateway 和流量费用,所以新加坡和印度站点选一即可。最终,服务器在上海、靠 HK 中转、从就近节点进入的设计,不仅可以满足不同地区的高访问速度,同时性价比也是相对合理的。

下文是此方案搭建的详细步骤,此处以上海、香港、印度为例,新加坡节点和印度节点相同不再赘述,供有兴趣的朋友参考(注以下步骤没有包括 SH 的出口):

一、构造网络

本章节参考的官方网站:

Azure 门户中创建站点到站点的连接:

https://docs.microsoft.com/zh-cn/azure/vpn-gateway/vpn-gateway-howto-site-to-site-resource-manager-portal

Azure 门户配置 VNet 到 VNet 的连接:

https://docs.microsoft.com/zh-cn/azure/vpn-gateway/vpn-gateway-howto-vnet-vnet-resource-manager-portal

使用 PowerShell 在 Azure VPN 网关上配置 BGP:

https://docs.microsoft.com/zh-cn/azure/vpn-gateway/vpn-gateway-bgp-resource-manager-ps

使用 Portal 构建三地的 VPN 连接

下表为下面命令用到的命令,供参考:

1. 创建 vNet 在 SH, HK, India;

a. 建立 Subnet1 放置 VM;

b. 建立 Gateway Subnet 给系统放 Gateway 的 Instance。

2. 创建 Virtual Network Gateway 在 SH, HK, India,Gateway 是 Route based VPN, Standard SKU。下面是 HK vNet Gateway 的示例:

约 30 分钟后部署完成。

3. 建立 Local Gateway 在 SH、HK,因为 SH 和 HK 之间是 S2S VPN,所以都要建立 Local Gateway 来定义对端的 Internet 接入点,否则在 Portal 界面上是无法看到对端网络接入点的。下图是 HK 的 Local Gateway 的示例:

4. 创建 sh to HK 之间的 Connection。分别从两个 Site 建立连接:

a. Sh to HK:Site to Site;

b. HK to Sh : Site to Site;

下图是 HK 到 Sh 的连接示例:

5. 创建 VM 挂在 shvnet 和 hkvnet 下面:

上海 FTP Server VM: shftp, D2, Centos 6.9, 10.1.1.4;

香港 Proxy VM: hkproxy, A2_V2, Centos 6.9, 10.2.1.4;

建立后两个 VM 能互相 ping 通。

6. 创建 hk to india 的 vnet to vnet connection Vnet to Vnet 连接因为这里在一个 Subsciption 中,在 Portal 界面上就能互相看到,所以不需要建立 Local Gateway,直接在 HK的vNet Gateway 中建立 HK to Ind 的 Vnet2Vnet 连接,在Ind 的 vNet Gateway 中建立 Ind to HK 的 Vnet2Vnet 连接即可。下图为从建立连接的屏幕拷贝:

Hkvgw 建立连接前:

添加连接,分别从 hkvgw 和 indvgw 出发:

建立连接后 Hkvgw 的界面:

建立连接后 indvgw 的界面:

Shvgw 的界面:

到此三地连接已经完整建立,但此时没有启用 BGP。

7. 验证连接

创建 India proxy VM: indproxy, A2_V2, Centos 6.9, 10.3.1.4;

此时 shftp 可以联通 hkproxy; hkproxy 联通 indproxy; 但是 shftp 和 indproxy 不通。

Enable VNP BGP

如果不配置 BGP,那么 SH 到 Ind 的网络是不通的,需要另外配置路由规则,Azure vNet Gateway 支持 BGP(需要Standard 级别以上),这个意味着 Enable BGP 以后,三个 site 的 vNet 如同一个网络。因为 BGP 的功能发布不久,目前 Azure Portal 不支持 enable BGP,只有通过 PowerShell 来启用。

本节在上面 Portal 建立成果的基础上,讲述在 Powershell 上如何启用 BGP,也可以帮助读者知晓需要改造哪些环节。

Powershell 推荐使用 Powershell IDEIDE 环境为命令、参数提示提供了很大的提示方便。当你敲下 “” 键时后面的命令或参数都可以跳出来,就像一个集成的编程环境,不再是存粹命令敲打,对记不住命令和参数的同学是个很大的帮助。

首先使用 Powershell  登陆中国 Azure,需要指定 EnvironmentName AzureChinaCloud,并定位你的Subscription。这里把这个窗口称为 PS Session 1:

PS C:\Users\jinnliu> Login-AzureRmAccount -EnvironmentName AzureChinaCloud;

查询当前的 Subscription:

PS C:\Users\jinnliu> Get-AzureRmContext;

若当前 session 不是你想要的 subscription,则查看所有 subscription:

PS C:\Users\jinnliu> Get-AzureRmSubscription;

并设置当前 session 的 subscription 为你想要的:

PS C:\Users\jinnliu> Select-AzureRmSubscription -SubscriptionName “Windows Azure Enterprise Trial”。

1.在 sh site,修改 vNet Gateway,设置 ASN 号码 65010

首先取得 vNet Gateway

PS C:\Users\jinnliu> $shvgw = Get-AzureRmVirtualNetworkGateway -ResourceGroupName ljnshrg -Name shvgw

2. 然后修改 vNet Gateway,设置 ASN 号码 (默认为 65515

PS C:\Users\jinnliu> Set-AzureRmVirtualNetworkGateway -VirtualNetworkGateway $shvgw -Asn 65010

Name                   : shvgw

ResourceGroupName      : ljnshrg

Location               : chinaeast

。。。此处忽略

BgpSettings            : {

“Asn”: 65010,

“BgpPeeringAddress”: “10.1.0.14”,

“PeerWeight”: 0

}

这个设置虽然不需要关闭 gateway,但是耗时比较长,动作完成后可以看到 ASN 号码改变。

2. 在 hk site 修改 vNet Gateway,设置 ASN 号码 65020;

开启另外一个 PowerShell Session,登陆全球 Azure,这时候不需要指定 EnvironmentName了,因为默认为全球Azure, 登陆以后定位你的 subscription, 这里把这个窗口称为 PS Session 2:

PS C:\Users\jinnliu> Login-AzureRmAccount

PS C:\Users\jinnliu> Get-AzureRmSubscription

PS C:\Users\jinnliu> Select-AzureRmSubscription -SubscriptionName “Visual Studio Enterprise”

设置 vNet Gateway:

PS C:\Users\jinnliu> $hkvgw = Get-AzureRmVirtualNetworkGateway -Name hkvgw -ResourceGroupName ljnhkrg

PS C:\Users\jinnliu> Set-AzureRmVirtualNetworkGateway -VirtualNetworkGateway $hkvgw -Asn 65020

Name                   : hkvgw

ResourceGroupName      : ljnhkrg

Location               : eastasia

。。。。

BgpSettings            : {

“Asn”: 65020,

“BgpPeeringAddress”: “10.2.0.14”,

“PeerWeight”: 0

}

3. PS Session1: 修改 sh site  的 Local Gateway,设置对端(HK)的 vNet GatewayASNBgp peering address prefix:

首先取得 local Gateway:

PS C:\Users\jinnliu> $shlgw = Get-AzureRmLocalNetworkGateway -Name shlgw -ResourceGroupName ljnshrg

再改 local Gateway 的 BGP 配值:

PS C:\Users\jinnliu> Set-AzureRmLocalNetworkGateway -LocalNetworkGateway $shlgw -AddressPrefix 10.2.0.14/32 -Asn 65020 -BgpPeeringAddress 10.2.0.14

Name                     : shlgw

ResourceGroupName        : ljnshrg

Location                 : chinaeast

GatewayIpAddress         : 52.175.30.95

LocalNetworkAddressSpace : {

“AddressPrefixes”: [

“10.2.0.14/32”

]

}

BgpSettings              : {

“Asn”: 65020,

“BgpPeeringAddress”: “10.2.0.14”,

“PeerWeight”: 0

}

4. PS Session2: 修改 hk siteLocal Gateway,设置对端(SH)的 vNet Gateway 的 ASNBgp peering addressprefix:

首先取得 local Gateway:

PS C:\Users\jinnliu> $hklgw = Get-AzureRmLocalNetworkGateway -Name hklgw -ResourceGroupName ljnhkrg

PS C:\Users\jinnliu> $hklgw.BgpSettingsText

null

再改 local Gateway 的 BGP 配置:

PS C:\Users\jinnliu> Set-AzureRmLocalNetworkGateway -LocalNetworkGateway $hklgw -AddressPrefix 10.1.0.14/32 -Asn 65010 -BgpPeeringAddress 10.1.0.14

Name                     : hklgw

ResourceGroupName        : ljnhkrg

Location                 : eastasia

GatewayIpAddress         : 139.219.234.238

LocalNetworkAddressSpace : {

“AddressPrefixes”: [

“10.1.0.14/32”

]

}

BgpSettings              : {

“Asn”: 65010,

“BgpPeeringAddress”: “10.1.0.14”,

“PeerWeight”: 0

}

5. 建立 SH 和 HK 之间的 S2S BGP enable 的连接:

若前面第一部分已经建立了Connection,需要先删除两端的连接。

PS Session1:在SH Site 建立 BGP enable 的连接:

PS C:\Users\jinnliu> New-AzureRmVirtualNetworkGatewayConnection -Name sh2hk -ResourceGroupName ljnshrg -Location chinaeast -VirtualNetworkGateway1 $shvgw -LocalNetworkGateway2 $shlgw -ConnectionType IPsec -SharedKey ljn321 -EnableBgp $true

PS Session2:在 HK Site 建立 BGP enable 的连接:

PS C:\Users\jinnliu> New-AzureRmVirtualNetworkGatewayConnection -Name hk2sh -ResourceGroupName ljnhkrg -Location eastasia -VirtualNetworkGateway1 $hkvgw -LocalNetworkGateway2 $hklgw -ConnectionType IPsec -SharedKey ljn321 -EnableBgp $true

稍后 connection 的状态显示 Succeeded  和 Connected。

注意 Sharekey 不要输成 AuthorizationKey,笔者不小心犯了小错,联不通找了半天才找到问题。

6. 在 ind site,修改 vNet Gateway,设置 ASN 号码 65030:

PS Session2: 前面已经设置了 HK vNet Gateway 的 BGP ASN  号码 65020,我们只要设置 India vNet Gateway 的 BGP ASN 号码 65030 就好。

PS C:\Users\jinnliu> $indvgw = Get-AzureRmVirtualNetworkGateway -Name indvgw -ResourceGroupName ljnindrg

 

PS C:\Users\jinnliu> $indvgw.BgpSettingsText

{

“Asn”: 65515,

“BgpPeeringAddress”: “10.3.0.14”,

“PeerWeight”: 0

}

 

PS C:\Users\jinnliu> Set-AzureRmVirtualNetworkGateway -VirtualNetworkGateway $indvgw -Asn 65030

7、建立 HK 和 Ind 之间的 Vnet2Vnet BGP enable 的连接:

若前面有 Connection,需要先删除两端的连接:

PS Session2:

在 HK site 建立 HK2Ind 连接:

PS C:\Users\jinnliu> New-AzureRmVirtualNetworkGatewayConnection -Name hk2ind -ResourceGroupName ljnhkrg -Location eastasia -VirtualNetworkGateway1 $hkvgw -VirtualNetworkGateway2 $indvgw -ConnectionType Vnet2Vnet -SharedKey ljn321 -EnableBgp $true

在 Ind Site 建立 Ind2HK 连接:

PS C:\Users\jinnliu> New-AzureRmVirtualNetworkGatewayConnection -Name ind2hk -ResourceGroupName ljnindrg -Location southindia -VirtualNetworkGateway1 $indvgw -VirtualNetworkGateway2 $hkvgw -ConnectionType Vnet2Vnet -SharedKey ljn321 -EnableBgp $true

过几分钟,connection 的状态显示 Succeeded 和 Connected。

7. 验证连接:

此时挂在 SH Site 的 shvnet、HK Site 的 hkvnet、India Site 的 indvnet 中的 VM,都可以互通互联了。

在 VM 里面 ping 测试:

Sh – HK  latency 约33 ms

HK – India(South) 约67 ms

Sh – India(South) 约96 ms   (通过HK中转)

这里,笔者也测试了直接从 SH 连到 India 的 Site 2 Site 的 VPN 连接,延时大大高于通过 HK 中转的连接。另外搭建了 SG  Site 的 proxy,  从 HK  到 SG 的 ping 延时也就 38 ms 左右,所以从 SH 到 SG(HK 中转)约 67ms,直接 SH 到 SG 的 S2S VPN,ping 延时 95ms 左右。

二、搭建 FTP 和两个 Proxy

这里笔者用 Azure VM 的 Centos 6.9 模板搭建了 FTP Server 和 Haproxy 配置,大家也可以在网上寻找,记录下来仅供不熟悉配置的同学使用,如果你对 FTP 或者 HAProxy 已经非常熟悉,可以跳过此内容,此章节部署的关键是:

  1. 关闭 OS level 的防火墙,如 setenforce = 0, stop iptables 的 service 等,使用 Azure 的 NSG 来控制 Inbound 的访问策略;
  2. 如果想搭建多个 Haproxy,那么一定是要配置多个 VSFTPD Service Instance 与之对应;
  3. VSFTPD 采用 Passive 模式。

FTP Server with multi instance

  1. 使用 putty 开启 shftp testadmin@159.237.202;
  2. 使用 Root 登陆 [testadmin@shftp ~]$ sudo su -;
  3. 安装 vsftpd:

[root@shftp ~]# yum install vsftpd

设置启动配置项:

[root@shftp ~]# chkconfig vsftpd on

4. 修改第一个 Instance 的配置文件/etc/vsftpd/vsftpd.conf

[root@shftp ~]# vi /etc/vsftpd/vsftpd.conf

样例:

anonymous_enable=NO

local_enable=YES

write_enable=YES

local_umask=022

dirmessage_enable=YES

xferlog_enable=YES

connect_from_port_20=NO

xferlog_file=/var/log/xferlog

vsftpd_log_file=/var/log/vsftpd.log

xferlog_std_format=NO

data_connection_timeout=10

listen=YES

listen_port=21

listen_ipv6=NO

pam_service_name=vsftpd

userlist_enable=YES

tcp_wrappers=YES

pasv_enable=YES

#标注HK Proxy的PIP

pasv_address=65.52.188.164

port_enable=YES

#标注 HK Proxy 的接收 Data 的端口

pasv_min_port=30000

pasv_max_port=30200

5. 生成并修改第二个 Instance 配置文件/etc/vsftpd/vsftpd_2.conf

[root@shftp ~]# cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd_2.conf

[root@shftp ~]# vi /etc/vsftpd/vsftpd_2.conf

anonymous_enable=NO

local_enable=YES

write_enable=YES

local_umask=022

dirmessage_enable=YES

xferlog_enable=YES

connect_from_port_20=NO

#instance 2

xferlog_file=/var/log/xferlog2

vsftpd_log_file=/var/log/vsftpd2.log

xferlog_std_format=NO

data_connection_timeout=10

listen=YES

#instance 2

listen_port=2121

listen_ipv6=NO

pam_service_name=vsftpd

userlist_enable=YES

tcp_wrappers=YES

pasv_enable=YES

#标注 Ind Proxy 的 PIP

pasv_address=52.172.39.131

port_enable=YES

#标注 Ind Proxy 的接收 Data 的端口

pasv_min_port=31000

pasv_max_port=31200

生成 Log 文件:

[root@shftp ~]# touch /var/log/vsftpd.log

[root@shftp ~]# touch /var/log/vsftpd2.log

6. 增加本地用户 testuser,指向目录/opt/testuser,禁止登录 SSH 权限:

[root@shftp ~]# useradd -d /opt/testuser -g ftp -s /sbin/nologin testuser

7. 设置用户口令:

[root@shftp ~]# passwd testuser

8. 修改目录权限:

[root@shftp ~]# chmod 777 /opt/testuser/

9. 重启 vsftpd 服务:

[root@shftp ~]# service vsftpd restart

Shutting down vsftpd:                                      [  OK  ]

Starting vsftpd for vsftpd_2:                              [  OK  ]

Starting vsftpd for vsftpd:                                [  OK  ]

这时候会自动启动两个 Instance,因为有两个配置文件在 /etc/vsftpd 目录下:

vsftpd.confvsftpd_2.conf

10. 查看 vsftpd 服务状态:

[root@shftp ~]# service vsftpd status

vsftpd (pid 27145 27139) is running…

这时候有两个 Instance 启动

11. 把 OS 的防火墙关闭:

[root@shftp ~]# setenforce 0

[root@shftp ~]# service iptables stop

[root@shftp ~]# service ip6tables stop

因为 SHFtp 和 HKproxy、Indproxy 通信都是通过内网,如果仅是开放 HK,IND 出口, Shftp 不需要加 NSG 的Inbound 规则。如果需要考虑开放 SH 的出口,就需要再增加一个 Instance 配置文件,以及设置 shftp 的 NSG 开放inbound 的 ftp、ftp-data 的端口号。

在 HK 搭建 Hkproxy

  1. 使用 putty 开启 hkproxy testadmin@65.52.188.164;
  2. 安装 Haproxy:

[root@hkproxy ~]# yum install haproxy

[root@hkproxy ~]# cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy_bk.cfg

[root@hkproxy ~]# chkconfig haproxy on

3. 修改配置文件:

[root@hkproxy ~]# vi /etc/haproxy/haproxy.cfg

一定要有下面 FTP 的配置内容:

listen ftp

bind *:21,*:30000-30200

mode tcp

server ftpserver 10.1.1.4 check inter 3000 port 21

4. 重新启动 haproxy:

[root@hkproxy ~]# service haproxy restart

5. 把 OS 的防火墙关闭:

[root@hkproxy ~]# setenforce 0

[root@hkproxy ~]# service iptables stop

[root@hkproxy~]# service ip6tables stop

6. 在 Azuer Portal 设置 HKproxy VM 的 Nsg:

添加 inbound ftp allow tcp 21,ftp-data allow tcp 30000-30200

完成后如下图:

在 Ind 搭建 Indproxy

这个步骤同 HK 的 Haproxy 的安装配置步骤,仅是 haprocy.cfg,需要配置成不同端口:

[root@indproxy ~]# vi /etc/haproxy/haproxy.cfg

一定要有下面 ftp  配置内容:

listen ftp

bind *:2121,*:31000-31200

mode tcp

server ftpserver 10.1.1.4 check inter 3000 port 2121

同时在 Indproxy VM 的 Nsg 中添加 inbound ftp allow tcp 2121,ftp-data allow tcp 31000-31200。

三、验证结果和测试入口

在 PC 端安装 ftp client 工具如 Filezilla 测试,配置 Filezilla 的 Site 如下:

HK Site1:  65.52.188.164 port 21

Ind Site2: 52.172.39.131 port 2121

User : testuser/*****