Rails入門書を読んだ後に知りたかったこと

初めてRailsの入門書を読んだ時に思った。

「なるほど、これでWebアプリを簡単に作れそうだ、開発中はrails serverでWEBrickなるものを立ちあげればlocalhostで見れる。でも作ったアプリをHeroku以外で公開するにはどうしたらいいんだ?サッパリわからん。」

この頃はそもそも何をどうやって調べればいいのかすらも分からなかった。

全くわからないままネットを徘徊して徘徊して徘徊して断片的な情報を集めて、なんとなく知識がつながってきたけれども、物凄く遠回りをした感じがある。なので当時の僕が欲しかったまとめを書いてみる。

この記事の想定読者と目標

想定読者はWebアプリを作ってみたいなと思ってRailsの入門書を読んでみたばかりで、root権限のあるサーバでWebアプリを運用したことのない人。特に、個人あるいは少人数でWebアプリを作ろうとしていて資金が潤沢ではないので小さく始めたい人。

各トピックを深く追っていくと物凄い長さになるし自分の手に余るので、*何を調べればいいかわかるところまで行くこと*を目標とする。

どこに配置するか

作成したアプリケーションを他の環境に配置することを*デプロイ*という。デプロイ先は本番環境(=プロダクション環境)の場合もあれば、本番環境に似せて作ったステージング環境の場合もある。

本番環境のアプリを稼働させる場所の候補としては

  1. Platform as a Service(PaaS)
  2. Infrastructure as a Service(IaaS)
  3. Virtual Private Server(VPS)

自前のサーバや、専用物理サーバは初期投資が大きすぎるので除外。またRailsアプリではroot権限をもらえない共用レンタルサーバで使うのは厳しいと思う。動かせたとしても、ソフトウェアを自由にインストール出来ない、常時起動のプロセスを作れないといった制約でまともに使えないと思う。

ざっくりと比較すると
設定や運用の手間 … PaaS > IaaS > VPS
コスパ(資源と価格) … PaaS < IaaS < VPS

PaaSはデプロイするのはすごく簡単で、Herokuは最初は無料だったりするけれど増強しようと思った時のコスパが悪い印象。必要な資源に対してあげられる利益が大きいサービスでは良さそう。PaaS独自のノウハウが必要になったりするのかもしれないが使い込んだことがないのでわからない。貴族の方にオススメ。

IaaSは自動でスケールアウト、冗長化、世界中のリージョンに配信できたりと様々なサービスがついているのも魅力。時間課金なので負荷の分散(varianceの方)が大きい場合にはVPSよりIaaSが適しているかもしれない。IaaSを使うための学習コストはある。値下げが進んでいるようだが、利益をあげられる見込みが立っていない段階で使い始めるにはかなり高い印象。

IaaSとVPSの境界はちょっと微妙で、VPSでもDigitalOceanLinodeでは時間課金だったり、APIでインスタンスをコピーして立ち上げたり落としたりをできるよう。コスパはVPSがダントツで良い。

ということで、小さく始めるならVPS。

サーバのOS

サーバのOSは基本Linuxだと思う。

ふつうのLinuxプログラミング Linuxの仕組みから学べるgccプログラミングの王道
青木 峰郎
ソフトバンククリエイティブ
売り上げランキング: 45,935

を流し読みしていたのが結構役に立った。Linuxも、Mac OS Xの基礎となっているDarwinもPOSIXという規格に則っているらしいのでMac OS Xを使う上でも役に立つ。

基本構成

Appサーバ

書いたアプリケーションのロジックに従ってコンテンツを返すサーバを*アプリケーションサーバ(Appサーバ)*と呼ぶ。WEBrickもAppサーバだがパフォーマンスに問題があるようで本番環境では使われない。

Railsで使えるAppサーバには

等があって、それぞれ特徴があるので自分のアプリケーションの性質に適したものを選ぶ。 といっても僕は最初何が適しているかなんてよくわからなかったのでハマっても情報が多そうなUnicornを選んだ。


Appサーバを変えてもRackによって抽象化されているので、書いたアプリケーションのコードを書き換える必要は無い。アプリケーションサーバ用の設定ファイルを追加したりする必要はある。

Webサーバ

基本的にユーザからのリクエストを直接Appサーバが受けて返すということはしない。なぜなら

といたったことがあるから。役割分担としては、*Webサーバ*が静的なコンテンツの配信を、
*リバースプロキシサーバ*がクライアントとアプリケーションの接点となって裏にあるAppサーバ等にリクエストをリレーする、ということになっているようだがApache HTTP Servernginxといった一つでどちらの機能も持っているものが使われることが多いよう。

DBサーバ

開発環境ではデフォルトのデータベースはsqliteだが、本番環境ではパフォーマンスや運用上便利な機能のためにPostgreSQLやMySQLが使われる(DBサーバ)。データの特性やデータをどのように使うかに依ってRDBMSではないNoSQLが使われることもある。

まとめ

まとめると、Webアプリはザックリと言って役割の異なる

から構成される。

はじめはVPS一台にWeb, App, DB全部載せで良いと思う。

サーバの設定

サーバを借りてまずしなければならないのは、Railsアプリが動くように必要なソフトウェアをインストール、設定すること(すぐデプロイできるイメージが提供されているものもある)。もし今後もアプリを作る、あるいはアプリのユーザが増えていくことを期待するというなら、自分の手で設定するよりはChefAnsible等のプロビジョニングツールを使ったほうが良い。同じ役割のサーバを複数作ったり、それらに同じ操作をすることになると手では厳しい。また、Linuxディストリビューションごとの差異やなんやかんやを抽象化してくれて嬉しい。Chefは複雑だけど

入門Chef Solo - Infrastructure as Code
伊藤直也 (2013-03-11)
売り上げランキング: 431

がすごく良くまとまっていてわかりやすかった。

実際にやってみるとうまくいかないことが結構出てくるので、本番環境用のサーバではなく
ローカルマシンにVirtual Box等で仮想マシンを建ててそこで試すのが良いと思う。
その際、上の入門Chef SoloにもあるようにVagrantを使うと仮想環境の構築が簡単にできて良い。

自分の場合は、まずLinuxサーバの設定関係のWebページを読み漁ってローカルマシン上の仮想マシンに

  1. sshで入って手で設定してみる
  2. 1を再現するChefのレシピを書く
  3. serverspecで実際に設定できているかをテストするコードを書く

という形でレシピを作っていった。テスト駆動にやっていきたいなら上の3を一番始めにやる。

ChefでRailsアプリが動く環境を作れるようになったら、ステージング環境を構築してRailsアプリを実際にデプロイしてみてデプロイの手順や、開発環境との違いのためにコケるところが無いかを確認する。

デプロイのためのツール

Chefでアプリケーションのデプロイまでも可能といえば可能だろうけれども、可能であることと適していることはもちろん違って、アプリケーションのデプロイにはそれに適したツールがある。Railsでよく使われるのはCapistrano

gemにはよくあることだけれど、Capistrano 2とCapistrano 3では結構使い方が変わっているので注意。自分はCapistrano 3を試したけれどパスワードでのsudoが出来なかったりということがあってCapistrano 2を使ってる。

ググればいろんなチュートリアルやレシピが出てくるはず。
一応自分が使っているCapistranoのレシピはen30/rails4-application-templateで見れる。

運用中

アプリケーションのモニタリング

New Relicが死活監視もできるし、パフォーマンスチューニングにも有用でオススメ。無料でも十分使える。

サーバのリソース監視

Ganglia等を使うと、CPUやメモリの使用状況やらネットワークにどれだけ入出力があるかといった各種データをグラフで見れる。

プロセス監視

MonitGod等のプロセス監視ツールを使えばAppサーバやWebサーバが落ちたら自動で復帰させたりできる。

負荷に耐えられなくなってきたら

そもそも負荷とは何なのか、といったことは

[24時間365日] サーバ/インフラを支える技術 ‾スケーラビリティ、ハイパフォーマンス、省力運用 (WEB+DB PRESS plusシリーズ)
安井 真伸 横川 和哉 ひろせ まさあき 伊藤 直也 田中 慎司 勝見 祐己
技術評論社
売り上げランキング: 14,519

が勉強になる。

この本の中に出てくる「推測するな計測せよ*1」は金言。

複数台構成へ

アプリケーションをチューニングしたが、それでもリソースが不足してきたという時にとる基本的な戦略には、サーバのスペックを上げていく*スケールアップ*と、複数台に仕事を分けて負荷を分散する*スケールアウト*がある。スケールアップには限界があるし、可能な場合はスケールアウトする方が安く済む。

ログを一箇所に集める

複数台構成になるとログが分散して困る。ログを集めるには色々方法があると思うけれど、自分の場合は、そのままの設定では複数のリクエストが入り混じって扱いづらいのでlogrageLTSV形式にしてファイルに書き出して、fluentdでtailしてログ収集用のサーバに送信し、ログサーバではデータベースに突っ込むと同時に各種数値をGrowthForecastでグラフ化している。GrowhForecastはPerlで書かれているがRubyで書かれたfocuslightもある。試していないけれどElastic Search + Kibanaが良いらしい。

おわりに

長くなりすぎた。色々書いたけれども自分もまだまだわからないことだらけ。

運用している間にも様々なトラブルが起こる。ブラックボックスでも問題を解決できる場合はあるが、より良い決断をするには低レベルの知識が必要だと感じる。

この記事がWebアプリを作り始める人達の助けになれば幸いだし、もっと知識のある人が「オマエ全然ワカッテナイ。コウダロ!」と記事を書いてくれるきっかけになっても嬉しい。

*1 プログラミングチュートリアルでも初級の段階でベンチマークをとるということを教えてくれたらいいのになと思う。一つのことを実現する際にも色々な方法があってプログラミングを始めた時はどれを選択すればいいのか全然分からなかった。少なくとも一つの指針としてはじめに計測することを教えて欲しかった。