fastec2: 面向普通用户的 AWS 计算机管理工具

技术
作者

Jeremy Howard

发布日期

2019年2月15日

这是关于 fastec2 系列文章的第1部分。要了解如何使用 fastec2 运行和监控长时间运行的任务,请查看第2部分

AWS EC2 是一个出色的系统;它允许任何人以每小时几美分的价格租用一台计算机,包括快速的网络连接和充足的磁盘空间。我特别感谢 AWS,因为多亏了他们的 Activate 项目,我们在 fast.ai 有大量的计算额度用于研究和开发。

但是,如果您曾花时间使用 AWS EC2,那么在进行设置时,您可能会发现自己陷入了缓慢而复杂的 AWS Console GUI 和冗长笨重的命令行界面(CLI)之间。虽然有各种工具可以简化 AWS 管理,但它们往往偏向于高级用户,专为在复杂架构中部署数十台计算机的人而编写。

那么,面向普通用户的工具在哪里呢?对于那些只想启动一两台计算机来完成一些工作并在完成后将其关闭的人来说,他们的工具在哪里?对于那些并不热衷于学习一大堆 AWS 特有术语,例如 VPC、Security Groups、IAM Roles,并且只想让它们消失的人来说,他们的工具又在哪里呢?

AWS Console 的体验

目录

  1. 概述
  2. 安装与配置
  3. 创建您的初始按需实例
  4. 创建您的 Amazon Machine Image (AMI)
  5. 启动并连接到您的实例
  6. 启动 Spot 实例
  7. 使用交互式 REPL 和 ssh API

既然我自己就是一个非常普通的普通人,我觉得我最好去写一个这样的工具。所以,它来了:fastec2。它适合您吗?以下是它旨在简化的一些功能的总结(这里的 'instance' 简单来说就是 'AWS 计算机')

  • 启动新的按需或 Spot 实例
  • 查看正在运行的实例
  • 启动实例
  • 使用 ssh 连接到指定名称的实例
  • 在 Spot 实例中运行长时间脚本并监控和保存结果
  • 创建和使用卷和快照,包括自动格式化/挂载
  • 更改实例类型(例如,添加或移除 GPU)
  • 查看按需和 Spot 实例类型的定价
  • 通过标准命令行或 Jupyter Notebook API 访问
  • Tab 补全
  • 提供 IPython 命令行交互式 REPL 用于进一步探索

我预计这将对从事数据分析、数据收集和机器学习模型训练的人最有用。请注意,fastec2 不是为了方便管理庞大的服务器群、设置复杂的网络架构或帮助部署应用程序而设计的。如果您想做这些事情,您可能需要查看 TerraformCloudFormation

为了了解它是如何工作的,我们将完整地演示如何创建一个新的 Amazon Machine Image (AMI),然后从这个实例启动一个 AMI,并连接到它。我们还将了解如何启动 Spot 实例,在其上运行长时间脚本,并收集脚本的结果。我假设您已经有一个 AWS 账户,并且了解使用 ssh 连接到实例的基础知识。(如果您不确定这一点,建议您首先按照 DataCamp 上的本教程进行学习。)请注意,fastec2 中许多最酷的功能都得益于出色的 FireParamikoboto3 库——在此向所有提供这些库的出色人员致以诚挚的谢意!

概述

我们希望 fastec2 支持的主要使用场景如下:您想要交互式地启动和停止各种类型的机器,每次都能自动获得相同的程序、数据和配置。有时,您会创建一个按需镜像(AMI),并根据需要启动和停止它。您可能还需要偶尔更改实例类型,例如添加 GPU 或增加内存。(这可以通过一个简单的命令立即完成!)有时,您会启动一个 Spot 实例来运行脚本并保存结果(例如,用于训练机器学习模型或完成网络抓取任务)。

要使其顺利工作,关键在于设置一个完全符合您需求的 AMI。您可能认为 AMI 是只有亚马逊的系统管理员天才才能为您构建的东西,但正如您将看到的那样,它实际上非常快速和容易。通过轻松创建和使用 AMI,您可以随时轻松地创建您所需的机器。

fastec2 中的所有功能都可以通过 AWS Console 和官方 AWS CLI 实现。此外,fastec2 还有很多事情做不了——它并非旨在实现完整功能,而是为了方便最常用的功能。但希望您会发现,就它提供的功能而言,它比市面上任何其他工具都更简单、更快速……

安装与配置

您需要 Python 3.6 或更高版本——如果您尚未安装 Python 3.6,我们强烈建议安装 Anaconda。它允许您拥有任意数量的不同 Python 版本和环境,并根据需要进行切换。要安装 fastec2

pip install git+https://github.com/fastai/fastec2.git

您还可以通过为您的 shell 安装 Tab 补全来节省一些时间。有关设置步骤,请参阅自述文件。安装后,在任何时候按下 Tab 键即可完成命令,再次按下 Tab 键可查看可能的备选项。

fastec2 使用 Python 接口与 AWS CLI 进行交互,因此您需要进行配置。CLI 使用区域代码,而不是您在控制台中看到的区域名称。为了查找您想要使用的区域代码,fastec2 可以提供帮助。要运行 fastec2 应用程序,请键入 fe2,后跟命令名称和任何必需的参数。命令 region 将显示与您提供的(区分大小写的)子字符串匹配的第一个代码,例如(请注意,我使用 '$' 表示您输入的行,其他行是响应)

$ fe2 region Ohio
us-east-2

现在您有了区域代码,就可以配置 AWS CLI 了

$ aws configure
AWS Access Key ID: XXX
AWS Secret Access Key: XXX
Default region name: us-east-2

有关如何设置以及获取 AWS 访问密钥的信息,请参阅配置 AWS CLI

创建您的初始按需实例

如果您可以快速创建完全按照您的喜好设置好的新实例,安装好所需的软件,下载好数据文件并配置完毕,那么使用起来就会方便得多。您可以通过创建 AMI 来做到这一点,AMI 只是您设置好的一台计算机的“冻结”版本,您可以根据需要几乎即时地多次重新创建它。

因此,我们将首先设置一个包含我们所需内容的 EC2 实例(我们将其称为您的基础实例)。(您可能已经设置好了一个实例,在这种情况下可以跳过此步骤)。

让事情变得更容易的一件事是确保您在 AWS 上有一个名为“default”的密钥对。如果没有,请立即上传或创建一个同名密钥对。虽然 fastec2 可以使用您指定的其他名称的密钥,但如果您不使用“default”,则每次都需要指定密钥名称。您不需要让基础实例的磁盘很大,因为稍后使用您的 AMI 启动新实例时,您随时可以使用更大的大小。一般来说,选择 60GB 是一个合理的尺寸。

为了创建我们的基础镜像,我们需要从某个包含 Linux 发行版的现有 AMI 开始。如果您已经有偏好的 AMI,请随意使用;否则,我们建议使用最新的稳定 Ubuntu 镜像。要获取最新 Ubuntu 的 AMI ID,请键入

$ fe2 get-ami - id
ami-0c55b159cbfafe1f0

这展示了 fastec2 的一个强大功能:所有以“get-”开头的命令都会返回一个 AWS 对象,您可以在该对象上调用任何方法或属性(每个此类命令也都有一个不带 get- 前缀的版本,该版本会打印对象的简要摘要而不是返回对象本身)。如上所示,在连字符后键入您的方法或属性名称。在此例中,我们正在获取由 get-ami 返回的 AMI 对象的 'id' 属性(该命令默认为最新的稳定 Ubuntu 镜像;有关其他 AMI 的示例,请参阅下文)。要查看属性和方法的列表,只需在命令后面不添加属性或方法即可调用

$ fe2 get-ami -

Usage:           fe2 get-ami
                 fe2 get-ami architecture
                 fe2 get-ami block-device-mappings
                 fe2 get-ami create-tags
                 fe2 get-ami creation-date
                 ...

现在您可以启动您的实例了——这将创建一个新的“按需”Linux 实例,完成后(大约需要几分钟)它将打印出名称、ID、状态和 IP 地址。该命令将等待新实例上的 ssh 可访问后才会返回

$ fe2 launch base ami-0c55b159cbfafe1f0 50 m5.xlarge
base (i-00c7f2f81a841b525 running): 18.216.25.57

fe2 launch 命令至少需要 4 个参数:要创建的实例名称、要使用的 AMI(可以是 ID 或名称——这里我们使用前面检索到的 AMI ID)、要创建的磁盘大小(以 GB 为单位)以及实例类型。您可以从此 AWS 页面了解可用的不同实例类型。要查看不同实例的定价,您可以使用此命令(将 m5 替换为您感兴趣的任何实例系列;请注意,目前仅显示美国价格,并且可能不准确或非最新——请使用 AWS 网站获取完整的价格列表)

$ fe2 price-demand m5
["m5.large", 0.096]
["m5.metal", 4.608]
["m5.xlarge", 0.192]
["m5.2xlarge", 0.384]
["m5.4xlarge", 0.768]
["m5.12xlarge", 2.304]
["m5.24xlarge", 4.608]

实例运行后,我们现在可以使用 ssh 连接到它

$ fe2 connect base
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.15.0-1032-aws x86_64)

Last login: Fri Feb 15 22:10:28 2019 from 4.78.240.2

ubuntu@ip-172-31-13-138:~$ |

现在您可以根据需要配置您的基础实例,例如使用 apt install 安装您想要的任何软件,复制您需要的数据文件等等。为了使用 fastec2 的一些功能(下文讨论),您需要在您的 AMI 中安装 tmuxlsyncd,因此请立即安装它们(sudo apt install -y tmux lsyncd)。此外,如果您将使用 fastec2 的长时间运行脚本功能,您需要在 ~/.ssh 目录中拥有一个私钥,该私钥具有连接到另一个实例以保存脚本结果的权限。因此,请复制您的常规私钥(如果不太敏感)或创建一个新的私钥(键入:ssh-keygen)并获取它创建的 ~/.ssh/id_dsa.pub 文件。

检查:在将您的实例制作成 AMI 之前,请确保您已经在实例中完成了以下操作:安装了 lsyncdtmux;复制了您的私钥。

如果您想连接到实例上的 jupyter notebook 或任何其他服务,您可以使用ssh 隧道。要创建 ssh 隧道,请在上方的 fe2 connect 命令中添加一个额外参数,传递一个整数(一个端口)或一个数组(多个端口),例如

# Tunnel to just jupyter notebook (running on port 8888)
fe2 connect od1 8888
# Two tunnels: jupyter notebook, and a server running on port 8008
fe2 connect od1 [8888,8008]

这不会在网络上的不同机器之间进行任何复杂的转发——它只是从您运行 fe2 connect 的计算机到您通过 ssh 连接的计算机的直接连接。因此,通常您会在自己的 PC 上运行此命令,然后(对于 Jupyter)在浏览器中访问 http://localhost:8888

创建您的 Amazon Machine Image (AMI)

配置好您的基础实例后,您可以创建自己的 AMI 了

$ fe2 freeze base
ami-01b7ceef9767a163a

这里的“freeze”是命令,“base”是参数。将 myname 替换为您希望“冻结”到 AMI 中的基础实例的名称。请注意,在此过程中您的实例将被重新启动,因此请确保您已保存所有打开的文档并且可以关机。该过程可能需要 15 分钟左右才能完成(对于数百 GB 的超大磁盘可能需要数小时)。要检查进度,您可以查看 AWS 控制台的 AMI 部分,或键入此命令(在创建镜像期间它会显示“pending”)

$ fe2 get-ami base - state
pending

(正如您将看到的,这使用了我们之前提到的 fastec2 的方法调用功能。)

启动并连接到您的实例

现在您已经获得了您的 AMI,可以使用该模板启动一个新实例了。创建新实例只需几分钟,操作如下

$ fe2 launch inst1 base 80 m5.large
inst1 (i-0f5a3b544274c645f running): 18.191.111.211

我们将我们的新实例命名为“inst1”,并使用我们之前创建的“base”AMI。如您所见,磁盘大小和实例类型不必与您创建 AMI 时使用的相同(尽管磁盘大小不能小于您创建 AMI 时的大小)。您可以查看 launch 命令的所有可用选项;我们将在下一节中了解如何使用 iopsspot 参数

$ fe2 launch -- --help

Usage: fe2 launch NAME AMI DISKSIZE INSTANCETYPE [KEYNAME] [SECGROUPNAME] [IOPS] [SPOT]
       fe2 launch --name NAME --ami AMI --disksize DISKSIZE --instancetype INSTANCETYPE
         [--keyname KEYNAME] [--secgroupname SECGROUPNAME] [--iops IOPS] [--spot SPOT]

恭喜,您已经从自己的 AMI 启动了第一个实例!您可以重复之前的 fe2 launch 命令,只需传入不同的名称即可创建更多实例,并使用 fe2 connect <name> 通过 ssh 连接到每个实例。要关闭实例,请在您的实例的终端中输入

sudo shutdown -h now

…或者您也可以在您自己的计算机的终端中输入(将 inst1 更改为您的实例名称)

fe2 stop inst1

如果在上述命令中将 stop 替换为 terminate,它将终止您的实例(即,它将销毁实例,并且默认情况下会删除实例上的所有数据;终止实例时,fastec2 也会删除其 name 标签,因此可以立即重新使用)。如果您希望 fastec2 等待实例停止,请使用此命令(否则它将在后台自动发生)

$ fe2 get-instance inst1 - wait-until-stopped

这里有一个非常方便的功能:停止实例后,您可以将其更改为不同的类型!这意味着您可以在廉价的实例类型上进行初步原型开发,然后在准备好时在超快的机器上运行大型分析。

$ fe2 change-type inst1 p3.8xlarge

然后您可以重新启动您的实例并像以前一样连接到它

$ fe2 start inst1
inst1 (i-0f5a3b544274c645f running): 52.14.245.85

$ fe2 connect inst1
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.15.0-1032-aws x86_64)

在操作了这么多实例之后,您可能会对创建了什么以及哪些正在运行感到困惑!要查明情况,只需使用 instances 命令

$ fe2 instances
spot1 (i-0b39947b710d05337 running): 3.17.155.171
inst1 (i-0f5a3b544274c645f stopped): No public IP
base (i-00c7f2f81a841b525 running): 18.216.25.57
od1 (i-0a1b47f88993b2bba stopped): No public IP

带有“No public IP”的实例在启动时将自动获得一个公有 IP。通常您无需担心 IP 是什么,因为您可以使用名称来 fe2 connect;但是如果需要,您随时可以通过 fastec2 获取 IP

$ fe2 get-instance base - public-ip-address
18.216.25.57

启动 Spot 实例

Spot 实例比按需实例便宜 70%(或更多)。但是,它们可能随时被关闭,不一定总是可用,并且在关闭时其根卷上的所有数据都会被删除(实际上,它们只能被终止;不能先关闭稍后重启)。Spot 实例的价格随时间、实例类型和区域而变化。要查看某个组(在此例中为 p3 类型)过去 3 天的实例定价,请输入

$ fe2 price-hist p3
Timestamp      2019-02-13  2019-02-14  2019-02-15
InstanceType
p3.2xlarge         1.1166      1.1384      1.1547
p3.8xlarge         3.9462      3.8884      3.8699
p3.16xlarge        7.3440      7.4300      8.0867
p3dn.24xlarge         NaN         NaN         NaN

让我们与按需定价进行比较

$ fe2 price-demand p3
["p3.2xlarge", 3.06]
["p3.8xlarge", 12.24]
["p3.16xlarge", 24.48]
["p3dn.24xlarge", 31.212]

看起来相当不错!要获取更详细的价格图表,请查看 AWS 控制台上的 Spot 定价工具,或者尝试使用 fastec2 的 jupyter notebook API。这个 API 与 fe2 命令完全相同,只是您需要创建一个 EC2 类的实例(可以选择向构造函数传递区域参数),然后调用该实例上的方法。(如果您以前没有使用过 Jupyter Notebook,那么您绝对应该试试,因为它非常棒!这里有一篇来自 DataQuest 的有用的教程可以帮助您入门。)在 notebook 中使用 price-demand 方法时,有一个额外功能可以为您绘制过去几周的价格图(请注意,在 notebook API 中,连字符必须替换为下划线)。

notebook API 中的 Spot 定价示例

要启动 Spot 实例,只需在您的 launch 命令中添加 --spot

$ fe2 launch spot1 base 80 m5.large --spot
spot1 (i-0b39947b710d05337 running): 3.17.155.171

请注意,这只是在请求一个 Spot 实例。您的请求可能没有可用容量。在这种情况下,几分钟后您会看到 fastec2 报告请求失败的错误。我们可以看到上述请求是成功的,因为它打印了一条消息显示新实例正在“运行”。

请记住:如果您停止这个 Spot 实例,它将被终止,并且所有数据都将丢失!而且 AWS 可以随时决定将其关闭。

使用交互式 REPL 和 ssh API

您如何知道哪些方法和属性可用?如何更方便地访问它们?答案是:使用交互式 REPL!一图胜千言:…

fastec2 REPL

如果您在返回对象的命令(目前是 instanceget-amissh 命令)末尾添加 -- -i,您将进入一个 IPython session,该对象将以特殊名称 result 可用。因此,只需键入 result. 并按下 Tab 键即可查看所有可用方法和属性。这是一个完整的 Python 解释器,因此您可以使用 Python 的全部力量与此对象进行交互。完成后,按两次 Ctrl-d 即可退出。

一个有趣的使用场景是尝试使用 ssh 命令,它提供了一个 API,可以通过 ssh 向远程实例发送命令。此命令返回的对象是一个标准的 Paramiko SSHClient,并附带一些额外功能。其中一个额外功能是 send(cmd),它将“cmd”发送到实例上的 tmux session(该 session 是自动启动的)。这主要设计用于您在脚本中使用,但您也可以通过 REPL 进行尝试,如下所示。

通过 REPL 与远程 tmux session 通信

如果您只想交互式地探索 fastec2 API,最简单的方法是使用 fe2 i 启动 REPL(您可以选择附加区域 ID 或区域名称的一部分)。一个名为 efastec2.EC2 对象将自动为您创建。键入 e. 并按下 Tab 键即可查看选项列表。IPython 会在智能自动调用模式下启动,这意味着您通常甚至不需要键入括号即可运行方法。例如

$ fe2 i Ohio
IPython 6.1.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: e.instances
inst1 (i-0f5a3b544274c645f m5.large running): 18.222.175.103
base (i-00c7f2f81a841b525 m5.xlarge stopped): No public IP
od1 (i-0a1b47f88993b2bba t3.micro running): 18.188.162.203

In [2]: i=e.get_instance('od1')

In [3]: i.block_device_mappings
Out[3]:
[{'DeviceName': '/dev/sda1',
  'Ebs': {'AttachTime': datetime.datetime(2019, 2, 14, 9, 30, 16),
   'DeleteOnTermination': True,
   'Status': 'attached',
   'VolumeId': 'vol-0d1b1a47539d5bcaf'}}]

fastec2 提供了许多方便的方法来管理 AWS EC2,并增加了功能使 SSH 和 SFTP 更易于使用。我们将在未来的文章中更详细地介绍 fastec2 API 的这些功能。

如果您想了解如何使用 fastec2 运行和监控长时间运行的任务,请查看本系列的第2部分,其中我们还将介绍 fastec2 如何帮助创建和使用卷和快照,包括自动格式化/挂载。