[AWS] WordPressのBitnamiというバナーを消す

概要

AWSのWordPressのBitnamiというバナーを消す方法です。

1.ターミナルからbitnamiというユーザー名でログインする

こんな感じ。

$ ssh -i ~/.ssh/MyKeyPair.pem bitnami@{パブリック DNS}

ログインすると下記のようなロゴが表示されます。

       ___ _ _                   _
      | _ |_) |_ _ _  __ _ _ __ (_)
      | _  |  _| ' / _` | '  | |
      |___/_|__|_|_|__,_|_|_|_|_|

2.バナーを非表示にする

$ sudo /opt/bitnami/apps/wordpress/bnconfig --disable_banner 1

3.Apacheを再起動する

$ sudo /opt/bitnami/ctlscript.sh restart apache

おそらく役立つ情報

痒いところに手が届くかもしれない記事を書いています。
フォローしてくれるとやる気になります!

続きを読む

[AWS] リージョンの変更

概要

オレゴンにインスタンスを作ってしまったので、東京へ移した際の方法です。

1.スナップショットを作成する

左のメニューからスナップショットをクリックし、インスタンスのスナップショットを作成します。

2.スナップショットのコピー

作成したスナップショットをクリックし、メニューからコピーをクリックします。
コピー画面が表示されたら、送信先リージョンの場所を東京を選択します。

3.リージョンの変更

右上のリージョンをオレゴンから東京へ変更します。

4.イメージの作成

スナップショットをクリックし、メニューからイメージの作成をクリックします。
注意点として、仮想化タイプを「ハードウェアアシストの仮想化」を選択することを間違えないでください。

5.AMIの確認

左メニューからAMIをクリックし、ファイルが作成されているか確認します。

6.インスタンスの作成

インスタンスを作成をクリックし、左メニューからマイAMIをクリックし、作成したAMIを選択し、インスタンスを作成します。
セキュリティキー、HTTPプロトコルなどは再設定が必要です。

おそらく役立つ情報

痒いところに手が届くかもしれない記事を書いています。
フォローしてくれるとやる気になります!

続きを読む

[AWS] EC2でSSHへアクセス制限をかける

概要

AWSのEC2でSSHへアクセス制限をかける方法です。

インスタンスを表示する

AWSにログインし、左メニューの「インスタンス」からアクセス制限をかけたいインスタンスをクリックする。
「説明」タブのセキュリティグループの右側にあるセキュリティをクリック

セキュリティグループを表示する

適応されているセキュリティグループが表示されたら「インバウンド」タブをクリックし「編集」をクリックする。

セキュリティグループを追加する

下記のように登録します。

タイプ プロトコル ポート範囲 ソース
SSH TCP 22 任意の番号

おそらく役立つ情報

痒いところに手が届くかもしれない記事を書いています。
フォローしてくれるとやる気になります!

続きを読む

raspberry pi で動かしてたお天気ツイート用ボットをAWS Lambda に移行した話

お天気ツイートボット

raspberry pi で お天気ツイートボットを動かしてました。しかし、WiFiドングルの不調が続いてツイート信頼性が落ちてきたので、より安定したプラットフォーム無いかなぁということで、AWS Lambda を使う発想に至りました。

raspberry pi での構成はこんなかんじでした

image.png

cron で シェルスクリプト(twitter.sh)を定期実行しています。このシェルスクリプトの中では単に、bam-weather(バイナリファイル)を実行しているだけです。ツイート自身はbam-weatherで行います。ちなみに、bam-weatherはgolangで書かれています。

お天気ツイートボットのソースは以下に置いてあります。
https://github.com/bamchoh/bam-weather

それを今回はこんな感じにしました。

image.png

cron は CloudWatch Events で代替しました。Lambdaはgolangが実行できないみたいなので、javascript経由でバイナリファイルを実行することでbam-weatherを実行しています。そのjavascript の詳細は以下のサイトに記述されています。また、以下のサイトにはAWS Lambda 上で実行するgolangバイナリの作り方も書いてあります。

http://blog.0x82.com/2014/11/24/aws-lambda-functions-in-go/

構成としてはそんなに大したことはないのと、内容も他のブログポストの内容を見れば大体わかると思います。ここでは私が詰まったところをご紹介したいなと思います。

AWS コンソールにログインできない問題

はい、Lambdaとは全然関係ないところで一番初めに躓きました。前回ログインしたタイミングでルートアカウントの二段階認証をONにしていたにもかかわらず、認証用デバイスを登録していなかったというわけのわからないことをしてしまい、ログインできないという致命的な問題にぶちあたりました。一応、サポートのサイトから問い合わせを送ることで解決したのですが、シアトルから電話がかかってきて、一瞬ビビりましたが、そこはサポートのサイトに書いてある通り「Please support Japanese.」とカタコトでしゃべったら、何かを察してくれたようで、日本のAWSカスタマーサポートから再度電話がかかってきて、事なきを得ました(札幌からかかってきてビビったのはまた別のはなし)

上記のようなトラブルにぶち当たったら、以下の記事を見ましょう。私は解決してから、この記事を見つけました。つらい。。。
http://qiita.com/saku/items/a6ea19ca0acddefda2e9

バイナリ実行できない問題

zipアーカイブを上げて、保存してテストを実行すると何故かエラーに、ログを確認するとError: spawn EACCESなるエラーが確認できました。EACCES ということはパーミッション関係かな?と思い、Lambda のロールの権限を変える方法を色々調べていたんですが、そういうことではありませんでした。原因は Windows でバイナリファイルを作っていたから でした。Windows は実行権限をバイナリファイルに付与できないので、Macを使ってバイナリを作成し、zipアーカイブすることで事なきを得ました。こんなところにもOS依存な問題があるとは。。。

ログ吐けない問題

バイナリを実行するとまたエラーが、open bam-weather.log: read-only file system というエラーでした。そのままですね、bam-weather.log は作れないよって感じだと思います。しかたなく、logファイルに吐くのをやめて、標準出力に出すようにコードを変更しました。

https://github.com/bamchoh/bam-weather/commit/f8eb7eb815188ea9f413b0db4cd19b9152e4d6bb

タイムゾーンが日本じゃない問題

テストを動かして、ツイート/トゥートされる様子を見れたので、その日は就寝。朝起きたときにちゃんとツイートされているかなー?とドキドキとワクワクが入り混じりながら床に就きました。朝起きると、ツイートはされてるんですが、日付が一日前。なんでだろうと考えていると、タイムゾーンを設定していないことに気付きました。(CloudWatch Events を設定するときもUTCで設定したのでピンときました)

調べると、以下の記事の設定をすればよさそうです。
http://qiita.com/nullian/items/39ecf1f6d0194b72e8e6

これは今日設定したばかりなので、明日に結果がわかりますが、おそらくこれで問題なく動き続けてくれるはずです。そうあってほしい。お願い!

まとめ

私の知識の不十分さにより、この一週間ハマり通しでしたが、何とかツイートボッドをraspberry pi から AWS Lambda に移行することができました。単純な構成の中にも、色々な制約や知識が必要であるということを再認識させられる良い機会だったかな?とポジティブに捉えています。なんにせよ、楽しかったです。今後は何か色々なものをAWSを使って作っていけたらなぁと思います。また浮いたraspberry pi で何かしたいなぁとも思っていますので、その時はまたこちらで記事を書かせていただこうかな。ではまた。

続きを読む

AWS IoT Buttonで"ゆれ"とツイートする

AWS IoT Buttonというものがあります。

こんなの↓

(出典:https://aws.amazon.com/jp/iotbutton/

簡単に言えばAmazon Dash Buttonの処理をカスタマイズ出来る版ってな感じのシロモノです。
これがあれば、あんなことやそんなことが出来ると夢が拡がる一方ですが、
取り敢えずはAWS IoT初体験として「押したら”ゆれ”とツイートするボタン」を試しに作ってみました。
特に意味はありません。

ちなみに2017年8月時点ではまだ日本での販売はされておらず、
今回入手したものは本家の米Amazonから購入しています。うっかり5個買っちゃった。

概観図

tweet_button1.png

Twitterのアプリ登録

Twitterへ投稿する処理を実装するためには、あらかじめアプリ登録を済ませておく必要があります。
具体的な手順は下記のとおりです(一連の手順やWebページのUIは変更される可能性有)。

  1. ボタンを押したとき呟くことになるアカウントでTwitterへログインする
  2. https://apps.twitter.com へアクセス
  3. 右上の「Create New App」を押す
  4. Name、Description、Websiteを適当に入力する
    • Websiteは必須項目なので何かしらを入力(https://twitter.com など)、Callback URLは空でOK
  5. Twitter Developer Agreementを確認してチェックを付けた後、「Create your Twitter application」を押す
  6. 登録成功した感じのページに遷移したらタブの「Keys and Access Tokens」を選択
  7. 下の方にある「Create my access token」のボタンを押す

ここまでの操作により、下に赤枠で示した4つの情報が確認できればTwitter側は準備完了です。

※Access Tokenは途中にあるハイフンも含むのでコピペの際に間違って消さないよう注意

AWS IoT Buttonのセットアップ

AWS IoT Buttonを利用するためにはAWSアカウントが必要です。
まだアカウントを作成していない場合はこちらなどから頑張ってサインアップします。

AWSコンソールへサインイン出来たら、
ここに書いてある通りにセットアップを実行します。

一つ注意点として、セットアップ手順を進めるPCが無線LANにアクセスできない端末の場合、
無線LANアクセス可能なPCへ証明書と鍵を送ってButtonの設定を完了させる必要があります。
これにもたついているとButtonへの接続が切れて入力やり直しとかになったりします。
まぁ今時そんなPCはまず無いと思いますが、念のため。
なんでこのPC無線LAN子機内蔵してないんだ……

Lambda関数の処理を実装

AWS IoT Buttonのセットアップ手順でLambda関数の作成までは行ったので、
その関数の処理をTwitterへ投稿する処理に変更します。
上でセットアップしたButtonが押されると、ここで書いた処理が実行されるという感じになるわけですね。

下記の手順は既にNode.js & npmがインストールされているという前提になります。

まず、作業ディレクトリを作成して、

mkdir iotbutton
cd iotbutton

Twitterのライブラリをインストールし、

npm install twitter

Twitterへ”ゆれ”と投稿する処理を書いてindex.jsとして保存した後、
(clientのパラメータにはTwitterでアプリ登録した際に確認したキーを指定)

const Twitter = require('twitter');

const client = new Twitter({
    consumer_key: 'xxxxxxxx',
    consumer_secret: 'xxxxxxxx',
    access_token_key: 'xxxxxxxx',
    access_token_secret: 'xxxxxxxx'
});

exports.handler = (event, context, callback) => {
    client.post('statuses/update', {status: 'ゆれ'}, function(error, tweet, response) {
        if (error) {
            console.log(error);
            callback(error);
            return;
        }
        console.log(tweet);
        callback();
    });
};

最後にnode_modulesindex.jsをzipで固めてLambda関数のコードとしてアップロードするだけです。
とっても簡単!

一度アップロードした後は、AWSコンソール上からインラインでコードの編集が出来るようになります。

動作確認

これで準備は全て整いましたので、早速試してみます。
ただし、ゆれてもいないときに一人ゆれツイートを投稿して誤爆しちゃったみたいな感じになるのは嫌なので
今だけ”This is a test tweet by Lambda.”に文言を変えています。

まずはButtonを押下。
少し間を空けてからタイムラインを更新すると……

tweet_button2.png

成功です!
これでもういつ地震が来ても大丈夫。

制限事項とか残課題とか

  • Buttonを押してから呟きが投稿されるまでに5秒~10秒くらいのタイムラグがある。自分で投稿した方が速そう
  • セットアップしたWi-Fiアクセスポイントのある場所でしか使えない。
  • 間違えて押すと悲しいことに。 → 2回押されたらキャンセル or 削除させる?

雑感

タイムラグが致命的なため、地震ツイートRTA用途には使えなさそうなのが非常に残念でした。

それはともかくとして、セットアップの容易さとAWSとの連携による汎用性の高さを併せ持つ
このButton(1個約20$)は魅力的で可能性を感じるプロダクトだと改めて実感しました。
早く日本でも販売開始してほしい。

余談ですが、国産のIoTプロダクトではMESHというのもありますね。
機会があればこっちも触ってみるかもしれません。

続きを読む

EC2(スポット)インスタンス上でChainerMNのマルチノード分散学習

EC2(スポット)インスタンスでChainerMNを使う(マルチノード分散学習)

概要

  • EC2(スポット)インスタンスでChainerMNのマルチノード分散学習をする方法

    • 環境変数の設定方法
    • sshにStrictHostChecking noを追加
    • セキュリティグループの設定(VPC内からの全アクセスを許可)
  • EC2上でマルチノード分散学習する場合の注意点
    • p2.xlargeを使ってマルチノード分散学習は性能がでない
    • g3.4xlargeを利用すると良い
  • マルチノード学習した際の性能の簡単な評価
    • ImageNetの学習ではp2.8xlargeを使う時と同等かそれ以上のコストパフォーマンス

やりたかったこと

スポットインスタンスの価格が比較的安いGPU1個のインスタンス(p2.xlargeg3.4xlarge)を複数使って、ディープラーニングの学習を高速化させたかった。

学習を高速にする手段としては、マルチノードで分散する以外に、そもそも1台あたりのGPU数を増やす、という選択肢もある。
しかし、GPUを複数個積んでいるEC2のインスタンスはどれも高いし、スポットインスタンスで価格を抑えられないことがある。例えば、p2.8xlargeはオンデマンドインスタンスの場合、\$7.2/hかかる。スポットインスタンスの価格は、ここ1週間くらいはp2.8xlargeが\$2.5/h弱のようだが、ちょっと前は\$72/hに張り付いていた。
あるいは、自前で学習用計算機用意する手もあるが、GPU複数台積むマシンとなるとかなり高くつくことになる。個人の趣味の範囲内だと、電気代を抜いてもAWSを使うより高くなる可能性が高そう。

なので、p2.xlargeなどのスポットインスタンスでの値段が低め(〜\$0.3/h)で抑えられているインスタンスを複数利用して、学習を高速化させるという方針に至った。オンデマンドのp2.8xlargeと比べて、スポットインスタンスのp2.xlargeg3.4xlargeは1GPU当たりの値段で1/3ほどなので、マルチノードの分散学習の複雑さや効率の悪さはGPUの台数で補えるという目論見。

ChainerMNを使った分散学習 in AWS

環境の準備

ChainerMNのインストール

ChainerMNをインストールする方法自体は、もう多数の記事・情報があるので、詳細は省く。自分はここChainerMNのチュートリアルを参考にした。
やったことを列挙すると、以下の通り。

  • CUDA 8.0のインストール
  • cuDNN 6.0のインストール
  • NCCL 1.xのインストール
    • GitHubのページにはno longer maintainedとあるが、まだNCCL2は使えかった
  • OpenMPIのビルド・インストール
  • Chainer、ChainerMNのインストール

この作業はGPUを積んでいる中で安いインスタンス(p2.xlarge)を利用すると良い。

環境変数の設定

sshに非対話モードで入った時に、CPATHLD_LIBRARY_PATHが適切な値(具体的にはcudaのパスを含む)になっていないと学習スクリプトがうまく動かない。
/etc/bash.bashrcを以下のようにした。

/etc/bash.bashrc
export PATH=/usr/local/cuda-8.0/bin:${PATH}
export LD_LIBRARY_PATH=/usr/local/cuda-8.0/lib64:${LD_LIBRARY_PATH}
export CPATH=/usr/local/cuda-8.0/targets/x86_64-linux/include:${CPATH}

以下のコマンドを叩いた時、PATHLD_LIBRARY_PATHが適切に設定されていれば良い。

$ ssh localhost 'env'

sshの設定

マルチノード分散学習をする際、インタラクティブな操作なしに別ノードへsshで接続できる必要がある。したがって、鍵認証の設定をする。また、デフォルトでは最初に接続しようとすると、Are you sure you want to continue connecting (yes/no)?のメッセージが出て、yes/noの入力を求められるので、手間を考えるとこれも対処する必要がある。

まず、鍵認証の設定をする。

$ ssh-keygen #パスフレーズなし、~/.ssh/id_rsaに置く
$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

次に、.ssh/configを以下のとおりにして、yes/no入力をなくす

~/ssh/.config
Host *
    StrictHostKeyChecking no

どちらもセキュリティ上良いとは言えないが、最終的にはAWSのセキュリティグループで外部ネットワークからのインバウンドを遮断して運用すれば許容範囲と思っている。

ENAの有効化

必要なのかはわからないが、UbuntuはデフォルトではENAが有効になっていないようだったので、有効にする。最新の手順はここにあるので、これの通りに行う。
やるべきことは以下の3つ

  1. インスタンス上で、ENAのモジュールを追加
  2. インスタンスを停止
  3. ローカルからaws CLIでENAを有効化

AWS上のリソースの準備

1. VPC、サブネット、プレイスメントグループの準備

それぞれ適当な名前で準備する。VPCとサブネットは一度EC2インスタンスを起動すればついでにできるし、プレイスメントグループは、EC2のコンソールから、ネットワーク&セキュリティ → プレイスメントグループのページに行って作成すれば良い。
なお、プレイスメントグループはいるのかどうか分からないが、ネットワークの帯域幅をフルに出すには必要らしいので自分は作成した。

2. 学習ノード用のセキュリティグループの準備

セキュリティグループの準備も必要。インバウンドルールでは、「すべてのトラフィック・すべてのポート範囲へのVPCからのアクセス」を許可する。本来はもっと絞りこめると思うが、調べるのが面倒だったのでVPC内に全部公開した。
EC2コンソール上では、すべてのトラフィック すべて 0-65535 カスタム <VPCのCIDR>となっていれば良い。

3. (Optional) AMIの作成

必要はないが、ここまで終えた時点でAMIを作っておくと別のことをしたい時に無駄な出費を防げる。
AMIの作成方法は省略。

学習スクリプトなどの準備

最後に、学習用のスクリプト、データセットなどを準備する。

今回、自分はchainermnについているImageNetのサンプルを使った。
git clone --depth 1 https://github.com/chainer/chainermn.gitとして、chainermnのソースを落とすとchainermn/examples/imagenetの下にImageNetのサンプルがあるのでこれを用いる。また、自分の場合、models_v2/nin.pyをchainerのexamples/imagenet/nin.pyに置き換えないと動かなかったので、chainerのソースも落としてきてcpした。

次に、データセットを準備する。データセットの準備方法は、ここここなどが参考になる。

ここまで終えたら、インスタンスを止めてAMIを作成する。

実行方法(1ノード)

テストも兼ねて1ノードで学習を走らせる場合は、インスタンスを起動した後、sshでログインして、

$ mpiexec -n 1 python3 ~/chainermn/examples/imagenet/train_imagenet.py train.txt test.txt

などとすれば良い。ここで、train.txt、test.txtはそれぞれ準備したデータセットのパス

参考: ChainerMN チュートリアル

実行方法(マルチノード)

上で作成した学習スクリプトの入ったAMIを利用し、スポットインスタンスを適当に何個か立ち上げる。この時、VPC、プレイスメントグループ、セキュリティグループは上で準備したものを忘れず利用する。
なお、別にスポットインスタンスでなくてもいいが、費用を抑えて実験してみたいだけならスポットインスタンスの方が適していると思う。ただし、スポットインスタンスが突然中断するリスクを減らすため、高めに価格を設定しておくと安心。

また、多少値段は上がるが、p2.xlargeでなく、g3.4xlargeを使うと良い (理由は”注意点”で後述)。

以下では、2台のg3.4xlargeインスタンスを立ち上げ、それぞれのプライベートIPが172.31.41.13172.31.41.14となったとする。
まず、どちらか1台(以下では172.31.41.13の方とする)にsshでログインする。ログインしたら、以下の内容のホストファイルを~/hostfileに作成する(パスはどこでも良い)。

~/hostfile
172.31.41.13 cpu=1
172.31.41.14 cpu=1

(プライベートIPは、その時立ち上げたスポットインスタンスを見て適宜修正する必要あり。)

次に、以下のコマンドを叩くと、2台のマシンで分散学習される。

$ mpiexec -n 2 --hostfile ~/hostfile python3 ~/chainermn/examples/imagenet/train_imagenet.py train.txt test.txt

参考: ChainerMN チュートリアル

注意点(ネットワークの帯域幅を考慮する必要あり)

GPU付きインスタンスの中ではp2.xlargeが値段は安いのだが、ネットワークの帯域幅が小さく、性能が出なかった。iperfを使ってはかった結果では、1.44Gbps。一方、g3.4xlarge10Gbpsでるというスペックだし、実際iperfではかると10Gbpsでた(情報提供:https://twitter.com/grafi_tt/status/895274632177000449 )。

いくら安く分散学習させたいと言っても、p2.xlargeだと性能向上が見られなかったので、g3.4xlargeを使う方が良いと思う。

性能確認

学習が高速化できるのか確認するため簡単な性能測定をした。なお、どれも1回しか計測してないし、真面目に条件を揃えたわけではないので、数字は参考程度に。

以下のパターンで、ImageNetの学習にかかる時間を測定した。

  1. g3.4xlarge1台で、ChainerMNを利用
  2. g3.4xlarge複数台(2, 4, 6, 8, 10, 12)で、ChainerMNを利用
  3. p2.8xlarge(8GPU)で、ChainerMNを利用

結果

以下の通り。
分散すればちゃんと高速化されるし、p2.8xlargeと比べても安いまたは同等程度の値段でほぼ同じ性能を出せている。ただ、この辺は学習させるネットワークやデータセットによって色々異なるんだろうな。

表1: 1エポック当たりの時間

条件 1エポックあたりの平均時間 (sec)
g3.4xlarge*1 34.4
g3.4xlarge*2 21.8
g3.4xlarge*4 12.5
g3.4xlarge*6 9.2
g3.4xlarge*8 7.9
g3.4xlarge*10 6.3
g3.4xlarge*12 5.2
p2.8xlarge 7.9

ちゃんと分散するにつれて短い時間で学習できている。


表2: 値段 – 総実行時間

条件 値段 (\$/h) 総実行時間 (sec)
g3.4xlarge*1 0.3 344.3
g3.4xlarge*2 0.6 217.8
g3.4xlarge*4 1.2 125.2
g3.4xlarge*6 1.8 92.4
g3.4xlarge*8 2.4 79.2
g3.4xlarge*10 3.0 63.0
g3.4xlarge*12 3.6 51.7
p2.8xlarge 7.2(オンデマンド) / 2.5(スポットインスタンス利用時) 79.1

備考:g3.4xlargeのスポットインスタンスの値段は\$0.3/hとして計算

p2.8xlargeをオンデマンドで利用する場合に比べると、より安く高速な学習ができる。p2.8xlargeがスポットインスタンスの場合と比べても、ほぼ同等の性能が今回の例では出た。


グラフ1: epoch – elapsed_time
graph1.png


グラフ2: epoch-validation/main/accuracy
graph2.png

epochが少なすぎてわかりやすいデータにならなかったが、分散させるほど同エポックでの精度は悪化する傾向にあるらしい。直感的にもそんな気はする。とはいえ、マルチノードの場合とp2.8xlargeでノード内で分散した場合では大きな精度の差は見つけられない。分散学習するなら、エポックを大きめに設定する必要があるようだが、それはマルチノード分散学習の問題というより、現在のChainerMN全体の問題の可能性が高い。


その他備考
分散学習では、最初の1回のmpiexecは時間がかかるらしい。上記計測は、2回目のmpiexecで行っている。原因は、ノード間の接続を確立する時間が追加されているからではないかと思うが、詳細は不明。ただし、学習時間が長くなるにつれて、その時間は無視できるものになると思われる。

まとめとか

少なくともImageNetでは、マルチノードの分散学習でも相当の学習時間の短縮が見込める。また、8/7からChainerMNを初めて5日でここまでできたので、非常に難しい作業が必要というわけでもない。
そのため、AWS上でのディープラーニング学習を高速化させたい時、選択肢に入れる価値はあると思う。最初に書いたような、複数GPUを積んだスポットインスタンスが高い時にも使えるし、あるいはp2.8xlargeを複数使ってさらに高速化する、という使い方もマルチノードの分散学習はできるはず。

一方で、データセットが増えた時どうなるのか、モデルが複雑になった時どうなるのか、などは調べてない。実際に使ってみるとたいして高速化されなかった、みたいなケースはありそう。

要改善点

とりあえずテストするだけなら上記手順でもできたが、実際にディープラーニングを利用するプロジェクトに組み込むとなると以下の点を改善しないといけない。

学習スクリプトの実行方法

本来は、aws CLIとかSDKからスポットインスタンスを立ち上げて、自動で学習を回したい(ここみたいに)。
そのためには、UserDataのスクリプトで学習スクリプトを実行する必要があるが、以下の点に注意が必要。

  1. mpiexecをするインスタンスの決定方法
  2. ホストファイルの作成方法
  3. すべてのインスタンスが立ち上がるまでの待ち合わせ処理

1については、特定のタグを全インスタンスに付けておき、aws ec2 describe-instancesで全インスタンスのプライベートIPを取得、辞書順最小のインスタンスでmpiexecすれば解決しそう。
2は、describe-instancesした時に全部のプライベートIPがわかるんだからホストファイルもついでに生成できる。
3は、ポーリングなりなんなりでやればできるはず。この時、ついでに学習パラメータの環境変数への展開やS3からデータセットのダウンロードも待ち合わせ処理すると色々便利そう。

中断時の対処

スポットインスタンスなので、たまに強制終了させられることがある。

  1. 定期的なS3へのスナップショットアップロード(systemd-timer)
  2. 1台でも終了したら全台終了して無駄な出費の削減
  3. 学習開始時にスナップショットがあればそれを読み込み

の3つの対処が必要。

続きを読む

awsrmを使ってALB配下のEC2インスタンスIDを取得する

ALBになってから ALB -> ( Listener ) -> Target group -> EC2インスタンス というつながりになりました。

「ALB配下のEC2インスタンスについてテストをしたい」というときに少し遠いです。

こういうときに awsrm を使うと直感的にEC2のインスタンスIDを取得できます。

require 'awsrm'

instance_ids = Awsrm::AlbTargetGroup.all(alb: 'my-alb-load-balancer-name').map do |target|
  target.instance_ids
end.flatten

これで、ALB配下の複数のTarget groupの下に紐付いているEC2インスタンスのIDを取得できます。

「ALBはTagで管理している」というときにも、

require 'awsrm'

alb_id = Awsrm::Alb.one(tags: {Role: 'web'}).id
instance_ids = Awsrm::AlbTargetGroup.all(alb: alb_id).map do |target|
  target.instance_ids
end.flatten

「複数のALB(VPC内のALB全て、など)」というときにも、

require 'awsrm'

instance_ids = Awsrm::Alb.all(vpc: 'my-vpc').map do |alb|
  Awsrm::AlbTargetGroup.all(alb: alb.id).map do |target|
    target.instance_ids
  end.flatten
end.flatten

と、直感的に記述できます。

インスタンスIDが取得できれば、awspecで「ALB配下のEC2インスタンスにスケジュールイベントがないこと」というテストを書くのも簡単です。

require 'awspec'
require 'awsrm'

instance_ids = Awsrm::AlbTargetGroup.all(alb: 'my-alb-load-balancer-name').map do |target|
  target.instance_ids
end.flatten

instance_ids.each do |id|
  describe ec2(id) do
    it { should be_running }
    it { should_not have_events }
  end
end

awsrmはawspecとは独立していますので、テスト以外にも様々な用途で活用できると思います。

もし、awsrmに実装して欲しいリソースがありましたら、PR/IssueやTwitterでのメンションなどよろしくお願いします。

続きを読む