beanstalkでNode.jsを動かしてみた (1) AMI作成編
某イベントでもこっそり使っていましたが、Node.jsをBeanstalkで動かしてみました。
Beanstalkが東京上陸したので、東京にもAMIを作成してみます。
AMIの作り方はいいから早く動かしたいぜ、という人は次のエントリをどうぞ!
準備
PHPのAMI(ami-32358433 PHPBeanstalk64-2012.03.30)を元に作業をします。
SecurityGroupでssh, httpと、3000を開けておいてください。
nvm導入
nvmを導入します (参考: Node.jsとnvmを初めてインストールするときのハマりポイントと対策 - ess sup)
[ec2-user@ip-10-153-59-170: ~] $ sudo yum install -y openssl-devel [ec2-user@ip-10-153-59-170: ~] $ sudo su - elasticbeanstalk [elasticbeanstalk@ip-10-153-59-170 ~]$ git clone git://github.com/creationix/nvm.git ~/.nvm [elasticbeanstalk@ip-10-153-59-170 ~]$ . ~/.nvm/nvm.sh [elasticbeanstalk@ip-10-153-59-170 ~]$ nvm install v0.6.15 : 'install' finished successfully (0.525s) Now using node v0.6.15 ~/.nvm/v0.6.15/bin/npm [elasticbeanstalk@ip-10-153-59-170 ~]$ echo . ~/.nvm/nvm.sh >> .bashrc [elasticbeanstalk@ip-10-153-59-170 ~]$ echo nvm use 0 >> .bashrc
npmを使い、node-devとexpressを入れておきます。
[elasticbeanstalk@ip-10-153-59-170 ~]$ npm install node-dev -g [elasticbeanstalk@ip-10-153-59-170 ~]$ npm install express -g
/var/www/htmlにexpressでアプリのひな形を作ります。
[elasticbeanstalk@ip-10-153-59-170 ~]$ cd /var/www/html [elasticbeanstalk@ip-10-153-59-170 html]$ echo launching... > index.html (注:deploy前にhealthyと判断されるために必要です) [elasticbeanstalk@ip-10-153-59-170 html]$ express . [elasticbeanstalk@ip-10-153-59-170 html]$ npm install [elasticbeanstalk@ip-10-153-59-170 html]$ node-dev app.js Express server listening on port 3000 in development mode
apache設定
sldeshare:AWSマイスターシリーズReloaded(AWS Beanstalk)にあるように、基本的にBeanstalkアプリはApache経由でアクセスされます。そこで、/に来たアクセスをlocalhost:3000にreverse proxyを行い、コンテンツにアクセス出来るように設定します。1つ注意が必要なのが、先ほどのスライドにあるような/_hostmanagerへのアクセスの設定までもproxyしてしまうと、hostがダウンしていると判定されてしまいます。
この設定は/etc/httpd/sites/hostmanager に書かれています。
## Setup proxy to redirect to HostManager for ELB Health Check <VirtualHost *:80> <Proxy *> Order deny,allow Allow from all </Proxy> ProxyPass /_hostmanager http://localhost:8999 retry=0 ProxyPassReverse /_hostmanager http://localhost:8999 ## Add an exclusion for the host manager communication so that it doesn't ## get globbed into the / proxypass ProxyPass /_hostmanager ! </VirtualHost>
ProxyPassの最後の行の後に
ProxyPass / http://localhost:3000/ ProxyPassReverse / http://localhost:3000/
と追加してapacheを再起動(sudo service httpd restart)すると、httpでつないでもnode.jsのアプリケーションにアクセスできるようになります。
deploy時スクリプト修正
実際にアプリケーションをdeployした後には、/etc/httpd/sites/application というファイルが生成され、下記のような内容となります。
NameVirtualHost *:80 <VirtualHost *:80> DocumentRoot /var/www/html LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" proxy SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded CustomLog "/var/log/httpd/application-access_log" combined env=!forwarded CustomLog "/var/log/httpd/application-access_log" proxy env=forwarded ErrorLog /var/log/httpd/application-error_log <Directory "/var/www/html"> Options Indexes FollowSymLinks AllowOverride All Order allow,deny Allow from all </Directory> ## Setup proxy to redirect to HostManager for ELB Health Check <Proxy *> Order deny,allow Allow from all </Proxy> ProxyPass /_hostmanager http://localhost:8999 retry=0 ProxyPassReverse /_hostmanager http://localhost:8999 ## Add an exclusion for the host manager communication so that it doesn't get globbed into the / proxypass ProxyPass /_hostmanager ! </VirtualHost>
このファイルは/opt/elasticbeanstalk/srv/hostmanager/lib/elasticbeanstalk/hostmanager/utils/apacheutil.rb というファイルで設定に応じて自動生成されます。先ほど行ったような修正と同じ事をするように、このスクリプトを修正します。
[elasticbeanstalk@ip-10-153-59-170 utils]$ diff apacheutil.rb.org apacheutil.rb 103a104,106 > > ProxyPass / http://localhost:3000/ > ProxyPassReverse / http://localhost:3000/
これにより、
ProxyPass /_hostmanager ! ProxyPass / http://localhost:3000/ ProxyPassReverse / http://localhost:3000/
と、先ほどのProxyPassの最後の行の後に追加されます。
/_hostmanager以下へのアクセスは優先されて処理され、それ以外のアクセスは / へのアクセスとする設定となります。
起動時スクリプト作成
インスタンス起動時に以下のようなスクリプトを自動で実行するようにします。
[elasticbeanstalk@ip-10-153-59-170 ~]$ cat > ~elasticbeanstalk/bin/startup.sh #!/bin/sh . ~/.nvm/nvm.sh nvm use 0 # use the latest installed while [ 1 ] do cd /var/www/html node-dev app.js sleep 5 done [elasticbeanstalk@ip-10-153-59-170 ~]$ echo 'sudo su - elasticbeanstalk startup.sh &> /opt/elasticbeanstalk/var/log/node.log' | sudo tee -a /etc/rc.local sudo su - elasticbeanstalk startup.sh &> /opt/elasticbeanstalk/var/log/node.log
これで起動時に自動でNode.jsが起動します。また、deploy時にはnode-devがカレントディレクトリを失って落ちるため、自動で再起動するようにしています。
もう1つ、下記のようなコマンドを先ほどのNode.js起動前に入れておくと何かの役に立つかもしれません。
(publicのhostnameやIPアドレスが環境変数から参照できるようにするものです)
[elasticbeanstalk@ip-10-153-59-170 ~]$ /opt/aws/bin/ec2-metadata -i -h -o -p -v | perl -pe 's/^/export /;s/-/_/;s/: /=/' > /etc/profile.d/ec2-meta-data.sh (ログインし直す) [elasticbeanstalk@ip-10-153-59-170 ~]$ echo $public_ipv4 175.41.200.42 [elasticbeanstalk@ip-10-153-59-170 ~]$ echo $public_hostname ec2-175-41-200-42.ap-northeast-1.compute.amazonaws.com
これにより、/etc/rc.localは
[elasticbeanstalk@ip-10-153-59-170 ~]$ cat /etc/rc.local #!/bin/sh # # This script will be executed *after* all the other init scripts. # You can put your own initialization stuff in here if you don't # want to do the full Sys V style init stuff. touch /var/lock/subsys/local /opt/aws/bin/ec2-metadata -i -h -o -p -v | perl -pe 's/^/export /;s/-/_/;s/: /=/' > /etc/profile.d/ec2-meta-data.sh sudo su - elasticbeanstalk startup.sh &> /opt/elasticbeanstalk/var/log/node.log
のようになりました。
AMI作成
さて、この状態で、AMIを作りましょう。
$ ec2-create-image i-133fad13 -n "NodeBeanstalk64-2012.04.25" -d "Elastic Beanstalk Node.js v0.6.15 64-bit" IMAGE ami-14c87815
AMIが出来ました!
(デプロイ編に続きます)