blog

DeNAのエンジニアが考えていることや、担当しているサービスについて情報発信しています

2017.04.25 技術記事

Capistranoを使ってS3等からpull型デプロイするgemを書いた、ほか

by ReiSugano

#ruby

このブログは「mobage developers blog」2017.4.25の記事を転載させていただきました。


こんにちは。ゲーム事業本部開発基盤部の池田(@progrhyme)です。 

先日、Ruby製デプロイツールのCapistranoと組み合わせて利用できるgemをいくつかRubyGemsに公開しました。

今回は、これらについて紹介します。

なお、いずれもソースコードはhttps://github.com/DeNADev/で公開しています。config/deploy.rbなどの具体的な設定方法については、各リポジトリのREADMEを参照ください。

capistrano-net_storage, capistrano-net_storage-s3について

capistrano-net_storageは、S3など外部のストレージシステムを経由したpull型デプロイの汎用的な仕組みを提供するgemです。

そのプラグインとして動作するcapistrano-net_storage-s3は、Amazon S3との通信部分を担っています。


両者を組み合わせることで、Amazon S3を経由したデプロイが可能になります。

pull型デプロイの仕組み

capistrano-net_storageのREADMEに掲載している図を用いて、概要を示します。

  1. デプロイ対象となるアプリケーションのアーカイブを作成します。

    1. リポジトリのスナップショットを生成し、.tar.gzなどの形式で圧縮します。

    2. オプションでbundlerにより依存gem一式をアーカイブに含めることができます。

  2. 作成したアーカイブをAmazon S3などリモートのストレージサーバにアップロードします。

  3. デプロイ対象の各サーバにsshし、リモートのストレージからアーカイブを取得し、展開します。

    1. このとき、必要に応じてアプリケーションの設定ファイル等をデプロイサーバから追加で配布することも可能です。


3. のプロセスは並列で実行可能なので、ストレージからのダウンロードに律速されないならば、対象サーバ数がいくら増加しても一定時間内にデプロイが完了します。言い換えれば、O(1)でのデプロイを達成できます。

類似ツールとの比較

Amazon S3等を経由してO(1)でpull型デプロイを実現するツールとして、以下があります。

これらに対するcapistrano-net_storageの特徴として、以下が挙げられます:

  • cap deployコマンドでデプロイ可能。

  • プラグインを実装することで他のストレージシステムも利用可能

  • (mamiyaに対して)Serfクラスタを用意する必要がない。

プラグインについては、今のところAmazon S3用以外のものの実装予定はありませんが、Capistrano::NetStorage::Transport::Baseを継承して作りやすくしているつもりなので、必要な方の参考になれば幸いです。

※4/26 追記
特徴として「Serf/Consulクラスタを用意する必要がない」と記していましたが、筆者に誤解があり、stretcherにおいてSerf/Consulは必須ではありませんでした。

想定するユースケース

以下のような環境でオススメです:

  • サーバ台数が多く、デプロイに時間がかかっている

  • Amazon S3などI/Oキャパシティの高いストレージが利用可能

  • デプロイにCapistranoを使っている

  • 開発言語がRubyである

また、capistrano-net_storageで提供するnet_storage:upload_archiveやnet_storage:pull_deployというタスクを分けて用いることで、リリースタグを作成した段階で外部ストレージにアーカイブをアップロードし、更にデプロイを高速化するといった運用も可能です。

開発の経緯

このプログラムのプロトタイプは、当時AWS上で展開していたあるサービスの担当者が開発したものです。

そのプログラムに手を入れる機会が有り、せっかくなので汎用的な仕組みにしてOSSとして公開するところまで持って行こう、と手を動かしていたら自然と出来上がりました。 

capistrano-deploy_lockerについて

こちらはRubyのFile#flockを使ったファイルロックにより、デプロイの排他実行を可能にするgemです。

config/deploy.rbに下の行を追記することで、排他ロックを取得します:

before ‘deploy:starting’, ‘deploy:lock’

これにより、複数のプロセスが同時にデプロイを試みた場合、後からデプロイしようとしたプロセスでは処理が失敗するようになります。

開発の経緯

このような機能が必要になったのは、運用時にアプリケーション担当者とインフラ作業やオートスケール時のデプロイがバッティングする可能性が出てきたからです。

特に、これを導入したサービスでは、負荷上昇に伴う自動スケーリングによって、サーバ投入時に最新のアプリケーションコードをデプロイするという仕組みになっていたため、「デプロイ時に声を掛け合う」ようなマニュアルの対応では限界があると考えられました。

また、同様の機能を提供するgemは、RubyGemsにおいてもいくつか見つかりましたが、使いづらいところがあったため、今回は別途開発するという選択をしました。

まとめ

以下のCapistranoプラグインを作成しました。

  • 外部ストレージ経由でのデプロイを可能にするcapistrano-net_storage

  • そのプラグインとして動作し、Amazon S3との通信を仲介するcapistrano-net_storage-s3

  • デプロイの排他制御を可能にするcapistrano-deploy_locker

機会があれば、ぜひご利用ください。

また、不具合や問題点などありましたら、GitHubのイシューやプルリクエストでお知らせください!

最後まで読んでいただき、ありがとうございます!
この記事をシェアしていただける方はこちらからお願いします。

recruit

DeNAでは、失敗を恐れず常に挑戦し続けるエンジニアを募集しています。