こんにちは、@r_takaishi です。今回は、筆者が所属しているシステム基盤チームで行ったデプロイパイプラインの改善について紹介します。
背景と課題
Reproでは多数のサービスをECS上で動かしており、それらのサービスは複数の言語・リポジトリで構成されています。また、サービスをChatOps、つまりSlackBotに指示を出してデプロイを行うための仕組みも存在しています。しかし、SlackBotからデプロイされているサービスは一部だけで、手元からデプロイするサービスも多数存在します。
SlackBotからデプロイするサービスと手元からデプロイするサービスの二種類が存在する要因に、SlackBotを含むデプロイパイプラインを構築する手間がかかるというものがあります。
Reproにおけるデプロイパイプラインを構成する主なソフトウェアは以下の3つです。
- Capistrano + github.com/reproio/ecs_deploy
- SlackBot (ruboty)
- Rundeck
CapistranoはコンテナイメージのビルドやECS Task DefinitionやECS Serviceの更新に使っています。これにより、手元から cap
コマンドを実行することでデプロイが可能です。また、SlackBotとRundeckを使うことでSlack上からデプロイを行うための仕組みも存在しています。SlackBotとRundeckを使う場合、開発者はSlack上で @bot deploy service_name branch_name
のようにBotに対してメンションします。SlackBotはメンションを受けるとRundeckでデプロイ用のジョブを実行します。そして、RundeckのジョブがCapistranoを実行してデプロイが行われます。
このデプロイパイプラインの課題は、SlackBotの構築とRundeckのジョブ追加をサービス追加毎に行う必要がある、という点です。新しいサービス用のデプロイパイプラインを用意したいとき、以下を行う必要があります。
- デプロイ用Slack Botの構築(SlackのBot作成とECS Serviceの作成)
- Rundeckジョブの追加
- Rundeckが使うAWS IAM Roleへの権限追加
- RundeckがGithubからリポジトリを取得するためのデプロイキーの設定(RundeckとGithubに設定)
SlackBotとRundeckジョブはほぼ同じものですが、サービス用に個別に追加する必要があります。これはもともとSlackBotやRundeckジョブが一つのリポジトリで開発されているRailsアプリケーション用に作られました。その後にサービスが増えたという歴史的経緯によるものです。
SlackBotの構築やRundeckジョブの追加自体は慣れているとそう難しいことではないし、時間もそこまで必要としません。しかし、サービス開発チームが行うには手間がかかる作業です。IAM Roleへの権限追加も何を追加する必要があるのかドキュメントが存在しておらず、不透明でした。
デプロイパイプラインの構築(CD環境の構築と言ってもよいでしょう)は、高速に、安定したプロセスでサービスをデプロイし続けるために重要です。CNCDが提示するCloudNativeTrailMapにおいてもCI/CDを序盤に行うことを推奨しています(CI/CDとContainerizationの順序は議論の余地がある領域ではあります)。そこで、デプロイパイプライン構築を楽にすべく改善を行うことにしました。
改善内容
今回行った改善は、ずばりSlackBotの構築とRundeckジョブの追加を不要にした、というものです。改善後のデプロイパイプラインは以下の構成です。
複数存在していたSlackBotとRundeckジョブは一つずつとなり、それぞれが複数のサービスに対応しました。これにより、サービス追加時にSlackBotとRundeckジョブを追加する必要はなくなりました。現在は以下の3作業を行えばSlackBotを使ってデプロイできるようになっています。
- Slack Botへの設定追加(yamlファイルに追記してSlackBotをデプロイするだけでOK)
- Rundeckが使うAWS IAM Roleへの権限追加
- RundeckがGithubからリポジトリを取得するためのデプロイキーの設定(RundeckとGithubに設定)
ちなみに、同じRundeckジョブが複数のサービスをデプロイしていますが、実際に実行するコマンドはそれぞれのサービス側で定義可能としています。デフォルトではRundeckジョブ側で定義している処理を行いますが(単純に cap deploy
コマンドを実行する)、サービス側リポジトリ内の所定位置にスクリプトを配置すればそのスクリプトを実行します。これにより、例えばGitのサブモジュールを使いたかったり、デプロイにCapistrano以外を使いたいようなケースにも対応することができます。
なお、IAM Roleへの権限追加やデプロイキーの設定もやや煩雑な作業であるため、改善できないか現在検討中です。
まとめ
サービス追加時にデプロイパイプラインを構築する手間を軽減すべく、SlackBotとRundeckジョブが複数のサービスを扱えるよう改善しました。これまで使われてきたデプロイパイプラインは昔作られたもので、問題なく利用できていたものです。しかし、ここ数年のうちにサービスの種類が増えたり、チーム毎に扱うサービスが分かれてきました。つまり、アーキテクチャや組織構造の変化に耐えられなくなったといえるでしょう。このような変化に対応するため、今回の改善を実施しました。デプロイパイプラインはサービス開発・運用において重要な要素であり、今後も継続的に改善したいと考えています。