この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
Auto Scaling を使った構成の場合、EC2 へのデプロイはどうやっているでしょうか?
AWS を使ってる方はご存知の方も多いと思いますが、EC2 には User Data という仕組みがあります。
User Data は、インスタンス起動時にタスクやスクリプトを実行する仕組みです。
今回この User Data を使って、自分自身のインスタンスから最新のソースを GitHub から取得してデプロイする方法についてご紹介したいと思います。
図で表すと以下のイメージですかね。
ssh localhost?
デプロイツールには Capistrano を使いますが、Capistrano は、デプロイ対象のサーバーに対してまず ssh で login を行います。
その後、サーバー上でデプロイ対象のコードの取得や、サービスの再起動をしたりしますが、
AutoScaling は自動でインスタンスが起動するので、どうやってデプロイさせるかがポイントです。
トリガーなどで外のインスタンスからデプロイしてもいいのですが、なるべく疎結合にすべきだと思うので、
自分自身(localhost)からデプロイを行うようにしてみます。
アプリケーション実行ユーザとして、deploy という名前のユーザを作って、localhost から ssh 出来るようにします。
# useradd -m deploy
# su - deploy
$ ssh-keygen
$ cd .ssh && mv id_rsa.pub authorized_keys
$ chmod 600 authorized_keys
上記の設定が済んだら、localhost にログイン出来るか試してみましょう。
[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ ssh localhost
The authenticity of host 'localhost (127.0.0.1)' can't be established.
ECDSA key fingerprint is xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'localhost' (ECDSA) to the list of known hosts.
Last login: Tue Jul 8 13:05:16 2014 from localhost
__| __|_ )
_| ( / Amazon Linux AMI
___|\___|___|
https://aws.amazon.com/amazon-linux-ami/2014.03-release-notes/
[ec2-user@ip-xxx-xxx-xxx-xxx ~]$
フィンガープリントの確認後、無事ログイン出来ましたね。
しかしここで 1 点注意点があります。EC2 は AMI から起動すると毎回ホスト鍵が変わるため、Capistrano からログインを行う際に、再度フィンガープリントの確認が対話的に行われてしまい、デプロイが上手くいかないのです。
これを解決するために、~/.ssh/config に以下を追記しておきましょう。
Host *
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
これでフィンガープリントのチェックを行わなくなります。
Capistrano
デプロイするサンプルは Rails のアプリケーションです。 Gemfile の一部を抜粋すると、以下の通りです。
source 'https://rubygems.org'
gem 'rails', '4.1.2'
group :development do
gem 'capistrano', require: false
gem 'capistrano-rbenv', require: false
gem 'capistrano-bundler', require: false
gem 'capistrano-rails', require: false
end
localhost からのデプロイ用に config/deploy 以下に local.rb というファイルを作りました。
# config/deploy/local.rb
server 'localhost', user: 'deploy', roles: %i(web app db)
set :branch, 'master'
set :rails_env, :production
そして、EC2上のデプロイ実行用のコードとアプリケーション実行元の場所はそれぞれ以下のようにしました。
- デプロイ実行用のコード: /home/deploy/my_rails_app
- アプリケーション実行元(デプロイ先): /data/my_rails_app
EC2 上からデプロイできる事を確認しておきましょう。
$ cd ~/my_rails_app
$ bundle install --path vendor/bundle --without production staging
$ bundle exec local deploy
...
INFO [b47eea5f] Finished in 0.037 seconds with exit status 0 (successful).
デプロイ用シェル
デプロイの確認が上手く行ったら、User Data から呼び出すシェルを作成します。
折角なので、staging と production をパラメータで切り替えられるようにしておきます。 *1
#!/bin/bash
#
# /data/bin/startup.sh
#
#######################
app_root=/data/my_rails_app/current/
source_path=$1
rails_env=$2
cd $source_path
git fetch --all
git reset --hard origin/master
bundle install --path vendor/bundle --without production staging --quiet -j8
bundle exec cap local-$rails_env deploy
Capistrano のファイルも、以下のように production と staging 用で分けました。 *2
local-production.rb
# config/deploy/local-procution.rb
server 'localhost', user: 'deploy', roles: %i(web app db)
set :branch, 'master'
set :rails_env, :production
local-staging.rb
# config/deploy/local-staging.rb
server 'localhost', user: 'deploy', roles: %i(web app db)
set :branch, 'master'
set :rails_env, :staging
これによって以下の指定でデプロイ出来るようになりました。
$ /data/bin/startup.sh /home/deploy/my_rails_app/ production|staging
User Data からシェルを呼び出す
マネージメントコンソールを開いて、User Data を指定します。
2 行目はログ出力用の指定です。
User Data は root ユーザとして実行されるので、su で deploy ユーザを指定しています。
実行結果を見てみる
インスタンスを AMI から起動したら、実行結果を確認してみましょう。
ログは、/var/log/user-data.log に書かれています。
+ su - deploy /data/bin/startup.sh /home/deploy/my_rails_app/ production
...
INFO[9fdf606a] Finished in 0.041 seconds with exit status 0 (successful).
無事デプロイが終わったようです!
AutoScaling で実行するには?
Auto Scaling で User Data を実行するには、launch config の作成時に指定が必要です。
以下は、aws cli を使って指定する例になります。
$ aws autoscaling create-launch-configuration \
> --launch-configuration-name "my-lc" \
> --image-id "ami-xxxxxxxx" \
> --user-data "/path/to/user-data.txt" \
> --instance-type "t2.micro"
まとめ
User Data を使って自動でデプロイする方法を紹介しました。一般的に BootStrap パターンと呼ばれたりします。
要点を掻い摘んで紹介しましたが、実際には Web サーバの設定や AMI の作成など他の準備も必要です。
こちらで紹介したパターン以外にも、稼働している EC2 とは別で新しいインスタンス群を用意して、DNS の向き先を切り替えるパターンなどもあります。
実際に production 環境で使う際は、更新しているソースが多かったりすると、デプロイに時間が掛かったりするので、その辺りは工夫が必要かと思います。