最速最安でDeep Learning 環境構築をAWSで行う

## 動機
kaggleで戦いたいがlocalなGPUがない。AWSを運用したいが、0.9$/月は高すぎる。AWSを使ったことがなくても、楽に安く運用したい。

## TL;DR
AWS spot instanceを使う。後は[このmedium記事](https://blog.slavv.com/learning-machine-learning-on-the-cheap-persistent-aws-spot-instances-668e7294b6d8)を参考にして改造した。もともとの記事だと[Fast.ai](https://github.com/fastai/courses/tree/master/setup)のAMIを推奨していたが、使い勝手が悪かったため、Amazon謹製のDL AMIを使うこととした。これによりTensorflow, pytorch, chainerの環境構築が一発でできる。

## 目標
- AWS spot instance/Oregon (us-west-2) p2 instance をscript から起動する。
- spot instance でもデータの移行を自動化する。

## Step1: DL のためのspot instanceを走らせる

### 準備
ubuntu 18.04のみで動作確認済み。Windowsはbash on ubuntuとか使えば楽かと思われる。

- AWSのアカウント登録。p2 instance使用申請。(script はOregon us-west-2 regionで書いているため、そこで申請が必要である。)
- [AWS cliのインストール](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/installing.html)
- 必要なscriptを[ここ](https://github.com/Fu-Om/ec2-spotter)からdownloadする。  

` git clone --depth=1 https://github.com/Fu-Om/ec2-spotter.git`

### Virtual Private Cloud(VPC)を設定する。
VPCとはInstance を走らせるNetwork設定と捉えている。[Amazon 公式 Document](http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Scenario1.html)に従って設定することができる。あるいは、怠け者ならば、

`./ec2-spotter/fast_ai/create_vpc.sh`

によっても設定できる。**このとき`subnetId`, `securityGroupId`がprintされる。これらは後々利用するため、控えておくこと。また、~/.ssh/aws-key-fast-ai.pemという秘密鍵が生成されるため確認しておく。**このscriptによって、port 22, port 8888- がそれぞれssh, jupyter notebook のために開放される。余談だが、私は `ssh -L 8888:localhost:8888`でsshするため、port 8888- はlocalhostのみに接続するように設定しているがこれは好みだろう。
※ec2-spotter/create_vpc.sh及びこれから利用するscriptは、[Fast.ai](https://github.com/fastai/courses/tree/master/setup)によるMOOC [Deep Learning for coders](http://course.fast.ai/)がもととなっている。

### 実際にspot instanceを起動する
今回はOregon us-west-2 regionにてspot instance を起動する。異なるregionにて起動する場合は、シェルスクリプトを適宜書き換える必要があるだろう。実行するのは、

``` bash
./ec2-spotter/fast_ai/start_spot_no_swap.sh --ami ami-0b43cec40e1390f34 \
--subnetId subnet-... --securityGroupId sg-...
```

** 起動されたインスタンスのIPがprintされるので控える。**

ここで、
 ami: OregonにおけるAmazon Deep Learning AMI ver15 を示すID
 subnetId: create_vpc.sh で生成されたsubnetId 
 securityGroupId: create_vpc.sh で生成されたsecuritdyGroupId

他にも、
volume_size: default 512GB. GBで設定。
key_name: default: aws-key-fast-ai. ログイン時に使用する鍵。 
ec2spotter_instance_type: default p2.xlarge. インスタンスの種類。 
bid_price: default 0.5$. 最高入札金額。最近Oregonでは0.3$程度で入札されている。自分の最高入札金額よりも高額な金額を入札された場合は強制シャットダウンに合うので注意。

### ログインしてみる
```
ssh -i ~/.ssh/aws-key-fast-ai.pem ubuntu@(前回のスクリプトでprintされたIP)
mkdir test_dir  #あとで引き継ぎができているか確認するためにディレクトリを作成
```
ログイン画面にて、
` conda create tensorflow_p36`
などのコマンドひとつで環境構築ができるようになっている。とても便利である。

## Step2: 構築環境や生成データを引き継ぎ可能にする。
せっかく構築した環境や分析結果が水泡に帰すと辛い。
まず、Elastic Block Storage(EBS)で固定化する。そして、新しいインスタンスを生成するときにそのEBSをroot / にmountするようにする。この記事では、新規の環境構築を前提に話を進めていく。[元の記事](https://blog.slavv.com/learning-machine-learning-on-the-cheap-persistent-aws-spot-instances-668e7294b6d8)には、すでに構築されたEBSをspot instanceにmountする方法も書かれている。

### 準備
[jq](https://stedolan.github.io/jq/)をインストールする。

### Config fileを生成する
前回、起動したspot instanceはfast-ai-gpu-machineと名前がつけられている。
`./ec2-spotter/fast_ai/config_from_instance.sh`
を実行するだけ。
あるいは、 --instance-id i-\*\*\*で使いまわすEBSをしていすることができる。
**注意:このスクリプトを走らせると、インスタンスをshutdownしてしまうので注意！**
これで、./ec2-spotter/my.confができる。この設定は、Oregon専用でハードコードされているので注意。

### 引き継いだSpot instanceを使う
`./ec2-spotter/fast_ai/start_spot.sh`
を実行するだけ。ただしroot volume を交換するために3分弱はかかる。root volumeのswap 前にログインすると、Man In the Middle attackの可能性があると警告を受けて弾かれる。落ち着いて、warning通りに登録した鍵を削除し、再度sshする。

### インスタンスを停止する
`aws ec2 terminate-instances --instance-ids i-***`
instance-ids: 停止したいインスタンスのId. Web console上からでも確認できる。

#### 感想
初めてのqiita 投稿。
Spot instanceだと、使用料金が1/3程度となった。
少しでもみなさんの環境構築が楽になりますように。