[レポート] モノリシックなシステムをサーバーレス化するための8つのステップ API310-R How to refactor a monolith to serverless in 8 steps #reinvent

CX事業本部@大阪の岩田です。 本エントリはAPI310-R How to refactor a monolith to serverless in 8 stepsのレポートとなります。

セッション概要

Refactoring a monolith to serverless can be intimidating, but there are discrete steps that you can take to simplify the process. In this chalk talk, we outline eight steps for successfully refactoring your monolith and highlight key decision points such as language and tooling choices. Through real-world examples of successful migrations, we uncover common mistakes, useful techniques for identifying components for migration and service boundaries, and processes for migrating large amounts of data without downtime. Bring your refactoring challenges to this interactive session to see how these techniques can be applied in the context of your own application.

レポート

Step1 逆コンウェイの法則

  • コンウェイの法則:
    • システム設計は、組織構造を反映したものになる
  • 作成したいソフトウェアに合わせて組織を構成する
  • サービスを実行する権限を与えられ、委任された小規模な自立したチーム
  • アマゾンの「2つのピザチーム」のスローガン
  • 信頼するが、検証はする
  • 集中管理とゲートキーピングに関するガイダンスとコンテキストを提供する
  • 最初に成功事例を作成する
  • チームがスキルアップする必要性を受け入れる

Step2 サービスの境界を定義する

  • リスクの小さな重要ではないビジネスプロセスからスタートする
  • モノリシックなシステムとの境界を定義し、別サービスとして切り出す
  • サービスは何らかのビジネスプロセスを表す必要があります
    • サービスは自立していること
    • サービスには明確な境界線が存在すること
    • サービスはデータを所有し、それらのデータの信頼できるソースです
    • サービスは、共有コントラクトとスキーマを介して疎結合になる
  • Entity serviceのアンチパターンに注意

  • TwitterのようなアプリケーションをMicroservice化する例
  • レガシーシステムで受け付けた要求をKinesisに流し、Kinesisの先の各MicroServiceにビジネスプロセスを実行させる

Step3 コードベースを整理する

  • 機能ごとに1つのリポジトリを作らないこと
  • サービスごとに1つのリポジトリを作る
    • 1つのデプロイメントスタック(Functionとその他のリソース)
    • 1つのCI / CDパイプライン
    • 別の分割されたリポジトリのインフラを共有する
    • CFNのOutput/Export、SSMパラメーターなどを通じて共有リソースを参照する
    • 共有ライブラリ(NPM、Maven、NuGetなど)を介してコードを共有する
  • モノリシックなリポジトリ
    • 小さなチームに最適、イテレーションの速度を優先
    • 規律と優れたツールが必要

Step4 ツールを選定する

  • デプロイメントフレームワーク、CI 、モニタリング、アラート...etc
  • 「Xに最適なツール」は存在しない。自身のユースケースに最適なツールを選択すること
    • ナレッジを最大化する
  • Lambda向けのデプロイメントフレームワークを利用し、独自に作成しないこと
    • Serverless Framework
    • SAM
    • CDK
  • デプロイ方法はプロジェクト全体で一貫している必要がある

Step5 Functionをシンプルに保つ

  • 単一責任の原則に従う
  • 関数の機能を容易に確認できるようになる
  • 1つの目的だけを持ったFunctionはよりセキュア
  • Functionの責務を1つに限定することでコールドスタートのパフォーマンスを向上できる

Step6 新サービスへは段階的に移行する

  • APIの互換性を維持する
  • カナリアリリース等の手法を活用し、徐々に新しいサービスへトラフィックを流していく
  • サービスはデータを所有する必要があるが、移行プロセスのリスクを最小化する必要がある
    • 最初にビジネス機能の所有者シップを新しいサービスに移動します
    • 後で新しいデータベースにデータを移行します
  • 同期的なAPI呼び出しよりもデータの同期を選択する
    • GDPRに留意する

  • 例えばこのような構成でMicro Service化すると、System Cが単一障害点となる

  • System DはSystem Cから同期されたDYnamoDBを利用することでSystem Cの障害の影響を受け辛くなる

Step7 テストについて再考する

  • モノリシックなアーキテクチャとは障害に対する考え方が変わる
  • ユニットテストのリターンは小さい
  • インテグレーションテストにフォーカスする
  • E2Eテスト向けにTemporaryのスタックを作成して活用する

Step8 システムに回復力を組み込む

  • システムの状況を計測できるようにする
  • 短く、そして適切なタイムアウト値を設定する
  • キューを利用してサービス間のスパイクトラフィックを回避する
  • StepFunctionsのようなサービスを使って分散トランザクションを管理する
  • 単一障害点避けるためにcircuid breaksを活用する
  • 障害の影響範囲を分離する
  • システムの弱点を理解するためにカオスエンジニアリングの実践を採用する

まとめ

サーバーレスという技術が一般的にも普及し始め、今後はこういったサーバーレス環境への移行案件も増えていきそうです。 セッションで話していたことを頭に起きながらしっかりアーキテクチャを学んでいきたいと思います。