セキュリティ系の勉強、その他開発メモとか雑談. GithubはUnity触っていた頃ものがメイン Twitterフォローもよろしくです

【terraform+capistrano+itamae】Railsのアプリケーションをawsにデプロイした時の備忘録③

前回capistranoでデプロイをする部分をやった。が、デプロイ先のaws内の準備は手動でやったので、その部分をitamae自動化したい。

thinline196.hatenablog.com

目的

itamaeaws上にRailsアプリが動作するのに必要な環境をセットアップできるようにする。最終的な流れとしては

terraform->itamae->capistrano

という作業手順になるはずである。

itamae

環境を整える手順としては

  1. yumのアプデ、git等のインストール
  2. rbenvのセットアップ
  3. その他gemが必要とする物(ImageMagickなど)


rbenvについては、インストールするレシピがあったのでそれを使用する。が、なぜかbundlerを上手くインストールできなかったので、手動で行う事にした。 GitHub - k0kubun/itamae-plugin-recipe-rbenv: Itamae plugin to install ruby with rbenv

その他は他サイトを参考に自前で書いてみる。 CapistranoとItamaeを使った複数環境へのプロビジョニング - neuro, Inc. エンジニアブログ

itamae呼び出し方法

itamaegemが入っていればフォルダ構成は自由だが、ファイル同士は相対パスで呼び出すのである程度構成は決めておくと良い。
僕はこんな感じ。
f:id:thinline196:20190704122143p:plain
下のような形で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のインストールだが、すでにインストールされていたら実行しないようにしている。また、今回指定したrmagick3.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

awsRDBを使用するため、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にアクセスするユーザをitamaecapistranoで対応させておくことだと思います。

余談

階層わかりにくかったので、下にもう少し詳しいののっけておきます。 f:id:thinline196:20190704124042p:plain
それとgistのファイルの説明の所に階層を地味にメモしているので何かの役に立てば、、