- 公開日
Amazon OpsWorksでRailsアプリを簡単Chefプロビジョニング

目次
本記事はChef Advent Calendar 2014の21日目の記事です。
OpsWorksとは?
公式サイトの説明は下記です。
設定管理サービスである AWS OpsWorks を使用すると、ユーザーは Chef を使用して、あらゆる種類およびサイズのアプリケーションを簡単に設定および運用できます。パッケージのインストール、ソフトウェア設定およびストレージなどのリソースを含む、各コンポーネントのアプリケーションのアーキテクチャおよび仕様を定義できます。
ポイントは以下の通り。
- Chefでサーバーをプロビジョニング・デプロイできる
- スタック > レイヤー > App という概念でシステムを構成
- インスタンスをタイムベース or ロードベースでスケールアウトできる
- OpsWorksで使われているレシピはGithubで公開されており実行コードが追える
- OpsWorksの用意したレシピに加えて自らのCustom Chefレシピを追加することも可能

【↑図】OpsWorksのStack & Layerの関係
料金
OpsWorksの使用自体にかかる料金は 0円 です。OpsWorks上で使用したAWSリソースの料金(ロードバランサ、EC2インスタンス、RDS等)のみがかかってきます。
RailsをOpsWorksにデプロイしてみよう
OpsWorksはとくにRailsアプリケーションとの相性が良く、今回はRails4.2のアプリケーションをOpsWorksにデプロイしてみようと思います。
今回デプロイするRailsアプリケーションのコードの最終形は下記になります。
https://github.com/toshimaru/opsworks-rails
デプロイ手順
スタックの追加
まずはAWS ConsoleからOpsWorksにいきAdd Stackしましょう。RegionとかVPCとかIAMとかは適宜設定してね。

こんなのがStackのトップ画面。

レイヤーの定義

Layer TypeはRails App、Ruby versionは2.1、nginx+unicornを選択する

追加されました。

レシピ
RecipesでOpsWorksにどんなレシピが設定されているかがわかります。レシピ名がGithubへのリンクになっており、どんなレシピが書かれているかを確認できます。

今回はこのままでOK.
インスタンスの追加
では次にAppインスタンスを追加。t1.microインスタンスで。

AddInstanceするとステータスがStoppedなのでstartで起動します。

10分くらいでセットアップが完了します。Statusがonlineでグリーンになれば準備OK.

Appの設定
次にデプロイするAppの設定を追加していきます。

こんな感じでAppを設定。
- Type: Ruby on Rails
- DataSource: 今回は特にないのでNone
- Applicationソース: GithubからデプロイしたいGithubのレポジトリURLを指定

SECRET_KEY_BASE(Rails4.2のsecrets.ymlで必要になる)もあわせてセットしましょう。

Deployments で Deploy Appしてみよう。

Appは先ほど設定したApp、CommandはDeployを指定してDeploy App!(マイグレーションが必要であればここでMigration ON)

SuccessすればOK.

幾つかのハマりポイント
Gemfile
下記のGemが必要になるのでコメントアウトされていることを確認すること。
gem 'therubyracer', platforms: :ruby
gem 'unicorn'
database.yml
RDSを設定していれば自動的に設定されるのですが、今回の場合設定していないので別途手でdatabase.ymlを作りました。
[root@rails-app1 current]# cat config/database.yml
default: &default
adapter: sqlite3
pool: 5
timeout: 5000
production:
<<: *default
database: db/production.sqlite3
CSSが適応されていない問題
「アレ、なんかCSSが効いていないっぽい!?」

これはasset:precompileが走っていないため。
rake asset:precompile というタスクを実行する必要がありますが、OpsWorksのRailsアプリケーションのデフォルトのデプロイ処理ではこのタスクを実行してくれません。
下記をdeploy/before_migrate.rbに設定する。
Chef::Log.info("Running deploy/before_migrate.rb")
env = node[:deploy][:rails_opsworks][:rails_env]
current_release = release_path
execute "rake assets:precompile" do
cwd current_release
command "bundle exec rake assets:precompile"
environment "RAILS_ENV" => env
end
これでデプロイ。

OK.
デプロイ・ディレクトリ
/srv/www/rails_opsworks/currentに最新の状態がデプロイされます。
ログ・ディレクトリ
/var/lib/aws/opsworks/chef Chefのログ、OpsWorksの設定JSONが格納されています。
まとめ
さてOpsWorksでのデプロイ手順を紹介してきましたが一体何が嬉しいのでしょうか。個人的なメリットは以下です。
- インスタンスが Disposable(廃棄可能)・Reproducible(再現可能) である
- いわゆる immutable infrastructure
- = サーバーをいつでも潰して全く同じ環境を再現できる!
- 「サーバーを増やしたい!」 → Add Instanceをポチるだけ
- Capistranoなどのデプロイツールのコードをゴチャゴチャ書く必要がなく、デプロイタスクはOpsWorks & Chefに一任できる
さいごに
Chef Advent CalendarといいながらChefよりもOpsWorks中心の内容になってしまいましたが、冒頭に書いたようにOpsWorksの用意しているレシピに加えて自らのCustom Chefレシピを定義することが可能です。現実的な運用を考えるとOpsWorksのレシピだけでプロビジョニング・デプロイレシピを完結させることは難しいと思うので、OpsWorksレシピ+Custom Chefレシピ の2つを組み合わせて運用していくのが現実的かと思います。