基于AWS云计算创建个人高性能计算集群

假如你希望拥有自己独立的计算集群,而不是和课题组混用一个集群,并且你不希望在硬件购置、维护上花很多时间,你可以尝试AWS的云计算服务。AWS云计算比起中国国内的云计算服务更为完善高效,性能也相当不错,并且价格也完全可接受。本文讲解如何快速地在AWS上搭建完整的小型高性能计算集群。

准备

首先注册亚马逊AWS账号。注册时需要提供VISA、MASTERCARD之类的美元信用卡信息。注册后可享受一年免费的初级服务,包括最低级别的服务器和存储空间等。

创建密钥对

参考官方文档https://aws.amazon.com/cn/getting-started/use-cases/hpc/的这一部分的讲解。密钥文件将用于免密ssh登录到控制节点。

安装配置CfnCluster

CfnCluster是一个命令行下管理计算集群的工具。安装和设置参见https://d0.awsstatic.com/Projects/P4114756/deploy-elastic-hpc-cluster_project.pdf。本文大部分内容也基于此文档,只是在细节上略有调整。

关于CfnCluster的config文件,我的略作修改后的配置是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[aws]
aws_region_name = us-east-2

[cluster default]
key_name = xxxxx
vpc_settings = public
initial_queue_size = 1
max_queue_size = 2
compute_instance_type = c4.2xlarge
cluster_type = spot
spot_price = 0.075

[vpc public]
vpc_id = vpc-xxxxxxxe
master_subnet_id = subnet-xxxxxxxx

[global]
cluster_template = default
update_check = true
sanity_check = true

这里xxx代表的需要根据自己AWS上的配置改写的。关于计算节点实例的选择,其实很灵活的,根据自己的计算需求选择就可以了。一般的小任务(需要不超过十个核心、时间小于半天)使用c4.2xlarge类型就足够了。注意这类计算优化节点不免费。

cluster_type设置为spot类型,能够极大节省计算费用。spot_price指定你可接受的价格上限。关于平均价格,可以在AWS控制台中找spot实例的历史价格查看。这个价格指的是假如当前市场价格没有高过这个价格,则可以正常启动、运行;假如高过,则停止实例运行(大致如此)。当然你也可以直接设置默认取市场价为价格上限,这样就绝对不会被中断了。然而目前的使用体验是对于小任务,完全不需要担心被中断的问题。从来没有遇到过被AWS中断。

initial_queue_size指的是创建集群时的节点数量,max_queue是最大节点数量。最小节点数量不设置的话默认为零。所以创建集群后你将看到一个控制节点和initial_queue个计算节点。如果你不提交任务,过一分钟左右计算节点的数目将被清零,只留下t2.micro一个控制节点(第一年t2.micro每月免费750小时)。当在控制节点上提交任务时,约两分钟计算节点将被扩展,扩展节点数量视任务数量、最大节点数设置和Alarm中信号的设置。

创建集群

使用

1
$ cfncluster create name_of_your_cluster

然后就全自动完成对集群的创建了。集群名称用于cfncluster对集群的控制。之后应该可以在AWS的控制台的EC2窗口中看到控制节点和初始计算节点。

免密登录控制节点

在首次通过ssh登录控制节点之前需要设置ssh。Linux下在用户目录的.ssh隐藏文件夹中打开config文件,添加控制节点信息:

1
2
3
4
5
Host your_server_name
Hostname xxx.xxx.xxx.xxx
Port 22
User ec2-user
IdentityFile ~/.ssh/xxxxx.pem

这里节点名字任意起,用在ssh和scp连接时替代输入ip地址。.pem密钥文件就是你在创建密钥对的时候下载保存的那个.pem文件,可以将其移动到.ssh文件夹中保管。用户名AWS建议就使用ec2-user就好,不要改。

在设置完ssh之后,就可以通过

1
$ ssh your_server_name

登录。第一次登录有个ssh warning直接yes就可以了。

控制节点的配置

首先通过修改或上传.bashrc等配置文件定义自己的工作环境。然后安装软件等。这里创建的AWS控制节点上使用yum安装,其软件包是AWS内部提供的源。安装python3需要

1
$ sudo yum install python36

然后通过切换默认python版本调到3.6

1
$ sudo update-alternatives --config python

然后就可以用pip直接安装python3的各种包。

设置ssh通讯免中断

一般情况在shell中ssh连接到控制节点后,一段时间没有使用,则ssh自动中断连接,表现为shell无反应。这是ssh的特性。为了避免ssh自动中断,可以在自己的电脑(作为客户端)的/etc/ssh/ssh_config中添加或修改

1
2
ServerAliveInterval 20
ServerAliveCountMax 999

就可以对任何ssh服务器(这里是控制节点)防止通讯中断。

提交任务

通过scp等将计算文件由本地上传至控制节点,然后通过qsub提交到计算节点。如果提交时没有计算节点,需要等待两分钟AWS自动扩展计算节点。对任务的控制基本与常见的公共计算集群一致。

更改集群设置

最常见的更改集群的目的是为了修改最大计算节点数量。只要修改.cfncluster文件夹中的config中的数字,然后用cfncluster命令更新就可以了

1
$ cfncluster update name_of_your_cluster

停止集群

cfncluster的stop指令本质上是将自动扩展组的min/max/desired都设置为零,从而将所有的计算节点全部关闭。要关闭主节点,貌似必须手动在EC2窗口中stop。stop之后最好不要再修改任何设置,以免cfncluster对集群失去控制。

控制节点不受cfncluster stop命令的影响。

由于第一年控制节点24小时运行是免费的,所以一般无需担心控制节点费用问题。然而在第一年后,不用集群时最好将其完全删除。一个遗留的内容是CloudWatch中的关于Auto Scaling Group的Metric,可以手动删除。

删除集群

1
$ cfncluster delete name_of_your_cluster

就可以完全删除,包括使用中的节点和数据盘、自动扩展(Auto Scaling Group)以及警报(Alarm)等。注意控制节点的文件将全部丢失。

关于数据盘

控制节点创建时自动挂载两个数据盘,一个是系统一个是用户文件;计算节点创建时只挂载一个系统盘。

收费

可以在AWS的billing中查看当月使用情况和账单。一般在建立账户24小时之后在会有统计数据。预算(Budget)功能可以在超过设定费用时向用户发送邮件报警,也需要在建立账户24小时之后设置。

关于spot实例的价格可以在Spot Request中查看。On-Demand Price是预留价格,下面的spot价格往往是预留价格的1/6~1/7。一般c4.2xlarge都比较便宜,在Ohio区的只要每小时$0.0677。

已知Bug及处理办法

自动终止计算节点失效

如果尝试手动stop或者reboot控制节点,将会产生重启后无法正常terminate计算节点的问题。此外偶尔Auto Scaling Group自动terminate会失效,导致完成计算的节点无法自动终止,如果不注意可能会浪费钱。所以建议在计算完成之后留意下是否正确终止计算节点,也可以在手机AWS客户端上关注。目前AWS对此无解决方案(https://github.com/awslabs/cfncluster/issues/339)。建议不要在EC2窗口中修改控制节点的任何设定

如果发生自动终止计算节点失效,则手动将Auto Scaling Group中的Desired改为0,之后EC2中的计算节点将自动关闭。不要在EC2中直接terminate计算节点,这样EC2马上会再开几个以保证计算节点数量达到Desired。

控制节点登录后提示更新

如果没有特殊需要,不要对节点进行sudo yum update更新,因为有可能带来未知错误,并且浪费公网流量。

任务卡在僵尸节点上

偶尔由于未知原因任务卡在已经被删除的节点上。这时候可以使用

1
$ sudo -u sgeadmin -i qdel -f job-ID

来强制删除任务。

僵尸节点残留在qhost中

偶尔节点在EC2窗口中已经终止,但是还残留在qhost表中。可以经过以下方法在控制节点上将其清除出集群:

1
2
3
4
5
6
7
8
9
10
11
# first, you need to disable the host from queue to avoid any jobs to be allocated to this host
$ sudo -u sgeadmin -i qmod -d all.q@ip-xxx-xxx-xxx-xxx-east-2.compute.internal
# wait for jobs to be finished execution on this host, then kill the execution script
$ sudo -u sgeadmin -i qconf -ke ip-xxx-xxx-xxx-xxx-east-2.compute.internal
# remove it from the cluster, this opens an editor, just remove the lines referring to this host
$ sudo -u sgeadmin -i qconf -mq all.q
# remove it from allhosts group, this also opens an editor, remove lines referring to this host
$ sudo -u sgeadmin -i qconf -mhgrp @allhosts
# remove it from execution host list
$ sudo -u sgeadmin -i qconf -de ip-xxx-xxx-xxx-xxx
# I normally go to the host and delete the sge scripts as well

对于僵尸节点,前两个命令失败是正常的。第三第四个命令都是打开一个编辑器(一般是vi),需要删除其中关于僵尸节点的内容。第三个命令,删除slots中的节点之后要确认行后没有逗号。第四个命令,如果删除后没有节点,需要在文件的hostlist后面跟一个NONE作为参数。