#179
インフラの引っ越しを行いました

多くの人がサービスをより快適に使えるようにするために、esaの本番サーバをHeroku (US region) からAWS (Tokyo region) に引っ越しました(※)。また、開発をより快適にするためにCI環境の引っ越しも行いました。

※ 先月後半から調査・検証を開始し、3/19のメンテナンスで移行を行いました。

#177: メンテナンス情報/完了/2016/03/19(土)/9:00-13:00 (JST)

project-mars.png (1.9 MB)

主な変更点

BEFORE AFTER
Web Server / Woker Heroku (US region) Docker on ECS(Tokyo region) + ECR
Cron Heroku Scheduler sidekiq-cron
DB Heroku Postgres RDS for PostgreSQL
DNS DNSimple Route 53
CI CircleCI Shippable + DigitalOcean
Auto Bundle Update circleci-bundle-update deppbot

以下、ざっくり説明していきたいと思います。

Web Server/Workerの移行

従来はHeroku(US region)にサーバがあったため、日本からのアクセスの場合チューニングをどう頑張っても数百msの遅延がありました。これをAWS(Tokyo region)に移行することで、ページを表示するのに要する時間が1/2 ~ 1/3まで改善されました。

Docker

移行開始直後は自分が不慣れなこともあり、このタイミングでDockerを採用する気はありませんでした。しかし、実際にECS上でのデプロイを検証したり、Dockerについて学習するうちに移行のイメージが掴めてきたのでDockerを採用することにしました。

もともとHerokuで動いていて The Twelve-Factor App にほぼ沿っていたので、やってみるとDocker移行への障壁はそれほどありませんでした。

コンテナ戦略

シンプルにするために、WebコンテナとWorkerのコンテナは同じものを使っていて、docker run の時のコマンドで違う動きをさせています。(このあたりはHerokuと同様ですね。)

nginxを別コンテナにするかwebコンテナと同居させるか迷いましたが、最終的にはnginxを使わないという判断をしました。assets系のファイルは基本的にS3+CloudFrontで配信されているためです。今のところこの構成で問題は発生していません。

ECS

git push heroku masterしたらあとはHerokuがよしなにやってくれる」ように、「TaskDefinitionを定義してServiceを更新したらあとはECSがよしなにやってくれる」ところが好きです。

デプロイのときに順番にLBから解除・登録したり、インスタンスの数を役割ごとに一定に保ってくれるので今のところほとんどHerokuの時と同じような運用ができています。

Cronの移行

aws lambda scheduled eventsone-off dynoを組み合わせて...」みたいなことをちょっと考えましたが、複雑になりすぎるのでsidekiq-cronというsidekiqの拡張を使うことにしました。もともとそれほど重要な定期処理はなかったので十分でした。

この移行はHeroku => AWS移行の数日前に行いました。

DBの移行

サービスをメンテナンス状態にしてからHeroku Postgres上でバックアップを行い、RDSにリストアしました。可用性を高めるためにmulti AZを有効にし、また暗号化オプションが有効になっています。

DNSの移行

Herokuで esa.io 等のNaked Domain(Apex Domain)を扱うためにDNSimpleを使っていましたが、AWS移行後は不要になったのでRoute53を使うようにしてあります。

CIの移行

従来CircleCIを使っていましたが、Docker移行後はdocker build 時にキャッシュを上手く扱えない問題があり、buildの時間が10分以上かかるようになってしまったため、Shippableに移行しました。こちらはdocker build時のキャッシュも別のbuildで使うことができます。また自分で用意したdocker imageを使ってCIを行うことができ、さらに自前で用意したホストマシン上でCIを行う事もできます。

試行錯誤の結果、DigitalOcean上のちょっと強いホストマシンとカスタマイズしたdocker imageを組み合わせ、build時のキャッシュを最大限活用することで、テストの実行時間を2分、デプロイを含めても3~5分程でbuildが終わるようになりました。

ss 2016-03-30 0.46.47.png (179.8 kB)

デプロイ用のブランチ戦略

Herokuを使っていた時はStaging環境はなく、masterにmergeしたら本番環境にデプロイされていました。流石にStaging環境無しで移行するのは難しかったので、以下のようなブランチ戦略をとり、Stagingへのデプロイ等を検証しながら作業を進めました。

branch action
master production/deployへのalias
$ENV/deploy $ENV 環境へweb, workerコンテナをデプロイ
$ENV/db-migrate $ENV 環境へone-offコンテナをデプロイしてdb:migrate

Auto Bundle Updateの移行

CircleCIを使用していた時は、 masutaka/circleci-bundle-update-pr を使っていましたが、Shippableに移行してしまったので、deppbot を使うようにしました。

ss 2016-03-30 17.01.33.png (115.5 kB)

機能的な違いはあまりありませんが、CHANGELOGやrelease noteへのリンクを貼ってくれるので気が利いていますね。

参考リンク

所感

いかがだったでしょうか。Herokuからの移行を考える場合に少しでもご参考になれば幸いです。

今回書ききれなかった細かい知見や、移行プロジェクトを進める中でのモチベーションの保ち方なども何らかの形でアウトプットしていけたらと思います。

今後も安定した快適なサービスを提供できるように最善を尽くしていく所存ですので、どうぞよろしくお願いいたします。

Comments0