【terraform+capistrano+itamae】Railsのアプリケーションをawsにデプロイした時の備忘録③
前回はcapistrano
でデプロイをする部分をやった。が、デプロイ先のaws
内の準備は手動でやったので、その部分をitamae
自動化したい。
目的
itamae
でaws
上にRails
アプリが動作するのに必要な環境をセットアップできるようにする。最終的な流れとしては
terraform
->itamae
->capistrano
という作業手順になるはずである。
itamae
環境を整える手順としては
yum
のアプデ、git
等のインストールrbenv
のセットアップ- その他
gem
が必要とする物(ImageMagick
など)
rbenvについては、インストールするレシピがあったのでそれを使用する。が、なぜかbundler
を上手くインストールできなかったので、手動で行う事にした。
GitHub - k0kubun/itamae-plugin-recipe-rbenv: Itamae plugin to install ruby with rbenv
その他は他サイトを参考に自前で書いてみる。
CapistranoとItamaeを使った複数環境へのプロビジョニング - neuro, Inc. エンジニアブログ
itamae呼び出し方法
itamae
のgem
が入っていればフォルダ構成は自由だが、ファイル同士は相対パスで呼び出すのである程度構成は決めておくと良い。
僕はこんな感じ。
下のような形でitamae
を実行させる。
bundle exec itamae ssh --host [ホスト名] --user ec2-user itamae/roles/app.rb
この場合、app.rb
から芋づる式に呼ばれる。app.rb
には呼び出し順にレシピを呼び出すだけでOK。
コマンドでyml
ファイルを渡して環境変数?を定義してあげる方法があるのだが、今回はレシピ側からinclude_recipe
してもらうことで環境変数を取り込む。ここには、ユーザ名や各パスワード、aws
内のRDB
のホスト名などを記述しておく。今回は特に気にしていないけれど、このファイルだけ適宜変更すれば、以降変更があってもレシピをいじらなくて済む。
node.reverse_merge
することで、レシピ内からnode[:hoge][:hoge]
のような形で値を取得できるようになる。
レシピ
基本的に各レシピ間に違いは少ないし、最悪の場合サーバ上で行うコマンドを全て書けば良いので一部だけ紹介しておく。
dependencies
一番初めに呼び出したレシピで、git
コマンドをインストールしたり、そもそもyum
のアップデートを走らせたりと大事なことはここでまとめてやっている。
一番最後の行はImageMagick
のインストールだが、すでにインストールされていたら実行しないようにしている。また、今回指定したrmagick
が3.0
で、yum
から入るImageMagick
のバージョンと上手く連動しないため、公式サイト経由でインストールしている。
users
cookbooks/users/default.rb
ではcookbooks/users/*/default.rb
を呼び出す指示だけ書きます。こうすることで作りたいユーザのレシピだけを指定して呼び出すことができ、レシピも整理できます。今回はmycalendar
というユーザを生成します。
# cookbooks/users/default.rb include_recipe "./mycalendar/default.rb"
名前の指定等は別ファイルから行います。freeze
とかはrubocop
先生がつけてくれました。
.bashrc.erb
には大したことは書いてないです。
# users/mycalendar/templates/.bashrc.erb # .bashrc # Source global definitions if [ -f /etc/bashrc ]; then . /etc/bashrc fi # User specific aliases and functions ex.global variable
authorized_keys
には今後手元からそのユーザでssh
接続するために使用する公開鍵をいれておきます。このユーザでssh
する予定がないならいらないかも。
sudoers.d
配下におきたい設定はここに書いておきます。僕はunicorn
を走らせる必要があるのでこれだけ設定しておきました。ここの設定をミスるとsudo
が使えなくなり詰むので回避策は考えておいてください
# users/mycalendar/files/etc/sudoers.d/mycalendar #user rule for mycalendar # unicorn mycalendar ALL=(ALL) NOPASSWD: /sbin/service unicorn start mycalendar ALL=(ALL) NOPASSWD: /sbin/service unicorn stop mycalendar ALL=(ALL) NOPASSWD: /sbin/service unicorn restart mycalendar ALL=(ALL) NOPASSWD: /sbin/service unicorn status
ruby
rubyはシステムにインストールします。
1つ目のinclude_recipe "rbenv::system"
は、rbenv
をいれられるgem
で環境変数に値を設定しておけばそれに従ってインストールしてくれます。今回はグローバルな所にインストールをしましたが、ユーザ別に入れることも可能です。その場合、ディレクトリ等が多少変わってくるので他のファイルも変更が必要になります。
その他
あと気をつける部分はnginx
のインストールと起動タイミングです。unicorn
と連動するようにしたのですが、僕のレシピではRails
の準備(ディレクトリの生成等)が終わる前にnginx
を起動するとエラーが発生しました。(nginx
の設定ファイルで指定したディレクトリが存在しないため) なので、nginx
の起動だけはRails
のレシピの最後で呼び出しています。
もう一つはディレクトリの生成と権限です。上の方でitamae
の実行をしているのはec2-user
というaws
のデフォルトのユーザで権限が強いです。よって基本的にディレクトリ生成時に指定がなければ所有者やグループがroot
になります。が、今回はmycalendar
というアプリケーションの実行に必要なだけの権限を付与したユーザを作り、そいつに作業をして欲しいのです。よってこのままでは、実行時に書き込み権限がなかったり、そもそもディレクトリにアクセスができないという自体にもなります。ので、ディレクトリ作成時にはなるべく、生成したユーザの権限を付与しておきましょう。(capistrano
でデプロイする場合にもmycalendar
ユーザを使用するので、権限がないディレクトリにデプロイするとエラーを吐きます。)
MySQL
aws
のRDB
を使用するため、mysql-server
はインストールしません。下で色々やっているのは、アプリがmysql
をいじる際に使用するユーザの生成です。パスワードはコマンドラインから流すしかなかったのでセキュアではありませんが、以下のようにしました。もっといい案があれば教えてください。
capistrano側の変更
rbenv
がユーザ毎へのインストールではなくなるので、パスを設定してあげます。
# config/deploy.rb .. # 追記 set :rbenv_path, "/usr/local/rbenv" ..
ssh
では新たに生成したユーザを使うので、上で登録した公開鍵の対の秘密鍵を使用するように指定します。
# config/deploy/production.rb ... - set :ssh_options, keys: "~/.ssh/id_rsa" + set :ssh_options, keys: "~/.ssh/mycalendar_id_rsa"
あと気にする点は、RDB
にアクセスするユーザをitamae
とcapistrano
で対応させておくことだと思います。
余談
階層わかりにくかったので、下にもう少し詳しいののっけておきます。
それとgist
のファイルの説明の所に階層を地味にメモしているので何かの役に立てば、、