Category: 大咖专栏


构建健壮的混合云网络——BJS DX篇

背景介绍:

近年来,随着公有云的普及,一方面,越来越多的用户选择利用公有云在弹性、灵活性等方面的优势,在云上部署新的应用系统,另一方面,大量的企业有很多现有的本地基础设施投资,所以企业上云的过程并不是一触而就的,期间势必存在云应用与本地数据中心应用并存的局面,为了更好的融合云与本地数据中心的应用环境,实现整体应用系统的稳定性和高可用性,构建一个健壮的混合云网络至关重要。

在AWS上,用来连接AWS与本地数据中心的方式主要有以下3种:

1.    纯VPN组网

2.    纯专线组网

3.    VPN与专线的混合组网

其中,对于AWS中国区来讲,由于AWS自身的VPN服务VGW目前尚未落地,客户急需要一个替代方案,能够达到类似于VGW的冗余及故障切换功能。

本篇主要讲述第二种组网方式,着眼点在于如何实现混合云网络的健壮性及故障自愈。

对于第一,第三种组网方式的高可用实现,请参考:

《构建健壮的混合云网络——BJS VPN篇》

《构建健壮的混合云网络——BJS DX+VPN篇》

对于如何实现对VPN流量的监控、故障告警及事件日志搜集,请参考:

《构建健壮的混合云网络——BJS DX+VPN篇》

拓扑图:

AWS与本地站点之间建立两条专线,为了保证一条专线故障后,剩下的专线能够承载所有的业务流量,建议使用主备模式,考虑到高可用,建议两条专线分别终结在SINNET和CIDS两个DX Location,并且可以使用两家专线提供商的链路。

配置步骤:

1.    申请专线

小于500M的专线由AWS APN Partner提供,这里以APN Partner方案为例,大于1G的专线接入请参考如下文档:

https://www.amazonaws.cn/en/documentation/directconnect/

向APN Partner申请链路,根据要求提供相关信息,通常包括用户AWS账号,专线带宽等信息。

2.    接受连接并创建virtual interface

当APN Partner建立好专线后,登入management console,选择Direct Connect服务,将可以看到相关的连接,需要选择接受连接。

创建Virtual Interface。

选择创建Private Virtual Interface,设置接口名称并与相关VPC的VGW关联

根据自己的需要设置互联地址及本地站点的AS号

3.    下载本地站点端路由器的配置

4.    修改本地路由器端BGP配置,实现主备冗余

a.    AWS侧出向流量主备通过AS-PATH属性实现

b.    本地站点侧出向流量主备通过Local-Preference属性实现

下面是本地站点侧,备份链路路由器上的参考配置:

route-map LOCAL-PRE permit 10

 set local-preference 50

!

route-map PREPEND permit 10

 set as-path prepend 1111 1111

router bgp 1111

 network 0.0.0.0

 neighbor 169.254.10.2 remote-as 17493

 neighbor 169.254.10.2 route-map LOCAL-PRE in

 neighbor 169.254.10.2 route-map PREPEND out

5.    确认接口up

6.    设置需要通过专线访问本地站点的路由表的下一跳为VGW

 

作者介绍:

余骏

亚马逊AWS解决方案架构师,负责基于AWS的云计算方案架构的咨询和设计,同时致力于AWS云服务在国内的应用和推广。在加入AWS之前,在思科中国担任系统工程师,负责方案咨询和架构设计,在企业私有云和基础网络方面有丰富经验。

构建健壮的混合云网络——BJS VPN篇

背景介绍:

近年来,随着公有云的普及,一方面,越来越多的用户选择利用公有云在弹性、灵活性等方面的优势,在云上部署新的应用系统,另一方面,大量的企业有很多现有的本地基础设施投资,所以企业上云的过程并不是一触而就的,期间势必存在云应用与本地数据中心应用并存的局面,为了更好的融合云与本地数据中心的应用环境,实现整体应用系统的稳定性和高可用性,构建一个健壮的混合云网络至关重要。

在AWS上,用来连接AWS与本地数据中心的方式主要有以下3种:

1.    纯VPN组网

2.    纯专线组网

3.    VPN与专线的混合组网

其中,对于AWS中国区来讲,由于AWS自身的VPN服务VGW目前尚未落地,客户急需要一个替代方案,能够达到类似于VGW的冗余及故障切换功能。

本篇主要讲述第一种组网方式,着眼点在于如何实现混合云网络的健壮性及故障自愈,并不会讲述太多的IPSec VPN知识。

对于第二,第三种组网方式的高可用实现,请参考:

《构建健壮的混合云网络——BJS DX篇》

《构建健壮的混合云网络——BJS DX+VPN篇》

对于如何实现对VPN流量的监控、故障告警及事件日志搜集,请参考:

《构建健壮的混合云网络——BJS DX+VPN篇》

拓扑图:

Strongswan-1和Strongswan-2分别作为Region A两个AZ内的VPN设备,与客户本地站点的internet出口设为分别建立两条VPN隧道,Private-1和Private-2分别模拟Region A两个AZ中的两台内网设备。

本场景需要实现如下目的:

1.    Private-1,Private-2能够与本地站点内的设备通过私网互通

2.    AWS侧能够检测VPN连接的健康状态并实现自动的故障切换

3.    AWS侧能够检测VPN设备的健康状态并实现自动的故障切换

4.    本地站点侧能够检测VPN连接的健康状态并实现自动的故障切换

5.    本地站点侧能够检测VPN设备的健康状态并实现自动的故障切换

系统工作流程:

1.    Strongswan-1和Strongswan-2设置开机自动运行vpn_monitor.sh脚本,该脚本首先会将Private-1和Private-2去往本地站点的路由分别指向本AZ中的VPN设备,即:Strongswan-1和Strongswan-2

2.    接着Strongswan-1和Strongswan-2会通过互相ping来检测对端的可达性,同时通过ping本地站点VPN设备的tunnel地址来检测VPN连接的可达性。

3.    如果Strongswan-1的VPN连接发生故障,Strongswan-1会将Private-1路由的target从Strongswan-1修改为指向Strongswan-2,连接恢复后,Strongswan-1会将路由切换回自身

4.    如果Strongswan-1发生故障,Strongswan-2的ping检测失败,Strongswan-2会将Private-1路由的target从Strongswan-1修改为指向Strongswan-2

5.    Strongswan-2接着会对Strongswan-1做stop,start操作

6.    当Strongswan-1在另外一台物理机上启动后,自动运行的脚本会将Private-1路由从Strongswan-2修改为指向Strongswan-1

配置步骤:

1.    为Strongswan-1和Strongswan-2创建合适的角色并关联

由于Strongswan-1和Strongswan-2需要对VPC路由表及EC2实例做操作,所以需要创建合适的角色并与实例关联。

在IAM服务中选择策略->创建策略

选择创建您自己的策略

使用如下内容设置策略文档,并点击创建策略

在IAM服务中选择角色->创建新角色

设置角色名称

选择AWS服务角色->Amazon EC2

选择筛选条件为客户管理的策略,并勾选之前创建的Strongswan_Policy

审核配置并点击创建角色

在创建Strongswan-1和Strongswan-2的EC2时,关联Strongswan_role角色

需要注意为Strongswan-1,Strongswan-2关联EIP,避免IP发生变化导致VPN无法建立,并且需要在控制台关闭源/目地址检查

2.    VPC网络规划

本场景的VPC的CIDR为172.16.0.0/16,一共需要至少四个子网分别对应4台EC2,Strongswan-1和Strongswan-2可以共用一张路由表,默认路由到IGW,Private-1和Private-2分别需要一张独立的路由表,关于如何配置VPC,子网,IGW,路由表等内容,可以参考如下文档:

Amazon Virtual Private Cloud用户指南

http://docs.amazonaws.cn/AmazonVPC/latest/UserGuide/VPC_Introduction.html

Strongswan-1和Strongswan-2所在子网的路由表设置如下

Private-1所在子网的路由表设置如下,eni-23fbd87a为Strongswan-1的网卡ID,10.10.0.0/16为本地站点网段

Private-2所在子网的路由表设置如下,eni-2d75e606为Strongswan-2的网卡ID,10.10.0.0/16为本地站点网段

3.    配置Strongswan

3.1  在Strongswan-1及Strongswan-2的/etc/sysctl.conf文件中添加如下内容,开启转发,关闭重定向及反向路径过滤:

net.ipv4.ip_forward = 1

net.ipv4.conf.all.accept_redirects = 0

net.ipv4.conf.all.send_redirects = 0

net.ipv4.conf.default.rp_filter = 2

运行sysctl –p使修改生效

3.2  安装Strongswan

修改/etc/yum.repos.d/epel.repo,将enabled=0修改成enabled=1

wget ftp://fr2.rpmfind.net/linux/centos/6.8/os/x86_64/Packages/trousers-0.3.13-2.el6.x86_64.rpm

rpm -ivh trousers-0.3.13-2.el6.x86_64.rpm

yum install strongswan -y

chkconfig strongswan on

3.3  配置Strongswan-1的strongswan

修改Strongswan-1的/etc/strongswan/ipsec.conf,添加如下内容,其中172.16.1.157为Strongswan-1的私网地址,54.223.192.238为Strongswan-1的公网地址,52.50.130.77为本地站点路由器的公网地址:

conn vpn1

            type=tunnel

            mobike=no

            authby=secret

            keyexchange=ikev1

            ike=aes128-sha1-modp1024

            esp=aes128-sha1-modp1024

            left=172.16.1.157

            leftid=54.223.192.238

            leftsubnet=0.0.0.0/0

            right=52.50.130.77

            rightsubnet=0.0.0.0/0

            auto=start

            dpddelay=3

            dpdtimeout=15

            dpdaction=restart

            mark=100

3.4  创建Strongswan-1的/etc/strongswan/ipsec.secrets文件,添加如下内容:

54.223.192.238 52.50.130.77 : PSK "cisco"

3.5  配置Strongswan-2的strongswan

修改Strongswan-2的/etc/strongswan/ipsec.conf,添加如下内容,其中172.16.2.126为Strongswan-2的私网地址,54.222.191.34为Strongswan-2的公网地址,52.51.34.140为本地站点路由器的公网地址:

conn vpn1

            type=tunnel

            mobike=no

            authby=secret

            keyexchange=ikev1

            ike=aes128-sha1-modp1024

            esp=aes128-sha1-modp1024

            left=172.16.2.126

            leftid=54.222.191.34

            leftsubnet=0.0.0.0/0

            right=52.51.34.140

            rightsubnet=0.0.0.0/0

            auto=start

            dpddelay=3

            dpdtimeout=15

            dpdaction=restart

            mark=100

3.6  创建Strongswan-2的/etc/strongswan/ipsec.secrets文件,添加如下内容:

54.222.191.34              52.51.34.140 : PSK "cisco"

3.7  下载脚本到Strongswan-1和Strongswan-2,修改如下内容

脚本下载地址:https://s3.cn-north-1.amazonaws.com.cn/junyublog/vpn_monitor.sh

VPN_ID="i-0430fe110cdec5835"

VPN_RT_ID="rtb-4b8f522f"

Remote_IP="169.254.40.105"

My_RT_ID="rtb-468f5222"

VPN_ID为peer的instance id,对于运行在Strongswan-1上的脚本,该值为Strongswan-2的instance id,对于运行在Strongswan-2上的脚本,该值为Strongswan-1的instance id

对于运行在Strongswan-1上的脚本,VPN_RT_ID为Private-2所在子网关联的路由表,对于运行在Strongswan-2上的脚本,VPN_RT_ID为Private-1所在子网关联的路由表

Remote_IP为对端本地站点路由器的tunnel地址

My_RT_ID为本机负责转发的EC2的路由表ID,对于运行在Strongswan-1上的脚本,该值为Private-1的路由表ID,对于运行在Strongswan-2上的脚本,该值为Private-2的路由表ID

4.    创建tunnel接口及路由表

在/etc/rc.d/rc.local文件中添加如下内容:

Strongswan-1:

litterbin=$(ip link add tunnel1 type vti local 172.16.1.157 remote 52.50.130.77 key 100)

litterbin=$(ip add add 169.254.100.2/30 remote 169.254.100.1/30 dev tunnel1)

litterbin=$(ip link set tunnel1 up mtu 1436)

litterbin=$(ip rule add priority 10 from all lookup 10)

ip route add 169.254.100.0/30 via 169.254.100.1 table 10

ip route add 10.10.0.0/16 via 169.254.100.1 table 10

/bin/bash ./home/ec2-user/vpn_monitor.sh > /tmp/log

其中169.254.100.2为Strongswan-1的tunnel口地址,169.254.100.1为对端本地站点路由器的tunnel口地址,172.16.1.157为Strongswan-1的私网地址,52.50.130.77为对端本地站点路由器的出口地址

 

Strongswan-2

litterbin=$(ip link add tunnel1 type vti local 172.16.2.126 remote 52.51.34.140 key 100)

litterbin=$(ip add add 169.254.200.2/30 remote 169.254.200.1/30 dev tunnel1)

litterbin=$(ip link set tunnel1 up mtu 1436)

litterbin=$(ip rule add priority 10 from all lookup 10)

ip route add 169.254.200.0/30 via 169.254.200.1 table 10

ip route add 10.10.0.0/16 via 169.254.200.1 table 10

/bin/bash ./home/ec2-user/vpn_monitor.sh > /tmp/log

其中169.254.200.2为Strongswan-2的tunnel口地址,169.254.200.1为对端本地站点路由器的tunnel口地址,172.16.2.126为Strongswan-1的私网地址,52.51.34.140为对端本地站点路由器的出口地址

5.    本地站点路由器参考配置

此处以Cisco路由器为例,思路如下:

a.    创建tunnel-based ipsec vpn

b.    通往VPC网段的路由指向tunnel接口,并且使用ip sla track

c.    设置ip sla检测Strongswan的tunnel ip可达性

d.    本地内网配置IGP,将静态路由重分发到IGP中

 

Cisco Router 1:

track 100 ip sla 10 reachability

!

crypto keyring KEYRING 

  local-address 10.10.1.100

  pre-shared-key address 54.223.192.238 key cisco

!

crypto isakmp policy 100

 encr aes

 authentication pre-share

 group 2

 lifetime 28800

crypto isakmp keepalive 10 10

crypto isakmp profile isakmp-profile

   keyring KEYRING

   match identity address 54.223.192.238 255.255.255.255

   local-address 10.10.1.100

!

crypto ipsec security-association replay window-size 128

!

crypto ipsec transform-set TRAN esp-aes esp-sha-hmac

 mode tunnel

crypto ipsec df-bit clear

!

crypto ipsec profile ipsec-profile

 set transform-set TRAN

 set pfs group2

!

interface Tunnel100

 ip address 169.254.100.1 255.255.255.0

 ip tcp adjust-mss 1387

 tunnel source 10.10.1.100

 tunnel mode ipsec ipv4

 tunnel destination 54.223.192.238

 tunnel protection ipsec profile ipsec-profile

 ip virtual-reassembly

!

router ospf 100

 router-id 1.1.1.1

 redistribute static subnets route-map static2ospf

!

ip route 172.16.0.0 255.255.0.0 Tunnel100 169.254.100.2 tag 100 track 100

!

ip sla 10

 icmp-echo 169.254.100.2 source-ip 169.254.100.1

 frequency 5

ip sla schedule 10 start-time now

!

route-map static2ospf permit 10

 match tag 100

 

Cisco Router 2:

track 100 ip sla 10 reachability

!

crypto keyring KEYRING 

  local-address 10.10.2.100

  pre-shared-key address 54.222.191.34 key cisco

!

crypto isakmp policy 100

 encr aes

 authentication pre-share

 group 2

 lifetime 28800

crypto isakmp keepalive 10 10

crypto isakmp profile isakmp-profile

   keyring KEYRING

   match identity address 54.222.191.34 255.255.255.255

   local-address 10.10.2.100

!

crypto ipsec security-association replay window-size 128

!

crypto ipsec transform-set TRAN esp-aes esp-sha-hmac

 mode tunnel

crypto ipsec df-bit clear

!

crypto ipsec profile ipsec-profile

 set transform-set TRAN

 set pfs group2

!

interface Tunnel100

 ip address 169.254.200.1 255.255.255.0

 ip tcp adjust-mss 1387

 tunnel source 10.10.2.100

 tunnel mode ipsec ipv4

 tunnel destination 54.222.191.34

 tunnel protection ipsec profile ipsec-profile

 ip virtual-reassembly

!

router ospf 100

 router-id 2.2.2.2

 redistribute static subnets route-map static2ospf

!

ip route 172.16.0.0 255.255.0.0 Tunnel100 169.254.200.2 tag 100 track 100

!

ip sla 10

 icmp-echo 169.254.200.2 source-ip 169.254.200.1

 frequency 5

ip sla schedule 10 start-time now

!

route-map static2ospf permit 10

 match tag 100

 

作者介绍:

余骏

亚马逊AWS解决方案架构师,负责基于AWS的云计算方案架构的咨询和设计,同时致力于AWS云服务在国内的应用和推广。在加入AWS之前,在思科中国担任系统工程师,负责方案咨询和架构设计,在企业私有云和基础网络方面有丰富经验。

利用Amazon CloudWatch 搭建无人值守的监控预警平台

资源与应用服务层监控

Amazon CloudWatch 监控和预警平台可以帮助客户统一管理和运维AWS云端和本地资源、服务和业务系统;使用 Amazon CloudWatch 可以收集和跟踪指标,收集和监控日志文件,设置警报。您可通过使用 Amazon CloudWatch 全面地了解资源使用率、应用程序性能和运行状况。使用这些分析结果,您可以及时做出反应,保证应用程序顺畅运行。

Amazon CloudWatch 的基本概念

请参考AWS 官方文档了解 Amazon CloudWatch的核心概念和术语,比如指标、命名空间、维度、时间戳、单位、统计数据、时间段、聚合、警报等。

基于CloudWatch 的监控预警平台架构

CloudWatch 提供了一套标准的API接口,用户可以利用该平台发布自定义应用、业务或者更加详细的系统指标。用户发布到Amazon CloudWatch 的指标是按时间排序的数据点集合,数据点本身可以来自于任何应用程序或者业务活动;指标通过名称、命名空间和维度进行唯一定义;维度可以帮助你设计数据点的分组特征或者类别,发布指标数据点时必须必须指定维度,比如虚机的CPU使用率,用户可以查看单独某个虚机的监控指标也可以按AutoScaling组来查看,这里的单个虚机或者AutoScaling组就是同一数据点的不同的维度。用户可以使用秒级甚至千分之一秒的频率发布自定义指标,但是Amazon CloudWatch 还是会将数据聚合到1分钟为最小粒度。

基于指标数据,用户可以翻译业务的波动异常到相应的指标,从而创建警报来和相应的操作来自动化应对各种异常情况,操作包括弹性伸缩(Auto Scaling)机制来应对访问流量变化或者Amazon SNS 主题订阅绑定的邮件通知、HTTP请求的调用和消息队列异步处理。

指标数据用户可以直接通过AWS 控制台进行的图形化按时间筛选、查看和分享;同时,用户也可以通过API接口获取指标数据进行第三方的处理和展示。CloudWatch默认保存两周的指标数据(海外区域部分可以支持免费存储最多15个月的统计数据,详情请查看AWS CloudWatch文档)。

本文的架构中,自定义指标收集不需要自己编程而是利用collectd守护进程进行监控和获取,同时利用CloudWatch Plugin for collectd直接将自定义指标发布和存储到CloudWatch中,用户随后可以基于自定义指标的进行自动化警报处理从而实现无人值守的统一监控平台。

什么是CloudWatch Plugin for collectd

CloudWatch一直支持用户发布自定义指标来存储、监控自己关心的业务、应用和系统健康状况;AWS最新发布了CloudWatch Plugin for collectd开源项目,该插件整合了collectd强大的收集各种类型统计数据的能力,帮助客户简化了开发收集自定义指标的相关工作,开箱即用地支持发布Apache、Nginx Web服务器应用指标,内存监控指标等监控数据到CloudWatch进行统一存储、展示和预警。

什么是collectd

collectd是一个基于C语言的守护进程,主要任务就是用来收集统计信息,它提供各种了存储方式来存储不同值的机制。它支持超过100种各类插件,下面大概列出一些比较常见的插件类型,具体的请参考collectd官方网站

  • Web应用:Apache、nginx
  • 数据库:MySQL、Oracle、PostgreSQL、memcached
  • 网络:OpenVPN、Ping、TCPConns、
  • 系统:Memory、Disk、FileCount、vmem、uptime、df

安装配置CloudWatch Plugin for collectd

下面的步骤以BJS区域的EC2为例来说明如何安装配置和使用CloudWatch Plugin for collectd:

用户授权

该插件支持IAM Role或者 IAM User两种方式的授权,按照AWS最佳实践,我们推荐使用IAM Role的方式进行授权。所以,开始之前,我们先创建一个IAM Role并赋予相应的权限。

创一个角色名字为role4collectd

然后在该角色的权限页面,创建角色策略,赋予该角色拥有发布指标的权限。

启动实例并绑定角色

如果你想在已经启动的EC2或者你自己的机器上启用该插件,可以忽略该步骤并创建一个具备CloudWatch发布指标权限的IAM User。

本文启动一个新的EC2实例并绑定上一步创建好的角色:

安装插件

登陆到EC2并更新系统。

[ec2-user@ip-10-0-0-6 ~]$ sudo yum -y install collectd
已加载插件:priorities, update-motd, upgrade-helper
正在解决依赖关系
--> 正在检查事务
---> 软件包 collectd.x86_64.0.5.4.1-1.11.amzn1 将被 安装
--> 解决依赖关系完成

下载CloudWatch Plugin for collectd 安装文件并执行,安装脚本会自动读取EC2的Meta Data,因此选项都可以默认选择,比如区域,EC2绑定的IAM Role等等。

[ec2-user@ip-10-0-0-6 ~]$ sudo -s
[root@ip-10-0-0-6 ec2-user]# wget https://raw.githubusercontent.com/awslabs/collectd-cloudwatch/master/src/setup.py
[root@ip-10-0-0-6 ec2-user]# chmod +x setup.py
[root@ip-10-0-0-6 ec2-user]# ./setup.py
[root@ip-10-0-0-6 ec2-user]# ./setup.py
Installing dependencies ... OK
Installing python dependencies ... OK
Downloading plugin ... OK
Extracting plugin ... OK
Moving to collectd plugins directory ... OK
Copying CloudWatch plugin include file ... OK

Choose AWS region for published metrics:
1. Automatic [cn-north-1]
2. Custom
Enter choice [1]:

Choose hostname for published metrics:
1. EC2 instance id [i-cc97bc74]
2. Custom
Enter choice [1]:

Choose authentication method:
1. IAM Role [role4collectd]
2. IAM User
Enter choice [1]:
Choose how to install CloudWatch plugin in collectd:
1. Do not modify existing collectd configuration
2. Add plugin to the existing configuration
Enter choice [2]:
Plugin configuration written successfully.
Stopping collectd process ... NOT OK
Starting collectd process ... OK

collectd和CloudWatch plugin for collectd到此就已经安装完成了。

定义发布到CloudWatch的指标

要在CloudWatch中存储和查看collectd收集的指标数据,需要完成两件事情(1)安装相应的collectd插件(2)在CloudWatch plugin配置文件中添加指标白名单。

查看CloudWatch plugin的指标白名单,版本collectd 5.5以下默认CloudWatch白名单指标是空的,也就是默认不会发布任何collectd的指标到CloudWatch:

[ec2-user@ip-10-0-0-6 ~]$ sudo cat /opt/collectd-plugins/cloudwatch/config/whitelist.conf

对于可用的collectd的指标数据类型,我们可以查看以下文件来确认,该文件包含没有发布到CloudWatch的指标类型,该文件是系统自动维护,不要人为进行修改:

blocked_metrics  plugin.conf      whitelist.conf
[ec2-user@ip-10-0-0-6 ~]$ sudo cat /opt/collectd-plugins/cloudwatch/config/blocked_metrics
# This file is automatically generated - do not modify this file.
# Use this file to find metrics to be added to the whitelist file instead.
cpu-0-cpu-user
cpu-0-cpu-nice
cpu-0-cpu-system
cpu-0-cpu-idle
cpu-0-cpu-wait
cpu-0-cpu-interrupt
cpu-0-cpu-softirq
cpu-0-cpu-steal
interface-lo-if_octets-
interface-lo-if_packets-
interface-lo-if_errors-
interface-eth0-if_octets-
interface-eth0-if_packets-
interface-eth0-if_errors-
load--load-
memory--memory-used
memory--memory-buffered
memory--memory-cached
memory--memory-free

假定我们对于内存相关指标比较感兴趣,可以将memory开头的指标类型添加到CloudWatch白名单:

[ec2-user@ip-10-0-0-6 ~]$ sudo vim /opt/collectd-plugins/cloudwatch/config/whitelist.conf
输入如下信息:

memory--memory-.*

重启collectd服务:

注:在BJS区域的EC2上默认安装和配置后,我们从日志会发现报错,主要原因是默认安装后的脚本不支持BJS区域,详细的错误识别请参考以下步骤。

打开debug模式:

重启collectd服务:

查看日志:

从下面的错误信息可以看到,脚本默认发布指标到如下的endpoint:https://monitoring.cn-north-1.amazonaws.com/, 但BJS区域的CloudWatch endpoint和海外区域的命名规则有差异,详细的AWS BJS区域服务的终端节点可以参考:中国(北京)区域

为了解决BJS区域终端节点的支持问题,我们需要更新插件的Python脚本文件使其支持BJS区域:

1.confighelper.py文件:该文件默认安装后的目录是 /opt/collectd-plugins/cloudwatch/modules/configuration

更新如下函数,

参考修改后的代码如下:

2. requestbuilder.py 文件:该文件默认安装后的目录为/opt/collectd-plugins/cloudwatch/modules/client

该类的主要功能是构建签名版本4的PutMetricData API请求,因此会使用到endpoint信息,具体请参考在线文档

更新如下函数,

参考修改后的代码如下:

重启collectd服务:

查看以 [AmazonCloudWatchPlugin] 开头的日志内容,从日志可以看出,我们添加到白名单的memory相关的日志包含四个不同的指标,每分钟发布一次:

登录AWS 控制台,打开到CloudWatch页面,左侧导航最底端有个自定义指标的选择框,下拉就可以选择collectd来查看刚刚发布的指标内容:

安装启用收集Apache监控数据插件

如果未安装配置好Apache Web服务器,可以参考 教程:在 Amazon Linux 上安装 LAMP Web 服务器 来搭建好该Web服务器环境。

通过以下命令可以查询 Amazon Linux AMI带有的collectd的插件列表:

apache的状态信息来自于自身的mod_status模块,collectd解析出例如传输的bytes大小,接受到的请求数量等指标;详情请参考该插件介绍页面;安装collectd apache 监控插件:

修改collectd的配置,默认安装的文件位置 /etc/collectd.conf:

LoadPlugin apache
<Plugin apache>
  <Instance “local”>
    URL “http://localhost/server-status?auto”
  </Instance>
</Plugin>

以下是针对httpd-2.2版本的参考配置,默认的配置文件位于/etc/httpd/conf/httpd.conf:

将apache相关状态指标加入到CloudWatch collectd插件配置的白名单列表,更新文件 /opt/collectd-plugins/cloudwatch/config/whitelist.conf :

重新启动相关服务:

这样我们就完成了安装配置新的collectd的apache插件,同时将apache的相关监控指标添加到CloudWatch的白名单,这样我们就可以无缝整合collectd的收集数据能力和CloudWatch统一存储、展示和预警能力,下图就是apache web应用相关的指标在CloudWatch中展示的结果:

基于CloudWatch指标创建警报

既然我们通过插件收集了很多系统和应用的指标,那如果发生一些异常或者超过预先定义的阈值的时候,我们如何去应对和处理呢?理想情况我们能够尽可能自动化来应对这些警报,即搭建“无人”值守的监控预警平台。下图是基于某一个采集指标定义警报及处理警报的操作的截图;当一个警报发生时,你可以定义一个或多个操作来应对和处理;你可以采取的操作类型有,发送邮件通知,发布消息到SNS服务,添加Auto Scaling操作,以及EC2实例操作;这里的EC2实例操作包含停止、终止、重启或恢复,任何EC2实例指标(在 AWS/EC2 命名空间中)或者包含“InstanceId=”维度的任何自定义指标都可以在警报中触发EC2实例操作。

一些限制

很多用户在开始接触CloudWatch的时候就非常关心性能问题,目前发布指标API PutMetricData 每秒可处理 150 个事务 (TPS),这是您每秒可以发出而不会受到限制的操作请求的最大数量,但可以在线请求提高限制;PutMetricData 同时支持GET和POST操作,请求最大大小分别为8KB和40KB。每个指标最多可以有10个维度;

总结

本文和大家一起学习了如何基于CloudWatch及collectd相关插件构建无人值守的监控预警平台;CloudWatch默认提供了AWS资源的基本监控数据,同时提供了CLI和REST API的方式供用户自行扩展自定义业务和系统指标数据; CloudWatch plugin for collectd 是AWS最新发布的一个开源插件,大家可以进一步通过学习该项目的源代码掌握如何基于Python扩展和集成AWS的服务。

作者介绍:

薛军

AWS 解决方案架构师,获得AWS解决方案架构师专业级认证和DevOps工程师专业级认证。负责基于AWS的云计算方案架构的咨询和设计,同时致力于AWS云服务在国内的应用和推广,在互联网金融、保险、企业混合IT、微服务等方面有着丰富的实践经验。在加入AWS之前已有接近10年的软件开发管理、企业IT咨询和实施工作经验。

一键搞定云端网络环境,让您轻松迁移至AWS!

一键搞定云端网络环境,让您轻松迁移至AWS!

知识补充:什么是AWS CloudFormation?

AWS CloudFormation 模板是一个文本文件,其格式符合 JSON 格式标准。您可使用任何扩展名(如.json、.template 或 .txt)保存这些文件。AWS CloudFormation可帮助您对AWS资源进行建模和设置,包括EC2实例、RDS实例、Auto Scaling Group、Elastic Load Balancing以及整个AWS VPC的网络环境。点击部署模板,成功创建堆栈之后,AWS 资源将正常运行。点击删除模板,所有堆栈中涉及到的资源将都删除。详细参考

http://docs.aws.amazon.com/zh_cn/AWSCloudFormation/latest/UserGuide/Welcome.html

注:此文章所用的AWS CloudFormation模板适合:

(1)由于项目紧急,您在一两天内就想上线,将资源部署在AWS平台上,之后再花时间学习AWS服务与功能。

(2)您想基于AWS实现自动化基础设施部署,比如快速实现开发 / 测试 / 生产环境,这个模板是您学习AWS一个好的开始。

模板下载:

AWS中国区模板:

https://s3.cn-north-1.amazonaws.com.cn/danrong-share/external/aws-template-bjs-addELB-V3.txt

AWS海外区模板:

https://s3.cn-north-1.amazonaws.com.cn/danrong-share/external/aws-template-global-addELB-V3.txt

注:为节约成本,此模板所启用的EC2配置很低,为t2.small。

模板主要解决的问题:

(1)启动VPC,网段为10.40.0.0/16(当然,模板可以自定义IP地址范围)。自动启动6个子网

Public Subnet 1(子网范围10.40.1.0/24)

Public Subnet 2(子网范围10.40.2.0/24)

Private Subnet 1(子网范围10.40.3.0/24)

Private Subnet 2(子网范围10.40.4.0/24)

Private DB Subnet 1(子网范围10.40.5.0/24)

Private DB Subnet 2(子网范围10.40.6.0/24)

打开DNS解析和主机名功能。

(2)启动2个路由表,添加规则Public Route table指向IGW,Private Route table指向NAT Instance。

(3)启动互联网网关IGW,并附加到VPC上。

(4)启动一台Nginx Based AMI作为Web Server,并申请弹性IP、Role(这里的权限是admin)绑定到这台EC2。

(注意:如果客户需要Apache HTTP,只需要把模板中的注释去掉换一下即可)

(5)启动一台NAT Instance作为网络地址转换。如果NAT需要高可用,使用模板(支持中国区)

https://s3.cn-north-1.amazonaws.com.cn/danrong-share/external/nat_monitor_cn.template

(6)启动一台Bastion Host,作为跳板控制,配置所需安全组。

(7)启动Web Server安全组,配置HTTP/22、SSH/22、ICMP/All

(8)启动NAT instance安全组,入站配置Private Subnet子网(只有Private Subnet内的EC2可以访问)。

(9)启动ELB作为负载均衡,启用跨AZ,设置对应所需安全组,添加HTTP/80监听器,健康检查等功能。

此模板启动的资源以及部署图

模板如何使用?

1.       打开AWS EC2服务,创建一个密钥对,比如awskey(用于SSH远程登录虚拟机)

2.       点击AWS CloudFormation服务

3.       点击“创建堆栈”,指定 Amazon S3 模板 URL,复制以下地址(如果海外区也一样)

https://s3.cn-north-1.amazonaws.com.cn/danrong-share/external/aws-template-bjs-addELB-V3.txt

4.       点击“下一步”,看到如下界面,再次点击“下一步”。

5.       勾选“我确认,AWS CloudFormation可能创建IAM资源”。

6.       最后一步点击“创建”,自动生成如下所有资源。

当模板点击创建完成之后,您只需要上传服务器代码以及配置所需要的数据库引擎,比如MySQL。

如果用到其它AWS服务,比如Amazon S3存储、Amazon ElastiCache缓存服务,也基于此模板之上继续创建资源,本文将不再阐述。

注意:当应用进入到生产系统时,可以修改安全组和数据库路由指向,只让前端应用可以访问数据库,以“最小权限”为原则。

作者介绍:

毛郸榕

亚马逊AWS解决方案架构师,负责基于AWS的云计算方案架构的咨询和设计,同时致力于AWS云服务在国内的应用和推广,毕业于北京航空航天大学云计算专业,硕士,毕业后直接加入亚马逊AWS中国。在大规模后台架构、自动化运维等方面有着丰富的实践经验。目前在集中精力学习新一代无服务器架构设计。

程序员的深度学习入门指南

本文根据费良宏在2016QCon全球软件开发大会(上海)上的演讲整理而成。

今天我想跟大家分享的话题与深度学习有关。事实上,深度学习本身是一个非常庞大的知识体系。今天的内容,不会涉及深度学习的理论知识,更多想从程序员的视角出发,让大家观察一下深度学习对我们程序员意味着什么,以及我们如何能够利用这样一个高速发展的学科,来帮助程序员提升软件开发的能力。

前言

1973年,美国上映了一部热门的科幻电影叫做《Westworld》,三年之后又有一个续集叫做《Futureworld》。这部电影在80年代初被引进到中国叫《未来世界》。那部电影对我来讲简直可以说得上是震撼。影片中出现了很多机器人,表情丰富的面部下面都是集成电路板。这让那时候的我觉得未来世界都是那么遥远、那么样的神秘。时间转到了2016年,很多朋友可能都在追看HBO斥巨资拍摄的同一个题材的系列剧《Westworld》。如果前两部电影还是局限在机器人、人工智能这样的话题,2016年的新剧则在剧情、以及对于人工智能的思考方面有了很大的突破。不再渲染机器人是否会威胁到人类,而是在探讨 “Dreams are mainly memories“这一类更具哲理的问题。记忆究竟如何影响了智能这个话题非常值得我们去思考,也给我们一个很好的启示 – 今天,人工智能领域究竟有了怎样的发展和进步。

今天我们探讨的话题不仅仅是简单的人工智能。如果大家对深度学习感兴趣,我相信各位一定会在搜索引擎上搜索过类似相关的关键字。我在Google上以deep learning作为关键字得到了2,630万个搜索的结果。这个数字比一周之前足足多出了300多万的结果。这个数字足以看得出来深度学习相关的内容发展的速度,人们对深度学习的关注也越来越高。

从另外的一个角度,我想让大家看看深度学习在市场上究竟有多么热门。从2011年到现在一共有140多家专注人工智能、深度学习相关的创业公司被收购。仅仅在2016年这种并购就发生了40多起。其中最疯狂的是就是Google,已经收购了 11 家人工智能创业公司,其中最有名的就是击败了李世石九段的 DeepMind。排名之后的就要数 Apple、Intel以及Twitter。以Intel 公司为例,仅在今年就已经收购了 3 家创业公司,Itseez、Nervana 和 Movidius。这一系列大手笔的并购为了布局人工智能以及深度学习的领域。

当我们去搜索深度学习话题的时候,经常会看到这样的一些晦涩难懂的术语:Gradient descent(梯度下降算法)、Backpropagation(反向传播算法)、Convolutional Neural Network(卷积神经网络)、受限玻耳兹曼机(Restricted Boltzmann Machine)等等。如你打开任何一篇技术文章,你看到的通篇都是各种数学公式。大家看到下面左边的图,其实并不是一篇高水准的学术论文,而仅仅是维基百科关于玻耳兹曼机的介绍。维基百科是科普层面的内容,内容复杂程度就超过了大多数数学知识的能力。

右边的那张图则是深度学习很流行的深度学习框架Theano 的一个简单的例子。对于大多数程序员而言学习这一类框架和程序代码的时候更让人抓狂,大段代码我们完全不明就里。我们看到的很多概念,对很多程序员来说觉得非常陌生,所以这确实是对程序员的一个很大的挑战。

在这样的背景之下,我今天的的话题可以归纳成三点:第一,我们为什么要学习深度学习;第二,深度学习最核心的关键概念就是神经网络,那么究竟什么是神经网络;第三,作为程序员,当我们想要成为深度学习开发者的时候,我们需要具备怎样的工具箱,以及从哪里着手进行开发。

为什么要学习深度学习

首先我们谈谈为什么要学习深度学习。在这个市场当中,最不缺乏的就是各种概念以及各种时髦新技术的词汇。深度学习有什么不一样的地方?我非常喜欢Andrew Ng(吴恩达)曾经用过的一个比喻。他把深度学习比喻成一个火箭。这个火箭有一个最重要的部分,就是它的引擎,目前来看在这个领域里面,引擎的核心就是神经网络。大家都知道,火箭除了引擎之外还需要有燃料,那么大数据其实就构成了整个火箭另外的重要组成部分——燃料。以往我们谈到大数据的时候,更多是强调存储和管理数据的能力,但是这些方法和工具更多是对于以往历史数据的统计、汇总。而对于今后未知的东西,这些传统的方法并不能够帮助我们可以从大数据中得出预测的结论。如果考虑到神经网络和大数据结合,我们才可能看清楚大数据真正的价值和意义。Andrew Ng就曾经说过“我们相信(神经网络代表的深度学习)是让我们获得最接近于人工智能的捷径”。这就是我们要学习深度学习的一个最重要的原因。

其次,随着我们进行数据处理以及运算能力的不断提升,深度学习所代表的人工智能技术和传统意义上人工智能技术比较起来,在性能上有了突飞猛进的发展。这主要得益于在过去几十间计算机和相关产业不断发展带来的成果。在人工智能的领域,性能是我们选择深度学习另一个重要的原因。

这是一段Nvidia 在今年公布的关于深度学习在无人驾驶领域应用的视频。我们可以看到,将深度学习应用在自动驾驶方面,仅仅经历了3千英里的训练,就可以达到什么样的程度。在今年年初进行的实验上,这个系统还不具备真正智能能力,经常会出现各种各样的让人提心吊胆的状况,甚至在某些情况下还需要人工干预。但经过了3千英里的训练之后,我们看到在山路、公路、泥地等各种复杂的路况下面,无人驾驶已经有了一个非常惊人的表现。请大家注意,这个深度学习的模型只经过了短短几个月、3千英里的训练。如果我们不断完善这种模型的话,这种处理能力将会变得何等的强大。这个场景里面最重要的技术无疑就是深度学习。我们可以得出一个结论:深度学习可以为我们提供强大的能力,如果程序员拥有了这个技术的话,无异于会让每个程序员如虎添翼。

神经网络快速入门

如果我们对于学习深度学习没有任何疑虑的话,接下来就一定会关心我需要掌握什么样的知识才能让我进入到这个领域。这里面最重要的关键技术就是“神经网络”。说起“神经网络”,容易混淆是这样两个完全不同的概念。一个是生物学神经网络,第二个才是我们今天要谈起的人工智能神经网络。可能在座的各位有朋友在从事人工智能方面的工作。当你向他请教神经网络的时候,他会抛出许多陌生的概念和术语让你听起来云里雾里,而你只能望而却步了。对于人工智能神经网络这个概念,大多数的程序员都会觉得距离自己有很大的距离。因为很难有人愿意花时间跟你分享神经网络的本质究竟是什么。而你从书本上读的到的理论和概念,也很让你找到一个清晰、简单的结论。

今天就我们来看一看,从程序员角度出发神经网络究竟是什么。我第一次知道神经网络这个概念是通过一部电影—1991年上映的《终结者2》。男主角施瓦辛格有一句台词:“My CPU is a neural-net processor; a learning computer.“(我的处理器是一个神经处理单元,它是一台可以学习的计算机)。从历史来看人类对自身智力的探索,远远早于对于神经网络的研究。1852年,意大利学者因为一个偶然的失误,将人类的头颅掉到硝酸盐溶液中,从而获得第一次通过肉眼关注神经网络的机会。这个意外加速了人对人类智力奥秘的探索,开启了人工智能、神经元这样概念的发展。

生物神经网络这个概念的发展,和今天我们谈的神经网络有什么关系吗?我们今天谈到的神经网络,除了在部分名词上借鉴了生物学神经网络之外,跟生物学神经网络已经没有任何关系,它已经完全是数学和计算机领域的概念,这也是人工智能发展成熟的标志。这点大家要区分开,不要把生物神经网络跟我们今天谈到的人工智能有任何的混淆。

神经网络的发展并不是一帆风顺的,这中间大概经历了三起三折的过程。

大约在1904年,人类已经对人脑的神经元有了最初步的认识和了解。1943年的时候,心理学家麦卡洛克 (McCulloch) 和数学家 Pitts 参考了生物神经元的结构,发表了抽象的神经元模型M。这个概念的提出,激发了大家对人智力探索的热情。到了1949年,有一个心理学家赫布(Hebb)提出了著名的Hebb模型,认为人脑神经细胞的突触上的强度上是可以变化的。于是计算科学家们开始考虑用调整权值的方法来让机器学习,这就奠定了今天神经网络基础算法的理论依据。到了1958年,计算科学家罗森布拉特(Rosenblatt)提出了由两层神经元组成的神经网络,并给它起了一个很特别的名字—“感知器”(Perceptron)。人们认为这就是人类智能的奥秘,许多学者和科研机构纷纷投入到对神经网络的研究中。美国军方也大力资助了神经网络的研究,并认为神经网络是比“曼哈顿工程”更重要的项目。这段时间直到1969年才结束,这个时期可以看作神经网络的一次高潮。事实上感知器只能做简单的线性分类任务。但是当时的人们热情太过于高涨,并没有清醒的认识到这点不足。于是,当人工智能领域的巨擘明斯基(Minsky)指出个问题的时候,事态就发生了反转。明斯基指出,如果将计算层增加到两层,则计算量过大并且缺少有效的学习算法。所以,他认为研究更深层的网络是没有价值的。明斯基在1969年出版了一本叫《Perceptron》的书,里面通过数学证明了感知器的弱点,尤其是感知器对XOR(异或)这样的简单分类任务都无法解决。由于明斯基在人工智能领域的巨大影响力以及书中呈现的明显的悲观态度,这很大多数多学者纷纷放弃了对于神经网络的研究。于是神经网络的研究顿时陷入了冰河期。这个时期又被称为“AI Winter”。将近十年以后,神经网络才会迎来复苏。

时间到了1986年,Rumelhar和Hinton提出了划时代的反向传播算法(Backpropagation,BP)。这个算法有效的解决了两层神经网络所需要的复杂计算量问题,从而带动了使用两层神经网络研究的热潮。我们看到的大部分神经网络的教材,都是在着重介绍两层(带一个隐藏层)神经网络的内容。这时候的Hinton 刚刚初露峥嵘,30年以后正是他重新定义了神经网络,带来了神经网络复苏的又一个春天。尽管早期对于神经网络的研究受到了生物学的很大的启发,但从BP算法开始研究者们更多是从数学上寻求问题的最优解,不再盲目模拟人脑网络。这是神经网络研究走向成熟的里程碑的标志。

90年代中期,由Vapnik等人提出了支持向量机算法(Support Vector Machines,支持向量机)。很快这个算法就在很多方面体现出了对比神经网络的巨大优势,例如:无需调参、高效率、全局最优解等。基于这些理由,SVM算法迅速打败了神经网络算法成为那个时期的主流。而神经网络的研究则再次陷入了冰河期。

在被人摒弃的十个年头里面,有几个学者仍然在坚持研究。这其中的很重要的一个人就是加拿大多伦多大学的Geoffery Hinton教授。2006年,他的在著名的《Science》杂志上发表了论文,首次提出了“深度信念网络”的概念。与传统的训练方式不同,“深度信念网络”有一个“预训练”(pre-training)的过程,这可以方便的让神经网络中的权值找到一个接近最优解的值,之后再使用“微调”(fine-tuning)技术来对整个网络进行优化训练。这两个技术的运用大幅度减少了训练多层神经网络的时间。在他的论文里面,他给多层神经网络相关的学习方法赋予了一个新名词— “深度学习”。

很快,深度学习在语音识别领域崭露头角。接着在2012年,深度学习技术又在图像识别领域大展拳脚。Hinton与他的学生在ImageNet竞赛中,用多层的卷积神经网络成功地对包含一千个类别的一百万张图片进行了训练,取得了分类错误率15%的好成绩,这个成绩比第二名高了将近11个百分点。这个结果充分证明了多层神经网络识别效果的优越性。从那时起,深度学习就开启了新的一段黄金时期。我们看到今天深度学习和神经网络的火热发展,就是从那个时候开始引爆的。

可以说在过去十几年时间里,图中这四位学者引领了深度学习发展最。第一位就是Yann LeCun,他曾在多伦多大学随 Hinton攻读博士后,现在是纽约大学的教授,同时还是Facebook人工智能最重要的推动者和科学家。第二位就是是之前我们多次提到的Geoffrey Hinton,现在是Google Brain。第三位是Bengio,他是蒙特利尔大学的教授,他仍然坚持在学术领域里面不断探索。Benjio主要贡献在于他对RNN(递归神经网络)的一系列推动。第四位是Andrew Ng(吴恩达),大家在很多媒体上见到过他。上个月他还来到北京参加过一次技术大会。因为他的华人身份更容易被大家接受。在纯理论研究上面Andrew Ng 的光芒不如上述三位大牛,甚至可以说有不小的差距,但是在工程方面的应用他仍然是人工智能领域的权威。

神经网络究竟可以用来干什么?神经网络如果放到简单概念上,可以理解成帮助我们实现一个分类器。对于绝大多数人工智能需求其实都可以简化成分类需求。更准确的描述就是绝大多数与智能有关的问题,都可以归结为一个在多维空间进行模式分类的问题

例如,识别一封邮件,可以告诉我们这是垃圾邮件或者是正常的邮件;或者进行疾病诊断,将检查和报告输入进去实现疾病的判断。所以说,分类器就是神经网络最重要的应用场景。

究竟什么是分类器,以及分类器能用什么方式实现这个功能?简单来说,将一个数据输入给分类器,分类器将结果输出。曾经有人问过这样一个问题,如果对一个非专业的人士,你如何用通俗表达方法向他介绍神经网络的分类器。有人就用了水果识别做为例子。例如,我非常喜欢吃苹果,当你看到一个新苹果,你想知道它是不是好吃是不是成熟,你鉴别的依据是很多年里你品尝过的许许多多的苹果。你会通过色泽、气味或其它的识别方法加以判断。这样判断过程在深度学习和神经网络里面,我们就称之为训练过的分类器。这个分类器建立完成之后,就可以帮助我们识别食入的每个苹果是不是成熟。对于传统的人工智能方法,例如逻辑回归来说,它的决策平面是线性的。所以,这一类的方法一般只能够解决样本是线性可分的情况。如果样本呈现非线性的时候,我们可以引入多项式回归。隐层的神经元对原始特征进行了组合,并提取出来了新的特征,而这个过程是模型在训练过程中自动“学习”出来的。

利用神经网络构建分类器,这个神经网络的结构是怎样的?

其实这个结构非常简单,我们看到这个图就是简单神经网络的示意图。神经网络本质上就是一种“有向图”。图上的每个节点借用了生物学的术语就有了一个新的名词 – “神经元”。连接神经元的具有指向性的连线(有向弧)则被看作是“神经”。这这个图上神经元并不是最重要的,最重要的是连接神经元的神经。每个神经部分有指向性,每一个神经元会指向下一层的节点。节点是分层的,每个节点指向上一层节点。同层节点没有连接,并且不能越过上一层节点。每个弧上有一个值,我们通常称之为”权重“。通过权重就可以有一个公式计算出它们所指的节点的值。这个权重值是多少?我们是通过训练得出结果。它们的初始赋值往往通过随机数开始,然后训练得到的最逼近真实值的结果作为模型,并可以被反复使用。这个结果就是我们说的训练过的分类器。

节点分成输入节点和输出节点,中间称为隐层。简单来说,我们有数据输入项,中间不同的多个层次的神经网络层次,就是我们说的隐层。之所以在这样称呼,因为对我们来讲这些层次是不可见的。输出结果也被称作输出节点,输出节点是有限的数量,输入节点也是有限数量,隐层是我们可以设计的模型部分,这就是最简单的神经网络概念。

如果简单做一个简单的类比,我想用四层神经网络做一个解释。左边是输入节点,我们看到有若干输入项,这可能代表不同苹果的RGB值、味道或者其它输入进来的数据项。中间隐层就是我们设计出来的神经网络,这个网络现在有不同的层次,层次之间权重是我们不断训练获得一个结果。最后输出的结果,保存在输出节点里面,每一次像一个流向一样,神经是有一个指向的,通过不同层进行不同的计算。在隐层当中,每一个节点输入的结果计算之后作为下一层的输入项,最终结果会保存在输出节点上,输出值最接近我们的分类,得到某一个值,就被分成某一类。这就是使用神经网络的简单概述。

除了从左到右的形式表达的结构图,还有一种常见的表达形式是从下到上来表示一个神经网络。这时候,输入层在图的最下方,输出层则在图的最上方。从左到右的表达形式以Andrew Ng和LeCun的文献使用较多。而在 Caffe框架里则使用的则是从下到上的表达。

简单来说,神经网络并不神秘,它就是有像图,利用图的处理能力帮助我们对特征的提取和学习的过程。2006年Hinton的那篇著名的论文中,将深度学习总结成三个最重要的要素:计算、数据、模型。有了这三点,就可以实现一个深度学习的系统。

程序员需要的工具箱

对于程序员来说,掌握理论知识是为了更好的编程实践。那就让我们我们来看看,对于程序员来说,着手深度学习的实践需要准备什么样的工具。

硬件

从硬件来讲,我们可能需要的计算能力,首先想到的就是CPU。除了通常的CPU架构以外,还出现了附加有乘法器的CPU,用以提升计算能力。此外在不同领域会有DSP的应用场景,比如手写体识别、语音识别、等使用的专用的信号处理器。还有一类就是GPU,这是一个目前深度学习应用比较热门的领域。最后一类就是FPGA(可编程逻辑门阵列)。这四种方法各有其优缺点,每种产品会有很大的差异。相比较而言CPU虽然运算能力弱一些,但是擅长管理和调度,比如读取数据,管理文件,人机交互等,工具也丰富。DSP相比而言管理能力较弱,但是强化了特定的运算能力。这两者都是靠高主频来解决运算量的问题,适合有大量递归操作以及不便拆分的算法。GPU 的管理能力更弱一些,但是运算能力更强。但由于计算单元数量多,更适合整块数据进行流处理的算法。FPGA在管理与运算处理方面都很强,但是开发周期长,复杂算法开发难度较大。就实时性来说,FPGA是最高的。单从目前的发展来看,对于普通程序员来说,现实中普遍采用的计算资源就还是是CPU以及GPU的模式,其中GPU是最热门的领域。

为什么是GPU?简单来说就是性能的表现导致这样的结果。随着CPU的不断发展,工艺水平逐步提高,我们开始担心摩尔定律会不会失效。但是GPU的概念横空出世,NVIDIA 的CEO 黄仁勋得意的宣称摩尔定律没有失效。我们看到最近几年,GPU处理能力的提升是非常惊人的。今年发布的Nvidia P100的处理能力已经达到令人恐怖的效果。与CPU处理能力做一个对比,虽然CPU的主频要远远高过GPU的主频,例如目前GPU在主频在0.5GHz到1.4gHz,处理单元达到3584个;而且最常见的CPU,比如Intel的处理器,大约只有20几个处理单元。这种差别是仅仅在处理单元的数量上就已经存在了巨大的差别。所以深度学习具备大量处理能力计算要求的情况下,GPU无疑具有非常强大的优势。

GPU并不是完全完美的方案!对于程序员来讲,我们也应该了解到它天生的不足。相比CPU,它仍然存在许多的局限。首先,比如:这种技术需要绑定特定的硬件、对编程语言的有一定的限制。简单来说,开发的灵活性不如CPU。我们习惯的CPU已经帮助我们屏蔽掉处理了许多的硬件上细节问题,而GPU则需要我们直接面对这些底层的处理资源进行编程。第二,在GPU领域不同厂商提供了不兼容的框架。应用的算法需要针对特定的硬件进行开发、完善。这也意味着采用了不同框架的应用对于计算环境的依赖。第三,目前GPU是通过PCIe外部配件的方式和计算机集成在一起。众所周知,PCIe连接的频宽是很大的瓶颈,PCIe 3.0 频宽不过7.877 Gbit/s。考虑到计算需求较大的时,我们会使用显卡构成GPU的集群(SLI),这个频宽的瓶颈对于性能而言就是一个很大的制约。最后,就是有限的内存容量的限制。现在Intel新推出的E7处理器的内存可以达到2TB。但是对于GPU而言,即使是Nvidia 的 P100 提供有16GB的内存,将四块显卡构成SLI(Scalable Link Interface)也只有64GB的显存容量。如果你的模型需要较大的内存,恐怕就需要做更好的优化才可以满足处理的需要。这些都是GPU目前的缺陷和不足。我们在着手使用GPU这种技术和资源的时候一定要意识到这一点。

GPU除了硬件上具备了一定的优势以外,Nvidia还为程序员提供了一个非常好的开发框架-CUDA。利用这个编程框架,我们通过简单的程序语句就可以访问GPUs中的指令集和并行计算的内存。对于这个框架下的并行计算内存,CUDA提供了统一管理内存的能力。这让我们可以忽略GPU的差异性。目前的编成接口是C语言的扩展,绝大多数主流编程语言都可以使用这个框架,例如C/C++、Java、Python以及.NET 等等。

今年的中秋节假期,我为自己DIY了一台深度学习工作站。起因是我买了一块GeForce GTX 1070显卡,准备做一些深度学习领域的尝试。因为我的老的电脑上PCIe 2.0 的插槽无法为新的显卡供电。不得已之下,只好更新了全部设备,于是就组装了一台我自己的深度学习工作站。这个过程是充满挑战的,这并不仅仅是需要熟悉各个部件的装配。最重要的是要考虑很多细节的的搭配的问题。比如说供电的问题,要计算出每个单元的能耗功率。这里面又一个重要的指标就是TDP( Thermal Design Power)。Intel 6850K的TDP值是140W,1070显卡的值是150W。于是,系统搭配的电源就选择了650W的主动电源。其次,如果我们用多块显卡(SLI),就必须考虑到系统频宽的问题。普通的CPU和主板在这方面有很大局限。就我的最基本的需求而言我需要的最大的PCI Expres Lanes 是 40。这样算下来,Intel i7-6850K就是我能找到最便宜而且可以达到要求的CPU了。

我在这两天的时间里面,走了很多弯路,所以就想跟大家分享一下我的经验。

第一,Linux在显卡驱动的兼容性方面有很多问题。大多数Linux 分发版本提供的 Nvidia显卡驱动是一个叫做Nouveau的开源版本的驱动。这个版本是通过逆向工程而开发的,对于新的Nvidia 的技术支持的很不好,所以一定要屏蔽这个驱动。第二,Nvida的驱动以及CUDA合cuDnn 的配置上也有很多搭配的问题。官方的版本只提供了针对特定Linux 分发版本的支持。相比较而言,Ubuntu 16.04 在这方面表现的更出色一些。再有就是CuDNN需要在Nvidia 官网注册以后才可以下载。第三,Nvidia 的驱动有很多版本。例如Nvidia P100架构的显卡需要最新的370版本才能支持,但是官网上可以下载的稳定版本只是367。最后,就是令人烦心的软件的依赖关系,安装的顺序等等。举一个例子,在GPU上编译Tensorflow 是不支持GCC 5.x的版本,只能自行安装 GCC 4.9并修改编译选项。另外,Bazel 也会对JDK 的版本有一定的要求。

除了自己去DIY一个深度学习工作站这个选项之外,另外一个选择就是采用云计算环境所提供的计算资源。不久之前 AWS 发布了最新一款深度学习的EC2实例类型,叫做p2。这个实例的类型使用了NVIDIA 的 K80的GPU,包括三种不同规格,第一种2xlarge,第二种是8xlarge,第三种是16xlarge。以p2.16xlarge为例,提供了16块K80 GPU ,GPU 显存达到了192G,并行处理单元的数量达到了惊人的39,936个。

当你在考虑去开发一个应用、去着手进行深度学习尝试的时候,我建议大家可以试试这种方式,这个选择可以很轻松的帮助我们计算资源以及硬件上各种麻烦的问题。

这是我前天为这次分享而准备的一个AWS 上p2的实例。仅仅通过几条命令就完成了实例的更新、驱动的安装和环境的设置,总共的资源创建、设置时间大概在10分钟以内。而之前,我安装调试前面提到的那台计算机,足足花了我两天时间。

另外,从成本上还可以做一个对比。p2.8xLarge 实例每小时的费用是7.2美元。而我自己那台计算机总共的花费了是¥16,904元。这个成本足够让我使用350多个小时的p2.8xLarge。在一年里使用AWS深度学习站就可以抵消掉我所有的付出。随着技术的不断的升级换代,我可以不断的升级我的实例,从而可以用有限的成本获得更大、更多的处理资源。这其实也是云计算的价值所在。

云计算和深度学习究竟有什么关系?今年的8月8号,在IDG网站上发表了一篇文章谈到了这个话题。文章中做了这样一个预言:如果深度学习的并行能力不断提高,云计算所提供的处理能力也不断发展,两者结合可能会产生新一代的深度学习,将带来更大影响和冲击。这个是需要大家考虑和重视的一个方向!

软件

深度学习除了硬件的基础环境之外。程序员会更关心与开发相关的软件资源。这里我罗列了一些自己曾经使用过的软件框架和工具。

  • Scikit-learn是最为流行的一个Python机器学习库。它具有如下吸引人的特点:简单、高效且异常丰富的数据挖掘/数据分析算法实现; 基于NumPy、SciPy以及matplotlib,从数据探索性分析,数据可视化到算法实现,整个过程一体化实现;开源,有非常丰富的学习文档。
  • Caffe专注在卷及神经网络以及图像处理。不过Caffe已经很久没有更新过了。这个框架的一个主要的开发者贾扬清也在今年跳槽去了Google。也许曾经的霸主地位要让位给他人了。
  • Theano 是一个非常灵活的Python 机器学习的库。在研究领域非常流行,使用上非常方便易于定义复杂的模型。Tensorflow 的API 非常类似于Theano。我在今年北京的QCon 大会上也分享过关于Theano 的话题。
  • Jupyter notebook 是一个很强大的基于ipython的python代码编辑器,部署在网页上,可以非常方便的进行交互式的处理,很适合进行算法研究合数据处理。
  • Torch 是一个非常出色的机器学习的库。它是由一个比较小众的lua语言实现的。但是因为LuaJIT 的使用,程序的效率非常出色。Facebook在人工智能领域主打Torch,甚至现在推出了自己的升级版框架Torchnet。

深度学习的框架非常之多,是不是有一种乱花渐欲迷人眼的感觉?我今天向各位程序员重点介绍的是将是TensorFlow。这是2015年谷歌推出的开源的面向机器学习的开发框架,这也是Google第二代的深度学习的框架。很多公司都使用了TensorFlow开发了很多有意思的应用,效果很好。

用TensorFlow可以做什么?答案是它可以应用于回归模型、神经网络以深度学习这几个领域。在深度学习方面它集成了分布式表示、卷积神经网络(CNN)、递归神经网络(RNN) 以及长短期记忆人工神经网络(Long-Short Term Memory, LSTM)。关于Tensorflow 首先要理解的概念就是Tensor。在辞典中对于这个词的定义是张量,是一个可用来表示在一些向量、标量和其他张量之间的线性关系的多线性函数。实际上这个表述很难理解,用我自己的语言解释Tensor 就是“N维数组”而已。

使用 TensorFlow, 作为程序员必须明白 TensorFlow这样几个基础概念:它使用图 (Graph) 来表示计算任务;在被称之为 会话 (Session) 的上下文 (context) 中执行图;使用 Tensor 表示数据;通过 变量 (Variable) 维护状态;使用 feed 和 fetch 可以为任意的操作(arbitrary operation) 赋值或者从其中获取数据。

一句话总结就是,TensorFlow 就是有状态图的数据流图计算环境,每个节点就是在做数据操作,然后提供依赖性和指向性,提供完整数据流。

TensorFlow安装非常简单,但官网提供下载的安装包所支持的CUDA 的版本是7.5。考虑到CUDA 8 的让人心动的新特以及不久就要正式发布的现状。或许你想会考虑立即体验CUDA 8,那么就只能通过编译Tensorflow源代码而获得。目前TensorFlow已经支持了Python2.7、3.3+。此外,对于使用Python 语言的程序员还需要安装所需要的一些库,例如:numpy、protobuf等等。对于卷积处理而言,cuDNN是公认的性能最好的开发库,请一定要安装上。常规的Tensorsorflow的安装很简单,一条命令足矣:

$ pip3 install —upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.11.0rc0-cp35-cp35m-linux_x86_64.whl

如果想评估一下或者简单学习一下,还可以通过Docker进行安装,安装的命令如下:

$ docker run -it -p 8888:8888 gcr.io/tensorflow/tensorflow

TensorFlow有很多优点。首先,目前为止,深度学习的开发框架里面TensorFlow的文档做的最好,对程序员学习而言是非常好的一点。第二,TensorFlow有丰富的参考实例,作为参考学习起来非常容易。第三,开发者社区活跃,在任何一个深度学习的社区里,都有大量关于TensorFlow的讨论。第四,谷歌的支持力度非常大,从2015年到现在升级速度非常快,这是其他开源框架远远达不到的结果。

参考TensorFlow的白皮书,我们会看到未来TensorFlow还将会有巨大的发展潜力。让我特别感兴趣是这两个方向。第一,支持跨多台机器的 parallelisation。尽管在0.8版本中推出了并行化的能力,但是目前还不完善。随着未来不断发展,依托云计算的处理能力的提升这个特性将是非常让人振奋的。第二,支持更多的开发语言,对于开发者来说这是一个绝大的利好,通过使用自己擅长的语言使用TensorFlow应用。这些开发语言将会扩展到Java、Lua以及R 等。

在这里我想给大家展示一个应用Tensorflow 的例子。这个例子的代码托管在这个网址上 https://github.com/anishathalye/neural-style。白俄罗斯的现代印象派艺术家Leonid Afremov善于用浓墨重彩来表现都市和风景题材,尤其是其雨景系列作品。他习惯用大色块的铺陈来营造光影效果,对反光物体和环境色的把握非常精准。于是我就找到了一张上海东方明珠电视塔的一张摄影作品,我希望通过Tensorflow 去学习一下Leonid Afremov 的绘画风格,并将这张东方明珠的照片处理成那种光影色彩丰富的作品风格。利用Tensorflow 以及上面提到的那个项目的代码,在一个AWS 的p2类型的实例上进行了一个一千次的迭代,于是就得到了下图这样的处理结果。

这个处理的代码只有350行里,模型使用了一个成名于2014年ImageNet比赛中的明星 VGG。这个模型非常好,特点就是“go depper”。

TensorFlow 做出这样的作品,并不仅仅作为娱乐供大家一笑,还可以做更多有意思的事情。将刚才的处理能力推广到视频当中,就可以看到下图这样的效果,用梵高著名的作品”星月夜“的风格就加工成了这样新的视频风格。

可以想象一下,如果这种处理能力在更多领域得以应用,它会产生什么样的神奇的结果?前景是美好的,让我们有无限遐想。事实上我们目前所从事的很多领域的应用开发都可以通过使用神经网络和深度学习来加以改变。对于深度学习而言,掌握它并不是难事。每一个程序员都可以很容易的掌握这种技术,利用所具备的资源,让我们很快成为深度学习的程序开发人员。

结束语

未来究竟是什么样,我们没有办法预言。有位作家Ray Kurzweil在2005年写了《奇点临近》一书。在这本书里面他明确告诉我们,那个时代很快到来。作为那个时代曙光前的人群,我们是不是有能力加速这个过程,利用我们学习的能力实现这个梦想呢?

作者介绍:

费良宏

亚马逊AWS首席云计算技术顾问,拥有超过20年在IT行业以及软件开发领域的工作经验。在此之前他曾经任职于Microsoft、Apple等知名企业,任职架构师、技术顾问等职务,参与过多个大型软件项目的设计、开发与项目管理。目前专注于云计算以及互联网等技术领域,致力于帮助中国的开发者构建基于云计算的新一代的互联网应用。

如何在AWS上构建基于 OpenSwan 的软件 VPN 解决方案

概述

随着云的普及以及即用即付的模式,正在被大家逐渐接受,那么在初期从原始数据中心到云迁移的过程中,为了保证数据的平稳迁移,并不推荐将应用以及数据库一次性的迁移到云中。所有项目都应该分阶段来进行,阶段迁移的情况下就必须要将云资源与本地数据中心的资源互连互通。

要做到互连互通,有三种备选方案,互联网,专线直连(DX)和 VPN。从三个方面比较下这三种解决方案,安全,稳定性以及费用。DX 服务无疑是最优的一种解决方案,提供安全稳定的网络性能,高吞吐量。由于国内专线铺设所带来的高昂费用,所以在初期阶段,DX 并不是一个最优的。这里面互联网是最便宜的,因为本身数据中心就已经支付了这部分费用,只要保证云中的资源可以上互联网就可以了,但互联网面临的问题是网络依赖互联网,互联网的网络性能并不是可控的,另外一方面是互联网的安全性。VPN 呢是基于互联网的服务,虽然不能保证网络性通的可控,但可以做到数据的安全。

就以上比较而言,在初期阶段,VPN 无疑是一种高性比的安全以及节约成本的方案。考虑到目前北京区域并不支持硬件VPN的服务,即Global区域的VPN Connection。那么有没有可以替代的方案呢?答案是肯定的,一切问题都难不倒我们伟大的开源组织,开源方案如 OpenSwan (今天的主角),StrongSwan,Raccoon等等了。除了开源的解决方案外,还有一些商业解决方案,比如Sanfor 深信服,Hillstone 山石,Checkpoint , Cisco CSR1000v等也可以部署,有兴趣的可以与相应的软件提供商联系。

前面说了那么多关于VPN的各种软件,那么该如何选择呢?这里我们从使用上来划分下吧,将VPN主要划分为两类,一类是工作于客户端到服务端的模式,像OpenVPN,SSL VPN,L2TP,PPTP这些都是需要客户端主动发起连接,拨到Server端在两者之间建立一个逻辑上的隧道 (tunnel)进行通信。这种方式一般适用于个人到总部场景。服务器是无法主动发起连接到客户端。

另外一种就是站点到站点(site-to-site)的模式,像OpenSwan,StrongSwan, Raccoon 等软件,这种情况下两端会各有一个设备负责来建立两个站点之间安全通信的隧道,任何需要到对端的通信都会触发设备来建立安全隧道通信。

那么公司原有数据中心与云通信都是双向通信,所以站点到站点更合理。

实际上这里说的 VPN 即是指 IPsec VPN,IPsec 是一种工业标准,只要支持这种标准的设备都可以互相协商建立一个安全的隧道出来,比如支持的硬件设备有路由器,防火墙以及专业的 VPN 设备。

说了这么多,下面我们就以 AWS 端为 OpenSwan 与 Cisco 的路由器之间的配置为例。

场景及拓扑

拓扑如上图,AWS端建立一个VPC(CIDR:192.168.0.0/16),包含两个子网,一个可以上互联网的Public子网192.168.1.0/24以及私有子网Private 192.168.2.0/24。在公有子网上会配置一台OpenSwan实例与公司的Cisco设备做VPN连接。

OpenSwan的EIP地址为54.223.152.218 子网:192.168.1.0/24

Cisco设备的公网地址为54.223.170.5 子网:10.1.2.0/24

目标:实现AWS上私有子网192.168.2.0/24和数据中心10.1.2.0/24双向互通

详细配置步骤

1.配置 VPC 基础环境

1.1 创建 VPC

在AWS console界面点击VPC,在左侧点击“您的VPC”, 创建VPC

名称标签: MyVPC

CIDR块: 192.168.0.0/16

租赁:默认

1.2 创建子网

将鼠标点到子网,选择创建子网

标签名称:Public

VPC:选择第一步创建好的VPC

可用区:保持默认

CIDR块:192.168.1.0/24

以同样的方法创建一个192.168.2.0/24的子网

1.3 创建路由表

点击路由表,创建路由表

名称标签:PrivateRoute

VPC:选择1.1创建好的VPC

创建完成以后,点到刚刚创建好的路由表,在页面下列点击子网关联,点击编辑

在192.168.2.0/24的路由前打勾,点击保存。

1.4 创建 IGW

点击Internet网关,创建Internet网关

名称标签:MyIGW

创建完成,点击附加到VPC

选择新创建好的VPC

2. 启动并配置 VPN 实例

2.1 启动实例

到EC2页面,点击启动实例。选择Amazon Linux

在详细信息页中,网络请选择新创建的VPC

子网选择192.168.1.0/24

点击下一步,存储标签等按需配置

配置安全组,选择创建一个新的安全组

添加规则

自定义的UDP规则,端口500 来源任何位置

自定义的UDP规则,端口4500 来源任何位置

自定义协议, 协议 50 来源任何位置

所有流量 来源为 192.168.2.0/24

注意:一定要放行来自于192.168.2.0/24的流量,否则无法通信。

最后审核启动,启动时指定一个用于登陆实例的key文件,如果没有创建一个新的。

2.2 配置弹性 IP (EIP)

在EC2页面,左侧导航栏找到弹性IP,申请分配新地址,并将其关联到新创建的OpenSwan实例。这里申请到的为 54.223.152.218。

2.3 关闭源/目的检查

在EC2页面点击OpenSwan实例,右键选择联网,更改源/目标检查,点“是,请禁用”

3. 安装配置 OpenSwan

3.1 登录到实例安装 OpenSwan

如何登陆实例请参考如下文档:

https://docs.amazonaws.cn/AWSEC2/latest/UserGuide/putty.html

登陆完成以后,运行如下命令安装OpenSwan

$ sudo yum -y install openswan

3.2 根据Cisco 参数来配置 OpenSwan

修改/etc/ipsec.conf去掉最后一行include /etc/ipsec.d/*.conf 的注释

$ sudo vim /etc/ipsec.conf

include /etc/ipsec.d/*.conf

 

Cisco路由器的配置如下:

crypto isakmp policy 10

encr aes

authentication pre-share

group 2

crypto isakmp key aws123 address 54.223.152.218

!

!

crypto ipsec transform-set OpenSwan esp-aes esp-sha-hmac

mode tunnel

!

!

!

crypto map OpenSwan 10 ipsec-isakmp

set peer 54.223.152.218

set transform-set OpenSwan

match address 100

!

!

interface GigabitEthernet1

ip address 54.223.170.5 255.255.255.252

ip mtu 1400

ip tcp adjust-mss 1360

crypto map OpenSwan

!

access-list 100 permit ip 10.1.2.0 0.0.0.255 192.168.2.0 0.0.0.255

ip route 0.0.0.0 0.0.0.0 54.223.170.6

根据cisco的配置创建OpenSwan的配置如下:

$ sudo vim /etc/ipsec.d/cisco.conf

conn cisco

authby=secret

auto=start

leftid=54.223.152.218

left=%defaultroute

leftsubnet=192.168.2.0/24

leftnexthop=%defaultroute

right=54.223.170.5

rightsubnet=10.1.2.0/24

keyingtries=%forever

ike=aes128-sha1;modp1024

ikelifetime=86400s

phase2alg=aes128-sha1

salifetime=3600s

pfs=no

配置解释:

leftid 标明本地对应公网IP

letftsubnet为本地子网

right为对端公网地址

rightsubnet为对端子网

ike为第一阶段参数

ikelifetime为第一阶段的生存时间

phase2alg为第二阶段参数

salifetime为第二阶段生存时间

结果如下图:

配置预共享密钥:

$ sudo vim /etc/ipsec.d/cisco.secrets

54.223.152.218  54.223.170.5: PSK “aws123”

启动openswan服务并做配置检查

$ sudo service ipsec start

$ sudo ipsec verify

3.3 修改系统参数

更改系统参数做IP转发并关闭重定向功能

编辑/etc/sysctl.conf内核配置文件,做如下修改

$ vim /etc/sysctl.conf

$ vim /etc/sysctl.conf

net.ipv4.ip_forward = 1

net.ipv4.conf.all.accept_redirects = 0

net.ipv4.conf.all.send_redirects = 0

net.ipv4.conf.default.send_redirects = 0

net.ipv4.conf.eth0.send_redirects = 0

net.ipv4.conf.default.accept_redirects = 0

net.ipv4.conf.eth0.accept_redirects = 0

配置完成以后,启用新的配置

$ sudo sysctl –p

3.4 更改 OpenSwan 的网卡 MSS 值

$ sudo iptables -t mangle -A FORWARD -o eth0 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1387

3.5 修改 VPC 私有子网路由表

找到VPC Console页面,在左侧点路由表,找到192.168.2.0/24关联的路由表(1.3中创建), 在页面下方点击路由,编辑

添加其他路由,

目标: 10.1.2.0/24

目标:OpenSwan实例ID (i-xxxxx)

4. 测试连通性

以上步骤都完成以后,就可以在192.168.2.0网段的实例进行测试了。使用 ping 测试到 10.1.2.x private 私有地址段的一个地址。

ping 10.1.2.3

检查 IPsec tunnel 状态:

$ sudo service ipsec status

IPsec running - pluto pid: 25674

pluto pid 25674

1 tunnels up

some eroutes exist

常见问题及排错

1.  IPsec Tunnel 没有正常建立

首先检查到对端 IP 是否可以通信,检查安全组是否放行 IKE 需要的端口 UDP 500。如果网络层没问题,检查各项参数配置是否有错误。

2. 隧道建立成功,但是无法进行通信

首先检查 IP forward 是否设置为 1?VPN 实例安全组是否放行了相应的策略?路由是否正确?NAT 是否影响?

3. NAT 问题

如果您的 CGW 配置了 NAT 与 VPN 工作,根据厂家不同对 VPN 包的处理顺序不一致,如果源 NAT 在 VPN 之前被处理了,因为源地址发生了改变,所以也就不会再被 VPN 处理,造成通信失败。像 Cisco 设备就需要做 NAT 的例外策略。主流的 Cisco ASA 就需要做相应修改,参考如下:

8.2 及以前的版本:

nat (inside) 0 access-list nat_exemption
access-list nat_exemption extended permit ip 192.168.1.0 255.255.255.0 10.0.0.0 255.255.255.0

8.3 及更新的版本:

object network obj-192.168.1.0

subnet 192.168.1.0 255.255.255.0

object network obj-10.0.0.0

subnet 10.0.0.0 255.255.255.0

nat (inside,any) source static obj-192.168.1.0 obj-192.168.1.0 destination static obj-10.0.0.0 obj-10.0.0.0 no-proxy-arp

如果您经过以上步骤还是不能成功搭建 VPN,AWS Support 提供专业化的技术支持,可根据您当前或计划的使用案例为您提供一套独特的工具和专业知识。建议您开案例联系Support 技术支持。

作者介绍:

侯晓鹏

亚马逊AWS云支持工程师,多年从事网络相关支持以及架构咨询工作,在加入 AWS 以前曾担任 Juniper 高级咨询专家,负责为企业网及运营商提供专业架构咨询及网络优化工作。现任亚马逊云支持工程师,AWS 认证 Direct Connect 服务专家。多次帮助大规模企业客户解决混合云复杂技术及架构问题。

Amazon CloudFront常见错误配置及解决方法

很多的用户在最初使用CloudFront做Web类内容分发的时候遇到无法调通的情况,本文总结了用户在配置过程中遇到的常见错误,内容涵盖了大部分用户遇到的情况。

错误一  源访问权限未放开

这种错误常见于用S3做源的情况, 引起这种错误的原因是s3的访问控制没有对CloudFront开放。从浏览器中返回的错误通常类似于下图:

更具体些,可分为以下两个场景:

场景1. CloudFront使用了Restrict Bucket Access

在创建distribution的时候选择了Restrict Bucket Access 为yes, 但 Grant Read Permissions on Bucket, 选择的是”No, I Will Update Permissions”, 而用户事后却没有在s3的桶里更新policy。如下图所示。

解决方法:

方法1, 在S3中增加桶的策略,使该桶允许该CloudFront访问,以下是policy示例,其中标黄部分需要替换成用户自己的信息。

{

                "Version": "2008-10-17",

                "Id": "PolicyForCloudFrontPrivateContent",

                "Statement": [

                                {

                                                "Sid": "1",

                                                "Effect": "Allow",

                                                "Principal": {

                                                                "AWS": "arn:aws:iam::CloudFront:user/CloudFront Origin Access Identity E344H6KAFBMK0I"

                                                },

                                                "Action": "s3:GetObject",

                                                "Resource": "arn:aws:s3:::elastictcoutputthumb/*"

                                }

                ]

}

方法2, 重新创建distribution, 新建的distribution中Grant Read Permissions on Bucket选择yes, Update bucket policy, 这样当distribution创建完成后,s3桶的policy会被自动更新。

场景2. 普通的S3回源

CloudFront 并未使用Restrict Bucket Access, 这种情况下如果s3中的对象没有设置成可被公共访问,也会出现Access Denied的错误。

解决方法:

可以通过设置s3桶的bucket policy或者设置s3中对象的Object ACL来实现。 例如,通过 AWS 控制台设置存储桶的bucket policy:

通过 AWS 控制台设置S3对象的Object ACL:

注:如果想了解S3访问控制的详细内容,请参考:http://docs.aws.amazon.com/AmazonS3/latest/dev/s3-access-control.html

错误二 使用自定义域名但未在CloudFront中配置

用户有时不直接使用CloudFront的distribution产生的域名,而是使用了自定义的域名并用CNAME的方式指到CloudFront的域名, 例如使用cdn.mydomain.com  CNAME到d1cbzf61pdxxxx.CloudFront.net。此外,如果使用Route53作为DNS, 也可以不采用CNAME的方式,而是采用Alias的方式。

CloudFront规定当使用自定义域名并配置该域名使用CNAME或Alias的方式指向CloudFront distribution的域名的时候,需要在CloudFront相应的distribution中提供该自定义的域名,如果使用了多个自定义的域名,则提供多个自定义的域名。如果没有提供,就会出现类似下图的错误:

解决方法:

可以通过AWS控制台,对distribution中的Alternate Domain Names(CNAMEs)进行设置:

错误三 访问路径错误

配置完CloudFront的Behavior后,用户有时不能给出正确的url来访问想要的资源。 出现访问错误, 如果是回源s3, 返回的错误通常如下:

如果是回源的自定义网站,返回的错误根据网站的不同而不同,例如:返回”找不到相应的页面”等错误。

解决方法:

避免这种错误很简单,了解CloudFront Behavior的url与所访问的源站资源的对应方法,即可判别自己的url是否正确. 以下举例说明:

某Behavior如下,该Behavior对应的origin ID是S3-hxybucket/Picture:

进入到Origin查看,可知Origin Domain Name and Path是hxybucket.s3.amazonaws.com/Picture

如果通过d1cbzf61pdxxxx.CloudFront.net/dog.jpg访问的话, 对应的源站资源是hxybucket.s3.amazonaws.com/Picture/dog.jpg

如果通过d1cbzf61pdxxxx.CloudFront.net/jpg/dog.jpg访问的话,对应的源站资源是hxybucket.s3.amazonaws.com/Picture/jpg/dog.jpg

即: 将CloudFront域名后面的路径追加到Origin Domain Name and Path (注意,除了Domain Name之外,还有Path) 所对应的路径后面, 就是对应到源站的资源, 用户通过该路径即可判断所使用的url是否正确。

错误四 HTTP Method 设置不当

在创建Behavior的时候, allowed http methods选项的默认值是GET和HEAD, 有时用户会使用其他的HTTP method, 例如POST, 此时如果还是用默认值,就会出错,返回的错误通常如下:

“This distribution is not configured to allow the HTTP request method that was used for this request. The distribution supports only cachable requests.”

解决办法:

办法很简单,在Behavior中重新设定一下Allowed HTTP Methods选项,使其包含所用的HTTP Method.

错误五 设置了Restrict Viewer Access 却没有使用Signed URL或Signed Cookie

在创建Behavior的时候,Restrict Viewer Access (Use Signed URLs or
Signed Cookies)选项的默认值是No, 如果用户改成了Yes, 此时该Behavior对应的资源必须使用Signed URL 或者Signed Cookie的方式访问,如果使用普通的Url访问,返回的错误通常如下:

解决方法:

方法1.使用signed url 或signed Cookie进行访问,具体参考:http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html

方法2. 将Restrict Viewer Access (Use Signed URLs or
Signed Cookies)的值改为No。如图:

错误六  Object Caching 设置不当

虽然能够访问到源,但有时用户会反映使用了CloudFront并没有加速访问,有时甚至效果还不如未使用CloudFront时。 这很可能是由于Object Caching设置不当造成的。

解决方法:

Object Caching有两个选项,分别是Use Origin Cache Headers 和 Customize。默认选项是前者。但是,当默认选择了Use Origin Cache Headers,而源的HTTP header中却没有Cache-control的头,那返回内容就不被缓存了。 因此,用户需谨慎选择,当源的返回值中没有Cache-control头的情况下,选择Customize,Customize中的Default值将会成为TTL时间(时间单位是秒)。

另外,如果源的返回值中存在Cache-control,而Object Caching又选择了Customize, 这种情况下返回的内容肯定会在CloudFront边缘节点中被缓存。但CloudFront会使用哪个值作为TTL呢? 这个在CloudFront 文档中有详细的描述, 详见: http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Expiration.html

作者介绍:

韩小勇

亚马逊AWS解决方案架构师,负责基于AWS的云计算方案架构咨询和设计,实施和推广,在加入AWS之前,从事电信核心网系统上云的方案设计及标准化推广 。

使用DMT工具迁移北京区域的数据库

在前面的blog《将Oracle数据库迁移到AWS云的方案》中谈到了多种将Oracle数据库从数据中心迁移到AWS云中的方法。其中 使用DMS服务迁移的方法简单实用,也支持异构数据库的迁移,很多朋友都想使用这种方法完成迁移。但是在北京区域不支持DMS服务,如何实现类似的迁移工作呢?其实在北京区域支持使用Database Migration Tool(DMT)来迁移数据库,DMT工具是DMS服务的前身,它是安装在Windows上的一个软件,迁移前只需要获取DMT工具的AMI,然后简单的配置后,就可以进行数据迁移了。本文主要讨论如何使用DMT将Oracle迁移到Amazon RDS数据库,示例的场景如下图所示:

在建立客户本地数据中心与AWS连接的时候,考虑到安全性问题,我们建议您通过VPN或者企业专线来建立数据库之间的连接,您只需确保您本地数据库端口(例如Oracle端口1521)对外可访问。如果您的业务对安全性要求较高,需要传输的数据量较大,同时,要求以较快速度传输的时候,可以采用专线迁移,但是这种方法成本较高,您需要根据您的业务需求来选择是通过VPN还是企业专线迁移。

在介绍DMT数据库迁移之前,我们首先介绍一下DMT迁移工具支持的数据库类型以及对源和目标数据库的限制:DMT目前支持将Oracle、SQL Server、MySQL、SAP Sybase以及PostgreSQL作为源或目标数据库,您也可以将Amazon Redshift作为您的目标数据库。同时,DMT也支持异构数据库的迁移,例如将Oracle迁移到MySQL。

DMT工具为我们迁移数据库提供了巨大的便利,然而,它也有一些限制条件,下表主要介绍DMT支持的三种常用关系型数据库版本以及相关限制条件。如果您需要了解更多有关DMT迁移数据库信息,请参考DMT用户手册:

https://s3.cn-north-1.amazonaws.com.cn/rdmt/RDS+Migration+Tool+User+Guide.pdf

使用DMT迁移主要有下面几个步骤:

(1)获取DMT的AMI

(2)启动DMT的AMI

(3)登陆DMT服务器

(4)配置服务器

(5)访问DMT工具

(6)迁移数据

1.获取DMT的AMI

如果您有数据库数据需要导出或者导入到AWS 北京区域中,首先您需要获取DMT的AMI镜像,然后根据镜像启动EC2服务器。获取DMT的镜像有两种方式:

(1)和支持您当前AWS账号的商务人员联系,他能帮您在后台申请访问DMT AMI的权限。

(2)您也可以自己在Support Center 中开case。在AWS Console中访问Support Center的方式如下图所示:

2.启动DMT的AMI

当您有能访问DMT的AMI以后,登陆您的AWS账号,进入Services->EC2->AMI的界面,选择“Private images”列表,就可以看到有一个Amazon_RDS_Migration_Tool的记录,这就是最新的迁移工具,如下图所示:

选择DMT点击上方的“Lunch”按钮,启动一个已经安装好DMT工具的服务器。接下来您需要配置您实例的类型、大小、实例所在VPC以及安全组和密钥等信息。具体配置步骤请参考官方文档:http://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/EC2_GetStarted.html

需要注意的是:

(1)在选择DMT服务器所在VPC的时候,尽量选择源或者目标数据库所在的VPC创建DMT服务器,这样可以加快迁移的速度。

(2)在配置安全组的时候,您的安全组应该允许RDP协议和https协议。由于DMT服务器是Windows Server服务器,因此您需要使用Windows远程桌面连接访问,此时需要RDP协议,source指定当前需要连接客户端的IP或者IP段。DMT工具可以通过浏览器来访问,因此需要设置https协议的安全组,如下图所示:

3.登陆DMT服务器

启动DMT服务器,并下载私钥后,就可以登陆DMT服务器了,如下图所示,当您的服务器状态显示为running,并且通过健康检查后,您的服务器就可以正常访问了。如下图所示:

选择您的DMT服务器,然后点击Connect,显示如下界面:

在此步骤中,您需要根据下载的私钥获取登陆Windows的密码。点击 get Password,显示如下图所示界面:

输入您前面下载的私钥的文件全部内容,点击 Decrypt Password后,您在界面上可以看到Administrator的密码,请记录下这个密码。下面就可以登陆服务器了。

本例中是使用MAC的Windows远程终端软件来访问DMT服务器,如果您使用Windows客户端,访问过程类似,输入远程DMT服务器的DNS名称,输入用户名和密码并连接。

连接上DMT终端后,您会看到Windows Server 2012的桌面如下图所示,桌面上有DMT工具。

连接到远程终端后,您可以根据需要修改访问Windows的密码,修改密码可以在控制面板中完成,界面如下:

4. 配置服务器

登陆到DMT服务器后,在界面上有Database Migration Tool Documentation的目录,进入目录并下载QuickStart Guide.下载过程中如果出现如下错误,请添加授信站点或者配置服务器解决错误。

下载Quick Start Guide和PDF阅读软件。

打开QuickStart Guide如下图所示,您可以按照您数据库的类型(Oracle, MySQL等)选择相应的驱动程序。

本例中由于迁移的是Oracle数据库,安装Oracle的驱动和客户端相对复杂,下面会详细解释如何安装Oracle驱动,其他驱动的安装请参考文档。点击Quick Start Guide中的Oracle Instant Client后面的链接后,出现如下界面(需要您有Oracle账号才能下载软件):

下载Instant Client Package-Basic: All files required to run OCI….的文件,也就是上图第一个黄色方框中的文件。

下载Instant Client Package-ODBC驱动,如上图第二个黄色方框。由于DMT安装在Windows Server上,因此有很多安全的限制,如果遇到禁止下载的错误,可以参照下图:

选择Internet,然后点击Customer level。

选择Downloads,然后Enable下载,就可以正常下载Oracle的软件了。

下载完成后,basic和odbc的包如上图所示。

创建 c:\oracle目录,将目录作为解压的目录,选中 basic-windows的文件,然后解压到oracle目录,如下图示:

选中odbc的压缩包,然后解压到c:\oracle

解压后的文件目录结构大致如下:

选中 odbc_install.exe并运行,如下图:

选择run,默认没有反应是正常状态 。

将变量 C:\oracle\instantclient_12_1添加到Path变量中,如下图所示:

增加TNS_ADMIN变量如下图所示:

在本例中,增加的变量TNS_ADMIN和变量Path的值相同。

5.访问DMT工具

先使用界面上的工具Stop Amazon RDS Migration Service停止DMT服务。这样避免刚才设置的环境变量没有应用DMT工具中。

在点击在桌面点击下面图标启动DMT服务。

启动后,如果见到下面的窗口:

表示启动成功。

选择图标就可以启动DMT的Web访问客户端,如下图所示:

见到Console的界面,表示DMT服务启动成功。DMT的console可以在服务器上访问,也可以在客户端访问,在外网访问只需要获取到DMT服务器的Public DNS,使用下面格式URL从外网访问DMT console。

https://your-public-dns/AmazonRDSMigrationConsole

访问console后,会弹出如下界面,输入访问windows的用户名和密码。

输入登陆系统的用户名和密码并登陆,显示如下界面:

在界面中使用Manage Database创建Source和Target数据库,创建Task就可以开始迁移您的数据库了。

6.使用DMT迁移数据

当您通过前面的步骤能够正确地访问DMT工具,说明配置基本成功,下面就可以通过DMT迁移您的数据库了。

Step1: 配置源数据库连接信息

点击上图中的Manage Databases->Add Database,输入数据库类型为Oracle,填好具体URL及数据库的Role信息,示例信息如下:

参数说明:

Name:给需要迁移的数据库定义一个名称,可以根据需要定义。

Description:给需要迁移的数据库一个详细的描述。

Role:需要迁移数据库的角色,如果是迁移中的源数据库,则选择SOURCE,如果是迁移中的目标数据库,则选择TARGET.

Connection String:对于传统Oracle数据库的格式为 ip:port/sid

User name:数据库连接的用户名

Password:数据库连接的密码

Step2: 配置目标RDS数据库连接信息

配置目标RDS数据库信息如下:

RDS的Connection String的格式为:

<database-name>.<rds-endpoint>:<port>/<sid>

Step 3:检查Source和Target数据库的归档模式和Supplemental Log

由于DMT工具可以捕捉数据库日志,将源数据库的变化复制到目标数据库,这种复制方式要求源和目标数据库都是归档的数据库,并且需要Supplemental Log的设置。

使用SQL PLUS连接源数据库,如果数据库处于非归档模式,则将数据库改为归档模式。

运行下面语句,修改Supplemental Log设置:

SQL> ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;

Database altered.

使用Oracle SQL Developer或者其他客户端工具连接RDS目标数据库,运行下面的语句:

exec rdsadmin.rdsadmin_util.alter_supplemental_logging(‘ADD’);

Step 4:创建Task

在主界面上点击“New Task”,如下图所示:

Task options: 定义复制的类型,Full Load表示将当前的表和数据拷贝到目标数据库。Apply Changes表示将当前时刻到停止复制前的日志变化同步到目标数据库。如果两个都选择,表示同步数据,并将捕捉到的数据库变化复制到目标数据库。

Step 5:定义Task

将Source和Target数据库的图标,拖入到左边的流程图中,如下图所示,我们定义了将OracleSourceDB复制到RDSDatabase中。

定义好流程后,点击Table Selection选择需要复制哪些表。如下图所示:

在此图中,我们复制的是TEST.T_USERS表。您也可以使用Patterns的方式匹配表名。

点击Task中的Run按钮,很快数据库就开始迁移了。

7. 错误诊断

(1)如果在测试数据库时出现oci.dll无法加载的错误,如下图所示:

这个错误一般说明你没有将instance client的路径配置到path变量中去。此时只需要配置好变量,然后停止并启动DMT服务就可以了。

(2)ORA-12170: TNS: Connect timeout occurred [122307] OCI error.

如果出现此错误,说明DMT工具连接数据库超时,此时请检查RDS数据库的Security Group是否开启了DMT服务器的1521端口的访问,或者检查数据库的防火墙等网络设置,确保DMT服务器能够正常访问Oracle服务器。

作者介绍:

蓝勇

AWS解决方案架构师,负责基于AWS的云计算方案架构的咨询和设计,同时致力于AWS云服务在国内的应用和推广,在DR解决方案、数据仓库、RDS服务、企业应用、自动化运维等方面有着广泛的设计和实践经验。在加入AWS之前,在甲骨文中国担任资深售前工程师,负责售前方案咨询和架构设计,在数据库,中间件,大数据及企业应用方面有丰富经验。

杨婉洁

亚马逊AWS解决方案架构师实习生,喜欢编程,熟悉Java、C++、JSP、HTML以及关系型数据库。曾在学校和企业参与数据分析项目,熟悉各类数据分析的算法。热爱大数据、云计算。

VPC中NAT的那点事

NAT就在那里

下图 是EC2实例通过IGW(Internet网关) 接入到Internet的示意图。熟悉AWS的读者会知道,这里EC2实例和Internet通信的两个方向上,实际上发生了如下的转换:

  • 从EC2实例发出的前往Internet的IP包,其源地址10.0.0.10在经过IGW时,会被转换为与实例关联的公网地址 54.232.0.1;
  • 从Internet发给54.232.0.1的IP包,经过IGW时其目的地址会转换为ENI对应的内网地址10.0.0.10并被送到 EC2实例;

可以看到,这里Internet网关就是起到实例的内网地址和公网地址一对一的基本 NAT(网络地址转换)的功能。

相比于没有NAT的场景,大部分的应用、软件不需要任何改变就能在基本NAT的场景下继续工作,例如基于HTTP协议的Web应用等;但是对于某些应用,例如FTP、VoIP等,网络地址转换会给应用带来一些意想不到的挑战。今天我们以历史悠久的FTP协议为例,来和大家探讨一下NAT给FTP这样的应用带来什么样的挑战,以及FTP应用和协议又是如何演进去适应它。

被动模式下的FTP

我们重温一下FTP的工作过程。客户端连接服务端TCP 21端口建立命令通道后,输入用户名密码完成登录;随后的每一次数据传输都需要另外建立数据通道进行; 如果数据通道由客户端发起,服务端接受,我们称之为被动模式;反之,如果数据通道由服务端发起,客户端接受,则称之为主动模式。

为简化讨论,我们以被动模式为例。

同一个私网内

我们在EC2实例10.0.0.10上搭建了一台FTP服务器,它监听在21端口。现在我们从同一个VPC里的另外一台EC2上运行FTP客户端;那么整个过程会很顺利。

从Internet访问

现在我们从位于Internet某处的一台PC上运行FTP客户端。

这里连接超时的原因显而易见,FTP服务端发送给客户端的IP地址是服务端的私有地址。位于Internet上的客户端无法建立与位于VPC内部的私有地址10.0.0.10直接通讯。

解决这个问题有多种方法,我们由简单到复杂分别叙述。

增强协议适配NAT

FTP协议针对NAT和其他因素,对协议进行了增强,提供了增强版的被动模式EPSV命令[1]。

下面的例子里,服务端不再显式指定IP地址,只提供数据通道的端口号。客户端默认与控制通道相同的IP地址建立数据通道。

可以看到,解决方案很优雅。实际上如果你在阅读本文的时候,绝大部分FTP服务端和客户端都已经实现了EPSV,而且优先使用它,所以FTP应用目前在EC2上是可以称之为开箱即用的。当然这需要客户端和服务端都支持增强的协议才能达成;如果我们不修改协议,能否解决这个问题呢。

放开那协议!我来!

有些时候,修改协议和实现需要多方协调和很长的时间才能完成。在RFC2428标准化之前,一些FTP实现就已经通过修改实现来适配基本NAT,而非修改协议。

以vsftpd为例,它允许通过配置文件vsftpd.conf中的配置项 pasv_address=54.232.0.1 告知服务端,在PASV被动模式下,应当指示客户端连接到配置项指定的IP(而不是服务端的私有IP)来适配基本NAT。

其他的一些常见应用例如VoIP类应用,也有类似的机制去适配基本NAT;例如引入STUN/TURN/ICE等方式[2]适配各种更加复杂的NAT穿越场景;但是针对部署在EC2上的基本NAT环境,也有通过实现上的简单调整,例如开源VoIP应用Asterisk就支持通过在配置文件/etc/asterisk/sip.conf里指定本机的公网地址和本地网段的方式来适配基本NAT。

nat=yes

externaddr=54.223.0.1

localnet=10.0.0.0/16

协议和实现我都不想动!

作为一枚任性的读者,如果您既不想动协议也不想动实现,这里笔者给读者介绍一种剑走偏锋的方式,读者若有兴趣,可以轻松愉快的在AWS上试一试,看看能否解决你的应用适配基本NAT。下面是一段shell脚本,当然是运行在Linux操作系统上的。

          #从EC2 实例元数据服务获取本实例的公网IP(如有)、私网IP

          public_ipv4=`curl -s http://169.254.169.254/latest/meta-data/public-ipv4`

          local_ipv4=`curl -s http://169.254.169.254/latest/meta-data/local-ipv4`

          #配置私网地址段,这里应为EC2实例所在VPC的地址范围

          local_net=10.0.0.0/16

          if [ “x${public_ipv4}” == “x” ]

          then

          echo “No public IPv4 address available for this instance, abort.”

          exit 1

          else

           #如果EC2实例的公网IP不为空,则将该公网地址添加到eth0上

          ip address add ${public_ipv4}/32 dev eth0

          #本地接受的连接,如果来源不是本VPC,那么将IP包的目的地址改写为公网IP

          iptables -t nat -A PREROUTING ! -s ${local_net} -d ${local_ipv4} -i eth0 -j DNAT –to ${public_ipv4}

          #本地发起的连接,如果出方向流量的源IP地址是公网地址,那么需要改写为私网IP

          iptables -t nat -A POSTROUTING -s ${public_ipv4} -o eth0 -j SNAT –to ${local_ipv4}

          fi

正常情况下,脚本执行完毕后,可以通过如下方式验证效果。

首先检查本实例的公网IP是否已经正确配置到eth0上。

~ # ip addr show dev eth0

eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc pfifo_fast state UP group default qlen 1000

link/ether 02:c7:6b:9b:d2:b6 brd ff:ff:ff:ff:ff:ff

inet 10.0.0.10/24 brd 10.0.0.255 scope global eth0

valid_lft forever preferred_lft forever

                  inet 54.232.0.1/32 scope global eth0

valid_lft forever preferred_lft forever

inet6 fe80::c7:6bff:fe9b:d2b6/64 scope link

valid_lft forever preferred_lft forever

可以看到,公有IP地址(54.232.0.1/32)已经成功添加到eth0接口。

然后检查iptables的NAT规则是否正确配置

~ # iptables -t nat -nvL

 

Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)

pkts bytes target     prot opt in     out     source               destination

               0    0  DNAT       all  —  eth0   *       ! 10.0.0.0/16        10.0.0.10            to:54.223.74.106

Chain INPUT (policy ACCEPT 1 packets, 64 bytes)

pkts bytes target     prot opt in     out     source               destination

 

Chain OUTPUT (policy ACCEPT 3 packets, 222 bytes)

pkts bytes target     prot opt in     out     source               destination

 

Chain POSTROUTING (policy ACCEPT 3 packets, 222 bytes)

pkts bytes target     prot opt in     out     source               destination

              0     0 SNAT       all  —  *      eth0    54.223.74.106        0.0.0.0/0            to:10.0.0.1

从上面可以看到传入、传出数据包的数量以及IP地址在传入前,传出后的地址改写情况。

最后分别从VPC内部和Internet连接到服务,验证结果

~ $ ss -nt

State       Recv-Q Send-Q            Local Address:Port                       Peer Address:Port

ESTAB        0          72                   54.223.74.106:21                            119.xx.x.xx:52425

ESTAB        0      1272                   54.223.74.106:12081                      119.xx.x.xx:23710

ESTAB        0          72                   10.0.0.10:21                                     10.xx.x.xx:48361

ESTAB        0      1272                   10.0.0.10:12090                               10.xx.x.xx:32115

笔者在没有修改任何vsftpd的配置文件的前提下,通过上述脚本的运行和配置,同一个VPC内部的客户端和Internet客户端都能完成FTP被动模式的文件传输全流程。

值得一提的是,本方法仅供参考,不建议在生产环境中大规模使用,推荐的解决方案请参考前文关于协议适配和实现适配。

[1] FTP Extensions for IPv6 and NATs  https://tools.ietf.org/html/rfc2428
[2] NAT Traversal Practices for Client-Server https://tools.ietf.org/html/rfc6314
作者介绍:

丁成银

AWS 解决方案架构师,获得AWS解决方案架构师专业级认证和DevOps工程师专业级认证。负责基于AWS的云计算方案架构的咨询和设计,同时致力于AWS云 服务在国内的应用和推广,在数字媒体、电信、互联网和游戏、企业混合IT等方面有着丰富的实践和设计经验。在加入AWS之前,历任数字媒体娱乐系统工程 师、宽带业务架构师、云解决方案架构师,负责数字媒体娱乐系统、云计算解决方案等服务的咨询和架构设计工作。

 

Amazon CloudWatch Events监控您应用的安全

每个应用程序时刻都在产生事件,Amazon CloudWatch Events能帮助您针对应用的事件进行有针对性的响应和处理,及时响应,并处理错误事件,存储和分析潜在的告警信息。在接下来的篇幅里,我将利用AWS的CloudWatch Events,Lambda,SNS,SQS等服务向您展示如何及时分析与处理应用事件。

在这个场景中,我将应用事件划分分三个等级(当然,在您的具体业务场景中,您可以根据实际情况划分任意多的等级),Green,Yellow,Red。Green代表应用正常,您不需要进行任何动作。Yellow表示您应用的健康检查失败,通过Lambda来处理该类型事件。Red表示您的应用在至少一台服务器上已经失败,立即通知运维部门处理。

以下是该场景中的架构示意图:

1. 最左边为您的应用服务器群,他们将各自的事件发送给CloudWatch Events;

2. 在CloudWatch Events中设置Rule来进行区分,并将对应的事件发送相应的目标,如Lambda,SNS,SQS;

3. 目标在收到事件后进行相应的处理;

具体步骤:

1.   创建3个目标,Lambda,SNS,SQS;

1.1, 目标1,创建Lambda函数,SampleAppDebugger;

1.2, 目标2,创建SNS主题,RedHealthNotifier;

1.3, 目标3,创建SQS消息队列,ReportInspectionQueue;

 

2.   创建CloudWatch Events Rule

2.1, 将以下内容保存为YellowPattern.json;

2.2, 使用以下命令创建名为myCustomHealthStatusYellow的规则;

2.3, 使用以下命令创建目标;

2.4, CloudWatch Event需要将事件发送给Lambda,所以需要给Lambda添加适当权限允许CloudWatch这么做;

3.   重复上面的步骤创建第2条规则,并设置目标为SQS和SNS,特别注意,不要忘记给SNS,SQS设置相应权限以允许CloudWatch发送事件过来;

3.1, 使用以下命令创建名为myCustomHealthStatusRed的规则,这里的RedPattern.json文件其实是将2.1步骤中的YellowPattern.json是一样的,只是将内容中的Yellow替换成了Red;

3.2, 创建两个目标,SQS,SNS;

3.3, 添加权限允许CloudWatch Events发送事件;

其他SNS,SQS权限设置相关,请参考该官方链接:http://docs.aws.amazon.com/zh_cn/AmazonCloudWatch/latest/events/resource-based-policies-cwe.html#sns-permissions

4.   进行测试,手动放入一些Red事件(我设置了个小脚本,每次运行都会放入61个事件),看看SQS及SNS情况;

这里我运行了三次脚本,所以SQS中有183条消息

看看邮箱中是否会收到邮件

5.   测试Yellow事件及Lambda反应;

Lambda被触发的次数

作者介绍:

郑进佳

亚马逊AWS解决方案架构师,在加入AWS之前,在多家跨国公司有着超过7年的架构设计和项目管理的经验,对AWS云端高可用架构有着深刻的理解,以及对企业级应用如何迁移到云端的架构设计有实战方面的经验。