オートスケール時のデプロイを User Data と Capistrano を使って行う(BootStrap パターン)

オートスケール時のデプロイを User Data と Capistrano を使って行う(BootStrap パターン)

Clock Icon2014.07.15 15:00

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Auto Scaling を使った構成の場合、EC2 へのデプロイはどうやっているでしょうか?

AWS を使ってる方はご存知の方も多いと思いますが、EC2 には User Data という仕組みがあります。
User Data は、インスタンス起動時にタスクやスクリプトを実行する仕組みです。
今回この User Data を使って、自分自身のインスタンスから最新のソースを GitHub から取得してデプロイする方法についてご紹介したいと思います。

図で表すと以下のイメージですかね。

Untitled

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 を指定します。

140709-0002

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 環境で使う際は、更新しているソースが多かったりすると、デプロイに時間が掛かったりするので、その辺りは工夫が必要かと思います。

脚注

  1. こうすることで AMI も 1 つで、共用出来ますね。
  2. 事前に Rails アプリケーションに staging 環境を追加しておく必要があります。

この記事をシェアする

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.