このドキュメントでは、復元性が高くスケーラブルなアプリを作成するためのパターンと手法、多くの最新アーキテクチャに関する実践における 2 つの基本的目標について説明します。適切に設計されたアプリは、需要の増減に応じてスケールアップまたはスケールダウンでき、サービス障害が生じた場合に対応できる十分な復元力を備えています。こうした要件に適合するアプリを作成し運用するには、計画と設計を慎重に行う必要があります。
スケーラビリティ: 需要を満たすための容量の調整
スケーラビリティとは、処理量が増減したときにリソースを追加または削除することでシステムがその変化にどのように対応できるかを表す尺度です。たとえば、スケーラブルなウェブアプリとは、ユーザーが 1 人の場合でも多数の場合でも正常に機能し、トラフィックのピークと低下を適切に処理するアプリを指します。
アプリが使用するリソースを調整するための柔軟性は、クラウドに移行する際のビジネス上の主要な促進要因です。適切な設計を行い、使用率が低下しているリソースを削除することによって、パフォーマンスやユーザーの操作性を損なうことなくコストを削減できます。同様に、リソースを追加することによって、トラフィックの増大時でも良好なユーザー エクスペリエンスを維持できます。このようにして、アプリが需要を満たすうえで必要なリソースのみを使用するようにできます。
Google Cloud には、スケーラブルで効率性に優れたアプリを構築する際に有用なプロダクトと機能が用意されています。
- Compute Engine 仮想マシンと Google Kubernetes Engine(GKE)クラスタは、定義した指標に基づいてリソース消費量を増減できるオートスケーラーと統合されます。
- Google Cloud のサーバーレス プラットフォームには、ゼロから大量の場合まで、リクエスト量に応じて迅速にスケールするマネージド コンピューティング、データベースなどのサービスが用意されており、お支払いは従量制です。
- BigQuery、Spanner、Bigtable などのデータベース プロダクトは、非常に広範囲なデータサイズに対応して一貫したパフォーマンスを実現できます。
- Cloud Monitoring には、さまざまなアプリとインフラストラクチャで使用できる指標が用意されており、スケーリングに関するデータドリブンの決定を行うことができます。
復元性: 障害に強い設計
復元性の高いアプリとは、システム コンポーネントに障害が発生した場合でも機能し続けるアプリを指します。復元性を実現するには、アーキテクチャのあらゆるレベルで計画を行う必要があります。復元性は、インフラストラクチャとネットワークの配置方法、アプリとデータ ストレージの設計方法にまで影響します。また、復元性の影響範囲にはユーザーと文化も含まれます。
復元性の高いアプリを作成し運用することは容易ではありません。このことは特に、インフラストラクチャ、ネットワーク、サービスの複数のレイヤを有する可能性がある分散アプリの場合に該当します。ミスやサービスの停止はつきものです。また、アプリの復元性は継続的に改善し続ける必要があります。計画を慎重に行うことによって、障害に対応するアプリの能力を改善できます。適切なプロセスと組織文化によって、障害から得られた知見をもとにアプリの復元性をさらに高めることもできます。
Google Cloud は、可用性が高く復元性に優れたアプリを構築する際に有用なツールとサービスを備えています。
- Google Cloud サービスは、世界各地のリージョンとゾーンで利用でき、可用性の目標を最も良く満たすようにアプリをデプロイできます。
- Compute Engine インスタンス グループと GKE クラスタは、1 つのリージョン内の利用可能な任意のゾーンで分散管理できます。
- Compute Engine のリージョン永続ディスクは、リージョン内のゾーン間で同期的に複製されます。
- Google Cloud には、ユーザーに最も近い正常なリージョンにトラフィックを転送できるグローバルなロード バランシングなど、アプリのトラフィックを管理するためのさまざまなロード バランシング オプションが用意されています。
- Google Cloud のサーバーレス プラットフォームには、冗長性とロード バランシングの組み込み機能を備えたマネージド コンピューティングとデータベース プロダクトが用意されています。
- Google Cloud は、ネイティブ ツールや一般的なオープンソース テクノロジーとの統合を通じて CI / CD をサポートし、アプリのビルドとデプロイの自動化を支援します。
- Cloud Monitoring には、アプリとインフラストラクチャ全体で使用できる指標が用意されており、アプリのパフォーマンスと健全性に関するデータドリブンの意思決定を支援します。
推進要因と制約
アプリのスケーラビリティと復元性を改善する際の要件や動機にはさまざまなものがあります。また、スケーラビリティと復元性の目標を達成するにあたって、対応力を制限する制約が存在する場合もあります。これらの要件と制約の相対的な重要性は、アプリのタイプ、ユーザーのプロファイル、組織の規模と成熟度によって異なります。
推進要因
要件に優先順位を付けることができるよう、組織のさまざまな部門の推進要因を検討してください。
ビジネス推進要因
ビジネス的観点から見た場合の一般的な推進要因には次のものがあります。
- コストとリソース消費を最適化する。
- アプリのダウンタイムを最小限に抑える。
- 使用率が増加してもユーザーの需要が満たされるようにする。
- サービスの質と可用性を改善する。
- 障害が発生した場合にも、ユーザーの操作性と信頼が維持されるようにする。
- 変化する市場の需要に対応するための柔軟性とアジリティを高める。
開発の推進要因
開発サイドから見た場合の一般的な推進要因には次のものがあります。
- 障害の調査に費やす時間を最小限に抑える。
- 新機能の開発に費やす時間を増やす。
- 自動化によって繰り返し作業を最小限に抑える。
- 最新の業界のパターンと手法を活用してアプリを構築する。
運用の推進要因
運用側の観点から考慮すべき要件には次のものがあります。
- 人間による介入を必要とする障害の発生頻度を低減する。
- 障害から自動的に復旧する機能を強化する。
- 自動化によって繰り返し作業を最小限に抑える。
- 特定のコンポーネントの障害による影響を最小限に抑える。
制約
制約により、アプリのスケーラビリティと復元性の向上が制限される場合があります。設計上の決定により以下の制約が生じる、あるいは制約の発生に寄与することがないようにします。
- スケーリングが困難なハードウェアまたはソフトウェアに対する依存関係。
- 高可用性の構成での運用が困難なハードウェアまたはソフトウェアに対する依存関係。
- アプリ間の依存関係。
- ライセンス上の制限。
- 開発チームおよび運用チームのスキル不足や経験不足。
- 自動化に対する組織の抵抗。
パターンと手法
このドキュメントの残りの部分では、復元性が高くスケーラブルなアプリを構築する際に有用なパターンと手法を定義します。これらのパターンは、インフラストラクチャの設計、アプリのアーキテクチャ、ストレージの選択、デプロイ プロセス、組織文化など、アプリのライフサイクル全体に影響します。
これらのパターンには、次の 3 つの明確なテーマがあります。
- 自動化。スケーラブルで復元性の高いアプリを構築するには、自動化が必要です。インフラストラクチャのプロビジョニング、テスト、アプリのデプロイを自動化することで、整合性と速度が向上し、人的エラーが最小限に抑えられます。
- 疎結合。システムを一連の疎に結合された独立したコンポーネントとして扱うことにより、柔軟性と復元性がもたらされます。独立性を原則として、リソースの物理的な分散方法とアプリを構築しストレージを設計する方法を決定します。
- データドリブンの設計。アプリの動作を理解するために指標を収集することは非常に重要です。アプリをスケーリングするタイミング、または特定のサービスが正常ではない状態にあるかどうかについての決定は、データに基づいて行う必要があります。指標とログは中核機能として位置づける必要があります。
インフラストラクチャのプロビジョニングを自動化する
自動化によって不変のインフラストラクチャを作成して環境の一貫性を改善し、より多くのデプロイを成功へと導きます。
インフラストラクチャをコードとして扱う
Infrastructure as Code(IaC)は、インフラストラクチャのプロビジョニングと構成をアプリケーション コードの処理と同じように扱うことを推奨する手法です。プロビジョニングと構成のロジックはソース管理に保存されるため、検出可能でありバージョン管理と監査を行うことができます。コード リポジトリに存在するため、継続的インテグレーションと継続的デプロイ(CI / CD)パイプラインの利点を活用し、構成に対する変更を自動的にテストしてデプロイできます。
インフラストラクチャのプロビジョニングから手動の手順を排除し、IaC により人的エラーを最小限に抑えることで、アプリと環境の一貫性および再現性が向上します。このように、IAC を採用することでアプリの復元性が高まります。
Cloud Deployment Manager では、柔軟なテンプレートを使用して Google Cloud リソースの作成と管理を自動化できます。また、Config Connector を使用すると、Kubernetes の手法とワークフローを使用してリソースを管理できます。Google Cloud には、Terraform、Chef、Puppet などの一般的なサードパーティ IaC ツールに対するサポートも組み込まれています。
不変のインフラストラクチャを作成する
不変のインフラストラクチャは、Infrastructure as Code のメリットに基づいた考え方です。不変のインフラストラクチャでは、デプロイ後にリソースを変更しないことが義務付けられています。仮想マシン、Kubernetes クラスタ、ファイアウォール ルールを更新する必要がある場合は、ソース リポジトリでリソースの構成を更新できます。変更をテスト、検証した後に新しい構成を使用してリソース全体を再デプロイします。すなわち、リソースを微調整するのではなく、リソースを再作成します。
不変のインフラストラクチャを作成することによって、デプロイとロールバックの予測可能性が向上します。これにより、構成のずれやスノーフレーク サーバーなど、可変インフラストラクチャに一般的に見られる問題も軽減されます。このようにして、不変インフラストラクチャを採用することによって環境の一貫性と信頼性がさらに向上します。
高可用性を重視した設計
可用性とは、サービスが使用できる時間の割合の尺度です。可用性は、サービス全体の正常性の主な指標としてよく使用されます。高可用性アーキテクチャは、一般的にコンポーネントを冗長的にデプロイすることで、サービスの可用性を最大化することを目的としています。端的に表現すれば、高可用性のアーキテクチャでは通常、コンピューティング リソースの分散、ロード バランシングやデータのレプリケーションによって高可用性が実現されています。
リソースを物理的に分散する
Google Cloud サービスは世界中のロケーションで利用可能です。これらのロケーションは、「リージョン」と「ゾーン」に分けられます。アプリの可用性やレイテンシなどの特性に及ぼす影響は、これらのリージョンとゾーンにアプリをどのようにデプロイするかに依存します。詳細については、Compute Engine のリージョン選択に関するおすすめの方法をご覧ください。
冗長性とは対象システムの全般的な可用性の向上を目的として、システムのコンポーネントを重複して配置することを指します。Google Cloud では冗長性は通常、アプリやサービスを複数のゾーン、場合によっては複数のリージョンにデプロイすることによって実現されます。サービスが複数のゾーンやリージョンに存在する場合、特定のゾーンやリージョンで発生するサービス障害への対応力が強化されます。Google Cloud では、そうした障害の発生を回避するよう万全を期していますが、ある種のイベントは予測不可能であり、あらかじめ備えておくのが最善と言えます。
Compute Engine のマネージド インスタンス グループを使用すると、仮想マシンのインスタンスをリージョン内の複数のゾーンに分散し、論理ユニットとして管理できます。Google Cloud には、リージョン内の 2 つのゾーンにデータを自動的に複製するリージョン永続ディスクも用意されています。
同様にリージョン クラスタを作成することによっても、GKE にデプロイされたアプリの可用性と復元性を改善できます。リージョン クラスタは、リージョン内の複数のゾーンに GKE コントロール プレーン コンポーネント、ノード、Pod を分散します。コントロール プレーン コンポーネントは分散されているため、1 つ以上の(ただし全部ではない)ゾーンが関係するサービスの停止中であっても、クラスタのコントロール プレーンには引き続きアクセスできます。
マネージド サービスを使用する
マネージド サービスを使用すると、アプリケーション スタックのすべての部分を個別にインストールしてサポートや運用を行うのではなく、アプリケーション スタックの一部をサービスとして使用できます。たとえば、MySQL データベースを仮想マシン(VM)にインストールして管理する代わりに、Cloud SQL に用意された MySQL データベースを使用できます。その場合は可用性に関するサービスレベル契約(SLA)を取得し、Google Cloud を利用してデータの複製、バックアップ、基盤となるインフラストラクチャを管理できます。マネージド サービスを利用することにより、インフラストラクチャの管理に費やす時間を削減し、アプリの信頼性の向上により多くの時間を割り当てることができます。
Google Cloud のマネージド型のコンピューティング、データベース、ストレージ サービスの多くは組み込みの冗長性を備えており、それによって可用性の目標の達成を支援できます。これらのサービスの多くには、リージョン モデルが用意されています。つまり、アプリを実行するインフラストラクチャは特定のリージョンに配置されており、対象リージョン内のすべてのゾーンで冗長的に利用できるように Google が管理しています。あるゾーンが使用不可能になった場合、アプリやデータは自動的にリージョン内の別のゾーンからサービスを配信します。
特定のデータベースとストレージ サービスもマルチリージョンにおける可用性を備えています。つまり、アプリを実行するインフラストラクチャは複数のリージョンに配置されています。マルチリージョンのサービスは、リージョン全体が消失してもサービスを継続できますが、通常はレイテンシの増加を伴います。
各階層での負荷分散
ロード バランシングではリソースのグループ間でトラフィックを分散できます。トラフィックを分散することで、他のリソースがアイドル状態である間に個々のリソースが過負荷状態になることを回避できます。ほとんどのロードバランサにはヘルスチェック機能が備わっており、正常ではない、あるいは利用できないリソースにトラフィックが転送されることを回避できます。
Google Cloud には、いくつかのロード バランシング オプションが用意されています。アプリが Compute Engine または GKE で実行されている場合は、トラフィックのタイプやソースなどの要素に応じて、最適なタイプのロードバランサを選択できます。詳細については、ロード バランシングの概要と GKE のネットワーキングの概要をご覧ください。
また、App Engine や Cloud Run などの一部の Google Cloud マネージド サービスは、トラフィックを自動的にロードバランスします。
ウェブ クライアントやモバイル クライアントなどの外部ソースから受信したリクエストをロードバランスするのが一般的な方法です。ただし、アプリ内の異なるサービスまたは階層間でロードバランサを使用することによっても、復元性と柔軟性を高めることができます。Google Cloud では、この目的のために内部のレイヤ 4 とレイヤ 7 を対象にロード バランシングを行います。
次の図は、us-central1
と asia-east1
の 2 つのリージョンでグローバル トラフィックを分散する外部ロードバランサを示しています。この図は、ウェブ階層から受信したトラフィックを各リージョン内の内部階層に分散する内部のロード バランシングについても示しています。
インフラストラクチャとアプリをモニタリングする
アプリの復元性とスケーラビリティを改善する方法を決定する前に、アプリの動作を理解する必要があります。アプリのパフォーマンスと状態に関連する一連の指標と時系列の全体に対するアクセス権を割り当てられていることによって、サービス停止を引き起こす前に潜在的な問題を発見できる場合があります。サービス停止が発生した場合には、その診断と解決に対しても有用な可能性があります。Google の SRE ブックでは、分散システムのモニタリングの章において、モニタリングのいくつかの手法について概要を示しています。
アプリの状態についての分析情報を示すのみでなく、指標を使用して自動スケーリング時のサービスの動作を制御することもできます。
Cloud Monitoring は Google Cloud の統合モニタリング ツールです。Cloud Monitoring は、イベント、指標、メタデータを取り込み、ダッシュボードとアラートで分析情報を提供します。ほとんどの Google Cloud サービスは指標を自動的に Cloud Monitoring に送信します。また、Google Cloud は多くのサードパーティのソースにも対応しています。Cloud Monitoring は、一般的なオープンソースのモニタリング ツールのバックエンドとしても使用でき、1 つの画面からアプリをモニタリングできます。
すべてのレベルでモニタリングする
アーキテクチャ内のさまざまなレベルや階層で指標を収集することで、アプリの正常性と動作に関する全体像を把握できます。
インフラストラクチャのモニタリング
インフラストラクチャ レベルのモニタリングにより、アプリのベースラインの正常性とパフォーマンスに関する情報を取得できます。このモニタリング手法によって CPU 負荷、メモリ使用量、ディスクへの書き込みバイト数などの情報を取得できます。これらの指標は、マシンが過負荷であるか、想定どおりに機能していないことを示すことがあります。
また、Cloud Monitoring では、自動的に収集される指標に加えて、Compute Engine VM(これらのマシンで実行されているサードパーティ アプリなど)からより詳細な情報を収集するためにインストールできるエージェントが提供されています。
アプリのモニタリング
アプリレベルの指標をキャプチャすることをおすすめします。たとえば、特定のクエリを実行するのに要する時間や、関連付けられた一連のサービス呼び出しを実行するのに要する時間を測定できます。このようなアプリレベルの指標は、お客様自身により定義されます。これらの指標は、組み込みの Cloud Monitoring 指標ではキャプチャできない情報です。アプリレベルの指標では、主要なワークフローをより詳細に反映した集約された状態をキャプチャでき、下位レベルのインフラストラクチャの指標で明らかにすることができない問題を特定できます。
また、OpenTelemetry を使用してアプリレベルの指標を取得することもおすすめします。OpenTelemetry は、テレメトリー データ用の単一のオープン スタンダードを提供します。OpenTelemetry を使用して、クラウド ファーストのアプリケーションとインフラストラクチャからデータを収集し、エクスポートします。その後、エクスポートされたテレメトリー データをモニタリングして分析できます。
サービスのモニタリング
分散アプリやマイクロサービス主導のアプリの場合は、アプリ内のさまざまなサービスやコンポーネント間のやり取りをモニタリングすることが重要です。これらの指標は、エラー数の増加やサービス間のレイテンシなどの問題を診断する際に有用です。
Istio は、マイクロサービスのネットワークに分析情報と運用制御を提供するオープンソース ツールです。Istio は、すべてのサービス通信の詳細なテレメトリーを生成し、Cloud Monitoring に指標を送信するように構成できます。
エンドツーエンドのモニタリング
エンドツーエンドのモニタリング(ブラックボックス モニタリング)は、外部に表示可能な動作をユーザーに対して表示される場合と同じ方法でテストします。この種類のモニタリングでは、定義したしきい値の範囲内でユーザーが重要な操作を完了できるかどうかを確認します。この大まかなモニタリングによって、よりきめ細かいモニタリングでは発見できない場合があるエラーやレイテンシを発見でき、ユーザーの視点で可用性を明らかにできます。
アプリの状態を公開する
高可用性を備えたシステムには、システムの中で正常な状態であり正しく機能している部分を特定するための、なんらかの手法が必要です。特定のリソースが正常ではないと判断される場合に、他の場所にリクエストを送信できます。通常、ヘルスチェックではエンドポイントからデータが取得され、サービスのステータスや正常性が特定されます。
ヘルスチェックは、ロードバランサに課された重要な処理です。仮想マシン インスタンスのグループに関連付けられたロードバランサを作成した場合は、ヘルスチェックの定義も行う必要があります。ヘルスチェックでは、ロードバランサが仮想マシンとの通信を行い、特定のインスタンスがトラフィックの受信を継続するべきかどうかについて評価する方法を定義します。ロードバランサのヘルスチェックは、インスタンスのグループを自動修復し、正常ではないマシンを再作成する目的でも使用できます。GKE で実行し Ingress リソースを使用して外部トラフィックのロード バランシングを実施している場合は、GKE が自動的にロードバランサに適したヘル