developer's diary

最近はc#のエントリが多いです

AWS SDK for JavaScript in the Browserでs3+js+facebookアプリのチュートリアルをやってみた際のハマりどころメモ

ブラウザからS3に画像をアップロードするfacebookアプリケーションのチュートリアルがあったので試してみました。

やってみたチュートリアル(※英語)

AWS SDK for JavaScript in the Browser (Developer Preview)にアクセス

f:id:mitsugi-bb:20140308200938p:plain

Getting Started をクリック。↓のようなページ。

f:id:mitsugi-bb:20140308201050p:plain

1.Facebookアプリを作成

Facebook developer pageにアクセスしCreate New appでアプリ作成。既にある場合はこの手順は不要。

f:id:mitsugi-bb:20140308203228p:plain

アプリの名称とカテゴリを入力して登録。アプリ名にfbとかfacebookという文字は含めることができなかった。

f:id:mitsugi-bb:20140308203902p:plain

作成したらアプリIDを控える。

f:id:mitsugi-bb:20140308204623p:plain

2.IAMの作成

IAM:Identity and Access Management の略です。

IAM consoleにアクセスして、Create New Role。

f:id:mitsugi-bb:20140308211939p:plain

ロール名を入力。

f:id:mitsugi-bb:20140308212034p:plain

Grant access to web identity providersを選択

f:id:mitsugi-bb:20140308212145p:plain

先ほどつくったFacebookのアプリIDを入力

f:id:mitsugi-bb:20140308212302p:plain

次へ。

f:id:mitsugi-bb:20140308212452p:plain

カスタムポリシーを選択。

f:id:mitsugi-bb:20140308212551p:plain

JavaScript in the BrowserのJSONをコピー

f:id:mitsugi-bb:20140308212831p:plain

コピーしたJSONを貼付ける。その際に、YOUR_BUCKET_NAMEの部分を自分のバケット名に置き換える。ここでやっていることは、facebookアプリのユーザがS3に対してどのような権限を持つかを記載しているみたい。

f:id:mitsugi-bb:20140308213047p:plain

あとはCreateRoleのボタンで作成完了。Role ARNの文字列は後から使います。

f:id:mitsugi-bb:20140308213404p:plain

3.S3バケットにCORSの設定

Amazon S3 consoleにアクセスして、 Edit CORS Configurationを選択。

f:id:mitsugi-bb:20140308214228p:plain

CROSSの内容をコピペして張り付け。 AllowedOriginの所は自分のドメインにしといた方が安全だけどもSSLでない場合は偽装できそうな気がする。。

f:id:mitsugi-bb:20140308214421p:plain

4.HTMLを作成してS3にアップ

サンプルのHTMLをコピーして、'YOUR_APP_ID', 'YOUR_ROLE_ARN','YOUR_BUCKET_NAME' をそれぞれ書き換える。

f:id:mitsugi-bb:20140308214740p:plain

でHTMLをS3にアップロード。

注意:バケットがtokyoの場合は他にも一部修正が必要です。

var bucket = new AWS.S3({params: {Bucket: bucketName},
      region: 'ap-northeast-1',
      maxRetries: 15});

regionを選択してないと、No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin api....ってエラーが発生します。

どうも作成途中のチュートリアルっぽいので一部修正

bucket.putObject(params, function (err, data) {
  if (err) {
    results.innerHTML = 'ERROR: ' + err;
  } else {
    var imageTag = "";
    results.innerHTML += imageTag;
  }
});

↓バケットにファイルをアップした際に、imgタグをinnerHTMLに設定するように修正

var fileurl = 'http://' + bucketName + '/' + objKey;
bucket.putObject(params, function (err, data) {
  if (err) {
    results.innerHTML = 'ERROR: ' + err;
  } else {
    var imageTag = '<img src="' + fileurl + '"/>';
    results.innerHTML += imageTag;
  }
});

5. 確認

S3にアップしたサイトにアクセスすると、facebookのログインを求められる。ログインしてる場合は省略される。

f:id:mitsugi-bb:20140308220552p:plain

ログイン後にアプリの認証。

f:id:mitsugi-bb:20140308220741p:plain

OKすると、ファイルアップロードのボタンが表示される。

f:id:mitsugi-bb:20140308220842p:plain

ファイルをアップロードすると、S3にアップロードされて、保存された画像がimgタグに書き出され表示される。

f:id:mitsugi-bb:20140308221035p:plain

生成されたimgタグを確認

f:id:mitsugi-bb:20140308221224p:plain

バケットにも反映されてる。

f:id:mitsugi-bb:20140308221343p:plain

f:id:mitsugi-bb:20140308221635p:plain

以上でチュートリアルが完了。

ふりかえり。

keep

s3に関する調査は今後も続けよう。

problem

リージョンを意識しわすれて、CROSS部分でハマった。 mitsugeek.netって自分のドメインのページでテストしてるのはあまり良くない。

try

セキュリティの部分。fecebookのユーザ単位で見れる見れない等の制御とかできるのか?他のユーザのディレクトリに保存できてしまうのか?アクセスログとかいるのか?

場合によっては緩いサービスでしか利用価値はないかもしれない。 とはいいつつも、Developer Previewということなので、 これでサービス運用は企業システムでは今のところあり得ない話かもしれない。

ec2のmicroインスタンスでPlay!2.1.1を動かす。

play frameworkに関するのslideshare(Play2.0+Javaでサービスを本番稼働させた話 #play_ja)を見ててそうそうと自分もハマった部分があったので、自分なりの解決策を。

問題

Amazon EC2 microでPlay!2.0が起動しない。
java -­‐Xms512M -­‐Xmx1536M
でPlay!2.0はデフォルト起動される      
  • --Xms512M:初期ヒープサイズを512Mに設定
  • --Xmx1536M:最大ヒープサイズを1536Mに設定
  • microインスタンスのメモリは613 Mでswapがない

解決策

cloud-initのYAMLをgistに書いてみました。

ec2のマイクロインスタンスでplayを動かす準備 ・時間の設定 ・文字コードの設定 ・swap領域の作成

cloud-initを利用して、インスタンス立ち上げ時にswapを作るという方法です。

swapの作成方法はAdding swap to an EC2 micro instance on Amazonを参考にしました。

いつものスポットインスタンスの起動スクリプトに組み込んで使ってます。

#!/bin/bash

AMI='ami-xxxxxxxx';
INSTANCE_TYPE='t1.micro';
PRICE='.003';
SUBNET='subnet-xxxxxxxx';
KEYPAIR='xxxxxxxxxx';
SECURITYGROUP='sg-xxxxxxxx';
DATA='#cloud-config
repo_upgrade: all
packages:
  - java-devel
  - git

runcmd:
  - [cp, /usr/share/zoneinfo/Asia/Tokyo, /etc/localtime]
  - [sed, -i, 's/LANG="en_US.UTF-8"/LANG="ja_JP.UTF-8"/', /etc/sysconfig/i18n]
  - [dd, if=/dev/zero, of=/var/swapfile, bs=1M, count=1024]
  - [mkswap, /var/swapfile]
  - [swapon, /var/swapfile]
';

#スポットインスタンスのリクエストを行う
SIR_ID=` ec2rsi $AMI -t $INSTANCE_TYPE -p $PRICE -n 1 -r one-time -s $SUBNET -k $KEYPAIR -g $SECURITYGROUP -d "$DATA" | awk '{if(NR==1) print $2;}' `

#2分間待機
sleep 120

TMP_EC2='';
while true; do
  #ec2のインスタンス情報取得(スポットインスタンスのIDを指定)
  TMP_EC2=`ec2din --filter "spot-instance-request-id=$SIR_ID"`;

  if test ${#TMP_EC2} -gt 0 ; then
    #情報が取得できた場合

    #インスタンス情報、ローカルIPの情報を取得する
    INSTANCE_ID=`echo $TMP_EC2 | awk '{ print $5 }'`;
    LOCAL_IP=`echo $TMP_EC2 | awk '{ print $52 }'`;

    #ループを抜ける
    break
  fi

  #30秒待機
  sleep 30
done

#IPアドレスを取得する
EIP_OBJ=`ec2allocaddr -d vpc`;
EIPALLOC=`echo $EIP_OBJ | awk '{ print $4 }'`
GLOBAL_IP=`echo $EIP_OBJ | awk '{ print $2 }'`

sleep 10

#IPアドレスをec2インスタンスに割り当てる
EIPASSOC_OBJ=`ec2assocaddr -a $EIPALLOC  -i $INSTANCE_ID -p $LOCAL_IP `

sleep 10

EIPASSOC=`echo $EIPASSOC_OBJ | awk '{ print $4}'`

#結果出力
echo "[info]instance_id: $INSTANCE_ID";
echo "[info]globalId: $GLOBAL_IP";
echo "[info]eipassoc: $EIPASSOC";
echo "[info]eipalloc: $EIPALLOC";
echo "[example] ssh -i ${KEYPAIR}.pem ec2-user@${GLOBAL_IP} ";
echo "[example] ec2disaddr -a $EIPASSOC ; ec2reladdr -a $EIPALLOC ; ec2kill $INSTANCE_ID ; "

なんだかんだいって、microインスタンスとsmallインスタンスには価格的な大きな壁があるので、 play framework2もmicroで使いたいです。 24h365d動かすならawsは少し高い気がしますが、実験はawsが手っ取り早いです。

CDPのBootstrapパターンの片鱗に触れてみる。cloudinitでgithubからwebサイトを取得してhttpd起動する。

CDPのBootstrapパターンの片鱗に触れてみる。ec2-request-spot-instancesでcloudinitでhttpd起動まで。の続きです。

cloudinitでgithubからサイト情報を取得して、httpdを起動する。という内容です。

#!/bin/bash

AMI='ami-xxxxxxxx';
INSTANCE_TYPE='t1.micro';
PRICE='.003';
SUBNET='subnet-xxxxxxxx';
KEYPAIR='xxxxxxxx';
SECURITYGROUP='sg-xxxxxxxx';
DATA='#cloud-config

packages:
  - httpd
  - httpd-devel
  - git

runcmd:
  - [/sbin/chkconfig, httpd, on]
  - [/etc/init.d/httpd, start]
  - [ git, clone, "https://github.com/mitsugeek/mitsugeek.net.git", "/var/www/html"]
';

#スポットインスタンスのリクエストを行う
SIR_ID=` ec2rsi $AMI -t $INSTANCE_TYPE -p $PRICE -n 1 -r one-time -s $SUBNET -k $KEYPAIR -g $SECURITYGROUP -d "$DATA" | awk '{if(NR==1) print $2;}' `

~~~~省略~~~~

省略部分はawsでVPC内にスポットインスタンスをリクエストしてEIP割り当てるまでのbashスクリプトと同じです。

5分くらいまつと、IPアドレスの情報が出力されるのでsafariでアクセス。

f:id:mitsugi-bb:20130417005952p:plain

PHPの環境であれば↓な感じ?

#!/bin/bash

AMI='ami-xxxxxxx';
INSTANCE_TYPE='t1.micro';
PRICE='.003';
SUBNET='subnet-xxxxxxxx';
KEYPAIR='xxxxxxxx';
SECURITYGROUP='sg-xxxxxxxx';
DATA='#cloud-config
repo_upgrade: all
packages:
  - httpd
  - httpd-devel
  - php
  - php-devel
  - php-pecl-apc
  - php-gd
  - php-mbstring
  - php-pdo
  - php-mcrypt-php

runcmd:
  - [cp, /usr/share/zoneinfo/Asia/Tokyo, /etc/localtime]
  - [sed, -i, 's/LANG="en_US.UTF-8"/LANG="ja_JP.UTF-8"/', /etc/sysconfig/i18n]
  - [/sbin/chkconfig, httpd, on]
  - [/etc/init.d/httpd, start]
';

#スポットインスタンスのリクエストを行う
SIR_ID=` ec2rsi $AMI -t $INSTANCE_TYPE -p $PRICE -n 1 -r one-time -s $SUBNET -k $KEYPAIR -g $SECURITYGROUP -d "$DATA" | awk '{if(NR==1) print $2;}' `

参考

CDPのBootstrapパターンの片鱗に触れてみる。ec2-request-spot-instancesでcloudinitでhttpd起動まで。

awsでVPC内にスポットインスタンスをリクエストしてEIP割り当てるまでのbashスクリプトは単にインスタンスが起動してEIPが割り当てられるだけでした。

次にCDP:Bootstrapパターンを試してみたいと思います。 とはいうもののcloudinit初めてなので、RPMパッケージのhttpdをインストールして起動するだけのシンプルな構成を試してみます。

#!/bin/bash

AMI='ami-xxxxxxxx';
INSTANCE_TYPE='t1.micro';
PRICE='.003';
SUBNET='subnet-xxxxxxxx';
KEYPAIR='xxxxxxxx';
SECURITYGROUP='sg-xxxxxxxx';
DATA='#cloud-config

packages:
  - httpd
  - httpd-devel

runcmd:
  - [/sbin/chkconfig, httpd, on]
  - [/etc/init.d/httpd, start]
';

#スポットインスタンスのリクエストを行う
SIR_ID=` ec2rsi $AMI -t $INSTANCE_TYPE -p $PRICE -n 1 -r one-time -s $SUBNET -k $KEYPAIR -g $SECURITYGROUP -d "$DATA" | awk '{if(NR==1) print $2;}' `

#2分間待機
sleep 120

TMP_EC2='';
while true; do
  #ec2のインスタンス情報取得(スポットインスタンスのIDを指定)
  TMP_EC2=`ec2din --filter "spot-instance-request-id=$SIR_ID"`;

  if test ${#TMP_EC2} -gt 0 ; then
    #情報が取得できた場合

    #インスタンス情報、ローカルIPの情報を取得する
    INSTANCE_ID=`echo $TMP_EC2 | awk '{ print $5 }'`;
    LOCAL_IP=`echo $TMP_EC2 | awk '{ print $52 }'`;

    #ループを抜ける
    break
  fi

  #30秒待機
  sleep 30
done

#IPアドレスを取得する
EIP_OBJ=`ec2allocaddr -d vpc`;
EIPALLOC=`echo $EIP_OBJ | awk '{ print $4 }'`
GLOBAL_IP=`echo $EIP_OBJ | awk '{ print $2 }'`

sleep 10

#IPアドレスをec2インスタンスに割り当てる
EIPASSOC_OBJ=`ec2assocaddr -a $EIPALLOC  -i $INSTANCE_ID -p $LOCAL_IP `

sleep 10

EIPASSOC=`echo $EIPASSOC_OBJ | awk '{ print $4}'`

#結果出力
echo "[info]instance_id: $INSTANCE_ID";
echo "[info]globalId: $GLOBAL_IP";
echo "[info]eipassoc: $EIPASSOC";
echo "[info]eipalloc: $EIPALLOC";
echo "[example] ssh -i ${KEYPAIR}.pem ec2-user@${GLOBAL_IP} ";
echo "[example] ec2disaddr -a $EIPASSOC ; ec2reladdr -a $EIPALLOC ; ec2kill $INSTANCE_ID ; "

上記スクリプトで、httpdがインストールされて起動されるインスタンスが立ち上がりました。

f:id:mitsugi-bb:20130410035625p:plain

これを改良していけば、git-hubやS3からサイトをダウンロードしてWEBサイトを起動するのはシンプルにできそうです。

参考エントリ

awsでVPC内にスポットインスタンスをリクエストしてEIP割り当てるまでのbashスクリプト

前回のエントリ、mac環境にbrew installでawsコマンドラインツールをインストールしてスポットインスタンスをあれこれawsコマンドラインツールで起動したスポットインスタンスにEIPを割り当てる(VPC環境)の内容をbashスクリプトにまとめてみます。

利用するコマンド

コマンド(リンク) 説明
ec2-request-spot-instances ( ec2rsi ) スポットインスタンスをリクエストする
ec2-describe-instances ( ec2din ) ec2インスタンスの情報を取得する
ec2-allocate-address ( ec2allocaddr ) EIPを取得する
ec2-associate-address ( ec2assocaddr ) EIPをインスタンスに割り当てる

処理手順

今回bashスクリプトにした手順

  1. スポットインスタンスをリクエストしてリクエストIDを変数に設定
  2. 3分待機
  3. リクエストIDを指定して、ec2のインスタンス情報を取得する(取得できるまで30秒毎に実行する)
  4. ec2インスタンス情報が取得できたらIPアドレスを取得する
  5. 取得したIPアドレスをec2インスタンスに割り当てる
  6. sshでのアクセス方法や、インスタンスを止める方法等を出力して終了

create-spot-instances.sh (今回作ったbashスクリプト)

#!/bin/bash

AMI='ami-xxxxxxxx';
INSTANCE_TYPE='t1.micro';
PRICE='.003';
SUBNET='subnet-xxxxxxxx';
KEYPAIR='xxxxxxxx';
SECURITYGROUP='sg-xxxxxxxx';

#スポットインスタンスのリクエストを行う
SIR_ID=` ec2rsi $AMI -t $INSTANCE_TYPE -p $PRICE -n 1 -r one-time -s $SUBNET -k $KEYPAIR -g $SECURITYGROUP  | awk '{if(NR==1) print $2;}' `

#3分間待機
sleep 180

TMP_EC2='';
while true; do
  #ec2のインスタンス情報取得(スポットインスタンスのIDを指定)
  TMP_EC2=`ec2din --filter "spot-instance-request-id=$SIR_ID"`;

  if test ${#TMP_EC2} -gt 0 ; then
    #情報が取得できた場合

    #インスタンス情報、ローカルIPの情報を取得する
    INSTANCE_ID=`echo $TMP_EC2 | awk '{ print $5 }'`;
    LOCAL_IP=`echo $TMP_EC2 | awk '{ print $52 }'`;

    #ループを抜ける
    break
  fi

  #30秒待機
  sleep 30
done

#IPアドレスを取得する
EIP_OBJ=`ec2allocaddr -d vpc`;
EIPALLOC=`echo $EIP_OBJ | awk '{ print $4 }'`
GLOBAL_IP=`echo $EIP_OBJ | awk '{ print $2 }'`

#IPアドレスをec2インスタンスに割り当てる
EIPASSOC_OBJ=`ec2assocaddr -a $EIPALLOC  -i $INSTANCE_ID -p $LOCAL_IP `
EIPASSOC=`echo $EIPASSOC_OBJ | awk '{ print $4}'`

#結果出力
echo "[info]instance_id: $INSTANCE_ID";
echo "[info]globalId: $GLOBAL_IP";
echo "[info]eipassoc: $EIPASSOC";
echo "[info]eipalloc: $EIPALLOC";
echo "[example] ssh -i ${KEYPAIR}.pem ec2-user@${GLOBAL_IP} ";
echo "[example] ec2disaddr -a $EIPASSOC ; ec2reladdr -a $EIPALLOC ; ec2kill $INSTANCE_ID ; "

実行結果

$ time ./create-spot-instances.sh 
[info]instance_id: i-bb4b84d4
[info]globalId: 54.236.67.208
[info]eipassoc: eipassoc-69a40b05
[info]eipalloc: eipalloc-9ea50af2
[example] ssh -i xxxxxxxx.pem ec2-user@54.236.67.208 
[example] ec2disaddr -a eipassoc-69a40b05 ; ec2reladdr -a eipalloc-9ea50af2 ; ec2kill i-bb4b84d4 ; 

real    4m53.571s
user    1m9.905s
sys 0m2.175s

sshアクセスする

ssh -i xxxxxxxx.pem ec2-user@54.236.67.208 

シャットダウンする

ec2disaddr -a eipassoc-69a40b05 ; ec2reladdr -a eipalloc-9ea50af2 ; ec2kill i-bb4b84d4 ; 

起動したあとに、atコマンドで50分後にシャットダウンするようにしておけば、使い過ぎは防げるかもしれません。

awsコマンドラインツールで起動したスポットインスタンスにEIPを割り当てる(VPC環境)

mac環境にbrew installでawsコマンドラインツールをインストールしてスポットインスタンスをあれこれの続きです。今回はVPC内に作成したインスタンスにIPアドレスを割り当てます。

  1. スポットインスタンスを借りる。
ec2rsi ami-XXXXXXXX -t t1.micro -p .003 -n 1 -r one-time -s subnet-XXXXXXXX -k XXXXXXXX -g sg-XXXXXXXX

2.スポットインスタンスのリクエストIDを指定して、EC2インスタンスの状態を取得する リクエスト中の場合はコマンドの返事は無いです。

ec2din --filter "spot-instance-request-id=sir-XXXXXXXX"

3.VPC用にEIPを取得する

ec2allocaddr -d vpc

4.起動したスポットインスタンスのインスタンスにVPCのEIPを割り当てる

ec2assocaddr -a eipalloc-XXXXXXXX -i i-XXXXXXXX -p 255.255.255.255

5.sshでアクセスする

ssh -i XXXXXXXX.pem  ec2-user@255.255.255.255

アクセスできたらAmazon Linux AMIの文字が。

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

openしたらcloseする。開けたら閉める。 ということで今度はEIPを外します。

1.インスタンスからEIPを外す

ec2disaddr -a eipassoc-XXXXXXXX

2.EIPを返却します。

ec2reladdr -a eipalloc-XXXXXXXX

3.ec2のインスタンスを返却します。

ec2kill i-XXXXXXXX

mac環境にbrew installでawsコマンドラインツールをインストールしてスポットインスタンスをあれこれ

awsのアクセス証明書のページで秘密鍵と証明書を作成してダウンロードする

ダウンロードした秘密鍵と証明書を配置

mkdir ~/.ec2
mv ~/Downloads/cert-*.pem  ~/.ec2/
mv ~/Downloads/pk-*.pem  ~/.ec2/

brewでec2-api-toolsをインストール

brew install ec2-api-tools
------↓結果↓------
Software installed with other package managers causes known problems for
Homebrew. If a formula fails to build, uninstall MacPorts/Fink and try again.
==> Downloading http://ec2-downloads.s3.amazonaws.com/ec2-api-tools-1.6.6.0.zip
Already downloaded: /Library/Caches/Homebrew/ec2-api-tools-1.6.6.0.zip
==> Caveats
Before you can use these tools you must export some variables to your $SHELL
and download your X.509 certificate and private key from Amazon Web Services.

Your certificate and private key are available at:
http://aws-portal.amazon.com/gp/aws/developer/account/index.html?action=access-key

Download two ".pem" files, one starting with `pk-`, and one starting with `cert-`.
You need to put both into a folder in your home directory, `~/.ec2`.

To export the needed variables, add them to your dotfiles.
 * On Bash, add them to `~/.bash_profile`.
 * On Zsh, add them to `~/.zprofile` instead.

export JAVA_HOME="$(/usr/libexec/java_home)"
export EC2_PRIVATE_KEY="$(/bin/ls "$HOME"/.ec2/pk-*.pem | /usr/bin/head -1)"
export EC2_CERT="$(/bin/ls "$HOME"/.ec2/cert-*.pem | /usr/bin/head -1)"
export EC2_HOME="/usr/local/Library/LinkedKegs/ec2-api-tools/jars"

install時に出力されるexportをbash_profileに記載

vi ~/.bash_profile
export JAVA_HOME="$(/usr/libexec/java_home)"
export EC2_PRIVATE_KEY="$(/bin/ls "$HOME"/.ec2/pk-*.pem | /usr/bin/head -1)"
export EC2_CERT="$(/bin/ls "$HOME"/.ec2/cert-*.pem | /usr/bin/head -1)"
export EC2_HOME="/usr/local/Library/LinkedKegs/ec2-api-tools/jars"
source ~/.bash_profile 

試しに、現在日付を開始日に指定してスポットインスタンスの価格確認をしてみる。

ec2dsph -t t1.micro -d Linux/UNIX --region us-east-1 -s `date +"%Y-%m-%dT00:00:00"`

次にVPCにスポットインスタンスをリクエストするコマンド

ec2-request-spot-instances ami-XXXXXXXX -t t1.micro -p .003 -n 1 -r one-time  -s  subnet-XXXXXXXX -k XXXXXXXXX -g sg-XXXXXXXX

パラメータはドキュメント参考でざっくりとした意味だけ書いてみます。

パラメータ 意味
t インスタンスタイプ
p 1時間あたりの価格
n 起動するインスタンスの数
r 1回のみならone-timeを利用
s vpcのサブネットを設定
k アクセス用のキーペア
sg セキュリティーグループのID

スポットインスタンスのステータス確認(awkで結果を変えてみてます。基本的には ec2dsirだけでOKだと思います)

ec2dsir | awk '{print $2"\t"$3}'

スポットインスタンスキャンセル(ec2csirを利用します。)

ec2csir sir-XXXXXXXX

起動はできました。このままだとEIP貼ってないので、この状態のままだと多分利用できません。 (すでにVPC内にアクセスできる状態にあるなら利用できます。)

追記: EIPの割当のエントリを書きました↓ awsコマンドラインツールで起動したスポットインスタンスにEIPを割り当てる(VPC環境)

macにknife-soloをインストール

rubyとかgemとかbundlerとか事前にインストールして下さい。

git clone git://github.com/matschaffer/knife-solo.git
cd knife-solo/
bundle
sudo rake install
mkdir ~/.chef
echo "knife[:solo_path] = '/tmp/chef-solo'" > ~/.chef/knife.rb

aws linuxの環境で確認

knife solo init chef-repo
cd chef-repo
knife solo prepare ec2-user@{host_name} -i  ~/xxxxx.pem 

nginxをインストールするcookbook作成

cd ~/chef-repo
knife cookbook create nginx -o nginx-cookbooks
vi nginx-cookbooks/nginx/recipes/default.rb

レシピ作成

nginx-cookbooks/nginx/recipes/default.rb

package "nginx" do
  action :install
end

端末へのセットアップ情報記述

vi nodes/{host_name}.json 

{host_name}.json

{
  "run_list":[
    "nginx"
  ]
}

レシピの実行

knife solo prepare ec2-user@{host_name} -i ~/xxxxx.pem 

こんな感じでしょうか。

ちなみに、詳しく知りたい方は@naoya_ito さんの電子書籍を読むことをおすすめします。

awsのvpcを試しました。

こんな感じの構成から初めて見ました。

f:id:mitsugi-bb:20130324010929p:plain

※画像はCacooで作りました。

US East (N. Virginia)が一番安いので、そこを利用もちろん実験はスポットインスタンスで。 microインスタンスの最低価格がいつの間にか$0.003になってました。安いですね。

手順メモ。

f:id:mitsugi-bb:20130324011935p:plain

左のメニューからVPC Dashboardを選択して、【Get started creating a VPC】のボタンを押す。

f:id:mitsugi-bb:20130324012212p:plain

「VPC with a Single Public Subnet Only」を選択して【Continue】ボタンを押す。

f:id:mitsugi-bb:20130324012409p:plain

次に、【Create VPC】ボタンを押す。

f:id:mitsugi-bb:20130324012708p:plain

f:id:mitsugi-bb:20130324012736p:plain

これでVPCは完成。次にEC2の仮想マシンを作ります。

f:id:mitsugi-bb:20130324013149p:plain

「0 Running Instances」を選択

f:id:mitsugi-bb:20130324013326p:plain

【Launch Instance】ボタンを押す。

f:id:mitsugi-bb:20130324013524p:plain

「Classic Wizard」を選択し【Continue】ボタンを押す。

f:id:mitsugi-bb:20130324013842p:plain

ラジオボタンを、Request Spot Instancesに会わせ、Launch Intoの項目で、EC2-VPCを選択し、 【Continue】ボタンを押す。

f:id:mitsugi-bb:20130324014027p:plain

【Continue】ボタンを押す。

f:id:mitsugi-bb:20130324014535p:plain

【Continue】ボタンを押す。

f:id:mitsugi-bb:20130324065344p:plain

【Continue】ボタンを押す。(キーが無かったら作ります。)

f:id:mitsugi-bb:20130324065523p:plain

Security Groupの設定です。 今回はSSHの確認だけを行いたい為22ポートのみ許可に設定して、 【Continue】ボタンを押す。

f:id:mitsugi-bb:20130324065907p:plain

【Submit】ボタンを押す。

f:id:mitsugi-bb:20130324070103p:plain

【Close】ボタンを押す。

f:id:mitsugi-bb:20130324070516p:plain

インスタンスが作成されました。 ただし、このままだとアクセス出来ないので、Elastic IPsを割り当てます。

f:id:mitsugi-bb:20130324070944p:plain

左のメニューからElastic IPsを選択して、【Allocate New Address】ボタンを押す。

f:id:mitsugi-bb:20130324071108p:plain

EIP used in で VPCを選択して、【Yes, Allocate】ボタンを押す。

f:id:mitsugi-bb:20130324071050p:plain

EIPを選択して、【Associate Address】ボタンを押す。

f:id:mitsugi-bb:20130324071303p:plain

ECインスタンスを選択して、【Yes, Allocate】ボタンを押す。

f:id:mitsugi-bb:20130324071348p:plain

これで割当完了。

f:id:mitsugi-bb:20130324071640p:plain

ここまでくればsshでアクセスして完了。

f:id:mitsugi-bb:20130324010929p:plain

この構成が完成しました。

M3 ダブルエクストララージインスタンス(m3.2xlarge)インスタンスでnode.jsのコンパイル

m3.2xlargeを試したくなり、一番安いバージニアのデータセンターを利用してみた。

f:id:mitsugi-bb:20130316234322p:plain

スペック

項目
メモリ 30 GiB
CPU 26 ECU(3.25 ECU × 8 仮想コア)

さっそくnode.jsのコンパイル。

予想ではコア数が増えてるだけなので、5分くらいかと思ってます。

rootで実行

sudo su -
yum -y install wget openssl-devel gcc-c++ make
wget http://nodejs.org/dist/v0.10.0/node-v0.10.0.tar.gz
time tar zxvf node-v0.10.0.tar.gz
cd node-v0.10.0
./configure
time make
make install

解凍時間

tar m1.xlarge m1.large m1.small t1.micro GMOクラウド VPS m3.2xlarge
real 0m0.851s 0m1.034s 0m3.999s 0m1.286s 0m1.553s 0m0.805s
user 0m0.680s 0m0.736s 0m1.712s 0m0.560s 0m0.737s 0m0.528s
sys 0m0.496s 0m0.504s 0m1.660s 0m0.420s 0m0.762s 0m0.464s

コンパイル時間

make m1.xlarge m1.large m1.small t1.micro GMOクラウド VPS m3.2xlarge
real 6m16.558s 6m14.260s 13m45.992s 39m51.288s 6m47.398s 4m30.627s
user 4m54.962s 4m52.074s 10m48.917s 29m23.018s 4m7.297s 3m27.629s
sys 0m46.923s 0m46.819s 2m15.564s 6m20.580s 0m37.334s 0m32.458s

思ったよりも速かったです。恐らくI/Oが良いのだと思います。

ab -c100 -n10000 をテスト

node.jsのHTTPサーバは https://gist.github.com/shigeki/4148268 を参考に。

Requests per second [#/sec] (mean)

- m1.xlarge m1.large m1.small t1.micro m3.2xlarge
1k 2949.32 1948.28 962.10 2521.37 3230.20
10k 1642.44 1652.94 119.313 1736.27 3443.22
100k - - - - 2531.25
1m - - - - 628.37
10m - - - - 69.76
100m - - - - 7.60 ( ab -c100 -n1000 )

ab -c100 -n1000 をテスト Requests per second [#/sec] (mean)

m3.2xlarge httpd nginx node.js
100m 13.00 13.76 7.92

ab -c100 -n1000 をテスト Requests per second [#/sec] (mean)

m3.2xlarge httpd nginx node.js
100m 13.00 13.76 7.92

ab -c1000 -n10000 をテスト Requests per second [#/sec] (mean)

m3.2xlarge httpd nginx node.js
1k 9645.21 13566.18 落ちる
10k 9686.05 12876.19 落ちる
100k 落ちる(Total of 9357 requests completed) 5377.25 落ちる
1M 落ちる(Total of 9593 requests completed) 1065.10 落ちる
10M 落ちる(Total of 1147 requests completed) 落ちる(ests Total of 1515 requests completed) 落ちる

nginxいいね。