Slide 1

Slide 1 text

Amazon CloudFrontを活用した ゼロダウンタイムを実現する安定的なデプロイメント Cloud Native Days Winter 2024 2024-11-29 株式会社SHIFT 品川 慶樹

Slide 2

Slide 2 text

1 登壇者紹介 名前: 品川 慶樹 所属: 株式会社SHIFT ソリューション本部ソリューション事業部 ITソリューション部アプリケーション開発テクノロジーグループ 役割: エンジニア 略歴: 新卒でSIerに入社しエンジニアとして 様々な業種のWebシステム系のソリューションの設計/開発/運用を経験 (金融/出版/製造業/広告/BPO、等) 2022年にSHIFT入社後はソリューション案件や自社プロダクトの開発に従事 GitHub: @s-yoshiki

Slide 3

Slide 3 text

1. 対象者 2. サービス説明 3. 既存システムの構成と運用 4. 抱えていた課題 5. 変更後の構成 6. メリット 7. Q&A 8. まとめ 2 アジェンダ

Slide 4

Slide 4 text

3 対象者 • AWSを採用したシステムの開発・運用に携わる方々 • CloudFrontが好きな方々

Slide 5

Slide 5 text

4 サービス説明: まん福について https://www.manpuku.app SHIFTでは品質保証事業以外にも 開発系ソリューションや 自社プロダクト系の事業も鋭意拡大中 福利厚生型のふるさと納税サービス 「まん福」

Slide 6

Slide 6 text

5 サービス説明: 技術構成 フロントエンド: React, Next.js バックエンド: NestJS + Prisma DB: MySQL 8.0 プラットフォーム: AWS (CloudFront/ECS/Fargate/RDS 等) その他: AWS CDK, GitHub, GitHub Actions pnpm + Turborepo 特徴として、複数のアプリケーション/ツールを Monorepo 方式で管理 バックエンドはモノリシックアーキテクチャで構成され部分的にモジュラモノリス要素も取り入れている BF/FE間はRESTful APIで連携し、SSRも活用している

Slide 7

Slide 7 text

6 既存システムの構成と運用: 構成の概要 • S3で静的コンテンツをホスティング、ECSでAPI/動的コンテンツを配信 • ECSのデプロイはローリングアップデートを実施 ※冗長化やネットワーク等の表現は省略 Webシステムで利用されることの多いオーソドックスな構成を採用

Slide 8

Slide 8 text

7 既存システムの構成と運用: 構成の概要 しかし実際には、様々な経緯により 複数のサービスが依存し合う複雑な状態である /動的Web /静的コンテンツ2 /静的コンテンツ1 /API1 /API2

Slide 9

Slide 9 text

8 既存システムの構成と運用: リリース時の運用作業 メンテナンス時はCloudFront Functionsを利用してS3に配置した静的画面へリクエスト先を変更する またCloudFront Functionsでアクセス制御も行い権限を持つ開発者だけがアプリケーションを参照する 通常稼働時 メンテナンス時 CloudFront Functions CloudFront Functionsでメンテナンス時のリクエスト振り分けとアクセス制御を行う メンテナンス.html 通常リクエスト 開発者の リクエスト 通常リクエスト ECSの イメージの更新

Slide 10

Slide 10 text

9 抱えていた課題 • デプロイ実行時に、メンテナンス画面に切り替えるため、ダウンタイムが発生していた • 本番環境でしか確認できないデプロイの妥当性や、環境変数、パラメータ等の検証が必要だった • ロールバックを行う際にダウンタイムが長時間化するリスクもあった 本番化の際にダウンタイムが発生していた 様々な解決方法を検討した結果 CloudFront Continuous Deployment をベースとした運用を採用

Slide 11

Slide 11 text

変更後の構成: 構成の全体像 10 通常のリクエスト 開発者のリクエスト Staging Distribution Production Distribution A環境 B環境 ポイントはALB/DB共有する2つの環境を用意 HTTPヘッダの種別・有無でリクエストを振り分ける ※ 詳細な説明は後述 Policy

Slide 12

Slide 12 text

変更後の構成: 構成の全体像 (補足) 11 ※補足として左図の通り、CloudFrontの プロダクション/ステージングディストリビューションは 一般的なシステム開発におけるステージングの概念とは 異なるものとして話を進めていきます Production Prod Stage Prod Stage Prod Stage Staging Develop

Slide 13

Slide 13 text

変更後の構成: CloudFront Continuous Deploymentの仕組みと特徴 12 • プロダクションとステージングの2つのディストリビューションで構成される • 2つのディストリビューション同一ドメインで参照できる • ステージングはプロダクションの設定をベースにオリジンやビヘイビアの調整が可能 • プロダクションにステージングの設定を反映(プロモート)することでリリースを行う ※マネジメントコンソールのCloudFrontのディストリビューションのページから参照することができる

Slide 14

Slide 14 text

変更後の構成: デプロイ時の動き 13 ALB/DB共有する同じ構成の2つの環境を用意 HTTPヘッダの種別・有無でリクエストを振り分け 通常のリクエスト 開発者のリクエスト Staging Distribution Production Distribution header=B headerなし header=B A環境 B環境 header=B header=A ★アクティブ環境 ALBのリスナールールでヘッダに基づいて A/B環境へのリクエストを振り分ける CloudFrontのオリジンの機能を利用し ヘッダが存在しない場合ヘッダをセットする 通常運用時は非アクティブ環境のサーバは落としている デプロイ前の状態 if (header!=B) header=A 通常運用時に一般ユーザが参照している環境 リクエスト振り分け判定は実際にはヘッダだけでなく Policyの有効/無効の条件にも影響されるが 便宜上省略する 開発者はWebページへのリクエストに 細工を施して特殊なヘッダを付与して参照する この資料では header=A/Bとしているが、 実際には特殊なヘッダ名/トークンを採用している

Slide 15

Slide 15 text

変更後の構成: デプロイ時の動き 14 通常のリクエスト 開発者のリクエスト Staging Distribution Production Distribution header=B headerなし header=B A環境 B環境 header=B header=A ★アクティブ環境 デプロイのワークフローを実行し、 ECRに新イメージをpushし、B環境のタスクを更新する コンテナイメージ if (header!=B) header=A ECSの更新は ローリングアップデート

Slide 16

Slide 16 text

変更後の構成: デプロイ時の動き 15 通常のリクエスト 開発者のリクエスト Staging Distribution Production Distribution header=B headerなし header=B A環境 B環境 header=B header=A ★アクティブ環境 Promote実行 B環境で動作確認を行い、問題がないことを確認できたらProduction Distributionに Staging Distributionの設定を反映する ヘッダ周りの挙動が変更される if (header!=B) header=A ↓ if (header!=A) header=B

Slide 17

Slide 17 text

変更後の構成: デプロイ時の動き 16 一般のリクエストはB環境の方へ振り分ける 役割を終えたA環境のリソースは停止する 通常のリクエスト 開発者のリクエスト Staging Distribution Production Distribution headerなし A環境 B環境 header=B ★アクティブ環境 デプロイ後の状態 if (header!=A) header=B

Slide 18

Slide 18 text

変更後の構成: デプロイ時のワークフロー 17 build deploy ECR ECS コンテナ イメージ GitHub Actionsの Workflowをキック 本番化検証 CloudFront 開発者 Deployment pipeline CDK Promoteを行う スクリプトの実行 1 2 3 4 5

Slide 19

Slide 19 text

18 メリット メリット • 既存のアプリケーションを稼働しながら新アプリケーションの本番環境テストが可能 • APIのインタフェースに破壊的な変更が発生しても考慮を必要としない • ロールバックが容易 • 任意のリソースを並行稼働することができる 既存の運用を維持しつつ無停止のデプロイを実現 デメリット • 2環境を並列稼働するのでコスト増

Slide 20

Slide 20 text

19 メリット: [補足]任意のリソースを並行稼働することができる 例えば一部のリソースのみ2環境用意して 他のリソースは単一のリソースにすることも可能 ECSだけでなくS3等も対象にすることができる /静的コンテンツ1’ /静的コンテンツ2 /API2 /静的コンテンツ1 /API1 /API1’

Slide 21

Slide 21 text

20 Q&A Q1. ECS で Blue/Green Deploy をやれば良いのでは? A 様々な経緯によりCloudFrontに紐つく複数のリソースが依存し合っている状態のため難しい。 加えて本番環境で検証を行うというワークフローを実現するのも難しい。 (技術的な問題+人的な問題) アーキテクチャがシンプルで綺麗に構築されており、ワークフロー等の制約がなければ、 ECS の Blue/Green Deploy という選択をしたと考えられる。

Slide 22

Slide 22 text

21 Q&A Q2. FE⇄BEのインタフェースの互換性が維持されるような機能開発を行えば良いのでは? A 理屈としては可能であるが、 それを実現できるような開発体制を敷き統制を図ろうとすると… (人的な問題)

Slide 23

Slide 23 text

22 Q&A Q3. 毎回このようなワークフローでリリース作業を進めるのは負荷になるのでは? A 軽微な内容のリリースやhotfixの反映は アクティブ環境に対してローリングアップデートを適用するなど、 負荷にならないよう柔軟に対応している。

Slide 24

Slide 24 text

23 Q&A Q4. 2環境構築した上でLB or CDNのレコードを入れ替えれば良いのでは? A IaCやSDKでの作り込みが難しく、 手動運用をするとしてもオペレーションミスの要因となるだろう。

Slide 25

Slide 25 text

24 Q&A Q5. DBのスキーマ変更の際に止める必要があるのでは? A (CDNの話から逸れますが) MySQLのオンラインDDL機能により、 多くのケースでDDL適用時のテーブルロックが発生しないため ダウンタイムなしでスキーマ変更が可能である。 オンラインDDLが有効とならない破壊的なDDLでも、 対象テーブルに対するアプリケーションの依存関係の計画的な調整や、 Feature Flagで制御しダウンタイムを限りなくゼロに近づけている。

Slide 26

Slide 26 text

25 まとめ: 導入した結果 イレギュラーな事態によりメンテナンスモードが発生したことはあったが、 ほとんどのリリース作業においてゼロダウンタイムを維持している 計画的メンテナンスによるダウンタイム時間 従来: 24時間/年 変更後: 1時間未満/年 ダウンタイムがほぼゼロになりSLAの水準を大きく上げることに寄与 稼働率換算: 99.72% → 99.99%

Slide 27

Slide 27 text

26 技術イベント毎月開催中 最新情報はXフォローで! ブースで質問受け付けます 是非お立ち寄りください