編集

次の方法で共有


Java 向け信頼性の高い Web アプリ パターン

Azure App Service
Azure Front Door

この記事では、信頼性の高い Web アプリ パターンの実装に関するガイダンスを提供します。 このパターンは、クラウド移行のために Web アプリを変更 (リプラットフォーム) する方法の概要を示します。 また、Well-Architected フレームワークの原則に沿った規範的なアーキテクチャ、コード、構成のガイダンスを提供します。

Java 向け信頼性の高い Web アプリ パターンを使用する理由

信頼性の高い Web アプリ パターンは、クラウドへの移行時に Web アプリを変更する方法 (リプラットフォーム) を定義する一連の原則と実装手法です。 クラウドで成功するために行う必要がある最小限のコード更新に焦点を当てています。 次のガイダンスでは、参照実装を例として使用し、架空の会社 Contoso Fiber のリプラットフォームの流れに従って、移行に関するビジネス上のコンテキストを説明します。 Java 向け信頼性の高い Web アプリ パターンを実装する以前は、Contoso Fiber には、Spring Boot フレームワークを使用するモノリシックなオンプレミスの顧客アカウント管理システム (CAMS) がありました。

ヒント

GitHub ロゴ。信頼性の高い Web アプリ パターンの参照実装 (サンプル) が用意されています。 これは、信頼性の高い Web アプリの実装の最終状態を表します。 この記事で説明する、コード、アーキテクチャ、構成に対するすべての更新プログラムを取り入れた実稼働グレードの Web アプリです。 この参照実装をデプロイして使用し、信頼性の高い Web アプリ パターンの実装について案内します。

信頼性の高い Web アプリ パターンの実装方法

この記事には、信頼性の高い Web アプリ パターンを実装するための、アーキテクチャ、コード、構成のガイダンスが含まれます。 以下のリンクを使用すると、必要な特定のガイダンスに移動できます。

  • ビジネス コンテキスト: このガイダンスをビジネス コンテキストに合わせて調整し、リプラットフォームに関する意志決定を促進する短期目標と長期目標を定義する方法を学習します。
  • アーキテクチャのガイダンス: 適切なクラウド サービスを選択し、ビジネス要件を満たすアーキテクチャを設計する方法について説明します。
  • コードのガイダンス: クラウドでの Web アプリの信頼性とパフォーマンス効率を向上させる、再試行、サーキット ブレーカー、キャッシュ アサイドの 3 つの設計パターンを実装します
  • 構成のガイダンス: 認証と承認、マネージド ID、適正サイズの環境、コードとしてのインフラストラクチャ、監視を構成します。

ビジネス コンテキスト

Web アプリのリプラットフォームの最初の手順は、ビジネス目標を定義することです。 サービス レベル目標やコスト最適化の目標、Web アプリケーションの将来の目標など、短期目標を設定する必要があります。 これらの目標は、クラウド サービスの選択と、クラウド内の Web アプリケーションのアーキテクチャに影響します。 99.9% のアップタイムなど、Web アプリのターゲット SLO を定義します。 Web アプリの可用性に影響を与えるすべてのサービスについて、複合 SLA を計算します。

たとえば、Contoso Fiber では、オンプレミスの顧客アカウント管理システム (CAMS) Web アプリを拡張して他のリージョンにリーチしたいと考えています。 Web アプリに対する需要の増加を満たすために、次の目標を確立しました。

  • 低コストで価値の高いコード変更を適用
  • 99.9% のサービス レベル目標 (SLO) にリーチ
  • DevOps プラクティスを採用
  • コスト最適化環境を作成
  • 信頼性とセキュリティを改善

Contoso Fiber は、オンプレミスのインフラストラクチャが、アプリケーションをスケーリングするためのコスト効率の高いソリューションではないと判断しました。 そこで、CAMS Web アプリケーションを Azure に移行することが、即時および将来の目標を達成するための最もコスト効率の高い方法であると判断しました。

アーキテクチャのガイダンス

信頼性の高い Web アプリ パターンには、いくつかの重要なアーキテクチャ要素があります。 エンドポイント解決を管理するための DNS、悪意のある HTTP トラフィックをブロックする Web アプリケーション ファイアウォール、受信ユーザー要求を保護してルーティングするためのロード バランサーが必要です。 アプリケーション プラットフォームは、Web アプリ コードをホストし、仮想ネットワーク内のプライベート エンドポイントを介してすべてのバックエンド サービスに対する呼び出しを実行します。 アプリケーション パフォーマンス監視ツールは、Web アプリの状態を把握するためのメトリックとログをキャプチャします。

信頼性の高い Web アプリ パターンの重要なアーキテクチャ要素を示す図。

図 1. 信頼性の高い Web アプリ パターンの重要なアーキテクチャ要素。

アーキテクチャの設計

目標復旧時間 (RTO) や目標復旧時点 (RPO) などの復旧メトリックをサポートするようにインフラストラクチャを設計します。 RTO は可用性に影響し、SLO をサポートする必要があります。 目標復旧ポイント (RPO) を決定し、RPO を満たすようにデータ冗長性を構成します。

  • インフラストラクチャの信頼性を選択します。 可用性のニーズを満たすために必要な可用性ゾーンとリージョンの数を決定します。 複合 SLA が SLO を満たすまで、可用性ゾーンとリージョンを追加します。 信頼性の高い Web アプリ パターンは、アクティブ/アクティブ構成またはアクティブ/パッシブ構成で複数のリージョンをサポートします。 たとえば、参照実装では、アクティブ/パッシブ構成を使用して 99.9% の SLO を満たしています。

    マルチリージョンの Web アプリの場合は、ビジネス ニーズに応じてアクティブ/アクティブ構成またはアクティブ/パッシブ構成をサポートするように、2 つ目のリージョンにトラフィックをルーティングするようにロード バランサーを構成します。 2 つのリージョンでは同じサービスが必要ですが、一方のリージョンにはリージョンを接続するハブ仮想ネットワークを配置する点が異なります。 ハブアンドスポーク ネットワーク トポロジを導入して、ネットワーク ファイアウォールなどのリソースを一元化および共有します。 仮想マシンがある場合は、ハブ仮想ネットワークに Bastion ホストを追加して仮想マシンを安全に管理します (図 2 を参照)。

    2 つ目のリージョンを設定し、ハブアンドスポーク トポロジを採用した信頼性の高い Web アプリ パターンを示す図。

    図 2. 2 つ目のリージョンを設定し、ハブアンドスポーク トポロジを採用した信頼性の高い Web アプリ パターン。

  • ネットワーク トポロジを選択します。 Web とネットワークの要件に適したネットワーク トポロジを選択します。 複数の仮想ネットワークを使用する場合は、ハブアンドスポーク ネットワーク トポロジを使用します。 これにより、オンプレミスと仮想ネットワークに対するハイブリッド接続オプションを使用した、コスト、管理、セキュリティの利点がもたらされます。

適切な Azure サービスを選択する

Web アプリをクラウドに移行する場合は、ビジネス要件を満たし、オンプレミス Web アプリの現在の機能に合わせた Azure サービスを選択する必要があります。 この配置により、リプラットフォーム工数を最小限に抑えることができます。 たとえば、同じデータベース エンジンを維持し、既存のミドルウェアとフレームワークをサポートできるサービスを使用します。 次のセクションでは、Web アプリに適した Azure サービスを選択するためのガイダンスを提供します。

たとえば、クラウドに移行する以前は、Contoso Fiber の CAMS Web アプリは、オンプレミスのモノリシックな Java Web アプリでした。 PostgreSQL データベースを備えた Spring Boot アプリです。 Web アプリは基幹業務サポート アプリです。 従業員向けです。 Contoso Fiber の従業員は、アプリケーションを使用して顧客からのサポート ケースを管理します。 Web アプリは、スケーラビリティと機能のデプロイに関する一般的な課題に苦しんでいます。 この出発点、ビジネス目標、SLO がサービスの選択を推進しました。

  • アプリケーション プラットフォーム: Azure App Service をアプリケーション プラットフォームとして使用します。 Contoso Fiber では、次の理由で、アプリケーション プラットフォームとして Azure App Service を選択しました。

    • 自然な進展: Contoso Fiber では、オンプレミス サーバーに Spring Boot jar ファイルをデプロイしており、そのデプロイ モデルの再設計の量を最小限に抑えたいと考えていました。 App Service では、Spring Boot アプリを実行するための堅牢なサポートが提供されており、Contoso Fiber が App Service を使用するのは自然な判断でした。 Azure Container Apps も、このアプリの魅力的な代替手段です。 詳細については、「Azure Spring Apps とは」および「Azure Container Apps 上の Java の概要」を参照してください。
    • 高い SLA: 実稼働環境の要件を満たす高い SLA を備えています。
    • 管理オーバーヘッドの削減: フル マネージドのホスティング ソリューションです。
    • コンテナー化機能: App Service は、Azure Container Registry などのプライベート コンテナー イメージ レジストリで動作します。 Contoso Fiber は、これらのレジストリを使用して、将来 Web アプリをコンテナー化できます。
    • オートスケール: Web アプリは、ユーザーのトラフィックに基づいて、迅速にスケールアップ/ダウン/イン/アウトできます。
  • ID 管理: ID およびアクセス管理ソリューションとして Microsoft Entra ID を使用します。 Contoso Fiber は、次の理由で Microsoft Entra ID を選択しました。

    • 認証と承認: アプリケーションは、コール センターの従業員を認証および承認する必要があります。
    • 拡張性: より大規模なシナリオをサポートするように拡張されます。
    • ユーザー ID 制御:コール センターの従業員は、既存のエンタープライズ ID を使用できます。
    • 承認プロトコルのサポート: マネージド ID に対して OAuth 2.0 をサポートします。
  • データベース: 同じデータベース エンジンを維持できるサービスを使用します。 データ ストアのデシジョン ツリーを使用します。 Contoso Fiber は、次の理由から Azure Database for PostgreSQL とフレキシブル サーバー オプションを選択しました。

    • 信頼性: フレキシブル サーバー デプロイ モデルでは、複数の可用性ゾーンにわたるゾーン冗長の高可用性がサポートされます。 この構成により、ウォーム スタンバイ サーバーが同じ Azure リージョン内の別の可用性ゾーンに維持されます。 この構成では、スタンバイ サーバーにデータが同期的にレプリケートされます。
    • リージョン間レプリケーション: 読み取りレプリカ機能を備えており、これによりデータを別のリージョンの読み取り専用レプリカ データベースに非同期的にレプリケートできます。
    • パフォーマンス: 予測可能なパフォーマンスとインテリジェント チューニングを提供し、実際の使用状況データを使用してデータベースのパフォーマンスを向上させます。
    • 管理オーバーヘッドの軽減: 管理義務を軽減するフル マネージドの Azure サービスです。
    • 移行のサポート: オンプレミスの単一サーバー PostgreSQL データベースからのデータベース移行がサポートされています。 移行ツールを使用すると、移行プロセスを簡略化できます。
    • オンプレミス構成との一貫性: Contoso Fiber が現在使用しているバージョンを含め、PostgreSQL のさまざまなコミュニティ バージョンがサポートされています。
    • 回復性。 フレキシブル サーバー デプロイによってサーバー バックアップが自動的に作成され、同じリージョン内のゾーン冗長ストレージ (ZRS) を使用して格納されます。 データベースはバックアップ保有期間内の任意の時点に復元できます。 バックアップと復元の機能により、Contoso Fiber がオンプレミスで作成できるよりも優れた RPO (許容可能なデータ損失量) が作成されます。
  • アプリケーション パフォーマンスの監視: Application Insights を使用して、アプリケーションのテレメトリを分析します。 Contoso Fiber は、次の理由で Application Insights を使用することを選択しました。

    • Azure Monitor との統合: Azure Monitor との最適に統合します。
    • 異常検出: パフォーマンスの異常を自動的に検出します。
    • トラブルシューティング: 実行中のアプリの問題を診断するのに役立ちます。
    • 監視: ユーザーがアプリをどのように使用しているかに関する情報を収集し、カスタム イベントを簡単に追跡できるようにします。
    • 可視性のギャップ: オンプレミス ソリューションには、アプリケーション パフォーマンス監視ソリューションがありませんでした。 Application Insights は、アプリ プラットフォームとコードとの簡単な統合を提供します。
  • キャッシュ: Web アプリ アーキテクチャにキャッシュを追加するかどうかを選択します。 Azure Cache for Redis は、Azure のプライマリ キャッシュ ソリューションです。 これは、Redis ソフトウェアに基づくマネージド インメモリ データ ストアです。 Contoso Fiber は、次の理由により、Azure Cache for Redis を追加しました。

    • スピードとボリューム: 一般的にアクセスされ、変化が遅いデータでは、データ スループットが高く、読み取りの待機時間が短くなります。
    • 多様なサポート: Web アプリのすべてのインスタンスが使用できる統合キャッシュの場所です。
    • 外部データ ストア。 オンプレミスのアプリ サーバーは、VM ローカル キャッシュを実行しました。 このセットアップでは、頻度の高いデータがオフロードされず、データを無効にできませんでした。
    • 非スティッキー セッション: キャッシュを使用することで、Web アプリはセッション状態を外部化し、非スティッキー セッションを使用できます。 オンプレミスで実行されているほとんどの Java Web アプリでは、メモリ内のクライアント側キャッシュが使用されます。 メモリ内のクライアント側キャッシュは適切にスケーリングされないため、ホスト上のメモリ占有領域が増加します。 Azure Cache for Redis を使用することで、Contoso Fiber はフル マネージドでスケーラブルなキャッシュ サービスを利用して、アプリケーションのスケーラビリティとパフォーマンスを向上させました。 Contoso Fiber はキャッシュ抽象化フレームワーク (Spring Cache) を使用しており、キャッシュ プロバイダーを交換するために必要な構成の変更は最小限でした。 Ehcache プロバイダーから Redis プロバイダーに切り替えることができました。
  • ロード バランサー: PaaS ソリューションを使用する Web アプリケーションでは、Web アプリのアーキテクチャと要件に基づいて、Azure Front Door、Azure Application Gateway、またはその両方を使用する必要があります。 ロード バランサーのデシジョン ツリーを使用して、適切なロード バランサーを選択します。 Contoso Fiber には、複数のリージョン間でトラフィックをルーティングできるレイヤー 7 ロード バランサーが必要でした。 Contoso Fiber は、99.9% の SLO を満たすためにマルチリージョンの Web アプリを必要としていました。 Contoso Fiber は、次の理由から Azure Front Door を選択しました。

    • グローバル負荷分散: 複数のリージョン間でトラフィックをルーティングできるレイヤー 7 ロード バランサーです。
    • Web application firewall: Azure Web Application Firewall とネイティブに統合されます。
    • ルーティングの柔軟性: アプリケーション チームは、アプリケーションの将来の変更に対応するために必要なイングレスを構成できます。
    • トラフィックの高速化: エニーキャストを使用して、最も近い Azure のポイント オブ プレゼンスにリーチし、Web アプリへの最速ルートを見つけます。
    • Custom Domain: 柔軟なドメイン検証で Custom Domain 名をサポートします。
    • 正常性プローブ: アプリには、インテリジェントな正常性プローブの監視が必要です。 Azure Front Door は、プローブからの応答を使用して、クライアント要求をルーティングするための最適な配信元を決定します。
    • 監視サポート: Front Door とセキュリティ パターンの両方に対応するオールインワン ダッシュボードがある組み込みレポートをサポートします。 Azure Monitor と統合するアラートを構成できます。 アプリケーションが各要求と失敗した正常性プローブをログに記録できるようにします。
    • DDoS Protection:第 3 から 4 層の DDoS Protection が組み込まれています。
    • コンテンツ配信ネットワーク: コンテンツ配信ネットワークを使用するように Contoso Fiber を配置します。 コンテンツ配信ネットワークは、サイト アクセラレーションを提供します。
  • Web アプリケーション ファイアウォール: Azure Web Application Firewall を使用して、Web での一般的な悪用や脆弱性からの一元的な保護を提供します。 Contoso Fiber は、次の理由から、Azure Web Application Firewall を使用しました。

    • グローバル保護: パフォーマンスを犠牲にすることなく、グローバルな Web アプリ保護を向上させます。
    • ボットネット保護: チームは、ボットネットに関連するセキュリティ上の懸念事項に対応するために、設定を監視、構成できます。
    • オンプレミスとのパリティ: オンプレミス ソリューションは、IT 部門が管理する Web アプリケーション ファイアウォールの内側で実行されていました。
    • 使いやすさ: Web Application Firewall は Azure Front Door と統合されています。
  • シークレット マネージャー: Azure での管理にシークレットを使用している場合は、Azure Key Vault を使用します。 Contoso Fiber は、次の理由で Key Vault を使用しました。

    • 暗号化: 保存時と転送中の暗号化をサポートします。
    • マネージド ID のサポート:アプリケーション サービスは、マネージド ID を使用してシークレット ストアにアクセスできます。
    • 監視とログに記録: 監査アクセスを簡単にし、格納されているシークレットが変更されたときにアラートを生成します。
    • 統合: Azure 構成ストア (App Configuration) およびWeb ホスティング プラットフォーム (App Service) とのネイティブ統合が提供されます。
  • エンドポイント セキュリティ: Azure Private Link を使用して、仮想ネットワーク内のプライベート エンドポイント経由でサービスとしてのプラットフォーム ソリューションにアクセスします。 仮想ネットワークとサービスとの間のトラフィックは、Microsoft バックボーン ネットワークをまたがります。 Contoso Fiber は、次の理由で Private Link を選択しました。

    • 強化されたセキュリティ通信: アプリケーションが Azure プラットフォーム上のサービスにプライベートにアクセスでき、データ ストアのネットワーク フットプリントが削減されるため、データ漏えいからの保護に役立ちます。
    • 最小工数: プライベート エンドポイントは、Web アプリが使用する Web アプリ プラットフォームとデータベース プラットフォームをサポートします。 どちらのプラットフォームも、変更が最小限になるように既存のオンプレミス構成をミラーリングします。
  • ネットワーク セキュリティ: Azure Firewall を使用して、ネットワーク レベルで受信トラフィックと送信トラフィックを制御します。 Azure Bastion を使用して、RDP/SSH ポートを公開することなく、仮想マシンに安全に接続します。 Contoso Fiber では、ハブ アンド スポーク ネットワーク トポロジを採用し、共有ネットワーク セキュリティ サービスをハブに配置したいと考えていました。 Azure Firewall では、スポークからのすべての送信トラフィックを検査することでセキュリティとネットワーク セキュリティを強化しました。 DevOps サブネット内のジャンプ ホストから安全にデプロイするために、Contoso Fiber には、Azure Bastion が必要でした。

コードのガイダンス

Web アプリをクラウドに正常に移行するには、再試行パターン、サーキット ブレーカー パターン、キャッシュアサイド設計パターンを使用して Web アプリ コードを更新する必要があります。

信頼性の高い Web アプリの重要なアーキテクチャにおける設計パターンのロールを示す図。

図 3。 設計パターンのロール。

各設計パターンは、Well-Architected フレームワークの 1 つ以上の柱に沿ったワークロード設計の利点を提供します。 実装する必要があるパターンの概要を以下に示します。

  1. 再試行パターン: 再試行パターンは、断続的に失敗する可能性のある操作を再試行することによって、一時的なエラーを処理します。 このパターンは、他の Azure サービスに対するすべての送信呼び出しに実装します。

  2. サーキット ブレーカー パターン: サーキット ブレーカー パターンは、一時的ではない操作をアプリケーションが再試行するのを防ぎます。 このパターンは、他の Azure サービスに対するすべての送信呼び出しに実装します。

  3. キャッシュアサイド パターン: キャッシュアサイド パターンは、データストアよりも頻繁に、キャッシュに対する追加とキャッシュからの取得を実行します。 このパターンは、データベースに対する要求に実装します。

設計パターン 信頼性 (RE) セキュリティ (SE) コスト最適化 (CO) オペレーショナル エクセレンス (OE) パフォーマンス効率 (PE) WAF の原則のサポート
再試行パターン RE:07
サーキット ブレーカー パターン RE:03
RE:07
PE:07
PE:11
キャッシュ アサイド パターン RE:05
PE:08
PE:12

再試行パターンを実装する

一時的なサービスの中断に対処するために、再試行パターンをアプリケーション コードに追加します。 これらの中断は、一時的な障害と呼ばれます。 一時的な障害は、通常は数秒以内に解決されます。 再試行パターンを使用すると、失敗した要求を再送信できます。 また、要求の遅延と、障害と認めるまでの試行回数を構成することもできます。

軽量のフォールト トレランス ライブラリである Resilience4j を使用して、Java で再試行パターンを実装します。 たとえば、参照実装では、サービス プラン コントローラーの listServicePlans メソッドを Retry 注釈で修飾することで、再試行パターンを追加します。 このコードは、最初の呼び出しが失敗した場合に、データベースからサービス プランの一覧への呼び出しを再試行します。 リファレンス実装では、再試行の最大試行回数、待機時間、再試行する必要がある例外を含む再試行ポリシーを構成します。 再試行ポリシーは application.propertiesで構成されます。

    @GetMapping("/list")
    @PreAuthorize("hasAnyAuthority('APPROLE_AccountManager')")
    @CircuitBreaker(name = SERVICE_PLAN)
    @Retry(name = SERVICE_PLAN)
    public String listServicePlans(Model model) {
        List<serviceplandto> servicePlans = planService.getServicePlans();
        model.addAttribute("servicePlans", servicePlans);
        return "pages/plans/list";
    }

サーキット ブレーカー パターンを実装する

サーキット ブレーカー パターンを使用して、一時的な障害ではないサービスの中断を処理します。 サーキット ブレーカー パターンは、アプリケーションが応答しないサービスに継続的にアクセスすることを防ぎます。 これにより、アプリケーションが解放され、CPU サイクルの無駄が回避されるため、アプリケーションはエンド ユーザーに対するパフォーマンスの整合性を維持します。

Spring Circuit BreakerResilience4j のドキュメントを使用して、サーキット ブレーカー パターンを実装します。 たとえば、参照実装では、Circuit Breaker 属性を使用してメソッドを修飾することで、サーキット ブレーカー パターンを実装しています。

キャッシュアサイド パターンを実装する

キャッシュアサイド パターンを Web アプリに追加して、メモリ内データ管理を改善します。 このパターンにより、データ要求を処理し、キャッシュと永続的ストレージ (データベースなど) の間の整合性を確保する責任がアプリケーションに割り当てられます。 これにより、応答時間が短縮され、スループットが向上し、さらなるスケーリングの必要性が軽減されます。 また、プライマリ データストアの負荷が軽減され、信頼性とコスト最適化が向上します。 キャッシュアサイド パターンを実装するには、次の推奨事項に従います。

  • キャッシュを使用するようにアプリケーションを構成します。 キャッシュを有効にするには、spring-boot-starter-cache パッケージを依存関係として pom.xml ファイルに追加します。 このパッケージは、Redis Cache の既定の構成を提供します。

  • 必要性の高いデータをキャッシュします。 必要性の高いデータにキャッシュアサイド パターンを適用して、その有効性を高めます。 Azure Monitor を使用して、データベースの CPU、メモリ、ストレージを追跡します。 これらのメトリックは、キャッシュアサイド パターンを適用した後に、より小さいデータベース SKU を使用できるかどうかを判断するのに役立ちます。 コード内の特定のデータをキャッシュするには、@Cacheable 注釈を追加します。 この注釈は、結果をキャッシュする必要があるメソッドを Spring に知らせます。

  • キャッシュ データを最新の状態に保ちます。 最新のデータベース変更と同期するように、定期的なキャッシュ更新をスケジュールします。 データ ボラティリティとユーザーのニーズに基づいて最適なリフレッシュ レートを決定します。 この方法により、アプリケーションはキャッシュ アサイド パターンを使用して、迅速なアクセスと最新の情報の両方を提供できます。 既定のキャッシュ設定は、Web アプリケーションに適していない可能性があります。 これらの設定は、application.properties ファイルまたは環境変数でカスタマイズできます。 たとえば、(ミリ秒単位で表される) spring.cache.redis.time-to-live 値を変更して、データが削除されるまでにキャッシュに保持される期間を制御できます。

  • データの一貫性を確保します。 データベース書き込み操作の直後にキャッシュを更新するメカニズムを実装します。 イベント駆動の更新または専用のデータ管理クラスを使用して、キャッシュの一貫性を確保します。 キャッシュとデータベースの変更を一貫して同期することは、キャッシュ アサイド パターンの主要な部分です。

構成ガイダンス

以降のセクションでは、構成の更新の実装に関するガイダンスを提供します。 各セクションは、Well-Architected フレームワークの 1 つ以上の柱と一致します。

構成 信頼性 (RE) セキュリティ (SE) コスト最適化 (CO) オペレーショナル エクセレンス (OE) パフォーマンス効率 (PE) WAF の原則のサポート
ユーザーの認証 & 承認を構成する SE:05
OE:10
マネージド ID を実装する SE:05
OE:10
適切なサイズの環境 CO:05
CO:06
自動スケーリングを実装する RE:06
CO:12
PE:05
リソースのデプロイの自動化 OE:05
監視を実装する OE:07
PE:04

認証と承認を構成する

Web アプリケーションを Azure に移行する場合は、ユーザーの認証と承認のメカニズムを構成します。 次の推奨事項に従ってください。

  • ID プラットフォームを使用します。 Microsoft ID プラットフォームを使用して、Web アプリ認証を設定します。 このプラットフォームは、1 つの Microsoft Entra ディレクトリ、異なる組織の複数の Microsoft Entra ディレクトリ、および Microsoft ID またはソーシャル アカウントを使用するアプリケーションをサポートします。

    Spring Boot Starter for Microsoft Entra ID は、Spring Security と Spring Boot を使用して簡単にセットアップできるように、このプロセスを合理化します。 さまざまな認証フロー、自動トークン管理、カスタマイズ可能な承認ポリシーと、Spring Cloud コンポーネントとの統合機能が提供されます。 これにより、手動ライブラリや設定の構成なしで、Microsoft Entra ID と OAuth 2.0 を Spring Boot アプリケーションに簡単に統合できます。

    たとえば、参照実装では、Web アプリの ID プロバイダーとして Microsoft ID プラットフォーム (Microsoft Entra ID) を使用しています。 これは、OAuth 2.0 の認証コード付与を使用して、Microsoft Entra アカウントでユーザーをサインインさせます。 次の XML スニペットでは、OAuth 2.0 承認コード付与フローで必要な 2 つの依存関係を定義しています。 依存関係 com.azure.spring: spring-cloud-azure-starter-active-directory により、Spring Boot アプリケーションで Microsoft Entra の認証と承認が有効になります。 依存関係 org.springframework.boot: spring-boot-starter-oauth2-client により、Spring Boot アプリケーションで OAuth 2.0 の認証と承認が有効になります。

    <dependency>
        <groupid>com.azure.spring</groupid>
        <artifactid>spring-cloud-azure-starter-active-directory</artifactid>
    </dependency>
    <dependency>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-oauth2-client</artifactid>
    </dependency>
    
  • アプリの登録を作成します。 Microsoft Entra ID では、プライマリ テナントにアプリケーションを登録する必要があります。 アプリケーションを登録することで、Web アプリへのアクセス権を取得するユーザーがプライマリ テナントに ID を確保できます。 たとえば、参照実装では、Terraform を使用して、アプリ固有のアカウント マネージャー ロールと共に Microsoft Entra ID アプリの登録を作成します。

    resource "azuread_application" "app_registration" {
      display_name     = "${azurecaf_name.app_service.result}-app"
      owners           = [data.azuread_client_config.current.object_id]
      sign_in_audience = "AzureADMyOrg"  # single tenant
    
      app_role {
        allowed_member_types = ["User"]
        description          = "Account Managers"
        display_name         = "Account Manager"
        enabled              = true
        id                   = random_uuid.account_manager_role_id.result
        value                = "AccountManager"
      }
    }
    
  • アプリケーションで承認を強制します。 ロールベースのアクセス制御 (RBAC) を使用して、アプリケーションのロールに最小限の特権を割り当てます。 重複を回避し、明確にするために、さまざまなユーザー アクションに対して特定のロールを定義します。 ユーザーを適切なロールにマップし、必要なリソースとアクションにのみアクセスできるようにします。 Spring Boot Starter for Microsoft Entra ID を使用するには、Spring Security を構成します。 このライブラリを使用すると、Microsoft Entra ID との統合が可能になり、ユーザーが安全に認証されるようになります。 Microsoft Authentication Library (MSAL) を構成して有効にすると、より多くのセキュリティ機能にアクセスできるようになります。 その機能には、トークン キャッシュとトークンの自動更新が含まれています。

    たとえば、参照実装では、Contoso Fiber のアカウント管理システムのユーザー ロールの種類を反映したアプリ ロールが作成されます。 ロールは承認時にアクセス許可に変換されます。 CAMS のアプリ固有のロールの例としては、アカウント マネージャー、レベル 1 (L1) サポート担当者、フィールド サービス担当者などがあります。 Account Manager ロールには、新しいアプリ ユーザーとお客様を追加するためのアクセス許可があります。 Field Service の担当者は、サポート チケットを作成できます。 PreAuthorize 属性は、特定のロールへのアクセスを制限します。

        @GetMapping("/new")
        @PreAuthorize("hasAnyAuthority('APPROLE_AccountManager')")
        public String newAccount(Model model) {
            if (model.getAttribute("account") == null) {
                List<ServicePlan> servicePlans = accountService.findAllServicePlans();
                ServicePlan defaultServicePlan = servicePlans.stream().filter(sp -> sp.getIsDefault() == true).findFirst().orElse(null);
                NewAccountRequest accountFormData = new NewAccountRequest();
                accountFormData.setSelectedServicePlanId(defaultServicePlan.getId());
                model.addAttribute("account", accountFormData);
                model.addAttribute("servicePlans", servicePlans);
            }
            model.addAttribute("servicePlans", accountService.findAllServicePlans());
            return "pages/account/new";
        }
        ...
    

    Microsoft Entra ID と統合するために、リファレンス実装では OAuth 2.0 承認コード付与フローが使用されます。 このフローにより、ユーザーは Microsoft アカウントでサインインできます。 次のコード スニペットは、認証と承認に Microsoft Entra ID を使用するように SecurityFilterChain を構成する方法を示しています。

    @Configuration(proxyBeanMethods = false)
    @EnableWebSecurity
    @EnableMethodSecurity
    public class AadOAuth2LoginSecurityConfig {
        @Bean
        SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
            http.apply(AadWebApplicationHttpSecurityConfigurer.aadWebApplication())
                .and()
                    .authorizeHttpRequests()
                .requestMatchers(EndpointRequest.to("health")).permitAll()
                .anyRequest().authenticated()
                .and()
                    .logout(logout -> logout
                                .deleteCookies("JSESSIONID", "XSRF-TOKEN")
                                .clearAuthentication(true)
                                .invalidateHttpSession(true));
            return http.build();
        }
    }
    ...
    
  • ストレージに対しては一時的なアクセスを優先します。 一時的なアクセス許可を使用して、共有アクセス署名 (SAS) などの不正アクセスや違反から保護します。 ユーザー委任 SAS を使用して、一時的なアクセスを許可するときのセキュリティを最大化します。 これは、Microsoft Entra ID の資格情報を使用し、永続的なストレージ アカウント キーを必要としない唯一の SAS です。

  • Azure で承認を強制します。 Azure RBAC を使用して、ユーザー ID に最小限の特権を割り当てます。 Azure RBAC は、Azure のリソース ID がアクセスできる対象、それらのリソースに対して実行できる操作、アクセスできる領域を決定します。

  • 永続的で高度なアクセス許可は避けます。 Microsoft Entra Privileged Identity Management を使用して、特権操作の Just-In-Time アクセスを許可します。 たとえば、開発者は多くの場合、データベースの作成/削除、テーブル スキーマの変更、ユーザーのアクセス許可の変更を行うために、管理者レベルのアクセス権を必要とします。 Just-In-Time アクセス権を使用して、特権タスクを実行するための一時的なアクセス許可をユーザー ID に付与しします。

マネージド ID を実装する

マネージド ID をサポートするすべての Azure サービスにマネージド ID を使用します。 マネージド ID を使用すると、Azure リソース (ワークロード ID) は、資格情報を管理することなく、他の Azure サービスに対して認証し、やり取りすることができます。 ハイブリッド システムとレガシ システムでは、移行を簡略化するためにオンプレミスの認証ソリューションを維持できますが、できるだけ早くマネージド ID に移行する必要があります。 マネージド ID を実装するには、次の推奨事項に従います。

  • 適切な種類のマネージドIDを選択します。 同じアクセス許可のセットを必要とする複数の Azure リソースがある場合は、ユーザー割り当てのマネージド ID を優先します。 各リソースに対してシステム割り当てのマネージド ID を作成し、すべてのリソースに同じアクセス許可を割り当てるよりも、この設定のほうが効率的です。 そうでない場合は、システム割り当てのマネージド ID を使用します。

  • 最小特権を構成します。 Azure RBAC を使用して、データベースでの CRUD アクションやシークレットへのアクセスなど、操作に不可欠なアクセス許可のみを付与します。 ワークロード ID のアクセス許可は永続的であるため、ワークロード ID にジャスト・イン・タイムまたは短期のアクセス許可を提供することはできません。 Azure RBAC が特定のシナリオに対応していない場合は、Azure サービス レベルのアクセス ポリシーで Azure RBAC を補完します。

  • 残りのシークレットを保護します。 残りのシークレットを Azure Key Vault に格納します。 各 HTTP 要求中ではなく、アプリケーションの起動時に Key Vault からシークレットを読み込みます。 HTTP 要求内での高頻度のアクセスにより、Key Vault のトランザクション制限を超える可能性があります。 アプリケーション構成を Azure App Configuration に格納します。

適切なサイズの環境

Azure サービスのパフォーマンス レベル (SKU) を使用して、過剰にならないように各環境のニーズを満たします。 環境のサイズを適切に設定するには、次の推奨事項に従います。

  • コストを見積もる。 Azure 料金計算ツールを使用して、各環境のコストを見積もります。

  • 実稼働環境のコストを最適化します。 運用環境には、運用に必要なサービス レベル アグリーメント (SLA)、機能、スケールを満たす SKU が必要です。 リソースの使用状況を継続的に監視し、実際のパフォーマンス ニーズに合わせて SKU を調整します。

  • 実稼働前の環境のコストを最適化します。 実稼働前の環境では、低コストのリソースを使用し、不要なサービスを無効にして、Azure Dev/Test 料金設定などの割引を適用する必要があります。 実稼働前の環境が実稼働環境と十分に同等であることを確認し、リスクが発生しないようにします。 このバランスにより、不要なコストを発生させずにテストを効果的に維持できます。

  • コードとしてのインフラストラクチャ (IaC) を使用して SKU を定義します。 IaC を実装することで、環境に基づいて適切な SKU を動的に選択してデプロイします。 このアプローチにより、一貫性が向上し、管理が簡略化されます。

たとえば、参照実装には、異なる SKU をデプロイする省略可能なパラメーターがあります。 環境パラメーターは、開発 SKU を選択するように Terraform テンプレートに指示します。

azd env set APP_ENVIRONMENT prod

自動スケーリングを実装する

オートスケールにより、Web アプリの回復力と応答性が維持され、動的なワークロードを効率的に処理できます。 オートスケールを実装するには、次の推奨事項に従います。

  • スケールアウトを自動化します。Azure オートスケールを使用して、実稼働環境での水平スケーリングを自動化します。 アプリケーションがさまざまな負荷を処理できるように、主要なパフォーマンス メトリックに基づいてスケールアウトするようにオートスケール ルールを構成します。

  • スケーリング トリガーを調整します。 アプリケーションのスケーリング要件に慣れていない場合は、最初のスケーリング トリガーとして CPU 使用率から始めます。 スケーリング トリガーを調整して、RAM、ネットワーク スループット、ディスク I/O などの他のメトリックを含めます。 目標は、Web アプリケーションの動作を合わせることで、パフォーマンスを向上させることです。

  • スケールアウト バッファーを指定します。 最大容量に達する前にトリガーするように、スケーリングのしきい値を設定します。 たとえば、100% に達するまで待機するのではなく、CPU 使用率 85% で実行するようにスケーリングを構成します。 このプロアクティブなアプローチは、パフォーマンスを維持し、潜在的なボトルネックを回避するのに役立ちます。

リソースのデプロイの自動化

自動化を使用して、すべての環境に Azure のリソースとコードをデプロイおよび更新します。 次の推奨事項に従ってください。

  • コードとしてのインフラストラクチャを使用します。 継続的インテグレーションと継続的デリバリー (CI/CD) パイプラインを通じて、コードとしてのインフラストラクチャをデプロイします。 Azure では、すべての Azure リソース用に Bicep、ARM (JSON)、Terraform のテンプレートがあらかじめ用意されています。

  • 継続的インテグレーション/継続的デプロイ (CI/CD) パイプラインを使用します。 CI/CD パイプラインを使用して、ソース管理からさまざまな環境 (テスト、ステージング、運用など) にコードをデプロイします。 GitHub プロジェクト用の Azure DevOps または GitHub Actions を使用している場合は、Azure パイプラインを利用します。

  • 単体テストの統合。 App Services にデプロイする前に、パイプライン内のすべての単体テストの実行と受け渡しに優先順位を付けます。 SonarQube などのコード品質およびカバレッジ ツールを組み込んで、包括的なテスト カバレッジを実現します。

  • モック フレームワークを導入します。 外部エンドポイントを含むテストでは、モック フレームワークを利用します。 これらのフレームワークを使用すると、シミュレートされたエンドポイントを作成できます。 これにより、実際の外部エンドポイントを構成し、環境間でテスト条件を統一する必要がなくなります。

  • セキュリティ スキャンを実行します。 静的アプリケーション セキュリティ テスト (SAST) を使用して、ソース コードのセキュリティ上の欠陥とコーディング エラーを見つけます。 さらに、ソフトウェア構成分析 (SCA) を実行して、サードパーティのライブラリとコンポーネントのセキュリティ リスクを調べます。 これらの分析用のツールは、GitHub と Azure DevOps の両方に簡単に統合できます。

監視の構成

アプリケーションとプラットフォームの監視を実装して、Web アプリのオペレーショナル エクセレンスとパフォーマンス効率を向上させます。 監視を実装するには、次の推奨事項に従います。

  • アプリケーション テレメトリを収集します。 Azure Application Insights で自動インストルメンテーションを使用して、コードを変更することなく、要求スループット、平均要求期間、エラー、依存関係の監視などのアプリケーション テレメトリを収集します。 Spring Boot では、Java 仮想マシン (JVM)、CPU、Tomcat など、Application Insights にいくつかのコア メトリックが登録されます。 Application Insights は、Log4j や Logback などのログ記録フレームワークから自動的に収集します。 たとえば、参照実装では、App Service の app_settings 構成の一部として、Terraform を介して有効になっている Application Insights が使用されます。 (次のコードを参照してください)。

    app_settings = {
        APPLICATIONINSIGHTS_CONNECTION_STRING = var.app_insights_connection_string
        ApplicationInsightsAgent_EXTENSION_VERSION = "~3"
        ...
    }
    

    詳細については、以下を参照してください:

  • カスタム アプリケーション メトリックを作成します。 Application Insights SDK を追加し、その API を使用することで、カスタム アプリケーション テレメトリをキャプチャするコード ベースのインストルメンテーションを実装します。

  • プラットフォームを監視します。 サポートされているすべてのサービスの診断を有効にし、関連付けのためにアプリケーション ログと同じ宛先に診断を送信します。 Azure サービスはプラットフォーム ログを自動的に作成しますが、診断を有効にした場合にのみ保存されます。 診断をサポートするサービスごとに、診断設定を有効にします。 参照実装では、Terraform を使用して、サポートされているすべてのサービスで Azure 診断を有効にしています。 次の Terraform コードは、App Service の診断設定を構成します。

    # Configure Diagnostic Settings for App Service
    resource "azurerm_monitor_diagnostic_setting" "app_service_diagnostic" {
      name                           = "app-service-diagnostic-settings"
      target_resource_id             = azurerm_linux_web_app.application.id
      log_analytics_workspace_id     = var.log_analytics_workspace_id
      #log_analytics_destination_type = "AzureDiagnostics"
    
      enabled_log {
        category_group = "allLogs"
    
      }
    
      metric {
        category = "AllMetrics"
        enabled  = true
      }
    }
    

参照実装をデプロイする

参照実装では、最初の導入フェーズで必要な変更に重点を置きながら、オンプレミスの Java アプリケーションから Azure への移行のシミュレーションを通じて開発者を案内します。 この例では、架空の会社である Contoso Fiber の顧客アカウント管理システム (CAMS) Web アプリ アプリケーションを使用しています。 Contoso Fiber は、Web アプリケーションについて次の目標を設定しています。

  • 低コストで価値の高いコード変更を実装する
  • 99.9% のサービス レベル目標 (SLO) を達成する
  • DevOps プラクティスを採用
  • コスト最適化環境を作成
  • 信頼性とセキュリティを向上させる

Contoso Fiber では、オンプレミス インフラストラクチャは、これらの目標を達成するコスト効率の高いソリューションではないと判断しました。 そして、CAMS Web アプリケーションを Azure に移行することが、直近および将来の目標を達成するための最もコスト効率の高い方法であると決定しました。 次のアーキテクチャは、Contoso Fiber の信頼性の高い Web アプリ パターンの実装の最終状態を表しています。

参照実装のアーキテクチャを示す図。図 4. 参照実装のアーキテクチャ。このアーキテクチャの Visio ファイルをダウンロードできます。