亚马逊AWS官方博客

协同合作伙伴 合力加速上云战略

“You can do what I cannot do. I can do what you cannot do. Together we can do great things.” -Mother Teresa

(你能做我所不及的,我能做你所不及的。双方合力,我们可以做些伟大的事情。– 修女特蕾莎)

不同的组织采取不同的方法与第三方进行专业技术合作。有些组织偏向于构建自己的技术;而另一些则将部分或全部研发工作外包,并将他们的技术运营交给第三方。不论你的组织处于什么位置,几乎可以肯定的是你与少数硬件、工具及云服务提供商合作开发针对内部和外部客户的产品和服务。

我已经与数百名在过去几年中不断发展其组织技术战略的高管交谈过,许多人开始重新审视自己的合作方式,因为他们开始了解云计算如何能够帮助他们改变自己的业务。这篇文章探讨了一些我观察到的云技术是如何改变整个技术圈的以及关于吸引合作伙伴的话题。

关注快速增长的生态系统

云生态系统的快速增长不断的令我感到惊讶。最近四年我参加了AWS re:Invent,每次我都对比前一年更大的合作伙伴规模感到惊讶。从全局来看,从2012年到2015年,合作伙伴的展位数量增长了一倍多,全部走完去了解最新的工具和技术从原来需要一个小时增长到了一天时间。没有更好的领域更适合风投来投资这一市场了。

貌似在这种快速增长的生态系统中寻找适合你的合作伙伴很难,但有多个供应商争夺你的业务对你也会是有利的。你的AWS客户经理和我们的AWS合作伙伴目录可以帮助你缩小选择范围,AWS Marketplace能够帮助你在几秒内从广泛的供应商和类别中发现并部署解决方案。

改变你的文化

现如今看到大型组织变得乐意与资金缺乏的、 “不可靠”的小型组织合作,来创建面向企业的工具、专业服务和管理服务等,这种现象是令人鼓舞的。当我在十五年前开始代表我的组织购买技术时,我被告知只能与规模大的公司长期合作。现在我看到很多财富500强公司与那些比我四岁女儿还年轻的公司合作,帮助他们处理最繁杂的问题。在一些情况下,这样做会帮助企业改变它们的整个业务。

当许多技术主管带领它们的组织走向数字化和客户至上的方向时,他们意识到如果可以接受年轻的基于云的供应商的一些文化,他们将可以实现更加迅速地反应。当我在Dow Jones担任CIO时,我和AWS合作的主要动机是吸收一些亚马逊的文化。我想要的是使亚马逊具备能够快速定位顾客、迅速反应的工具。我也迫切想构建一个DevOps文化来鼓励尝试。许多年轻的供应商—2nd Watch, Cloudreach, Cloud Technology Partners, Minjar, New Relic, App Dynamics, Chef, Puppet, CloudEndure,也出于同样的原因在发掘新的业务。

这并不是说现存的大型工具和服务提供商不能快速利用这种转变的优势。在许多情况下,它更适合利用现有的关系来改造业务或文化。

在你关注的领域寻找可靠的合作伙伴

你应该始终致力于与你业务目标相一致的组织合作。如果你正想具有DevOps能力,并且希望你的团队学会怎样“运行他们所构建的”,例如,确保你的合作伙伴能够帮助你具有像他们所展示的那样的能力。这也是AWS开发了AWS认证计划的原因之一。我们希望确保你在我们的平台上能成功,这个计划会协助你找到能帮你在这些领域取得成功的合作伙伴,这些领域也是你的组织特别关注的。我们现在正在这个生态系统中的一些领域开发认证系统,如DevOps移动安全数字媒体市场和商务大数据存储健康管理生命科学微软工作负载SAPOracle等。

不论你的组织处于什么合作状态,我们都乐于帮助你找到合适的合作伙伴来实现你的目标。

作者介绍

史蒂芬·奥本

史蒂芬·奥本 (Stephen Orban) 于 2014 年9月加入亚马逊AWS 担任企业战略总经理。奥本与多名企业技术高管合作,在云如何实现业务成果、加快创新和简化流程方面进行经验和战略分享。在加入亚马逊AWS 之前,奥本曾在道琼斯担任首席信息官 (CIO)一职,他通过借力 AWS 和其他软件即服务 (SaaS) 合作伙伴,引入现代软件开发方法、实现降低成本、执行云优先政策。这些转型变革加快了产品开发周期并提高了全部业务线的生产能力,这其中就包括《华尔街日报》、MarketWatch.com、道琼斯通讯社及Factiva。奥本还曾在彭博有限合伙公司(Bloomberg LP)工作 11 年,并且在股权和消息平台担任不同的领导职务;2008 年,奥本创建彭博体育(Bloomberg Sports)并担任首席技术官 (CTO)。

 

畅谈CIO该如何合并业务和技术

“以始为终。” — 史蒂芬·柯维(Stephen R. Covey)

与以往相比,现在成功的技术管理人员必须帮助其负责执行的同事了解技术如何融入——或者,更好地促进——他们的业务。向组织阐明这样的思考,其实就是向你的执行同事阐明你有关于组织的业务目标的指令,以及你是这个执行团队的关键成员。

目前的商业格局正在被一些公司打破。因为创建和运营这些公司的管理人员不仅懂得如何让技术融入业务,而且定义了技术在他们整个行业中扮演的角色:酒店行业的AirBnb,叫车服务行业的Uber,智能家居行业的Nest Labs,存储领域的Dropbox就是几个相关的例子。这对传统行业跟上步伐造成了压力,同时也给IT管理人员提供了无处不在的机会。没有人能比那些整个职业生涯都在从事技术工作的人更适合来阐述如何使用技术来满足日益增长的市场需求。这对我们这些已经在大公司度过了大部分职业生涯的人尤其如此。我们讲企业术语,了解哪些约束是硬性的,哪些是弹性的,以及对于每个C级同行你必须做什么。让它们的技术主管在幕后工作的企业已经不可能成功了。

而且,因为云带走了很多传统上与企业IT相关联的未分化繁重负担,所以现在的IT管理人员可以投入更多的时间和资源来从事那些驱动业务和保持组织竞争力的活动。云正是这些颠覆性力量的关键因素。使用相同的要素不一定会带给你拓展业务的想法,但它会为开放竞争环境提供了更多的可能性。

对于那些希望带领自己的组织使用云的人们,我提供以下一些观点:

与你的同事换位思考(Empathize with your peers)

云不仅仅是一个技术转变。它更是每一个管理层人员应该关注的业务转变。你的职责是来考虑云会如何影响你的执行团队的职责或者考虑它可能会带来什么影响。

我不可能在一篇文章里覆盖所有类型的管理者,但是:

首席财务官(CFO)通常被较低的前期成本以及只支付你所使用的东西所吸引。我见过很多因为逐月变化的成本导致的不和谐,但我总是发现特别是当你从容量规划和维护活动的负担中解脱出来时,总的成本会是很低的。随着时间的增长,在产品研发(资产创造)过程中,能够每个月与管理者紧密合作、了解更多成本预期的环境、管理资源的使用、交错购买RI、考虑如何核算劳动力成本等,正在成为关注的焦点。

首席营销官(CMO)通常希望保持公司的品牌新颖,并对不断变化的市场情况做出反应。把品牌网站从每月更新一次变成一天更新几次会带来什么影响?一个可无限扩展的数据仓库将如何帮助CMO更好地了解他们的客户?如果几乎没有什么代价,他们会在一小部分用户身上做什么尝试?

人力资源副总裁(VPs of HR)想看到的是你能照顾好你的员工以及你如何招聘新的人才。充分利用AWS培训与认证(AWS Training and Certification),并随时让我们的专业知识培训成为你的培训课程的一部分。我将在后续有关这个话题的文章中探讨如何教育你的员工。而且只要愿意去学习,你的团队的任何人都可以帮助你去完成这种培训。此外,还能了解参与此培训的其他公司是如何招聘新员工及如何管理老员工的过渡。比如,如何让DevOps融入你的组织,以及“运行你所构建的(run-what-you-build)”意味着什么?

CEO关注所有这些事情,以及如何让公司保持竞争力。用你从其他高管所学的东西来帮助塑造一个完整的视界,并用现代科技展示如何实现。如此一来,你将可以在同样的限制下做一些不可能完成的事情。

在Dow Jones,我设立了一个目标,每个月与几个管理者共餐。在这段时间里,我只听取他们的受挫经历。我用我所学的来调整我们的策略,并且确保我向他们反馈了他们的影响力是如何改变了我们的方向。这是一个简单的关于如何迎合他们需求、构建信任并获取支持的例子。这里的关键是不仅要聆听,还要根据你所学的来采取行动。

谋求帮助(Enlist help)          

你不必单独做这件事。你可以考虑在培训中把你的客户经理当成你的导师。他们乐意与你以及你的管理团队一起工作,帮助塑造周围的信息及迁移到云的好处,使之与你的业务接轨。如果影响已经超出了客户经理的专业知识范围,他们将寻找到合适的人选,不管是AWS的内部或外部人员。我们乐意为你创造与有同样想法的人沟通的机会。而且这不只是在我们的活动中,而是在培训的任何时刻。在最近一次活动中我和其他公司有过几个参考电话,从其他管理者学习既是一种教育也是一种验证。

AWS合作伙伴网络(AWS Partner Network)以及AWS培训和认证(AWS Training and Certification)也是重要的资源,它们能帮助你加快你的培训进程。我多次强调它们是最佳实践,但我发现很多企业与他们的HR部门合作把AWS培训作为我们整个培训的首要部分。在Dow Jones,DevOps团队与HR合作并定期举行DevOps日,来交付优化的工具和最佳实践。这是在分布全球的团队中分享技能的好方法。再次强调,你的客户经理可以帮助你很好地连接这些领域。

发展IT品牌(Evolve the IT brand)

我跟很多渴望提高自己部门品牌的IT主管交谈过。我在Bloomberg花了超过十年的职业生涯来开发促进业务的软件。我去Dow Jones的原因之一是帮助他们转变一种观念 – IT部门是一个成本中心。其实,IT部门也是驱动和赋能业务的部门。我觉得我对我的部门中辛勤工作和奉献的每个人有所亏欠,他们对我们正在推动的改变是很有帮助的。

AWS是作出这些转变的基础的一部分,但大部分在执行层面的工作在于了解每一个管理者的痛点,了解他们在IT中不想要什么,以便调整技术帮助他们实现自己的目标。在使用云提供的更好和更快的结果的几个月后,我们花了几个月再培训管理者团队和他们的部门来使用我们的技术而不是IT。这看似微妙,但它为我们之间的沟通带来有了有意义的变化,并且对由部门到公司整体的变化做出了贡献。

作者介绍

史蒂芬﹒奥本

史蒂芬·奥本 (Stephen Orban) 于 2014 年9月加入亚马逊AWS 担任企业战略总经理。奥本与多名企业技术高管合作,在云如何实现业务成果、加快创新和简化流程方面进行经验和战略分享。在加入亚马逊AWS 之前,奥本曾在道琼斯担任首席信息官 (CIO)一职,他通过借力 AWS 和其他软件即服务 (SaaS) 合作伙伴,引入现代软件开发方法、实现降低成本、执行云优先政策。这些转型变革加快了产品开发周期并提高了全部业务线的生产能力,这其中就包括《华尔街日 报》、MarketWatch.com、道琼斯通讯社及Factiva。奥本还曾在彭博有限合伙公司(Bloomberg LP)工作 11 年,并且在股权和消息平台担任不同的领导职务;2008 年,奥本创建彭博体育(Bloomberg Sports)并担任首席技术官 (CTO)。

在云端试验时的“有所为和有所不为”

“The best way to show that a stick is crooked is not to argue about it or to spend time denouncing it, but to lay a straight stick alongside it” ― D.L. Moody

(“验证一根木棒是弯曲的最好的方法不是争论或花时间去抨击,而是放一根笔直的木棒在它旁边” – 慕迪)

现在越来越多的公司意识到,正确的、科学的使用云可以让入云试验更简单、经济和低风险。而且有这种试验文化的公司会在今天的市场有更多的竞争筹码。试验带来创新,这是实现新想法的史无前例的好时机。那么应该从哪里着手呢?当你在你的组织中创建试验文化时,四类“有所为和有所不为”是值得你去考量的。

1.管理预期

不是每次尝试的结果都符合你的预期,但是每次尝试都是学习和提高你运营能力的机会。如果你的组织未形成一个“从失败中学习”的习惯,那就从小事做起,确保让每个人知道你把哪些项目当作试验项目。你可以通过以下方式来管理你的项目利益相关方的预期 – 清楚地了解试验的意图、你期望什么样的产出、你怎样测试和衡量结果、你想从中学习到什么。据我所知,如果管理者知道他的组织会从试验中学到什么或使它变得更好的话,即使这个试验没有什么确定地产出,他们也会对这个试验心存感激。

不要从每个人都要求有产出的项目着手

如果你是一个试图创建实验文化的变革推动者,在你的变革旅程中不要从每个人都要求有产出的项目着手。例如我不会建议你在年终预算上做试验。我曾经合作的一个CEO告诉过我失败是可以有的,除非当它不可以失败的时候。接受一个增长的过程,慢慢增加你进行的试验,不要超出你的组织的可接受范围。

2.鼓励你的团队计划试验

每个组织都有自己的方式来决定哪些项目获得技术资源。不幸的是,一些组织现在把技术或IT部门当成成本中心并且想象与实际相去甚远。好的想法可以来自任何地方,当然当它来自于项目之外的时候,大部分的技术专家都有其独特的观点。对于那些刚开始使用云的组织来说情况尤其如此——把云应用于项目上的人处于实施试验的最佳位置,这些试验利用了使业务从云中受益的独一无二的能力。协助维护你的团队的提议,将你的员工置于可以影响执行团队投资的项目上。

在你知道怎样评价这个试验时再开始它

你期望把时间花在正确的试验上,确保从中学到的内容可以提高你的运营能力和产品。在让你的团队进行一个试验之前,你应该知道他们会评测什么以及怎样去评测。如果你在测试你的网站新功能,什么样的指标意味着成功?页面浏览量?点击量?放弃量?这种小但重要的尽职的调查行为将迫使你的团队首先去思考为什么他们要进行这个试验。这也将迫使你的团队优先进行正确的试验。

3.考虑DevOps的制度化试验

一个DevOps的文化也许是把试验制度化带到您组织的有力途径。将运行所构建的与自动化结合起来可以大大减少发布改变的时间,允许你更频繁地发布并在失效时更快回滚。成熟的DevOps组织也制定A / B测试框架,让他们同时尝试不同的用户体验和不同的用户群,看看哪一个效果最好。

不要怀疑你的团队

怀疑是阻碍你团队的“最有力”的方法,并且打开了失败之门。当你学会适当地预期试验、评测它们,并对它们进行快速迭代,你会发现在你开始怀疑之前你会接受你的方法。确保你的团队在思考正确的评测试验方式,并且提出尖锐的问题是十分必要的。但是与其质疑他们交付的能力不如帮助团队解决问题。人们倾向于跟随相信他们能成功的领导者

4.鼓励整个组织参与

当你通过试验开始快速交付的时候,组织的其它成员将会被你的方式所吸引。那就拉他们进来。尝试进行覆盖不同业务领域的编程马拉松,让你的股东帮助确定怎样测评试验,向你的组织询问他们想进行哪个领域的试验。但并不是每个公司选择给他们员工时间来试验,他们通常吹捧这个为竞争优势。至少这种活动能提高员工们的士气和黏性。在我在亚马逊任职期间里,我发现任何人只要能够通过思考和书面形式表达试验,通常能得到机会尝试一下。这是我们特殊的文化的一部分,也是一个用来吸引和留住创新者和创造者的重要手段。

不要让试验延缓或中止交付

不要让你的团队因为只是一个试验而拖延交付。虽然失败和学习都是允许的,但在试验中未交付是不允许的。软件仍旧需要被交付测试,通常它也需要被放到生产环境的流量中被测评。试验并不意味着你可以推迟评测或降低质量。毕竟你依旧是在运营业务。

作者介绍

史蒂芬﹒奥本

史蒂芬·奥本 (Stephen Orban) 于 2014 年9月加入亚马逊AWS 担任企业战略总经理。奥本与多名企业技术高管合作,在云如何实现业务成果、加快创新和简化流程方面进行经验和战略分享。在加入亚马逊AWS 之前,奥本曾在道琼斯担任首席信息官 (CIO)一职,他通过借力 AWS 和其他软件即服务 (SaaS) 合作伙伴,引入现代软件开发方法、实现降低成本、执行云优先政策。这些转型变革加快了产品开发周期并提高了全部业务线的生产能力,这其中就包括《华尔街日报》、MarketWatch.com、道琼斯通讯社及Factiva。奥本还曾在彭博有限合伙公司(Bloomberg LP)工作 11 年,并且在股权和消息平台担任不同的领导职务;2008 年,奥本创建彭博体育(Bloomberg Sports)并担任首席技术官 (CTO)。

专线直连AWS建立混合IT环境实务指南

AWS Direct Connect简介

云计算已经走入到每个企业中。然而,一些大型企业过去都是自建数据中心,购买了大量的基础设施,在使用公有云服务时又不能抛弃原有的设备,因此采用混合云的方式,既可以保护原有的投资,又可以通过公有云的方式来随时按需使用。很多企业都正在通过混合云的方式来逐步走上全方位采用云的道路。

过去,用户需要通过在传统的公网架设VPN(Virtual Private Network,虚拟专用网络),来保障数据传输的安全性,但是,这种方式无法完全保证带宽、低延迟、时效性。而AWS Direct Connect可以实现低带宽的成本,更稳定的网络性能,更可靠的网络效果,并且可以兼容AWS其他的云计算服务帮助用户实现混合云的架构。

AWS Direct Connect服务使用标准的802.1q VLAN标准,可将连接客户数据中心和AWS的单个专线连接逻辑分割成多个虚接口(Virtual Interface)。这样客户可以通过同一个连接访问共享资源(如通过公有IP 地址空间提供服务的Amazon S3中的对象)和专有资源(如使用私有IP空间在VPC中运行的Amazon EC2实例),同时又能在公有和专用环境之间保持网络隔离。

如下图所示,从客户路由器到AWS Direct Connect路由器的以太网连接上的不同VLAN与不同的虚接口相关联,客户可以通过Public VIF访问诸如S3,DynamoDB、AWS API端点等在公共地址空间中的服务,也可以通过Private VIF与绑定到VPC的VGW相连接,实现对多个VPC的访问。

AWS Direct Connect有 1Gbps 和 10Gbps 两种端口可用。客户可以通过建立多个连接来实现更大的带宽和更高的冗余。而对于带宽要求不高的客户也可向支持 AWS Direct Connect 的 APN 合作伙伴预定带宽粒度更细的托管连接。需要注意的是每个托管连接仅能支持访问单个VPC,或者只能访问公有地址空间的AWS服务端点。当然客户可以通过多个托管连接用于访问多个VPC。

常见的接入场景及分工界面

场景一: 客户网络边界已经到达特定Direct Connect 节点

如图所示,客户在特定的Direct Connect 节点(图中虚框所示位置)所在的机房已经部署了网络边界设备,那么可以向运营该节点的运营商订购 到AWS Direct Connect路由器的楼内跳线即可完成连接。

此场景下,分工界面较为简单:

各部分的技术要求分解如下:

场景二: 客户通过以太网专线 与AWS Direct Connect互联

如图所示,客户数据中心的网络边界通过AWS合作伙伴或者独立第三方提供的以太网专线相互连接。

此场景下, 802.1q VLAN终结在客户侧路由器上, AWS Direct Connect路由器与 客户路由器建立BGP邻居并相互发布路由信息;这里特别需要关注的是,以太网专线需要支持VLAN透传,确保双方向的以太网帧能够携带正确的VLAN 标签抵达对端。

此场景下,建议分工界面如下:

各部分的技术要求分解如下:

场景三: 客户通过 MPLS网络与AWS Direct Connect互联

如图所示,客户数据中心的网络边界通过AWS合作伙伴或者独立第三方提供的MPLS网络相互连接。

此场景下, 802.1q VLAN终结在MPLS 网络的PE路由器上, AWS Direct Connect路由器与 PE路由器建立BGP邻居并相互发布路由信息;

建议分工界面如下:

各部分的技术要求分解如下:

当然对于某些MPLS服务提供商而言,上述技术需求不一定能够满足;在这种场景下,客户可以通过在Direct Connect节点部署CE路由器来解决,此时这个场景就等同于前述场景一,相当于客户把网络边界通过第三方MPLS网络延伸到Direct Connect 节点。

案例、经验与最佳实践

案例一

某客户A需要建设连接国内总部和海外某AWS Region的以太网专线;因客户自身供应商名单的限制,客户选用了独立的第三方供应商建设专线,在建设过程中由于网络资源和覆盖不全,供应商又将该连接的海外部分链路分包给其它供应商,导致在整个实施过程周期长、沟通成本高、进度缓慢; 在最后楼内跳线环节中出现了尾纤插错口的差错,但是由沟通效率低,该问题耗费了接近一周时间才最终修正。

经验与最佳实践:

  • 支持 AWS Direct Connect 的 APN 合作伙伴[1]具备丰富的项目实施经验和完善的流程,能够快速完成Direct Connect连接的部署,建议客户在实施时予以考虑;
  • 楼内跳纤环节,自测环节应当在客户路由器或专线终结设备处面向AWS侧做硬环,客户可自助在控制台上观察该连接对应的AWS侧路由器的接口的状态,如果连接状态未能从down跳转为up,责说明光纤或连接有异常,需要即时排查;全流程的排查请参见AWS Direct Connect用户指南的相关章节[2];

案例二

某客户B在与独立的第三方供应商购买以太网专线的过程中,未能充分沟通VLAN透传的技术需求,导致在专线实施的最后验证环节专线供应商因资源利用率的问题拒绝支持此技术要求,除非客户大幅提升专线带宽。

经验与最佳实践:

  • 在前期需求沟通阶段客户应与供应商充分沟通所适用场景的技术需求,避免后期被动;
  • 部分独立的第三方专线供应商在特定场景下会对提供千兆光口、VLAN透传等功能,附带要求客户承诺比较高的签约带宽(例如50Mbps ~ 200Mbps,具体请咨询相关专线供应商)才予以满足;
  • 在低带宽、连接单个VPC的场景下,建议客户向支持 AWS Direct Connect 的 APN 合作伙伴预定连接;

案例三

某客户C使用场景二所示的以太网专线连接与AWS 互联,并选用了独立的第三方运营商进行专线建设。在专线铺设过程中,第三方运营商因资源问题无法直接在终结设备上提供1000BASE-LX光口,而是 使用了独立的电转光设备完成接口类型转换。在后续的使用过程中,曾经出现由于该转换设备出现故障而导致专线临时中断, 影响了业务可用性。

经验与最佳实践:

  • 专线的可用性取决于整条链路中可靠性最弱的一环,客户需要与专线供应商明确各个环节的可用性SLA及如何保障的议题;
  • AWS Direct Connect支持客户通过多条连接实现相互负载分担和冗余,同时也支持专线与VPN之间的相互备份。可用性要求较高的场景下,建议客户通过两个或以上的Direct Connect连接,或者采用VPN备份方式在专线意外中断时保护业务可用性;
  • 专线的备份机制需要时常验证和演练,确保在异常情况下能够按预期工作;

案例四

某客户D的业务需求需要一条能够保证从AWS海外区域到国内某数据中心的低延迟、稳定的链路用于传输实时视频流。通过与支持AWS Direct Connect 的 某APN 合作伙伴订购了一条带宽为20Mbps的托管连接,整个实施过程在3天以内即告完成,客户实测带宽和线路丢包率、抖动等都符合业务需求,而且该连接的带宽具备一定弹性。该APN合作伙伴承诺的扩容等后续服务的响应和实施周期等都明显快于传统方式。

经验与最佳实践:

  • 对于小带宽、仅需要与单个VPC进行互联的应用场景,支持 AWS Direct Connect 的 APN 合作伙伴的托管连接能够给予客户更快的实施周期和更灵活的签约带宽;在适用的场景、或者项目周期较为紧迫的情况下推荐选用;
  • 客户可以订购多个类似的托管连接,实现与多个VPC分别互联;

参考链接

[1]   http://aws.amazon.com/cn/directconnect/partners/

[2]  http://docs.aws.amazon.com/zh_cn/directconnect/latest/UserGuide/Troubleshooting.html

作者介绍

丁成银

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

手把手教你调校AWS PB级数据仓库

什么是一个好的数据仓库?
Redshift是AWS云计算中的一个完全托管的,PB级别规模的数据仓库服务。即使在数据量非常小的时候(比如几百个GB的数据)你就可以开始使用Redshift,Redshift集群可以随着你数据的增加而不断扩容,甚至达到PB级。云计算中数据仓库的优势非常明显,不需要license,不需要预先配置非常大的数据仓库集群,扩容简单,仅仅需要为你实际所使用的数据仓库付费。
Redshift作为一个企业级数据仓库完全支持SQL语法,无学习成本,支持很多种客户端连接,包括各种市场上的BI工具,报表以及数据分析工具。

Redshift的概览
Redshift通过支持大规模并行处理(MPP),列式存储,对不同列数据使用不同数据压缩算法,关系型数据仓库(SQL),灵活的扩容管理等众多优点,兼顾了数仓性能,同时也考虑学习成本及使用成本。

Redshift系统架构及要点
图1,Redshift系统架构图

  • 主节点负责客户端与计算节点之间的所有通讯,编译代码并负责将编译好的代码分发给各个计算节点处理,负责分配数据到不同的计算节点,主节点对客户不可见的,无需客户管理主节点的压力,更重要的是主节点免费。
  • 计算节点是具体的干活的,并处理好的任务送给主节点进行合并后返回给客户端应用程序。每个计算节点都有自己独立的CPU,内存以及直连存储。Redshift集群规模大小通常就是指计算节点的个数以及计算节点机器类型。
  • 节点分片是指将计算节点被分成若干的分片,根据计算节点类型不同,每个节点包含的分片数量不同,通常1个vCPU对应一个分片,ds2的机型除外。每个分片都会分配独立的内存及存储资源,接受来自主节点分配的任务。分片跟另外一个重要概念Dist Key紧密相关, 这里先提一下,接下来会具体介绍Dist Key。
  • 排序键(Sort Key)是一个顺序键,即Redshift会根据这个键来将数据按顺序存储在硬盘上。Redshift的查询优化程序(只要理解有这么个东西存在就好,客户不需要任何维护,对客户也是透明的)也会根据这个排序来进行执行查询优化计划。这是Redshift性能调优的一个非常重要的参数。
  • 分配键(Distribution Key)是控制加载到表的数据如何分布在各个计算节点的一个键,有好几种分布的风格,接下来会重点讲到,这是Redshift调优的非常重要的另外一个参数。

Redshift的几个常用最佳实践
选择最佳排序键

  • 如果最近使用的数据查询频率最高,则指定时间戳列作为排序键的第一列;
  • 如果您经常对某列进行范围筛选或相等性筛选,则指定该列作为排序键;
  • 如果您频繁联接表,则指定联接列作为排序键和分配键;

熟悉Redshift的朋友可能知道可以指定多列作为排序键,而且排序键还有两种方式,组合式和交叉式。限于篇幅的原因,在接下来的调优测试中我们采用的是某一列作为排序键,如果有对其他排序键风格感兴趣的朋友,可以单独联系我们进行讨论。

选择最佳分配键

选择表分配方式的目的是通过在执行查询前将数据放在需要的位置来最大程度地减小重新分配步骤的影响,最好这个查询不需要二次移动数据。

分配键有三种风格,均匀分布(Even),键分布(Key),全分布(All),默认是均匀分布。

  • 根据共同列分配事实数据表和一个维度表;

事实数据表只能有一个分配键。任何通过其他键联接的表都不能与事实数据表并置。根据联接频率和联接行的大小选择一个要并置的维度。将维度表的主键和事实数据表对应的外键指定为 DISTKEY。

  • 根据筛选的数据集的大小选择最大的维度;

只有用于联接的行需要分配,因此需要考虑筛选后的数据集的大小,而不是表的大小。

  • 在筛选结果集中选择基数高的列;

例如,如果您在日期列上分配了一个销售表,您可能获得非常均匀的数据分配,除非您的大多数销售都是季节性的。但是,如果您通常使用范围受限谓词进行筛选以缩小日期期间的范围,则大多数筛选行将位于有限的一组切片上并且查询工作负载将偏斜。

  • 将一些维度表改为使用 ALL 分配;

如果一个维度表不能与事实数据表或其他重要的联接表并置,您可以通过将整个表分配到所有节点来大大提高查询性能。使用 ALL 分配会使存储空间需求成倍增长,并且会增加加载时间和维护操作,所以在选择 ALL 分配前应权衡所有因素。

优化COPY,提高数据加载速度
当你将要数据加载到Redshift的某个表时,不要让单个输入文件过大,最好是将这些输入文件切成多份,具体数量最好是跟分片数量匹配,这样可以充分利用所有分片,配合分配键能达到最佳效果。

图2,COPY输入的最优方式

让COPY选择自动压缩
作为数据仓库,Redshift通常会需要大量导入数据,这时使用做多的,效率最好的是COPY命令。在使用COPY时建议将COMPUPDATE参数设置为ON,这样数据在加载进库时是自动压缩的,好处是可以节省存储空间,提高查询的速度,不过这会增加数据加载进表的时间,这个可以根据你的业务需求,再具体衡量。

Redshift调优实战
测试结论

  1. 选择合适的排序键,分配键,及自动压缩对表的查询速度,存储效率很大提升。本次测试中,优化后查询速度有高达75%的提升,存储空间节省50%。
  2. 相同节点类型情况下,多节点性能比单节点性能提升明显。本次测试中,采用了4节点与单节点对比,4节点查询速度比单节点提升75%。
  3. 节点数量相同的情况下,dc系列节点的查询速度比ds系列节点的查询速度要快。本次测试中,采用了dc1.large和ds1.xlarge两种节点类型进行对比,dc系列节点的查询速度比ds系列快20% 。
  4. 使用JOIN与不使用JOIN查询速度无明显差别。本次测试中,三个不同的查询及对应的JOIN查询,在查询速度上的差别非常小。这部分的详细测试结果,请参见附录一。
  5. 查询速度达到一定值时,再增加节点对查询优化的效果有限。本次测试中,在相同环境中,将节点数量从8个dc1.large节点增加到12个dc1.large节点,三个查询只有一个查询的速度有一定提升,其他2个查询速度基本没有太大变化。这部分的详细测试结果,请参见附录二。

图3,调优前后性能对比图

备注:性能对比图从三个方面进行了对比,数据加载速度表存储空间查询的速度。本次测试的原始数据放在AWS Oregon S3,Redshift也在Oregon区域。

 

测试场景
表1,本次测试中用到的表及表的大小

图4,本次测试中表之间的关系

测试步骤

注意:本次测试步骤已假设Redshift集群已启动,且用户知道如何通过JDBC方式连接Redshift集群。

Before(不做任何优化):

  1. 创建表(不指定排序键和分配键);
  2. 加载数据(不进行自动压缩);
  3. 查询Redshift中各个表的存储空间;
  4. 执行三种不同查询,均取第2次查询所耗时间;
  5. 相同条件,使用JOIN查询所耗时间;

After(指定排序键和分配键,加载数据时进行了自动压缩):

  1. 删除表;
  2. 创建表(指定排序键和分配键);
  3. 加载数据(根据不同数据类型选择合适的压缩算法);
  4. 查询Redshift中各个表的存储空间;
  5. 执行三种不同查询,均取第2次查询所耗时间;
  6. 相同条件,使用JOIN查询所耗时间;

测试截图
图5,单个节点(ds1.xlarge)的数据加载时间(优化前)

图6,单个节点(ds1.xlarge)的数据加载时间(优化后)

图7,单个节点(ds1.xlarge)的数据存储空间(优化前)

图8,单个节点(ds1.xlarge)的数据存储空间(优化后)

图9,单个节点(ds1.xlarge)的查询时间(优化前)

图10,单个节点(ds1.xlarge)的查询时间(优化后)

图11,4个节点(ds1.xlarge)的数据加载时间(优化前)

图12,4个节点(ds1.xlarge)的数据加载时间(优化后)

图13,4个节点(ds1.xlarge)的数据存储空间(优化前)

图14,4个节点(ds1.xlarge)的数据存储空间(优化后)

图15,4个节点(ds1.xlarge)的查询时间 (优化前)

图16,4个节点(ds1.xlarge)的查询时间 (优化后)

图17,4个节点(dc1.large)的数据加载时间 (优化前)

图18,4个节点(dc1.large)的数据加载时间 (优化后)

图19,4个节点(dc1.large)的数据存储空间 (优化前)

图20,4个节点(dc1.large)的数据存储空间 (优化后)

图21,4个节点(dc1.large)的查询时间 (优化前)

图22,4个节点(dc1.large)的查询时间 (优化后)

 

本次测试中用到的命令参数
Before (优化前)

CREATE TABLE part

(

p_partkey     INTEGER NOT NULL,

p_name        VARCHAR(22) NOT NULL,

p_mfgr        VARCHAR(6) NOT NULL,

p_category    VARCHAR(7) NOT NULL,

p_brand1      VARCHAR(9) NOT NULL,

p_color       VARCHAR(11) NOT NULL,

p_type        VARCHAR(25) NOT NULL,

p_size        INTEGER NOT NULL,

p_container   VARCHAR(10) NOT NULL

);

CREATE TABLE supplier

(

s_suppkey   INTEGER NOT NULL,

s_name      VARCHAR(25) NOT NULL,

s_address   VARCHAR(25) NOT NULL,

s_city      VARCHAR(10) NOT NULL,

s_nation    VARCHAR(15) NOT NULL,

s_region    VARCHAR(12) NOT NULL,

s_phone     VARCHAR(15) NOT NULL

);

CREATE TABLE customer

(

c_custkey      INTEGER NOT NULL,

c_name         VARCHAR(25) NOT NULL,

c_address      VARCHAR(25) NOT NULL,

c_city         VARCHAR(10) NOT NULL,

c_nation       VARCHAR(15) NOT NULL,

c_region       VARCHAR(12) NOT NULL,

c_phone        VARCHAR(15) NOT NULL,

c_mktsegment   VARCHAR(10) NOT NULL

);

CREATE TABLE dwdate

(

d_datekey            INTEGER NOT NULL,

d_date               VARCHAR(19) NOT NULL,

d_dayofweek          VARCHAR(10) NOT NULL,

d_month              VARCHAR(10) NOT NULL,

d_year               INTEGER NOT NULL,

d_yearmonthnum       INTEGER NOT NULL,

d_yearmonth          VARCHAR(8) NOT NULL,

d_daynuminweek       INTEGER NOT NULL,

d_daynuminmonth      INTEGER NOT NULL,

d_daynuminyear       INTEGER NOT NULL,

d_monthnuminyear     INTEGER NOT NULL,

d_weeknuminyear      INTEGER NOT NULL,

d_sellingseason      VARCHAR(13) NOT NULL,

d_lastdayinweekfl    VARCHAR(1) NOT NULL,

d_lastdayinmonthfl   VARCHAR(1) NOT NULL,

d_holidayfl          VARCHAR(1) NOT NULL,

d_weekdayfl          VARCHAR(1) NOT NULL

);

CREATE TABLE lineorder

(

lo_orderkey          INTEGER NOT NULL,

lo_linenumber        INTEGER NOT NULL,

lo_custkey           INTEGER NOT NULL,

lo_partkey           INTEGER NOT NULL,

lo_suppkey           INTEGER NOT NULL,

lo_orderdate         INTEGER NOT NULL,

lo_orderpriority     VARCHAR(15) NOT NULL,

lo_shippriority      VARCHAR(1) NOT NULL,

lo_quantity          INTEGER NOT NULL,

lo_extendedprice     INTEGER NOT NULL,

lo_ordertotalprice   INTEGER NOT NULL,

lo_discount          INTEGER NOT NULL,

lo_revenue           INTEGER NOT NULL,

lo_supplycost        INTEGER NOT NULL,

lo_tax               INTEGER NOT NULL,

lo_commitdate        INTEGER NOT NULL,

lo_shipmode          VARCHAR(10) NOT NULL

);

copy customer from ‘s3://lyz/redshift/customer’

credentials ‘aws_access_key_id= your-key;aws_secret_access_key=your-secret-key’

gzip compupdate off region ‘us-west-2’;

 

copy dwdate from ‘s3://lyz/redshift/dwdate’

credentials ‘aws_access_key_id= your-key;aws_secret_access_key= your-secret-key ‘

gzip compupdate off region ‘us-west-2’;

 

copy lineorder from ‘s3://lyz/redshift/lineorder’

credentials ‘aws_access_key_id= your-key;aws_secret_access_key= your-secret-key ‘

gzip compupdate off region ‘us-west-2’;

 

copy part from ‘s3://lyz/redshift/part’

credentials ‘aws_access_key_id= your-key;aws_secret_access_key= your-secret-key ‘

gzip compupdate off region ‘us-west-2’;

 

copy supplier from ‘s3://lyz/redshift/supplier’

credentials ‘aws_access_key_id= your-key;aws_secret_access_key= your-secret-key ‘

gzip compupdate off region ‘us-west-2’;

 

select count(*) from LINEORDER;

select count(*) from PART;

select count(*) from  CUSTOMER;

select count(*) from  SUPPLIER;

select count(*) from  DWDATE;

 

select stv_tbl_perm.name as table, count(*) as mb

from stv_blocklist, stv_tbl_perm

where stv_blocklist.tbl = stv_tbl_perm.id

and stv_blocklist.slice = stv_tbl_perm.slice

and stv_tbl_perm.name in (‘lineorder’,’part’,’customer’,’dwdate’,’supplier’)

group by stv_tbl_perm.name

order by 1 asc;

 

— Query 1

— Restrictions on only one dimension.

select sum(lo_extendedprice*lo_discount) as revenue

from lineorder, dwdate

where lo_orderdate = d_datekey

and d_year = 1997

and lo_discount between 1 and 3

and lo_quantity < 24;

 

— Query 2

— Restrictions on two dimensions

 

select sum(lo_revenue), d_year, p_brand1

from lineorder, dwdate, part, supplier

where lo_orderdate = d_datekey

and lo_partkey = p_partkey

and lo_suppkey = s_suppkey

and p_category = ‘MFGR#12’

and s_region = ‘AMERICA’

group by d_year, p_brand1

order by d_year, p_brand1;

 

— Query 3

— Drill down in time to just one month

 

select c_city, s_city, d_year, sum(lo_revenue) as revenue

from customer, lineorder, supplier, dwdate

where lo_custkey = c_custkey

and lo_suppkey = s_suppkey

and lo_orderdate = d_datekey

and (c_city=’UNITED KI1′ or

c_city=’UNITED KI5′)

and (s_city=’UNITED KI1′ or

s_city=’UNITED KI5′)

and d_yearmonth = ‘Dec1997’

group by c_city, s_city, d_year

order by d_year asc, revenue desc;

After(优化后):

drop table part cascade;

drop table supplier cascade;

drop table customer cascade;

drop table dwdate cascade;

drop table lineorder cascade;

 

CREATE TABLE part (

p_partkey     integer             not null sortkey distkey,

p_name        varchar(22)      not null,

p_mfgr           varchar(6)      not null,

p_category    varchar(7)      not null,

p_brand1      varchar(9)      not null,

p_color          varchar(11)      not null,

p_type           varchar(25)      not null,

p_size            integer             not null,

p_container   varchar(10)     not null

);

 

CREATE TABLE supplier (

s_suppkey                 integer        not null sortkey,

s_name        varchar(25)    not null,

s_address     varchar(25)    not null,

s_city             varchar(10)    not null,

s_nation         varchar(15)    not null,

s_region        varchar(12)    not null,

s_phone       varchar(15)    not null)

diststyle all;

 

CREATE TABLE customer (

c_custkey     integer        not null sortkey,

c_name        varchar(25)    not null,

c_address     varchar(25)    not null,

c_city             varchar(10)    not null,

c_nation         varchar(15)    not null,

c_region        varchar(12)    not null,

c_phone       varchar(15)    not null,

c_mktsegment      varchar(10)    not null)

diststyle all;

 

CREATE TABLE dwdate (

d_datekey            integer       not null sortkey,

d_date               varchar(19)   not null,

d_dayofweek       varchar(10)   not null,

d_month            varchar(10)   not null,

d_year               integer       not null,

d_yearmonthnum       integer            not null,

d_yearmonth          varchar(8)           not null,

d_daynuminweek       integer       not null,

d_daynuminmonth      integer       not null,

d_daynuminyear       integer       not null,

d_monthnuminyear     integer       not null,

d_weeknuminyear      integer       not null,

d_sellingseason      varchar(13)    not null,

d_lastdayinweekfl    varchar(1)    not null,

d_lastdayinmonthfl   varchar(1)    not null,

d_holidayfl          varchar(1)    not null,

d_weekdayfl          varchar(1)    not null)

diststyle all;

 

CREATE TABLE lineorder (

lo_orderkey                   integer         not null,

lo_linenumber           integer             not null,

lo_custkey                 integer             not null,

lo_partkey                  integer             not null distkey,

lo_suppkey                integer             not null,

lo_orderdate              integer             not null sortkey,

lo_orderpriority          varchar(15)     not null,

lo_shippriority            varchar(1)      not null,

lo_quantity                 integer             not null,

lo_extendedprice       integer             not null,

lo_ordertotalprice      integer             not null,

lo_discount                integer             not null,

lo_revenue                integer             not null,

lo_supplycost            integer             not null,

lo_tax                         integer             not null,

lo_commitdate         integer         not null,

lo_shipmode              varchar(10)     not null

);

 

copy customer from ‘s3://lyz/redshift/customer’

credentials ‘aws_access_key_id=your-key;aws_secret_access_key=your-secret-key’

gzip region ‘us-west-2’;

 

copy dwdate from ‘s3://lyz/redshift/dwdate’

credentials ‘aws_access_key_id= your-key;aws_secret_access_key= your-secret-key ‘

gzip region ‘us-west-2’;

 

copy lineorder from ‘s3://lyz/redshift/lineorder’

credentials ‘aws_access_key_id= your-key;aws_secret_access_key= your-secret-key ‘

gzip region ‘us-west-2’;

 

copy part from ‘s3://lyz/redshift/part’

credentials ‘aws_access_key_id= your-key;aws_secret_access_key= your-secret-key ‘

gzip region ‘us-west-2’;

 

copy supplier from ‘s3://lyz/redshift/supplier’

credentials ‘aws_access_key_id= your-key;aws_secret_access_key= your-secret-key ‘

gzip region ‘us-west-2’;

 

select stv_tbl_perm.name as table, count(*) as mb

from stv_blocklist, stv_tbl_perm

where stv_blocklist.tbl = stv_tbl_perm.id

and stv_blocklist.slice = stv_tbl_perm.slice

and stv_tbl_perm.name in (‘lineorder’,’part’,’customer’,’dwdate’,’supplier’)

group by stv_tbl_perm.name

order by 1 asc;

 

— Query 1

— Restrictions on only one dimension.

select sum(lo_extendedprice*lo_discount) as revenue

from lineorder, dwdate

where lo_orderdate = d_datekey

and d_year = 1997

and lo_discount between 1 and 3

and lo_quantity < 24;

 

— Query 2

— Restrictions on two dimensions

 

select sum(lo_revenue), d_year, p_brand1

from lineorder, dwdate, part, supplier

where lo_orderdate = d_datekey

and lo_partkey = p_partkey

and lo_suppkey = s_suppkey

and p_category = ‘MFGR#12’

and s_region = ‘AMERICA’

group by d_year, p_brand1

order by d_year, p_brand1;

 

— Query 3

— Drill down in time to just one month

 

select c_city, s_city, d_year, sum(lo_revenue) as revenue

from customer, lineorder, supplier, dwdate

where lo_custkey = c_custkey

and lo_suppkey = s_suppkey

and lo_orderdate = d_datekey

and (c_city=’UNITED KI1′ or

c_city=’UNITED KI5′)

and (s_city=’UNITED KI1′ or

s_city=’UNITED KI5′)

and d_yearmonth = ‘Dec1997’

group by c_city, s_city, d_year

order by d_year asc, revenue desc;

附录一
图23,查询1所耗时间,8节点(dc1.large)

图24,查询1使用JOIN所耗时间,8节点(dc1.large)

图25,查询2所耗时间,8节点(dc1.large)

图26,查询2使用JOIN所耗时间,8节点(dc1.large)

图27,查询3所耗时间,8节点(dc1.large)

图28,查询3使用JOIN所耗时间,8节点(dc1.large)

附录二
图29,查询1所耗时间,12节点(dc1.large)

图30,查询2所耗时间,12节点(dc1.large)

图31,查询3所耗时间,12节点(dc1.large)

作者介绍:

郑进佳

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

 

 

 

分布式神经网络框架 CaffeOnSpark在AWS上的部署过程

一、介绍
Caffe 是一个高效的神经网络计算框架,可以充分利用系统的GPU资源进行并行计算,是一个强大的工具,在图像识别、语音识别、行为分类等不同领域都得到了广泛应用。有关Caffe的更多内容请参考项目主页:

http://caffe.berkeleyvision.org/

不过Caffe的常用部署方式是单机的,这就意味着它的水平扩展能力受到了限制。使用者可以通过在系统中添加多个GPU的方式提高并发度,不过其并发能力最终受到单系统可支撑的GPU数量的限制。同时,神经网络计算往往又是计算消耗很大的,所以人们在使用Caffe的时候都可能会希望有一种并行计算框架可以支持Caffe。

而我们知道Spark是基于内存的计算框架,基于Yarn, Mesos或者是Standalone模式,它可以充分利用多实例计算资源。因此,如果能够结合Caffe和Spark,Caffe的能力将得到更充分的发挥。 基于这些原因,Yahoo开源的CaffeOnSpark框架受到的极大的关注。

有关CaffeOnSpark的源代码和相关文档,请大家参考:

https://github.com/yahoo/CaffeOnSpark

今天我们要进一步讨论的是如何在AWS EC2上部署CaffeOnSpark, 充分利用AWS服务提供的GPU实例构建强大的分布式神经网络计算框架。

在CaffeOnSpark的文档中有明确指出EC2上部署CaffeOnSpark的步骤,具体请参考:

https://github.com/yahoo/CaffeOnSpark/wiki/GetStarted_EC2

但是文档的一些部分写得比较简单,初步接触的读者可能在执行过程中遇到一些问题,所以在这里将我个人的安装配置过程整理了一下供大家参考。

安装过程大概可以分为四部分:

下面会在“环境准备”一节中具体描述这几个步骤的细节。

二、环境准备
首先我们打开文档https://github.com/yahoo/CaffeOnSpark/wiki/GetStarted_EC2, 看看文档中刚开始的部分对于环境准备的要求。

里面首先提到我们需要准备“EC2 Key pair”, 就是要准备EC2启动需要的密钥对。当然,为了创建“EC2 Key pair”,为了启动EC2,你首先需要一个AWS账号。有关AWS账号的申请和基本使用这里就不细述了,请参考其它相关文档。需要注意的是你拿到的AWS账号需要有基本的权限才能完成CaffeOnSpark的安装工作,其中包括创建EC2实例,创建安全组等。

“EC2 Key pair”是你在创建EC2实例时创建的密钥对,创建过程中你有一次机会下载私钥文件,就是文中提到的pem文件。如果你之前没有创建过EC2,你也可以直接在EC2控制台的“网络与安全->密钥对”界面中点击“创建密钥对”按钮进行创建。同样,创建过程中你有一次机会下载pem文件,下载后注意保管好该文件,后面都会依赖这个文件。

按文档的描述,有了以上的资源以后就可以执行以下命令:

为了准备环境,我们需要先理解一下上面的脚本。脚本的刚开始部分是一系列变量的定义,我们先了解这些变量的作用。

第一句比较简单,从变量名可以知道这是指定了要使用的AMI的ID:

这个镜像是一个已经安装好Spark、CaffeOnSpark,并加载了常用神经网络测试数据的Ubuntu镜像。该镜像由CaffeOnSpark团队提供,已经共享给所有AWS账号。

不过稍有AWS使用经验的同学会意识到,这样的命令是针对特定的区域(Region)的,因为同一个AMI镜像拷贝到不同AWS区域时它们的AMI ID是不一样的。在命令行中如果指定了一个AMI的ID,就意味着这些命令只能在特定的AWS区域正常工作。

所以我们需要继续查看后续命令,看看哪里指定了区域。幸运的是,命令的第二行就是指定区域的命令:

我们知道区域代码“eu-west-1”指的是欧洲(爱尔兰) 区域,意味着我们运行完这个样例后我们的CaffeOnSpark群集是运行在欧洲(爱尔兰) 区域的。因为EC2 key pair也是按区域分的,所以我们创建的EC2 key pair也应该是在欧洲(爱尔兰) 区域。

为了在欧洲(爱尔兰) 区域创建你的EC2 key pair,你可以点击AWS控制台右上角的区域选择框,选择欧洲(爱尔兰) 区域,然后再按步骤进入EC2的控制台创建EC2 key pair.

同时,你也可以去EC2控制台的“映像->AMI”界面查找镜像ID为ami-5ff7782c的镜像,记得查看时选择“映像类型”为“公有映像”,而不是“我拥有的”。找到这个镜像你还可以仔细查看一下其它相关信息。

如果你发现镜像列表中没有ID为ami-5ff7782c的镜像,有可能你阅读本文的时候相关方已经更新了新的镜像,你可以去CaffeOnSpark的主页

https://github.com/yahoo/CaffeOnSpark 找到更新版本的指导,获得新的镜像ID。

进一步往下看可以看到指定AZ的命令行:

其中eu-west-1c代表c可用区,有关可用区的相关概念在这里也不细述了,对可用区(AZ)概念有疑惑的同学请参考其它AWS基础文档。

再往下是指定worker数量的命令:

表示这个群集需要两个工作实例,需要注意的是创建的Spark群集中有一个主实例,多个工作实例,其中主实例会使用一般的实例类型,而工作实例会使用GPU实例。这里的参数就表示希望启动两个GPU实例作为工作实例。

我们知道,AWS上的GPU实例也有类型之分,现在可以使用的GPU类型有g2.2xlarge和g2.8xlarge两种,到底工作实例会使用什么GPU类型呢,下面的参数就是为了指定工作实例的实例类型。可以选择g2.2xlarge或者是g2.8xlarge。注意下面两行中第二行被注释掉了,表示只有第一句生效,就是使用g2.2xlarge实例类型。

接着是指定竞价实例的最高价格,有关竞价实例的细节请参考AWS相关文档,使用竞价实例大概就是设定一个可以接受的价格去参加实例拍卖的竞价,如果你的出价比别人高你就可以拍得实例。下面这句就是设置竞价为0.8美金每小时:

后面我们继续分析命令会知道,后续执行命令的时候会使用下面的参数,表示希望使用竞价实例作为工作实例。但是这不是CaffeOnSpark所必须的,如果你不希望使用竞价实例,可以不使用以下参数,这样就可以使用“按需实例(OnDemand)”了。

接着就是运行真正的命令了,运行的命令是:

后面带有许多参数,在具体了解不同参数的作用前,我们先得思考,这个spark-ec2命令从哪里来? 如果你之前曾经安装过Spark,在你的Spark主目录里就可以找到ec2目录,里面有spark-ec2命令。 我自己的环境中曾经安装过Spark 1.5,所以也可以找到这个ec2/spark-ec2命令,不过如果我尝试去执行这里的这些命令的话会报错,报“不可知的Spark版本”错误。原因是这里的脚本指定目标Spark是1.6.0, 但是我们运行的Spark是1.5,所以会报错。所以我重新启动了一个新的实例安装了Spark 1.6,以执行spark-ec2命令。有关Spark 1.6的安装,下面的章节会有介绍部分安装过程,现在我们先看看这里spark-ec2命令的不同参数有什么:

其中–key-pair和–identity-file是用来指定EC2 key pair的,就是EC2要使用的密钥,–key-pair用于指定密钥的名称,–identity-file用于指定密钥的pem文件的路径:

接着 –ebs-vol-size是用于指定EBS卷大小的,这里设置了50G,因为镜像大小的原因,你不能把–ebs-vol-size设置的太小,这里就是用样例中的50G吧:

接着是通过–instance-type指定工作实例的实例类型,这里是用了前面定义的变量,按前面我们变量的定义,下面的参数会是用g2.2xlarge作为工作实例的实例类型:

接着是通过–master-instance-type参数指定群集主实例的类型,因为主实例不参与神经网络计算,所以主实例可以不用选择GPU实例,这里是用了m4.xlarge:

然后是用–ami参数指定实例创建时是用的镜像ID:

-s参数用于指定工作实例的数量,这里引用了之前定义的参数,我们把它设置成2,就是会启动两个工作实例:

–spot-price就是前面提到的是用竞价实例的参数,如果你不希望是用竞价实例,直接删除这个参数就好了:

–copy-aws-credentials用于指定是否拷贝AWS授权证书,这里不用细究它的作用:

–hadoop-major-version=yarn 和 –spark-version用于指定Hadoop的运行框架信息和Spark的版本:

–no-ganglia 表示不需要使用ganglia


–user-data用于指定实例启动时的需要完成的动作,这个参数非常重要,CaffeOnSpark安装过程中的很多设置都是因为设置了这个“User-Data”才完成的。这里设置的user-data指向CaffeOnSpark目录的scripts子目录中的。这就意味着我们在使用这个命令的时候应该已经拥有CaffeOnSpark的代码了,具体的获取方法在下一节中有详细描述:

最后就是真正“启动”的参数了,这里同时指定了群集的名称,本例为“CaffeOnSparkDemo”,注意,这个群集名称需要是区域内唯一的,如果你希望进行多次测试,又不希望受之前测试的干扰,每次启动时需要在这里设置不同的群集名称:

理解了整个命令,我们再次总结一下我们需要完成的工作:

我们假设你已经做好了a、b两步,下一节会详细讲解步骤c,紧接着第四节会讲解步骤d:测试校验过程

三、安装过程
下面开始详细讲解我的安装过程。

1.    准备工作机

这一步骤就是启动一个EC2,没有什么特别的需要强调。因为平时都习惯使用Amazon Linux,所以我创建工作机时选择了Amazon Linux镜像。另外就是启动这台EC2也需要一个EC2 key pair,这里可以使用上一节提到的准备好的EC2 key pair, 也可以使用其它EC2 key pair。就是说工作机的密钥和CaffeOnSpark群集的密钥没有关系的,你使用同一对密钥可以,使用不同密钥也可以。

2.    安装Spark 1.6

这一步是在工作机上安装Spark 1.6,如果已经有工作机部署好Spark 1.6的就可以跳过这步。当然,如果你很熟悉Spark的安装过程,也可以直接跳过这一小节。

启动EC2工作机后ssh登录到工作机,按习惯先运行了:, 以更新组件。

接着运行了:来安装git命令,后面获取Spark源代码和CaffeOnSpark源代码都用它呢。

然后通过以下命令获得Spark 1.6的稳定版本:

为了编译Spark,你可以使用Maven或者是sbt,我通过以下命令安装了sbt:

在Spark源代码根目录运行:, 让sbt开始下载需要的组件,运行完进入sbt界面的话先退出来。

接着运行以下命令编译Spark:

我编译的是yarn版本,其实在这里参数-Pyarn不是必须的,我只是后续要执行yarn相关的任务,所以选择了带yarn的版本。

另外,你也可以直接运行Spark源代码目录中的生成可部署的版本,完整命令如下:

为了方便以后使用,我将编译好的Spark移动到以下目录:, 接着,修改一下文件,增加Spark路径的设置:

执行命令让配置项直接生效后,你就可以开始测试一下你的Spark了,比如可以直接运行spark-shell试试。

最后,为了确认spark-ec2命令也正常工作,可以去spark安装目录的ec2子目录下执行命令,不带任何参数,系统会返回spark-ec2命令的帮助文字,你也可以顺便了解以下spark-ec2命令的具体使用方法。

3.    下载CaffeOnSpark源码

如上所述,在安装CaffeOnSpark过程中,其中一个关键点就是在群集实例创建时传入了特定的User-Data,这份User-Data就是来自CaffeOnSpark项目的“scripts/ec2-cloud-config.txt”文件。 为了获得这份“scripts/ec2-cloud-config.txt”文件,我们需要下载CaffeOnSpark源码包,当然你也可以单独下载这个文件,不过为了以后的代码学习,建议整个将CaffeOnSpark项目clone下来。 具体命令如下:

下载了CaffeOnSpark源代码后,修改一下~/.bash_profile文件,设置变量指向CaffeOnSpark的源文件目录,方便后续引用。

4.    运行安装命令

后面就可以开始运行安装命令了,其实这里还有几个参数需要设置,不过为了加深印象,我们可以直接运行命令,遇到错误提示时再修改相关参数。

为了运行安装命令,我们创建一个shell文件,比如叫install.sh,里面的内容就是从CaffeOnSpark项目的EC2安装指导中拷贝的。 为了方便大家,再次贴上该文档的链接:

https://github.com/yahoo/CaffeOnSpark/wiki/GetStarted_EC2

然后再重复把安装命令都贴上来:

给install.sh赋予正确的权限后开始运行它:,然后你会看到下面这样的错误:

错误的意思是没有设置 ,相当于没有设置访问AWS的用户名,该命令无法访问AWS。 所以你需要找到你”Access key”和”secret key”。如果你有足够权限,你可以从AWS控制台上为自己创建“Credential”,然后下载”Access key”和”secret key”。或者你的AWS管理员应该给你分配过”Access key”和”secret key”。有关”Access key”和”secret key”就不在这里展开了,如果你对”Access key”和”secret key”的使用还有疑惑,请参考相关文档。

如果你通过export命令设置了 ,但是没有设置,运行命令时会报另一个错误:

相当于是只设置了用户名,没设置密码。

也就是说你需要将你的设置到环境变量里,才能给CaffeOnSpark安装脚本足够的权限。这里再强调一下,你使用的对应的账号本身需要有足够的权限,比如创建EC2的权限,创建安全组的权限等。

设置完”Access key”和”secret key”后,再次运行,你可能会遇到如下错误:

因为样例命令中并没有设置变量和变量,相当于是没有设置密钥名和密钥pem文件路径。

所以你需要定义 变量和变量,一个指向你的密钥名,一个指向你的密钥pem文件路径。

再次运行命令,应该就可以正常开始安装了,安装过程时间比较长,建议启动screen命令后再执行。

运行命令,其实后台调用的是spark-ec2命令,spark-ec2命令会给AWS发送指令,创建指定的实例并完成相关设置工作。

注意,安装过程中有一步会提示是否格式化硬盘之类的提示,需要手工确认后才能继续进行。

最后,如果一切正常,在一系列的日志输出后,你将看到类似下面这样的提示:

这表明CaffeOnSpark安装成功了,你可以启动一个浏览器,访问以上URL进行验证,打开页面后看到的应该是类似以下页面的Spark主页:

同时,你可以通过ssh连接到Spark的主节点上查看相关文件和日志,具体命令类似于:

要注意,用户名使用的是root

四、校验测试
安装好CaffeOnSpark后,你可以从安装日志里找到Spark群集的主节点DNS名称,接着就可以ssh进去测试了。

如我们平常测试Caffe一样,我们可以使用mnist数据集。CaffeOnSpark的镜像中包括了mnist数据集,在目录CaffeOnSpark主目录的data子目录下。

完整的测试脚本如下,其中关键几部分内容后面有详细解释:

首先我们要留意的是下面这两句:

这两句是针对g2.2xlarge写的,有一个GPU设备,8核。

如果是使用g2.8xlarge的化,需要修改成:

就是有4块GPU,32核。

接着是清除HDFS上测试相关的目录:

然后就是关键部分,通过spark-submit命令向spark群集提交任务,运行的是打包好的Caffe网格计算包中的

有关这里spark-submit命令中的细节就不详细说明了,有机会我们在分析CaffeOnSpark使用方法的文章中继续讨论。

最后,运行完spark-submit命令后,通过HDFS命令输出的结果。

如果执行上面的完整脚本的话,你会在命令行会看到类似下面的输出:

恭喜,你已经顺利完成了CaffeOnSpark的安装测试,可以开始你的分布式深度神经网络之旅了。

五、其它
在安装结束后,你就可以开始使用分布式的神经网络框架了。不过,考虑到实际的情况,还是有几个地方可以再稍微展开一下的。

1. AMI镜像

文档中使用的镜像是在欧洲(爱尔兰)区域的,在CaffeOnSpark公开的文档中没有看到其它区域的镜像。所以,如果你希望在其它区域使用CaffeOnSpark,你需要把镜像拷贝到对应的区域,或者是在对应的区域创建CaffeOnSpark镜像。

如果是拷贝镜像,你没有权限直接拷贝镜像ami-5ff7782c。你需要使用镜像ami-5ff7782c创建一个实例,然后对该实例执行镜像操作,最后才把新创建的镜像拷贝到指定区域。

如果你希望在对应区域创建CaffeOnSpark镜像,可以参考官方文档里有关创建CaffeOnSpark镜像的指引文档:

https://github.com/yahoo/CaffeOnSpark/wiki/Create_AMI

按照这个指引,你可以从一个基础版本的Ubuntu开始,自己从头开始创建CaffeOnSpark镜像。

2.    GPU实例情况

你在搭建自己的CaffeOnSpark框架的时候要提前考察目标区域的是否提供GPU实例。

3.    自动化安装过程

我们这次安装CaffeOnSpark使用了Spark里的spark-ec2命令,spark-ec2命令其实调用了spark-ec.py这个Python脚本,如果你打开脚本spark-ec.py,你可以看到整个spark-ec2命令创建Spark群集的过程。

也就是说,如果你在特殊场景下需要手动安装CaffeOnSpark,或者是在安装过程中有特定的动作要执行,你可以参考spark-ec.py的具体实现。

六、总结
工具最终是为目标服务的,当我们有合适的工具使用时,我们可以更好地思考如何实现目标。本文介绍了CaffeOnSpark的安装过程,希望这篇文章可以帮助你快速设置好CaffeOnSpark这个工具,从而可以更好地实现你的目标。

深度神经网络已经被证明是一个有效的机器学习方法,通过CaffeOnSpark和AWS服务,我们可以建构一个巨大的深度神经网络群集。这时候,海量数据的加载和运算都不再是问题,现在唯一的问题就是你要拿深度神经网络解决做什么。

一切都准备好了,出发吧,祝你好运!

作者:

邓明轩

亚马逊AWS解决方案架构师;拥有15年IT 领域的工作经验,先后在IBM,RIM,Apple 等企业担任工程师、架构师等职位;目前就职于AWS,担任解决方案架构师一职。喜欢编程,喜欢各种编程语言,尤其喜欢Lisp。喜欢新技术,喜欢各种技术 挑战,目前在集中精力学习分布式计算环境下的机器学习算法。

打造DIY版Echo:树莓派+ Alexa 语音服务

关于本文
本文详细阐述了如何在Java客户端和Node.js服务器上使用和测试Alexa语音服务。

本实例需要用Node.Js来获取Login的授权码。

本指导提供详细的操作指南对于在取得示例授权码、依赖性和在运行Pi的过程中相应的硬件部署。对于Windows, Mac,或者通用的Linux指令,可以看这里的向导

开始
所需硬件
1. Raspberry Pi 2 (Model B)在亚马逊上购买升级:当然,Raspberry 3也是可以的,请点击这里查看详细操作。Pi的用户-请点击这里来获取帮助。
2. 微型的-USB 电源线 供树莓派来使用(包括在树莓Pi中)
3. 微型的 SD 卡– 需要预装NOOBS – Raspberry Pi 8GB Preloaded (NOOBS) Micro SD Card
4. 网线
5. USB 2.0 小型麦克风 – Raspberry Pi 没有自带麦克风,需要外接来与Alexa进行交互-在亚马逊上购买
6. 外部扬声器3.5mm音频插座/立体声耳机插孔-在亚马逊上购买
7. 一个 USB 鼠标和键盘,以及一个支持HDMI的外部显示器 – 如果由于某种原因无法通过SSH协议进入到你的树莓派时,我们也推荐你使用USB键盘、鼠标和一个便于使用的HDMI显示器。稍后可以查看关于“SSH”协议的内容。
8. 无线WiFi适配器(可选)在亚马逊上购买
所需技能
1. 基础编程知识
2. 熟悉脚本

0 – 设置树莓派

1. 将装好NOOBS的SD卡插入树莓派

2. 插入USB2.0的迷你麦克风和无线wifi适配器(可选)
3. 插入USB的键盘和鼠标.
4. 连接显示器

1 – 启动树莓派

1. 连接电源                                                                                                                                                                                               2. 你的树莓派会启动,并显示可以安装的操作系统列表                                                                                                                 3. 选择Raspbian 并点击 Install

4. Raspbian将会启动安装流程. 注意:这个过程可能会持续一段时间。                                                                                       5. 按照完毕后,配置菜单 (raspi-config) 将会启动. 这里你可以设置一些基本参数:例如启用摄像头 ,然后选择Finish

6. 启动后,登录到你的树莓派,默认用户名是pi,密码是raspberry

更多信息: raspberrypi.org

2 – 安装应用和依赖包

注意: 你需要安装Terminal来安装使用Alexa Voice Services所需的组件. Terminal 是默认安装的,你可以从桌面上进入Terminal。可以点击这里了解更多关于Terminal的信息。

2.1 – 在树莓派上打开 SSH

SSH允许从另一台计算机远程访问的树莓派的命令行(只要它们都在同一网络上)。这样您不需要将您的树莓派连接到外部显示器 。
SSH默认情况下在树莓派是启用的 。如果你在工作的时候遇到一些有关SSH的问题,确保它已经被安装。在使用raspi-config 组件时,确保SSH已经安装好。
在Terminal中输入以下内容:

sudo raspi-config

然后导航到SSH,单击回车选择安装SSH服务器

2.2 – 使用SSH 登录到Raspberry Pi
现在,请SSH到您的树莓派。这样做之前必须确保你已经知道你的树莓派的IP地址。
键入以下命令到终端:
hostname -I
> 192.168.1.10 //this is an example Raspberry Pi’s IP – it would be different for you

如果你是在Windows PC上,按照这的说明SSH Using windows

现在,你知道你的树莓派的IP地址,就可以使用SSH远程连接到它 。要做到这一点,打开电脑上的终端程序 并键入以下内容:

pi@<YOUR Raspberry Pi IP ADDRESS>

它会提示你输入密码。注:为用户PI默认密码为raspberry
现在你可以远程连接到您的树莓派,并可以且通过SSH远程连接你安装所有的工具。

2.3 – 安装VNC服务器

VNC是一个允许远程控制树莓派界面的图片化的桌面分享系统。这会让操作变得很方便由于摆脱了外部的显示器。

sudo apt-get install tightvncserver

打开VNL服务器

请键入:tightvncserver来打开VNC服务器

你将会被要求设置一个密码。当你需要远程连接到树莓派时,请执行该操作。

在启动时运行VNC服务器

如果你想确保在你重启树莓派之后,VNC服务器会自动启动,请键入以下脚本:

cd /home/pi

cd .config

注意:确保“.”在文件夹前面。这使文件夹成为一个隐藏的文件夹。

mkdir autostart

cd autostart

通过键入以下命令,创建一个新的配置:

nano tightvnc.desktop

编辑文件中的以下文本:

[Desktop Entry]

Type=Application

Name=TightVNC

Exec=vncserver :1

StartupNotify=false

按住ctrl-X后在键入Y来保存更改。

这样的话,下一次你重启VNC服务器时将会自动刷新。

通过VNC服务器连接到树莓派

Mac系统: 请参阅 https://www.raspberrypi.org/documentation/remote-access/vnc/mac.md
Windows系统: https://www.raspberrypi.org/documentation/remote-access/vnc/windows.md
Linux系统: https://www.raspberrypi.org/documentation/remote-access/vnc/linux.md
(如果你喜欢的话)你现在可以不需要连接到显示器,鼠标键盘.随着SSH和VNC的安装, 外部显示器是可选择的。通过树莓派来感受自由吧。

2.4 – 安装VLC
通过输入下面命令获取VLC媒体播放器:
sudo apt-get install vlc-nox vlc-data
注意:如果你正在运行树莓派或者已经安装了VLC,你需要执行以下的命令来移除这俩个相冲突的库文件。
sudo apt-get remove –purge vlc-plugin-notify

sudo rm /usr/lib/vlc/plugins/codec/libsdl_image_plugin.so

无法获取错误:在你安装VLC时,遇到无法获取的错误时,尝试输入以下代码

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install vlc-nox vlc-data

注意:运行”sudo apt-get upgrade”脚本时可能会花费一段时间,请耐心等待
源: https://www.raspberrypi.org/forums/viewtopic.php?f=66&t=67399

确保VLC安装成功

whereis vlc
这条命令会告诉你VLC的安装位置.

大多数的项目会存在/usr/bin中

一般会显示下面的结果
vlc: /usr/bin/vlc /usr/lib/vlc /usr/share/vlc /usr/share/man/man1/vlc.1.gz

设置VLC的环境变量

敲入以下命令:

export LD_LIBRARY_PATH=/usr/lib/vlc
export VLC_PLUGIN_PATH=/usr/lib/vlc/plugins

查看环境变量是否生效

echo $LD_LIBRARY_PATH
> /usr/lib/vlc

echo $VLC_PLUGIN_PATH
> /usr/lib/vlc/plugins

2.5 – 下载并安装 Node.js
确认Node.JS 还没有被安装

node -v
> command not found
然后输入:

sudo apt-get update
sudo apt-get upgrade
设置apt-get  repo的源:

curl -sL https://deb.nodesource.com/setup | sudo bash –
安装Node:

sudo apt-get install nodejs

2.6 – 安装JDK环境
你需要安装 Java Development Kit (JDK) version 8 或者更高.

步骤1: 从Oracle的网站下载 JDK 8.

下载 Linux ARM 32 Soft Float ABI (文件名jdk-8u77-linux-arm32-vfp-hflt.tar.gz)

注意:虽然苹果和一些智能手机有用64位的ARMv8,但是到现在为止没有树莓的64-位ARM的处理器在pis系统上可用

步骤 2: 解压内容 解压缩并安装到 /opt 目录下:

sudo tar zxvf jdk-8u77-linux-arm32-vfp-hflt.tar.gz -C /opt

设置默认Java环境到jdk1.8

sudo update-alternatives –install /usr/bin/javac javac /opt/jdk1.8.0_77/bin/javac 1

sudo update-alternatives –install /usr/bin/java java /opt/jdk1.8.0_77/bin/java 1

sudo update-alternatives –config javac
sudo update-alternatives –config java
注意:如果被要求选择一个可替换,请键入你刚刚安装的相对应的jdk 版本号-例如-jdk1.8.0_77

通过下面的命令确认版本:

java -version
javac -version

2.7 – 安装Maven
步骤 1: 下载 Maven

从以下链接下载apache-maven-3.3.9-bin.tar.gz文件

https://maven.apache.org/download.cgi

步骤 2:解压内容  解压压缩包的内容到 /opt 目录中

sudo tar zxvf apache-maven-3.3.9-bin.tar.gz -C /opt

步骤 3:告诉你的命令解析器在哪里找到maven  由于将在系统配置文件中设置这些,因此这对所有用户可用

创建一个新的文件 /etc/profile.d/maven.sh, 然后在里面输入以下内容:

export M2_HOME=/opt/apache-maven-3.3.9
export PATH=$PATH:$M2_HOME/bin
保存这个文件。退出并退回到树莓派中然后内容脚本就会生效,可以输入以下代码来进行测试:

mvn -version

3 – 开始使用Alexa的语音服务

3.1 – 注册一个免费的亚马逊开发者帐户

获取免费亚马逊开发者账户

3.2 – 下载对树莓派示例应用程序代码和依赖

下载示例应用程序从Github repo上下载zip文件。如果要下载这个包,您必须同意Alexa的语音服务协议

3.3 – 复制并解压你的树莓派.zip文件

1.直接下载你的树莓派的zip文件,复制,然后解压您的树莓派的zip文件。                                                                                   2.请在您的树莓派记下它的位置。进一步的说明将把这个位置<REFERENCE_IMPLEMENTATION>

3.4 – 注册产品并创建一个安全配置文件

1.登录亚马逊开发者门户网站 – developer.amazon.com                                                                                                                   2.单击应用和服务选项卡 – > Alexa的 – > Alexa的语音服务 – >入门

3.在注册产品类型菜单中,选择Device。

4.填写并保存以下值:

设备类型信息

1.设备型号ID:my_device

2.显示名称:My Device

3.单击下一步

安全配置文件

1.单击安全配置文件下拉菜单中选择“创建一个新的配置文件

2.常规选项卡

o安全配置文件名称:Alexa的语音服务示例应用程序安全配置文件

o安全配置文件说明:Alexa的语音服务示例应用程序安全配置文件说明

o单击下一步

客户端ID和客户端密钥会为你生成。

1.现在点击网络设置选项卡

o确保您刚才创建的下拉菜单中选择安全配置文件,然​​后单击“编辑”按钮。

o允许的来源:点击“添加另一个”,然后输入https://本地主机IP:3000

o允许返回网址:点击“添加另一个”,然后输入https://本地主机: 3000 / authresponse

o单击下一步

设备详细信息

1.图像:以下测试图像保存到电脑上,然后上传:

2.分类:其它                                                                                                                                                                                             3.说明:Alexa的语音服务的示例应用程序测试                                                                                                                      4.你对商业化的预期时间是多久?:长4个多月/ TBD您的预计时间表                                                                                        5.有多少设备,你打​​算商业化?:0                                                                                                                                                        6.单击下一步

亚马逊音乐

1.启用亚马逊音乐?:否(您可以选择选择是,如果你想与亚马逊的音乐实验中填写必填字段。但是,亚马逊音乐不要求 使用Alexa的语音服务。)                                                                                                                                                                       2.单击提交按钮

您现在可以生成自签名的证书。

4 – 生成自签名证书

步骤1: 安装 SSL

sudo apt-get install openssl

验证安装

whereis openssl
> openssl: /usr/bin/openssl /usr/share/man/man1/openssl.lssl.gz
修改目录到 <REFERENCE_IMPLEMENTATION>/samples/javaclient.

cd <REFERENCE_IMPLEMENTATION>/samples/javaclient – //your sample apps location

步骤2: 修改SSL配置文件: ssl.cnf, 将所有YOUR_开头的变量值替换为真实值.

Note that countryName must be two characters. If it is not two characters, certificate creation will fail. Here’s what the ssl.cnf file would look like, replacing country, state, locality with your respective info.

请您注意国家名必须是俩个字符。如果不是俩个字符,证书可能会创建失败。单击这里你将会看到ssl.cnf是什么样子的,替换你相对应的国家、洲、地区的信息

步骤3: 将下面文件设置为可执行的属性:

chmod +x generate.sh

步骤4: 运行脚本,生成证书:

./generate.sh

步骤 5: 过程中你会被提示输入一些信息:

1.提示输入product ID, 请输入my_device
2.提示输入 serial number, 请输入123456
3.提示输入password, 请输入你希望的密码 ,例如: talktome (也可以留空)

步骤6: 编辑Node.js server 的配置文件

文件的位置在:

<REFERENCE_IMPLEMENTATION>/samples/companionService/config.js.
进行下列变更:

  • 设置sslKey to                                                                                                                 <REFERENCE_IMPLEMENTATION>/samples/javaclient/certs/server/node.key
  • 设置sslCert to                                                                                                              <REFERENCE_IMPLEMENTATION>/samples/javaclient/certs/server/node.crt
  • 设置sslCaCert to                                                                                                 <REFERENCE_IMPLEMENTATION>/samples/javaclient/certs/ca/ca.crt

注意: 不要使用 ~ 来代表根目录. 必须使用绝对路径.

因此, 不使用~/documents/samples, 而用/home/pi/documents/samples.

步骤7:编辑JAVA客户端的配置文件

这个配置文件在以下位置:

<REFERENCE_IMPLEMENTATION>/samples/javaclient/config.json.

做出以下配置:

  • 设置companionApp.sslKeyStore 到                                                          <REFERENCE_IMPLEMENTATION>/samples/javaclient/certs/server/jetty.pkcs12
  • 设置companionApp.sslKeyStorePassphrase 到                                                                                                                      上述第五步中证书生成代码中的密码
  • 设置companionService.sslClientKeyStore 到                                                              <REFERENCE_IMPLEMENTATION>/samples/javaclient/certs/client/client.pkcs12
  • 设置companionService.sslClientKeyStorePassphrase到                                                                                                       上述第五步中证书生成代码中的密码
  • 设置companionService.sslCaCert to到                                                       <REFERENCE_IMPLEMENTATION>/samples/javaclient/certs/ca/ca.crt

5 – 安装依赖包
更改目录到 <REFERENCE_IMPLEMENTATION>/samples/companionService

cd <REFERENCE_IMPLEMENTATION>/samples/companionService
输入下列命令来安装依赖包:

npm instal

6 -安装安全配置文件

1.打开web浏览器,并访问以下网址 https://developer.amazon.com/lwa/sp/overview.html

2.在接近页面顶部的位置,在下拉菜单中选择你刚才创建的安全配置然后单击确认

3.进入一个隐私政策地址栏,该地址栏以http:// 或者 https://开头。在此例子中,你可以进入一个模拟仿真的地址栏例如http://example.com
4.[或者]你也可以上传一个图片。这个图片将被显示在使用者的同意登陆亚马逊网站的页面上。
5.单击保存。

6.然后打开Alexa Voice Service示例应用程序安全配置文件,单击显示客户ID和客户隐私。这项操作会展示出客户的ID和客户的隐私。保存这些值。你将会看到这些图片。

7 – 更新配置文件

通过VNC登陆树莓派

步骤1:更新config.js。导航到以下的文件然后在一个文本编辑器中打开该文件。

<REFERENCE_IMPLEMENTATION>/samples/companionService/config.js

在该文件中编辑以下几个值 –

  • 客户ID: 把你在前几个步骤里复制的客户ID以字符串的形式粘贴在客户ID中。
  • 客户秘密: 把你在前几个步骤里复制的客户机密以字符串的形式粘贴在客户机密中。
  • 产品: 产品的对象包含一个你在开发者门户创建的与产品类别ID一致的密钥和一个属于一系列特定的产品标志符的数值。如果你是根据以上的指导操作的,产品序列ID是my device。那个独特的产品序列号可能是任何数字类型的字符串,比如说123456。以JSON产品为例:products:{“my_device”: [“123456”]}

保存文件。

步骤2:更新config.json。 导航到以下的文件然后在一个文本编辑器中打开该文件。

<REFERENCE_IMPLEMENTATION>/samples/javaclient/config.json
在文件中编辑以下值:

  • 产品ID : 以字符串的形式输入my_device
  • dsn: 输入一个数字型的字符串,这个字符串是你在服务器端的config.js页面中用来描述产品对象里的产品标志符数值。例如:123456。
  • provisioning方法: 输入companionService。

保存文件。

步骤 3: 准备pom.xml文件

到下面的文件同时在文本编辑器中打开该文件。

<REFERENCE_IMPLEMENTATION>/samples/javaclient/pom.xml
增加以下的代码在pom.xml文件中< 依赖性 >部分:

<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>4.1.0</version>
<scope>compile</scope>
</dependency>

8 – 运行服务器

通过VNC登陆树莓派

在你的windows终端或者命令提示符中打出以下代码:

cd <REFERENCE_IMPLEMENTATION>/samples/companionService
npm start

你已经成功开启这个服务器,并且运行在端口3000上。

9 – 开启客户端

打开一个新的Window终端或者选项卡(在Raspbian中 输入SHIFT+CTRL+TAB)

cd <REFERENCE_IMPLEMENTATION>/samples/javaclient

搭建应用平台

在你搭建app平台之前,确认项目是正确的同时所有必要的信息都是有效的。你可以通过执行以下的代码来确认:

mvn validate

通过执行以下代码下载依赖性文件并且搭建应用平台:

mvn install

当安装已经完成时,你在终端上可以看到“成功创建”的信息。

执行客户端的应用:

现在可以输入以下的脚本执行客户端的应用:

mvn exec:exec

10 -从亚马逊登陆页面中获得权限

1.当你执行客户端时,window桌面可能会弹出一个类似于以下文本的讯息:

“通过访问以下网址注册你的设备,然后请跟随指令操作:https://localhost:3000/provision/d340f629bd685deeff28a917一旦完成了请单击OK”

从弹出的窗口中复制URL地址然后粘贴到web浏览器。示例:以下为用来复制和粘贴的URL地址

https://localhost:3000/provision/d340f629bd685deeff28a917

注意:由于使用的是自签名证书,你将看到一个关于不安全网页的警告。这是一个意外。在测试的时候可以忽略这个警告,该网页是安全的。

2.将会跳转到亚马逊的登陆页面。输入你的亚马逊证书。

3.将跳转到开发者权限页面,确认许可你的设备可以通过刚才设置的安全配置文件。

单击Okay

4.你现在将会再次跳转到一个以https://localhost:3000/authresponse开始的后面跟着查询字符串的URL地址栏。这个网页的主体部分将说明设备已经准备好

5.回到Java 应用然后单击OK按钮。这个客户端现在已经可以接受Alexa请求。

6.单击开始音频按钮然后在开始讲话之前等待音频提示。在你听到音频提示前会花费一到二秒

当你完成语音时,单击停止音频的按钮。

现在开始与Alexa 交谈

询问天气:单击开始音频的按钮。

你:今天西雅图的天气怎么样? 单击停止音频按钮。

Alexa:现在西雅图的气温报告。

你可以询问Alexa一些有意思的问题

在单击了“开始音频”之后,一旦你听见了音频提示,下面是一些问题你可以尝试去和Alexa交流

要求歌曲回播: 播放Bruce Springsteen
常识知识:太阳的质量是多少克?
极客:机器人的三定律是什么?
娱乐: 你可以跳rap麽?
设置定时期: 设置一个俩分钟的定时期
设置闹钟: 设置一个早上 7:30 的闹钟

更多的关于音乐回放的功能  “前一首”,“播放/暂停”,和“下一首”按钮在Java客户端交互界面上被用来展示音乐按钮事件。你可以使用音乐按钮而不是与Alexa讲话来改变播放列表的顺序。比如说,你可以按“播放/暂停”按钮来暂停和重复开始一首在音轨上的音乐。

为了更好的展示“播放/暂停”按钮,你可以说出以下命令: 在iHeartRadio上播放DC101,然后按“播放/暂停”按钮。如果按钮按下,这首音乐会终止。再次按下“播放/停止”按钮重新开始这首音乐。

11 – 常见问题解答

我有一个与AVS一起工作的树莓派,但是我不能从Alexa中听到音频回应

检查看一下是否你正在看通过终端的响应和是否在你的Alexa 应用上看到了响应卡。如果是的,你可能需要强制音频通过local 3.5mm插孔,而不是HDMI输出(这可能发生即使你没有一个HDMI显示器插入)。

为了促使音频通过local 3.5mm插孔,打开终端,然后输入以下代码:

sudo raspi-config

可以查看一下链接Raspberry Pi Audio Configuration

如何寻找树莓派的IP地址?

hostname -I

无法获取错误

在你安装VLC时,如果遇到了一些无法获取的错误,试图输入以下代码

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install vlc-nox vlc-data

在npm上有一些问题

如果你在安装结点后遇到一些“npm 无法找到”的问题(树莓的老版本结点), 尝试一些以下操作:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install npm

如果我不能为派找到网络接口怎么办?

可以查看以下URL了解如何在派上建立笔记本电脑的wifi和网络接口的连接https://www.hackster.io/Anwaarullah/sharing-wifi-with-raspberry-pi-using-a-lan-cable-ae1f44

ssl.cnf文件是什么样的?

单击这里将会看到ssl.cnf文件是什么样子的,并且根据你自己的国家、洲、地区来相应的替换

 “无法连接到配套服务”的错误

这可能是因为以下三种情况的其中一种

1.不良证书– 这可能是下面情况的一个结果

  • 不良的ssl cnf文件(可以查看一下常见问题是什么样的)
  • 不正确的java版本
  • 在config.json文件中可能有错误的密码

2.不正确的产品ID -确保以下值是一致的-

  • 设备型号的信息-在亚马逊开发人员门户信息上的设备型号ID
  • 在SSL证书产生的产品ID号(当被generate.sh触发时)
  • 在 config.json上的产品ID
  • 在产品上的“密码”和在config.js页面上 “密码”:[“值”]

3.不正确的DSN- 确保这些值是一致的

  • 在config.json页面上的dsn
  • 在产品上的“值”和在config.js页面上 “密码”:[“值”]

4.配套服务没有运行

作者介绍:

王毅

亚马逊AWS中国云解决方案架构师,获得了AWS解决方案架构师专业级别的认证。专门负责在国内推广AWS云平台技术和各种解决方案。有超过13年的IT领域咨询和实施经验,专注于云计算领域。在此之前,他是IBM全球服务服务部门的资深架构师经理,负责咨询和实施SOA,企业系统集成,云计算平台等解决方案在中国及亚太地区的推广和服务咨询工作。

将VMware 中的Ubuntu 12.04 映像导入成Amazon EC2 AMI

(本操作文档部分叙述内容与技术知识引用自AWS官方网站)

要在 Amazon EC2 中使用您的 VM,您必须首先将其从虚拟化环境中导出,然后使用 AWS Command Line Interface (AWS CLI) 或 API 工具将其导入 Amazon EC2。(AWS Console不支持从VM导入AWS的操作功能。)

从总体上看,要将VM导入到Amazon EC2中,需要经过以下五个步骤:

1. 安装 AWS CLI。

2. 为 VM 导入 Amazon EC2 做准备。

3. 从虚拟化环境中导出 VM。

4. 将 VM 导入 Amazon EC2。

5. 在 Amazon EC2 中启动实例。

本次实验使用VMware Workstation 10,把Ubuntu原生镜像ubuntu-12.04.5-desktop-amd64.iso导入到VMware Workstation 10。自行个性化操作后,利用VMware Workstation 10导出OVF映像的功能,获得VM的vmdk文件。并用AWS CLI,以流优化型 ESX 虚拟机磁盘 (VMDK) 映像格式把它导入到Beijing Region的AMI当中。(AWS并不完全支持所有基于Windows或Linux操作系统的系统版本,具体的支持列表请查看http://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/VMImportPrerequisites.html)。

一.安装AWS CLI
在本地安装AWS CLI具体请查看http://docs.aws.amazon.com/zh_cn/cli/latest/userguide/installing.html。需要注意的是,安装完客户端后,需要在AWS账户的IAM->用户->(目标用户)->安全证书 中创建并下载访问安全密钥,根据下载的Excel文件中的AWS Access Key ID和AWS Secret Access Key,配置好AWS CLI。具体请看以下截图。

二.为 VM 导入 Amazon EC2 做准备

把个性化操作后的Ubuntu VM从VMware Workstation 10导出前,需要在VM中进行以下几步重要的操作:

1. 在VM中启用SSH远程访问,并保证VM防火墙允许外部访问VM。虽然允许基于密码的SSH,但为安全起见,建议使用公共密钥登录。

2. 在VM中配置一个非root用户。虽然允许root登录,但为了安全起见,建议配置一个非root用户。

3. 确保您的 Linux VM 将 GRUB(传统 GRUB)或 GRUB 2 作为其启动加载程序。

4. 确保您的 Linux VM 使用下列根文件系统之一:EXT2、EXT3、EXT4、Btrfs、JFS 或 XFS。

5. 关闭所有反病毒软件,从您的 VMware 虚拟机上卸载 VMware 工具。

6. 保持您的网络设置为 DHCP 而不是静态 IP 地址。

在本次的操作中,由于我们使用原生的Ubuntu ISO文件,因此一般情况下,我们只需要操作上述的第1、2、6点即可。

三.从虚拟化环境中导出 VM

AWS支持下列四种映像格式:

1. 用于导入磁盘和 VM 的 RAW 格式。

2. 固定和动态虚拟硬盘 (VHD) 映像格式,该格式与 Microsoft Hyper-V 和 Citrix Xen 虚拟化产品兼容。目前不支持 VHDX 映像。VM Export 仅支持动态虚拟硬盘 (VHD)。不支持固定 VHD。

3. 流优化型 ESX 虚拟机磁盘 (VMDK) 映像格式,该格式可与 VMware ESX 和 VMware vSphere 虚拟化产品兼容。只能将通过 VMware 中的 OVF 导出过程创建的 VMDK 文件导入 Amazon EC2

4. 启动虚拟装置 (OVA) 映像格式,该格式支持将映像与多个硬盘一起导入。

AWS官方文档中提到Citrix Xen、Microsoft Hyper-V 和 VMware vSphere这三款虚拟化环境软件。其中VMware vSphere支持导出OVF格式和OVA格式。而最常用的VMware Workstation系列软件,则只支持导出OVF格式。考虑到VMware vSphere是一款操作系统软件,而VMware Workstation是一款应用软件,为了简化复杂程度,我们使用VMware Workstation 10,也就决定了我们使用第三种的映像格式。

当在VM上个性化操作后,关闭VM,然后在VMware Workstation 10菜单栏中的“文件”->”导出为OVF”中把选中的VM导出到磁盘中。导出后一共有.mf、.ovf、.vmdk三个文件,个别操作系统的VM会出现.iso原生镜像文件。其中.mf文件是一些文件SHA的集合,主要起到防止映像文件被非法用户篡改的验证作用。.ovf文件相当于配置文件,它保证了映像文件vmdk、资源文件iso与虚拟机domain配置之间的正确对应。.vmdk文件是具体的映像资源。在这里,我们只需要把.vmdk文件上传到AWS S3的bucket即可

四.将 VM 导入 Amazon EC2
在这一步中,我们需要使用AWS CLI操作S3中的.vmdk文件,把该文件转换为AMI。在这个过程当中,我们所使用的CLI命令import-image需要在我们的账户中创建名为vmimport的角色,并为该角色配置相关的策略和为使用IAM身份登录的用户配置权限后(http://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/VMImportPrerequisites.html),才能够执行特定的操作。因此在转换为AMI前,我们需要先操作我们的账户。下面会逐步介绍。

1. 使用 aws iam create-role 命令创建名为 vmimport 的角色,并向 VM Import/Export 提供对该角色的访问权。

具体命令:

aws iam create-role --role-name vmimport --assume-role-policy-document file://trust-policy.json

其中trust-policy.json文件的内容为:

{

   "Version":"2012-10-17",

   "Statement":[

      {

         "Sid":"",

         "Effect":"Allow",

         "Principal":{

            "Service":"vmie.amazonaws.com"

         },

         "Action":"sts:AssumeRole",

         "Condition":{

            "StringEquals":{

               "sts:ExternalId":"vmimport"

            }

         }

      }

   ]

}

特别注意事项:

(1) 必须将外部 ID 命名为vmimport,不能是其他的名字。

(2) trust-policy.json文件当中的”Version”并非是用户自定义版本号,而是AWS中vmimport的版本号,因此请保留”Version”:”2012-10-17″不变。

2. 为角色vmimport创建策略。

具体命令:

aws iam put-role-policy --role-name vmimport --policy-name vmimport --policy-document file://role-policy.json

其中role-policy.json文件的内容为:

{

   "Version":"2012-10-17",

   "Statement":[

      {

         "Effect":"Allow",

         "Action":[

            "s3:ListBucket",

            "s3:GetBucketLocation"

         ],

         "Resource":[

            "arn:aws-cn:s3:::vm.vincentqiu.cn"

         ]

      },

      {

         "Effect":"Allow",

         "Action":[

            "s3:GetObject"

         ],

         "Resource":[

            "arn:aws-cn:s3:::vm.vincentqiu.cn/*"

         ]

      },

      {

         "Effect":"Allow",

         "Action":[

            "ec2:ModifySnapshotAttribute",

            "ec2:CopySnapshot",

            "ec2:RegisterImage",

            "ec2:Describe*"

         ],

         "Resource":"*"

      }

   ]

}

特别注意事项:

(1) 同样地,要求保留role-policy.json文件中的”Version”:”2012-10-17″不变。

(2) 需要特别注意上述role-policy.json文件中红色标注的两行,分别有两个注意事项:第一,如果VM映像所在的S3为中国区内,则需要以“arn:aws-cn:s3”开头标注资源;如果VM映像所在的S3为中国区外的标准AWS区域,则只需要使用一般的“arn:aws:s3”开头标注资源。第二,上述的vm.vincentqiu.cn为本人的VM映像在S3中的bucket名字,用户可根据情况替换成自己的bucket名字。

3. 为使用IAM身份登录的用户配置权限。

如果您以 AWS Identity and Access Management (IAM) 用户身份登录,那么您的 IAM 策略中需要以下权限才能导入或导出 VM。

{

  "Version": "2012-10-17",

  "Statement": [

    {

      "Effect": "Allow",

      "Action": [

        "s3:ListAllMyBuckets"

      ],

      "Resource": "*"

    },

    {

      "Effect": "Allow",

      "Action": [

        "s3:CreateBucket",

        "s3:DeleteBucket",

        "s3:DeleteObject",

        "s3:GetBucketLocation",

        "s3:GetObject",

        "s3:ListBucket",

        "s3:PutObject"

      ],

      "Resource": ["arn:aws:s3:::mys3bucket","arn:aws:s3:::mys3bucket/*"]

    },

    {

      "Effect": "Allow",

      "Action": [

        "ec2:CancelConversionTask",

        "ec2:CancelExportTask",

        "ec2:CreateImage",

        "ec2:CreateInstanceExportTask",

        "ec2:CreateTags",

        "ec2:DeleteTags",

        "ec2:DescribeConversionTasks",

        "ec2:DescribeExportTasks",

        "ec2:DescribeInstanceAttribute",

        "ec2:DescribeInstanceStatus",

        "ec2:DescribeInstances",

        "ec2:DescribeTags",

        "ec2:ImportInstance",

        "ec2:ImportVolume",

        "ec2:StartInstances",

        "ec2:StopInstances",

        "ec2:TerminateInstances",

        "ec2:ImportImage",

        "ec2:ImportSnapshot",

        "ec2:DescribeImportImageTasks",

        "ec2:DescribeImportSnapshotTasks",

        "ec2:CancelImportTask"

      ],

      "Resource": "*"

    }

  ]

}

 

4. 创建新的导入映像任务。

经历了上述角色和账户操作后,我们现在终于可以使用 aws ec2 import-image 创建新的导入映像任务!

具体命令:

aws ec2 import-image --description "Ubuntu 12.04 vmdk" --disk-containers file://containers.json

其中containers.json文件的内容为:

[{

    "Description": "VM import first CLI task",

    "Format": "vmdk",

    "UserBucket": {

        "S3Bucket": "vm.vincentqiu.cn",

        "S3Key": "OVA_ubuntu_12.04/Ubuntu12.04-disk1.vmdk"

    }

}]

如果该VM具有多个显示磁盘,import-image命令也支持具有多个显示磁盘的VM导入Amazon EC2中。在这种情况下,containers.json文件的内容类似于:

[{

    "Description": "First CLI task",

    "Format": "vmdk",

    "UserBucket": {

        "S3Bucket": "my-import-bucket",

        "S3Key": "my-windows-2008-vm-disk1.vmdk"

    }

},

 

 {

    "Description": "Second CLI task",

    "Format": "vmdk",

    "UserBucket": {

        "S3Bucket": "my-import-bucket",

        "S3Key": "my-windows-2008-vm-disk2.vmdk"

    }

}]

特别注意事项:

(1) 上述命令中的description均为注解部分,用户可以根据自己的需要进行修改。

(2) 上述红色字体中的”Format“的值取决于第三步中导出VM的映像格式。如果导出的VM映像格式为ova,请把”Format“的值改为ova。本次实验使用的是流优化型 ESX 虚拟机磁盘 (VMDK) 映像格式,所以”Format“的值为vmdk。

(3) 上述红色字体中的”S3Bucket“的值指的是VM映像所在S3的bucket名字,而”S3Key“的值指的是VM映像所在bucket中的具体路径名,用户可以根据自身情况进行修改。需要注意的是,设定”S3Key“的值时,请注意S3中文件夹的存在。请按照“文件夹/子文件夹/……/文件名”的格式进行填写。

当执行完该命令后,如果没有错误发生,CLI会返回任务响应。在任务相应中含有一个ImportTaskId的值,我们保存下来,方便下面查询使用。

5.检查您的导入映像任务的状态

具体命令:

aws ec2 describe-import-image-tasks --cli-input-json "{ \"ImportTaskIds\": [\"import-ami-fggrs8es\"], \"NextToken\": \"abc\", \"MaxResults\": 10 } "

注意事项:

(1) 上述命令中的红色部分为导入映像任务的id值,用户根据上一步保留的ImportTaskId值自行替换,即可查询该任务的情况。

(2) 当使用上述命令查询任务状态时,根据AWS的处理进度,返回任务响应中的Status依次为“Pending”、“Converting”、“Updating”、“Updated”、“Preparing AMI”等。整个的处理过程持续10+分钟,请用户耐心等待。隔一段时间再次查询后,如果Status为“Completed”,则表示映像转换完成,用户可以在EC2的AMI镜像中找到它。

五.在 Amazon EC2 中启动实例
当生成AMI镜像后,我们就能够通过EC2按照正常的方法创建对应的实例。但需要注意的是:您的实例将只有一个 Ethernet 网络接口。另外,对于不同的操作系统,import-image命令对其Licence、最低存储、Internet协议、实例类型等方面有不同的限制和要求,具体请查看http://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/VMImportPrerequisites.html的《要求和限制》部分。

作者介绍:

邓明轩

亚马逊AWS解决方案架构师;拥有15年IT 领域的工作经验,先后在IBM,RIM,Apple 等企业担任工程师、架构师等职位;目前就职于AWS,担任解决方案架构师一职。喜欢编程,喜欢各种编程语言,尤其喜欢Lisp。喜欢新技术,喜欢各种技术挑战,目前在集中精力学习分布式计算环境下的机器学习算法。

邱越俊

亚马逊AWS解决方案架构师实习生,擅长Web开发,熟悉使用Java、Javascript、Html5、Mysql数据库,曾在多个互联网公司从事软件平台开发工作,对计算机网络架构、云平台的开发和部署有一定的经验。

 

使用Docker封装IPSec安全网关

随着云成为新常态,越来越多的客户开始采用AWS云服务,使用VPN隧道安全的连接到AWS成为一个常见的场景。本文介绍一种仅需少量交互与配置即可与多个AWS VPC建立动态路由VPN连接并在各个互联VPC之间转发流量的方案。该方案主要使用了Docker、IPSec套件strongSwan、动态路由软件BIRD,并在此基础上,使用AWS SDK for Python( Boto 3)、docker-py等实现快速建立与AWS VPC的动态VPN。

项目中使用的Dockerfile、相关的shell脚本以及Python应用等源文件均已经在这里开放,做为一种快速部署Customer Gateway的方法,供各位读者参考。

本文假定读者从概念上理解AWS VPC、IPSec VPN以及动态路由协议BGP。如果希望了解更多如何与AWS VPC建立VPN连接的信息,读者可以参考 AWS VPC 网络管理员指南。

如何使用

我们从最基本的场景开始,假定您需要将本地网络与单个AWS VPC通过IPSec隧道互联。

图中Customer Gateway应为一台可以访问Internet且IP固定的 Linux服务器, 这台服务器将作为IPSec网关和BGP路由器,将内部网络与AWS VPC通过IPSec隧道和BGP动态路由协议连接起来。

在Customer Gateway上执行如下预备工作:

一、我们需要 预先安装和配置好docker引擎;

二、我们的脚本使用了Python和一些第三方库,所以需要安装Python 2.7或更新版本以及Python包管理工具,例如pip

三、通过pip安装如下软件包;

a. boto3 —— AWS SDK for Python,用于获取VPN连接的配置信息

b. xmltodict —— 便于python处理XML格式的数据

c. docker-py —— 用于连接docker engine并创建、运行容器

四、配置boto3连接AWS的 IAM凭证,需要注意使用的IAM用户需要拥有执行describe_vpn_connections API所需的权限。

$ cat  ~/.aws/credentials

[default]

aws_access_key_id = YOUR_KEY

aws_secret_access_key = YOUR_SECRET

建立连接

参照AWS VPC用户指南中关于“设置VPN连接”章节的指导,完成如下步骤:

步骤一、创建虚拟专用网关,附加到目标VPC并启用路由传播;

步骤二、创建客户网关,输入Customer Gateway的公网IP地址,选择动态路由,并输入65000作为本地网络的BGP ASN号;

步骤三、创建虚拟专用网关和客户网关之间的VPN连接,每个VPN连接包含两条相护冗余的VPN隧道;

步骤四、在Customer Gateway上执行peer.py 脚本,传入目标VPC所在的region名称和vpn连接id,该脚本将会调用AWS API下载指定的VPN连接的配置信息、然后连接Docker Engine创建cgw 容器并将关键参数作为环境变量传入容器;

步骤五、cgw容器会根据传入的环境变量完成自举并发起到AWS侧虚拟专用网关的2条动态路由VPN连接。

CGW容器的实现

正常的容器运行中的进程信息可见下图

可以看到容器中共有4个进程,其功能分别为:

一、cgw.sh 容器启动脚本,主要在容器开始运行时完成以下动作;

a. 根据传入的环境变量生成strongSwan、BIRD的配置文件

b.  配置virtual tunnel interface以便将两条ipsec隧道暴露给动态路由软件

c. 拉起strongSwan、BIRD

二、strongSwan守护进程,负责与虚拟专用网关协商和交换加密、解密密钥、调用Linux内核中IPSec相关的系统调用设定隧道;

三、BIRD守护进程;

a. 与虚拟专用网关的两个端点分别建立BGP邻居关系并以10秒的间隔持续检测对端是否健康

b. 与本地网络中其他路由器建立BGP邻居关系并将路由信息发布到本地网络和AWS VPC;实现本地网络与AWS VPC的互通

c. 当两条隧道中的一条由于某种原因发生故障,BIRD会检测到邻居状态的改变从而自动将流量切换到另外一条健康的隧道中去,从而实现了VPN连接的冗余

扩展性和可用性

一、如果需要与多个不同的VPC建立多条VPN连接,那么只需要重复前面建立连接的步骤在同一台服务器上创建多个cgw容器,分别建立与不同的虚拟专用网关的VPN连接即可。如下图所示

但是要做到不同VPC之间的流量互通,我们还需要在多个cgw容器之间建立iBGP邻居关系。传统的iBGP互联要求full mesh,这里我们为了简化部署和配置,可以在容器所在服务器上运行BIRD并将其配置为路由反射器,所有cgw容器都与路由反射器建立邻居关系并学习到其他容器、隧道的路由信息,从而实现多个VPN连接之间的流量互通。

二、如果需要保证高可用,需要在不同的VPN网关之间实现互为备份,那么可以通过运行两台物理服务器,各自建立与AWS VPC的VPN连接,通过动态路由协议来实现故障流量切换;

三、如果需要进一步增大吞吐量,超出单个服务器的可用带宽的情况下,我们可以将cgw容器分散到多个物理服务器上实现水平扩展;同样的,在服务器之间需要建立iBGP邻居关系并交换路由信息;

作者介绍:

丁成银

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

如何使用AWS Auto-reboot和Auto-recovery进一步提升单机高可用

根据AWS的推荐设计原则,搭建一个云端应用系统时,需要记住的一个原则是“design for failure”,也就是系统架构设计的时候需要考虑到应用系统的每一个层面,包括硬件和软件是可能出现故障的,并据此在应用系统架构设计上消除单一故障点,从而实现高可用性的系统架构。

有些应用由于历史或其他原因,没有按照这个原则设计高可用的架构,因此在部署上存在单一故障点,比如某一台EC2实例的软件或者底层硬件出现故障的时候会影响到这部分应用。如何保证或者大大提高单机EC2的可用性是非常重要的问题。

针对这些用户的需求,AWS推出了两个非常有用的监控功能:自动重启(auto reboot)EC2实例的CloudWatch警报和自动恢复(auto recovery)EC2实例的CloudWatch警报。这两个警报能够在你设定的阀值内自动重启因为实例故障或者底层硬件故障的EC2实例,最快时间恢复实例健康,从而大大降低了down机时间,让应用系统快速从软件或者底层的软硬件故障中自动地恢复,大幅度提升应用的整体可用性。具体介绍如下:

  • 自动恢复EC2实例的CloudWatch警报

任何物理机都可能发生故障,云端的物理主机也不例外。使用AWS云平台,当底层硬件发生故障时,你无需人工干预或者联系AWS的支持工程师帮助您处理并恢复实例,通过事先创建CloudWatch 的StatusCheckFailed_System(状态检查失败(系统))警报监控 EC2 实例,在实例运行的物理主机发生底层硬件故障的时候能够自动触发警报,一方面根据配置发送通知给贵司相关人员,另一方面以最快时间将实例迁移到健康的物理硬件上,并保持实例 ID、私有 IP 地址、弹性 IP 地址以及所有实例元数据不变。

自动恢复实例的Cloudwatch警报有以下要求:

·       仅支持C3、C4、M3、R3 和 T2 实例类型

·       仅支持VPC 中的实例,不支持EC2-Classic 实例

·       仅支持完全使用EBS 存储的实例,不支持使用任何实例存储卷的实例

  • 自动重启EC2实例的CloudWatch警报

以前当您遇到由于实例内部的软件故障导致实例无法正常访问时,你只能选择手动重启实例让实例从故障中恢复,这个过程由于需要人工的干预,可能导致较长时间的实例不可访问。现在,您可以创建Cloudwatch的StatusCheckFailed_Instance(状态检查失败(实例))警报监控 EC2 实例,并在实例运行状况检查失败时自动重启此实例,从而实现在短短几分钟时间内即可重启您的实例并恢复实例。重启实例时,其仍驻留在相同的物理主机上,因此您的实例将保留其公有 DNS 名称、私有 IP 地址及其实例存储卷上的任何数据。

  • 如何配置

为了大幅度提升单机的高可用性,建议您在一个实例上同时配置上述两种Cloudwatch警报,以监控软硬件故障并自动恢复实例。配置的时候需要注意的一点是:使用IAM user创建两个警报,其中自动重启EC2实例的警报的检测周期必须要大于自动恢复实例的警报的检测周期,比如下面例子中,自动重启EC2实例的检测周期是3,自动恢复EC2实例的检测周期是2。

自动重启EC2实例的警报的示例(StatusCheckFailed_Instance):

自动恢复EC2实例的警报的示例(StatusCheckFailed_System):

 

更多信息请参考

http://docs.aws.amazon.com/zh_cn/AmazonCloudWatch/latest/DeveloperGuide/UsingAlarmActions.html#AddingRecoverActions

http://docs.aws.amazon.com/zh_cn/AmazonCloudWatch/latest/DeveloperGuide/UsingAlarmActions.html#AddingRebootActions