inSmartBank

B/43を運営する株式会社スマートバンクのメンバーによるブログです

B/43のFargateを使ったBlue/Greenデプロイシステムの変遷

イントロ

こんにちは!SREを担当してます上平と申します。 このエントリーでは スマートバンクが提供する B/43サービスの裏側のデプロイシステムに関して紹介したいと思います!

自分自身の振り返りも兼ねてどうして現在のデプロイシステムに至ったのかをお話ししたいと思います、これからデプロイシステムの構築を検討されている方の参考になれば幸いです。

RDBを使用したWebアプリのデプロイ方法を構築する中で、発生した問題にどう対処し、より安定したデプロイを行うようにしてきたかを紹介します。

想定される読者

  • RDBを用いたWebアプリケーションで Blue/Green デプロイを行なっている方
  • AWS CodePipeline をどう組むか悩んでいる方

デプロイにおいて実現したかった要件

環境構築当初、デプロイで実現したかった要件をまとめました。

  • サービスダウンタイム無く、デプロイが行えること
  • 障害発生時にすばやく前回の状態に切り戻せること
  • AWS 製品を活用して、可能な限りシンプルな構成にすること

デプロイ方法の考察

デプロイ方法の比較

要件を満たすデプロイ方法は大きく分けてローリングアップデートとBlue/Greenデプロイの2パターン存在し、AWS公式ページでも紹介されています。それぞれの比較を簡単に紹介したいと思います。

ローリング更新 - Amazon Elastic Container Service

CodeDeploy による ブルー/グリーンデプロイ - Amazon Elastic Container Service

ローリング Blue/Green
構成 シンプル 複雑(別途CodeDeployが必要)
コスト 安い 高い(一時的に2倍)
ダウンタイム 少ない 少ない(ほぼゼロ)
ロールバック 時間がかかる 簡単
障害 新旧が混在するので問題が発生しやすい 新旧の環境が完全に分離されるため問題が発生しにくい
TargetGroup 複数設定可能 BlueとGreenのみ (LBのpathなどでTGを分けれない)
注意点 - ロードバランサーが存在しないworkerなどでは選択不可

デプロイ構成としてはECSにお任せできるローリングアップデートの方がシンプルですが、Blue/GreenデプロイではCodeDeployを別途構築する必要があります。

コスト面ではローリングアップデートの方は1台ずつ更新をかけるのに対し、Blue/Greenデプロイでは現状と同じ台数のコンテナを準備するため、一時的にコストがかかってしまいます。

デプロイにおけるダウンタイムはどちらも少ないものの、ロールバックに関してはトラフィックの切り替えで済んでしまうBlue/Greenデプロイの方が簡単です。

ローリングアップデートでは1台ずつ更新をかけるため一時的に新旧のコンテナが存在し、その状態でサービスインしているため障害が発生しやすい状態になってしまいます。

また構築時の注意点としてはBlue/GreenデプロイにはTargetGroupが必ず2つ必要になり、それ以下でも以上でも設定できません。なのでロードバランサーが不要なJob WorkerなタイプのコンテナではBlue/Greenデプロイを選択できません。

最終的に選んだデプロイ方法の紹介

最終的には下記理由から大半のコンテナではBlue/Greenデプロイを採用することにしました。

  • デプロイによるサービス停止をなくすことができる
  • 新旧のコンテナ(サービス)が混在しないので、ユーザーには一貫して同一のコンテンツが展開される
  • デプロイ先(新環境)に問題が発生した場合は自動で切り戻しされる
  • (現在はローリングアップデートでもサーキットブレーカーによって切り戻し可能です)

しかし、一部のJob Workerだけローリングアップデートを実施しています。Blue/Greenデプロイには2つのTargetGroupが必要となり、ロードバランサーに紐づけができないJob Workerなどはローリングアップデートを採用しています。

デプロイ方法の紹介

弊社で実施しているデプロイのシステムに関してサービスイン当初と現在を紹介し進化した過程をご紹介いたします!

※サービスイン当初とは 2021年1月頃になります

サービスイン当初のデプロイの紹介

フロー図

なぜこうしたか

サービスイン当初のデプロイ環境はシンプルに構築しました。 弊社ではAWSを中心にサービスを構築しており、コンテナサービスを使用しております。

その前提もありAWSのCodeBuild+CodeDeployを使ったAWS CodePipelineを採用しました。 サービス構築当初、デプロイシステムはシンプルに以下のフローで構築しました。

  • Source → Build → Deploy

運用する中ででてきた課題の紹介

SecretsManager

AWS Secrets Manager(シークレットのローテーション、管理、取得)| AWS

弊社の環境では、コンテナを使用し、重要な秘匿情報はSecretsManagerに保存されています。コンテナの起動時には、SecretsManagerからこの情報を取得し、環境変数としてセットしています。

秘匿情報の管理 / 更新に関してはSREチームが、実装者から依頼を受けて、Terraformで秘匿情報を追加しSecretsManagerに反映させる運用をしていたためデプロイフローとは別で作業が発生しておりました。

しかし、この運用ではSRE側の作業が完了していない状態でデプロイされると、コンテナ起動時に環境変数をセットする際にエラーが発生し、コンテナが起動できないケースがありました。

そのため環境変数の管理をデプロイフローに組み込む様にデプロイフローを見直す必要がでてきました。

DB migrate

アプリケーションのデプロイではデータベースのマイグレーションが必要なリリースも有ります。

弊社ではRailsアプリケーションを動かしているため、当初はコンテナ起動時に以下のようにマイグレーションコマンドを実行していました。

bundle exec rake db:migrate && bundle exec rails server

しかし、コンテナが複数台構成になると、マイグレート作業は一度で良いにも関わらず複数のコンテナが実施してしまい、DBへの負荷が発生していたので、解消する必要がありました。

現在のデプロイの紹介

フロー図

なぜこうしたか

フローとしては下記のようになっています。

  • Source → Build → Build-Secrets → DB-migrate → Deploy

秘匿情報に関してはTerraformで秘匿情報の管理をするのではなく、各リポジトリにて管理するように変更しました。

リポジトリ内の暗号化された秘匿情報をAWSCLIを使ってAWS SecretsManagerにupdateするAWS CodeBuildを作成し、AWS CodePipelineのstageとして組み込むようにしました。

マイグレートの問題もAWS CodePipelineのstageとして設定することにし、AWS CodepielineからLambdaを起動し、DBマイグレートを実施するFargateタスクを起動することで実現しました。

運用してみての所感やTips紹介

上記のフローを構築後に更に発生した問題点や、手直ししたことなどを紹介したいと思います。

SecretsManagerでの秘匿情報管理について

アプリケーションコードと秘匿情報は密接に紐ついているので、秘匿情報のみをTerraformで管理するよりも、リポジトリ内で同時管理する方がデプロイフローに組み込むことができて一貫性を担保できます。また、SecrestsManagerの仕様上、取り扱える文字数に限界があり、シークレットを分割する必要がありました、そこで秘匿情報を分割して管理するように変更しました。

環境変数として、秘匿な情報とそうでない情報があり、今まではそれら全てを暗号化した状態で管理していましたが、分割の必要もあったことから、それぞれのファイルとして分割して管理するようにしました。

起動時に実行するコマンドについて

上記のDBマイグレートのように各コンテナが起動時に同じ動作をする共通処理はデプロイフローに組み込むと良いなと思いました。秘匿情報の更新とDBマイグレートをデプロイフローにて行うことによって、起動してくるコンテナが他のコンテナと起動時の処理で競合することなく最新の状態で起動することができます。

何をAWS CodePiplineのstageとして実行すると良いのかを考えましょう。

デプロイのTips

弊社ではデプロイが実施された場合は、Event Bridgeで検知後、lambdaが動きSlackへ通知してます。失敗時などは絵文字を変えることで早期発見できるように工夫しています。

  • デプロイ成功

  • デプロイ失敗

まとめ

今回は弊社のデプロイシステムをご紹介させていただきました。発生した問題に対して対応することでデプロイフローも安定してきたとはいえ、まだまだ完成形ではないと思っています。例えば、既に以下の課題も発生しており、改善点はまだまだあります。

  • デプロイのたびにbuildしており時間がかかるので事前にbuildは済ませておきたい。
  • 開発環境が1つなので開発者間で利用待ちをする機会が増えて、開発スピードの低下に繋がってきた。

特に後者の問題は早急に解決する必要があると感じ、現在はプルリクエスト別に個人開発環境が作成できるように構築を変更しています。どのように開発環境を改善していったかは、また次回以降のブログにてご紹介できればと考えております。

We create the new normal of easy budgeting, easy banking, and easy living.
In this blog, engineers, product managers, designers, business development, legal, CS, and other members will share their insights.