こんにちは、神崎です。今年の6月頃にアドサーバーのアプリケーションサーバ群をAWS ElasticBeanstalk w/ Dockerに置き換えをおこないました。
これにより、アプリケーションレイヤーのauto-scaling環境の構築、deployのフローの自動化、rubyなどのMiddlewareの入れ替えが比較的容易にできる環境になりました。
既存の環境は、以前ブログで紹介したとおり、EC2上にruby2.0でunicorn+sinatraで構築していました。
- iQONの広告配信システム - VASILY DEVELOPERS BLOG
構成
Containerの内部構成は下記のようになっており、中央にある、ad-serverがアプリケーションの実態のContainerになります。それ以外は、nginx,mackerel,fluentdのContainerがあり、それぞれが特定の役割を担ってアドサーバー全体を構成しています。
デプロイフローは以下のようなフローになり、特定のbranchのgithubにpullrequestをおくりmergeされると、hookされて、eb deployがはしり、docker containerがdeployされます。
またアプリケーション用のDocker imageは、baseとなるrubyとsupervisorをbuildしたimageを作成し、さらにアドサーバで必要なgem類を構築したimageを作成しています。baseのimageとアプリケーションのimageを分けているのは、アドサーバー以外のアプリケーションでも流用しやすくするためです。
外部サービスの利用
コードの管理にはgithub、DockerRegistryにquay.io、CIにCircleCIを利用しています。これらを連携させることで、上記のように自動でdeployしたり、auto-scalingさせたりを実現しています。
トラブル
ElasticBeanstalk+Docker環境に移行してから、概ね大きな問題も起きずにいたのですが、数回トラブルも発生しました。
docker-pullに失敗してダウン
一番大きなトラブルとしては、人的ミスが大きな原因ですが、DockerRegistryとして利用しているquay.ioのパスワードを変更したために、docker pullに失敗して、デプロイができず、アドサーバー全体がダウンすることがおきました。
dockercfgファイルにquay.ioのマスタのaccountを設定してしまっていたため、quay.ioのパスワードを変更したタイミングで、invalidな状態となり、docker pull時にログインに失敗。
また、auto-scalingにより大量にdocker pullが行われるタイミングがあったため、quay.ioのaccountがロックされ、しばらくの間、docker pullができない状態が発生してしまいました。
quay.ioにはdeploy用のrobot accountが設定できるので、そちらを利用することで、上記のような問題は起きないようにしました。
deployに失敗
eb deploy prod
でebコマンドがデプロイ時にs3にputするソース一式のファイルの名前がconflicして、デプロイに失敗しました。ebコマンドのs3にputするファイル名は、gitのcommithashの4文字で固定されているので、それが重複して発生しました。
このときは、ElasticBeanstalk+Docker環境を構築中にebコマンド以外で作ったファイルと重複してしまった様子だったので、常にebコマンドでdeployを実行すれば防げるものだと思います。デプロイに失敗するだけならまだ良いのですがフロー的には、コードがデグレードした状態でデプロイされることも考えられるので、そこは気を使う必要があります。
また、Elasticbeanstalkのapplication versions(ソース一式)は500個が上限なので、定期的にWebConsoleから掃除してあげたほうが安心です。
ruby2.2.3へ
Docker化したので、rubyの入れ替えもやりやすくなりました。そこで先日ruby2.2.3へ入れ替えを実施しました。
下準備としては、ベースとなるDocker imageをruby2.2.3でdocker buildしてそれを元にしてアドサーバーに必要なものをセットアップしたDocker imageを作成することで完了です。
デプロイには、ruby2.2.3を含んだDocker imageのsha1 hashを、Dockerrun.aws.jsonで指定してあげるだけで、入れ替えのデプロイ作業は完了です。アドサーバーはもともと、広告の配信と各種イベントの処理だけで、そこまで複雑なことはしていないので、ruby2.2.3にしたことによるコードの変更は、利用しているgemのupdateの対応を一箇所しただけでした。
ruby2.2.3による変更で遅くなっては意味が無いのですが、今回は、GCの最適化の恩恵をうけることができました。アドサーバーは50msec以下のレイテンシを最低ラインにしており、GC Executionが5~10msecかかっていたのが1msec以下に縮小しました。
以上、アドサーバーをElasticBeanstalk+Dockerに移行し、ruby2.2.3へ入れ替えの紹介でした。
最後に
VASILYでは、新しい技術が大好きなエンジニアを募集しています。少しでもご興味のある方は是非こちらからご応募よろしくお願いいたします。