ServerkitでRailsが動く環境をつくる

Serverkit というプロビジョニングツールがあるんですが、実用的な使用例があまり存在していないので、紹介も兼ねながら、ServerkitでNginx・Unicorn・Railsが動く環境を構築する方法を書いてみようと思います。

想定ケース

「これまで手元のPCでRailsアプリを開発してきたが、そろそろ本番環境で動かすことを想定して、AWSでEC2インスタンスを用意してデプロイして試してみたい」という利用シーンを例に考えます。EC2インスタンスのOSにはAmazon Linuxを利用することにし、初期状態からデプロイ可能な状態への変更を自動化することを目標にします。

レシピの記述と適用

手短にまとめると、ssh ホスト名 だけでログインできるように ~/.ssh/config を設定したあと (ec2-userでログインするためにHostを設定するなど)、手元に以下のようなYAMLファイルを用意すると、serverkit apply serverkit/recipe.yml --hosts=ホスト名 というコマンドで変更を適用できるようになります。意外と短い。serverkit というコマンドが手元で実行できるように、gem install serverkit などでインストールしておくのも必要なので注意しましょう。接続先のサーバに入れる必要はないです。

resources:
  # 古いかもしれないので yum update
  - type: command
    script: yum update --yes

  # yum経由でnginxを入れる
  - type: package
    name: nginx

  # serverkit/nginx.conf を接続先サーバの /etc/nginx/nginx.conf に配置する
  - type: remote_file
    destination: /etc/nginx/nginx.conf
    group: root
    mode: 0644
    owner: root
    source: serverkit/nginx.conf

  # nginxを起動させておく
  - type: service
    name: nginx

  # nginxとunicornのプロセスを実行するためユーザをつくる
  - type: user
    name: alice

  # 公開鍵を教えたりしてSSH経由でユーザaliceでログインできるようにする
  - type: directory
    path: /home/alice/.ssh
  - type: file
    group: alice
    owner: alice
    path: /home/alice/.ssh/authorized_keys
  - type: line
    path: /home/alice/.ssh/authorized_keys
    line: ssh-rsa AAAAB3N...

  # rbenvとRubyを入れる
  - type: rbenv_ruby
    dependencies: true
    global: true
    profile_path: /home/alice/.bashrc
    user: alice
    version: 2.3.0

個々の項目の内容や意図はコメントに書いた通りなので省略しますが、Serverkitはこのように、理想的な状態を定義したYAMLファイルを用意して serverkit apply コマンドに渡すと、指定したホストをその状態に変更してくれます。Serverkitではソフトウェア間の依存関係の解決などは行ってくれず、どういう状態が理想かを自分で考えて定義してあげる必要がありますが、そのぶんルールは単純です。

要件とともにレシピが大きくなってきた場合は、こういう感じで複数のレシピにファイルを分割できます。適当な粒度でいい感じの名前を付けて分けられるとよいですね。

resources:
  - type: recipe
    path: serverkit/base.yml
  - type: recipe
    path: serverkit/mysql-dependencies.yml
  - type: recipe
    path: serverkit/nokogiri-dependencies.yml
  - type: recipe
    path: serverkit/ssh.yml
  - type: recipe
    path: serverkit/nginx.yml
  - type: recipe
    path: serverkit/ruby.yml
  - type: recipe
    path: serverkit/node.yml

大量のパッケージをインストールしたいがYAMLを記述するのが面倒とか、様々な理由で動的にレシピの内容を生成したくなってきたら、拡張子を recipe.yml.erb に変更すればYAMLの内容を動的に生成できます。YAMLでメタプログラミングみたいな記法を導入するとひどいことになりそうだったので、何か動的にやりたい場合は無難にERBテンプレートでYAMLを生成することになってます。レシピが巨大になった場合も、最終的にまず1つの大きな定義ファイルが生成されて、それを読み込んでその状態に変更する、という流れは一緒です。

おわり

YAMLでレシピを書いて適用するだけということで、あまり説明するところがありませんでした。レシピを書くには type: packagetype: user など、どういうtypeが利用できるのか、どういう値を渡せるのか、どういう振る舞いをするのかということを知る必要があるので、https://github.com/serverkit/serverkit を見ながらやっていくと良いと思います。いろいろ足りない機能があると思うので、独自の定義を追加してGemにしたり各位やっていってもらえると助かります。

参考記事

Serverkitを使ってみたいという方は、以下の記事も参考になるかもしれません。