クラウドワークス エンジニアブログ

日本最大級のクラウドソーシング「クラウドワークス」の開発の裏側をお届けするエンジニアブログ

Herokuで本番サービスを運用する際にやっておきたいこと & 構成の事例

f:id:yo-iida:20160901110900p:plain

こんにちは、最近アルコールが入っていたらなんでもいいと思うようになってきた @yo-iida です。🍻

今回はみんな大好きHerokuのお話です。

サービス立ち上げ期に大活躍するHerokuですが、CrowdWorks内でもいくつかのプロダクトで本番までHerokuで運用しているサービスがあります。

今回は私が携わっている社内プロダクトでのtipsを紹介します。

やっておきたいこと

Heroku PipelineとReview appを使いこなす

Herokuで本番運用するのであれば、Heroku上にproduction, stagingなどの各環境を用意する必要があります。

このとき便利なのがHeroku Pipelineという機能です。

f:id:yo-iida:20160901114245p:plain

この機能を使うと、開発環境から本番までの一連の環境をひとつのプロダクトとして管理できます。
またHeroku Pipelineと合わせて使いたいのが、Review app機能です。Review app機能はGitHub上のPull Requestごとにappを自動で立ち上げてくれる機能です。deploy後の動作確認が格段に効率化します。

これらの機能を利用すると、

  • developブランチからtopicブランチを切ってPull Requestを作るとReview appが立ち上がり
  • topicブランチがdevelopブランチにマージされるとstaging appに自動デプロイされ
  • developブランチからmasterブランチにマージして最後は任意のタイミングで本番にデプロイ

といった具合にブランチ運用とアプリケーションをうまく連携させることができます。

Pipelineの具体的な使い方は去年のアドベントカレンダーに書いています。Heroku Pipelineを使ってみる

本番とデータ同期できるpreview環境を追加する

Heroku PipelineとReview appだけでも便利なのですが、私のプロジェクトでは、preview環境というものを導入しています。

これは、本番リリース前に本番データを同期させてパフォーマンス面での最終動作確認を行うための環境です。

たとえば本番のデータ量が大きくなってくると、stagingでの動作検証では問題がなかったのに本番にリリースして予期せぬ障害が起きる可能性があります。これは動作検証しているデータが異なることが原因です。

これを解決するために通常のリリースフローの中に必ず本番とデータ同期させて確認するフローにしています。

環境名 Review app staging preview production
用途 Pull Request毎の確認環境 develop最新の確認環境 master最新の環境で本番データを用いての最終動作確認 本番サービス
デプロイタイミング PRを作成した時 トピックブランチからdevelopへマージされた時 developからmasterへマージされた時 heroku pipelineでpromoteした時

productionからpreviewへのデータ同期は下記のようなシェルスクリプトを組んで行っています。

同期スクリプトの例

  # S3の同期
  # *****-productionからACL=public-readを明示的に指定してsyncする
  # ※ --aclオプションを指定しないとprivateでsyncされてしまう
  # また、sync元にないファイルを --delete オプションで削除している
  # http://docs.aws.amazon.com/cli/latest/reference/s3/sync.html
  echo "== copying bucket to preview from production =="
  aws s3 sync --delete --acl public-read s3://*****-production s3://*****-preview

  # postgresqlの同期
  # https://devcenter.heroku.com/articles/heroku-postgres-backups#direct-database-to-database-copies
  echo ""
  echo "== copying database to preview from production =="
  heroku pg:copy *****::DATABASE DATABASE --app *****-preview --confirm *****-preview

  # DBのマスク
  echo ""
  echo "== mask preview db users =="
  heroku run rake mask_users --app *****-preview

上から、

  • S3の同期(ストレージとしてS3を使っていなければ必要ありません)
  • DBの同期
  • 本番データのマスク(ユーザーのメールアドレスとパスワードをダミーデータに一括変換するrake taskを実行しています)

となっております。

Herokuはaddonで色々なDBを扱えますが、標準のPostgresqlだとコマンドひとつでこのようなことが簡単にできるのでおすすめです。

Heroku上のアプリケーションはすべてRAILS_ENV=productionで動かす

以上のようにPipeline上に複数のアプリケーションを用意してきましたが、大事なことがひとつ。

これらのアプリケーションはRAILS_ENV=productionで動かす ようにしましょう。

公式にも下記のように書かれています。

You should use RAILS_ENV=production or RACK_ENV=production for your staging applications to minimize surprises while deploying to production.

Managing Multiple Environments for an App | Heroku Dev Center

確認環境は限りなく本番に近い状態にしておくべきだという考えです。

当初は別のRAILS_ENVで起動していた環境も運用していたのですがRAILS_ENVが異なることでその環境で動いていたgemが設定不足によりproductionで動かないといったトラブルもありました。
このような経緯から私のプロジェクトでもHeroku上のアプリケーションはすべてproductionで動かすようにしています。

すべてproductionで動かす場合でも、環境毎に設定を変えたいということがあるとおもいますが、これはHerokuの環境変数で設定するようにします。

たとえば、stagingと本番でS3の接続先を変えたい場合は環境変数でアプリケーションのふるまいを変えるようにします。

The services and libraries that your application uses may also need their own configuration variables set, mirroring those on production. For example, you may use a different S3 bucket for staging than you do on production, so you will use different values for the keys

DBのバックアップ設定をしておく

いざというときのためにDBの自動バックアップを設定しておくとよいでしょう。

heroku pg:backups schedule DATABASE_URL --at '02:00 Asia/Tokyo' --app *****

上記のように設定すると毎日2時にバックアップを作ってくれます。

f:id:yo-iida:20160905130615p:plain

リストアも簡単にできるようになっています。

heroku pg:backups restore b100 DATABASE_URL --app *****

Production Checkを行う

本番サービスで稼働させるために必要な設定になっているかをHerokuがチェックしてくれる機能です。

f:id:yo-iida:20160905131449p:plain:w200

appの右上のメニューから確認することができます。

f:id:yo-iida:20160905131513p:plain:w400

dynoの冗長化ができているかやDBのバックアップができているか、その他DNSSSLの設定、モニタリング設定ができているかを自動チェックしてくれます。

使っているプランやスケール数によってはオールグリーンにならない場合もあるかとおもいますが、参考程度にみておくとよいかと思います。

アプリケーションのビルドの仕組みを知っておく

HerokuのビルドはHerokuが提供しているbuildpackというツールが担当しています。

buildpackは、rubyであればGemfileを探して、bundle installし、assets:precompileし、圧縮してdynoに配信、という処理を行います。

buildpackは通常1言語なのですが、最近のアプリケーションではjs側はnodeに任せることが多く、ビルド時にnpmも使うことが多くなっていると思います。

このような場合には、buildpackを複数使うことでnpmからインストールしたライブラリをrails側で使うといったことが可能になります。

buildpackの追加は以下ようにコマンドからでも、ダッシュボードからでも可能です。

Using Multiple Buildpacks for an App | Heroku Dev Center

f:id:yo-iida:20160901155553p:plain

さらに、アプリケーションが育ってくるとデプロイの際に色々な付加的な処理をやらせたくなることもあると思います。

たとえば、マイグレーションを実行したい、とか、Seedを流したいとかがあります。

その際には、下記のbuildpackを追加して使うと、任意のrake taskをデプロイの最後に実行してくれるようになります。

github.com

このように、buildpackはHeroku公式のものと、第三者がカスタムして作ったものがあります。

ビルドの仕組みを知っておくことで、必要に応じて組み合わせることで複雑なアプリケーションのビルドも可能になると思います。

構成の事例

私のプロジェクトで使っているaddonを含めた全体構成図は下記のようになっています。

f:id:yo-iida:20160901124801p:plain

Standard以上のdynoを使用する

外向けのサービスであれば Standard 2X dynos を利用したほうがよさそうです。が、立ち上げ期の負荷が小さい時期には Standard 1X dynos でも問題ないでしょう。

Standard 1X以上にしておくメリットはdyno自体の処理能力以外にも以下のような機能が使えるようになります。

  • スケールアウトが容易にできるようになる

f:id:yo-iida:20160901125734g:plain

CLIからもできますがダッシュボードからグイーンってやれるのも便利ですよね。

  • メトリクスのダッシュボードが使えるようになる

f:id:yo-iida:20160901130301p:plain

dynoに関するメトリクスが見れるようになります。

アラート機能はレスポンスタイムとスループットのエラーレートが使えるようになります。

ミドルウェアはHeroku公式に寄せる

DBやKVSではHeroku公式addonとしてPostgresqlとRedisが用意されているので、特に理由がなければこれらを使うのがよさそうです。

コスト的にも他のaddonと比べて安いですし、Heroku公式なので管理画面や機能も充実していること、また、公式という安心感があります。

特にHeroku Postgresのcliまわりはいざというときに便利な機能がそろっていると感じます。

https://devcenter.heroku.com/articles/heroku-postgresql#using-the-cli

監視系

監視系も一通りaddonで揃います。

アプリケーションのエラー監視はRollbarがよいでしょう。

先日 @ctokoro_me が書いていたRollbarの記事(エラーモニタリングサービス Rollbar と GitHub Issue を利用したエラー対応フロー - クラウドワークス エンジニアブログ)もaddon経由で使っており、参考になるかと思います。

監視のアラートは基本的にはslackに投げるようにしているのですが、ここではPaperTrailとLibratoの通知について最低限の設定を紹介します。

ログ監視: PaperTrail

f:id:yo-iida:20160901133032p:plain

PaperTrailはログ監視のツールでaddonに追加してダッシュボードを開くとこのようにリアルタイムでログが流れてきます。

下のフォームから検索クエリを投げられるので、たとえばrailsのエラーログだけを抽出したいというときには下記のようにします。

f:id:yo-iida:20160901133720p:plain

検索クエリでSearchしてSave Searchしておくと、

f:id:yo-iida:20160901133937p:plain:w300

検索設定を保存しておけます。

また、この検索クエリで新しいログが流れたときにその内容をアラートで飛ばすことができ、

f:id:yo-iida:20160901134345p:plain

このような設定にしておくと、

f:id:yo-iida:20160901134624p:plain:w600

ログが流れた時点でslackに通知することができます。

railsのログだけでなくherokuのログも流れるので他の監視サービスと組み合わせて使うのがよいでしょう。

メトリクス監視: Librato

Libratoはメトリクス監視のツールです。DataDog等と同じカテゴリのツールです。

addonとしてはHerokuのメトリクス監視に特化しており、アプリケーション以外のdynoの状況やその他ミドルウェアの監視に役立ちます。

取れるメトリクスはDataDogのように柔軟には設定できないのですが、Herokuで運用する分には十分でしょう。

f:id:yo-iida:20160901135358p:plain

スペースと呼ばれるものがメトリクスのグルーピングで、紫のスペースは最初から作られているHerokuのデフォルト設定です。

ここから各メトリクスの通知設定を行ってもよいのですが、特に見たいものを別で管理したいので、青色の監視項目スペースを新しく作成しています。

f:id:yo-iida:20160901135804p:plain

中身はこんなかんじです。 社内利用なのでまだ数字が小さいです(。◉ᆺ◉)

チャートを新しく作る場合は、右上プラスボタンを押してグラフの種類を選びます。

f:id:yo-iida:20160901140103p:plain

次にチャートに入れたいメトリクスを選び、

f:id:yo-iida:20160901140957p:plain

表示方法を設定すれば完了です。

f:id:yo-iida:20160901140936p:plain

チャートはスナップショットしてslackに送ることもでき、

f:id:yo-iida:20160901144624p:plain:w300

スナップショット作成から、

f:id:yo-iida:20160901144638p:plain:w300

メッセージを編集して送信。

f:id:yo-iida:20160901143944p:plain:w400

こんなかんじでチャートを簡単に共有できます。

アラート設定はスペースの設定とは別になっています。

トップの右上のアラートボタンを押すとアラートの画面に遷移します。

f:id:yo-iida:20160901141311p:plain:w200

現在はこのようなアラートを設定しています。

f:id:yo-iida:20160901141705p:plain

たとえば、DBコネクション数のアラート設定は下記のようになっています。

f:id:yo-iida:20160905140545p:plain

editから条件の設定ができます。

f:id:yo-iida:20160901143320p:plain

閾値の設定は、現在使っているプランから自分で計算して設定しましょう。

f:id:yo-iida:20160901143547p:plain

あとは通知サービスのほうにslackを設定すれば、

f:id:yo-iida:20160901143931p:plain:w600

こんな具合にアラートが飛びます。

1点、Libratoは一度エラーが起こると、アラートが飛び続けます(。◉ᆺ◉)。 エラー自体は続いていなくても、ダッシュボードから Resolve を押さないとslackにずっと飛んでくるので必ず対応して止めましょう。

外形監視: Pingdom

Pingdomは外形監視のサービスです。

上記で書いてきた監視はいずれもサーバー内部でエラーが起こったりサーバー自体にエラーが起きていないかを監視するものですが、さらに外からHTTPリクエストが届くかどうかを監視するサービスとしてPingdomがあります。

ネットワーク障害が起きている場合など、中ではエラーが起きていなくてもアクセスできないケースがありますが、これは外形監視サービスを使わないと察知することができません。

これもaddonから使えるので必要に応じて使うとよいでしょう。

CDN: Fastly

CDN系のaddonでは、いくつか選択肢がありますがFastlyがよいでしょう。

FastlyはInstant Purge(即時削除)という機能があり、通常CDNではキャッシュの削除に時間がかかりますが、即時の削除が可能となっているところも他にはない点です。

余談ですが、CDN検討の際に、CloudFront経由のasset_syncで配信するという手もあるのですが、Herokuでは奨励されていません。(Please Do Not Use Asset Sync | Heroku Dev Center

DNS: PointDNS

DNS系はPointDNS, ZerigoDNSがあります。機能はどちらも大差はありません。

UIの好みでPointDNSを使っています。

addon以外のサービス

Heroku以外ではストレージとしてS3を使っています。

ストレージサービスでS3に勝てるサービスは現状ないですね。

メール配信はSendGridを使っています。

社内のメール全体をSendGridで運用している経緯からaddonは使っていないですが、addonでも問題ありません。

最後に

Herokuのいいところをいろいろ紹介してきましたが、Herokuには制約もあります。

ビルド時に圧縮されるアプリケーションのファイルをスラグと呼んでいますが、

  • スラグ容量が300MB以下であること
  • コンパイル時間が15分以内であること

という制約があります。

普通に考えると結構厳しい制約だと思いますが、assetsを外部化したり、コードが肥大化しそうなところはドメインごと別アプリケーションにしていくなど、コードをメンテナンス性高く綺麗に保つための制約であると捉えることもできます。

もちろんサービスの成長に伴って、最終的にAWSに移行するとか、もしくは他のインフラに乗り換えるとかフェーズによって技術の取捨選択は必要だと思いますが、立ち上げからサービスが成長するまでHerokuで運用してみるというのは結構ありな選択ではないかと考えています。

We're hiring!

クラウドソーシングのクラウドワークスではアプリケーション開発に集中するためにクラウドサービスを使い込んで効率的な開発にチャレンジするエンジニアを募集しています!

www.wantedly.com

興味のある方はお寿司ランチを無料で食べながらお話してみませんか?

crowdworks.co.jp

© 2016 CrowdWorks, Inc., All rights reserved.