Category: 大咖专栏


打造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之前,历任数字媒体娱乐系统工程师、宽带业务架构师、云解决方案架构师,负责数字媒体娱乐系统、云计算解决方案等服务的咨询和架构设计工作。