Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

水平スケーリングを使いこなす:CloudOpsチームのための実践ガイド

By Josh PalmerJun 24, 202613 min read

このページはEnglishDeutschEspañolFrançaisItalianoPortuguêsでもご覧いただけます。

要点: 水平スケーリングとは、個々のマシンを増強するのではなく、サーバーインスタンスを追加してworkloadを分散させる手法です。予測困難なトラフィックに耐える信頼性とコスト効率を兼ね備えたクラウドアーキテクチャの基盤ですが、状態管理、負荷分散、オートスケーリング設定といった複雑さも伴うため、キャパシティの限界に達する前に設計しておく必要があります。

どんなアプリケーションにも上限があります。しばらくはCPU増強、メモリ追加、ストレージの高速化といったハードウェアのアップグレードで上限を引き上げられますが、いずれ1台のサーバーでは処理しきれなくなり、増強コストが得られる価値を上回るようになります。ここでスケールアップからスケールアウトへと判断を切り替えることになります。

スケールアウト、つまり1台を大きくするのではなくサーバーを追加して負荷を分担させる方式は、今日のクラウドアプリケーションの大半を支えるアーキテクチャです。トラフィックの急増を吸収して落ちない仕組みであり、エンジニアの過剰な作業に頼らずに冗長性を確保する手段であり、最悪ケースの見積もりではなく実需要にインフラコストを比例させる方法でもあります。

本ガイドでは、水平スケーリングの仕組み、適する場面と適さない場面、そしてAWS、Google Cloud、Kubernetes上で信頼性と複雑さを両立させながら実装する方法を、CloudOpsチーム向けに整理します。

水平スケーリングとは何か、どう機能するのか

水平スケーリングとは、単一ノードの容量を増やすのではなく、リソースのインスタンスを追加して複数ノードにworkloadを分散させることです。垂直スケーリングが1台のサーバーを増強する(CPUコア追加、メモリ増設)のに対し、水平スケーリングはリクエストを処理するサーバーの台数そのものを増やします。フリートの前段にロードバランサーを置き、受信トラフィックを利用可能なインスタンスへ振り分けることで、特定のノードがボトルネックになるのを防ぎます。

プラットフォームによって細部は異なりますが、基本パターンは共通です。AWSではAuto Scaling GroupがCloudWatchメトリクスを監視し、使用率が指定の閾値を超えるとEC2インスタンスを自動で起動・終了します。KubernetesではHorizontal Pod Autoscaler(HPA)がCPU・メモリ使用率(またはカスタムメトリクス)を監視し、稼働ポッド数を調整します。Google CloudではManaged Instance GroupがCompute Engineのworkloadに対して同じ役割を果たします。いずれもコントローラー層がスケーリング判断を担うため、エンジニアが手作業で対応する必要はありません。

パフォーマンスとキャパシティへの影響は

水平スケーリングは、キャパシティモデルを固定的な上限から動的なレンジへと変えます。垂直スケーリング構成のシステムは、利用可能な最大インスタンスタイプでも処理しきれなくなった時点で頭打ちになります。一方、適切に構成された水平スケーリング構成のシステムは、アーキテクチャか予算が制約になるまでインスタンスを追加し続けられます。

パフォーマンス上のメリットは、地理的分散と組み合わせるとさらに大きくなります。複数のアベイラビリティゾーンにインスタンスを分散配置すれば、1つのゾーンで障害が起きてもアプリケーション全体は止まらず、代替インスタンスが起動するまでの間、トラフィックは影響を受けたゾーンを迂回します。トレードオフはノード間レイテンシです。通信が必要な分散インスタンスは、単一サーバー構成では生じないネットワークの往復コストを負担するため、レイテンシに敏感な処理ではこれが効いてきます。

水平スケーリングはコストとリソース管理にどう影響するか

水平スケーリングは、垂直スケーリングよりもインフラコストを実需要に近づけます。垂直スケーリングのサーバーはトラフィックの多寡にかかわらず、プロビジョニングされたサイズのまま稼働し続けます。水平スケーリングのフリートはオフピーク時に縮小し、スパイク時に拡大できるため、一時的な容量にはオンデマンド料金、予測可能なベースラインには予約料金を充てる構成が可能です。

ただしこの連動が成立するのは、オートスケーリングポリシーが適切にチューニングされている場合だけです。スケールアウトの閾値が早すぎたり、スケールインがインスタンスを十分速く撤収できなかったりすると、コスト面の優位性はそのまま無駄に変わります。ベースラインフリートにコミットメント型の価格設定(AWS Savings Plans、GCPの確約利用割引)を適用し、オンデマンドのバースト容量を組み合わせる構成が、多くのチームにとって最適なコストプロファイルになります。

とくにKubernetesのworkloadでは、スケーリングポリシーそのものと同じくらい、ポッドのrequestsとlimitsのライトサイジングが重要です。requestsが過大なポッドはビンパッキング効率を損ない、結果としてworkloadが本来必要とする以上のノードがクラスタに必要になります。DoiT PerfectScale for Kubernetesは、ポッドのrequestsが実際の使用パターンと乖離している箇所を自動で検出し、ライトサイジングの機会を可視化します。

水平スケーリングが持ち込む運用上の複雑さとは

インスタンスが増えれば、管理対象の表面積も広がります。設定ドリフト、フリート全体へのパッチ適用、ログの集約、分散トレーシングのいずれもが、単一サーバー時代より格段に難しくなります。備えがないチームは、特定のインスタンスタイプでだけバグが再現したり、1リクエストを追跡するために40個のポッドのログを突き合わせる必要が出てきたりして、その難しさをすぐに思い知ることになります。

基本対策はInfrastructure as Code(Terraform、Pulumi、CloudFormation)です。稼働中のインスタンスを変更するのではなく、既知の正常イメージから差し替えるイミュータブルインフラのパターンは、設定ドリフトを根本から排除します。集約ログと分散トレーシングがあれば、複数インスタンスをまたいだデバッグも現実的に行えます。

CloudOpsチームにとって水平スケーリングと垂直スケーリングはどう違うか

垂直スケーリング(スケールアップ)と水平スケーリング(スケールアウト)は、どちらか一方を選ぶ関係ではありません。本番アーキテクチャの大半は両方を併用しています。水平スケーリングされたフリートの内側で、workloadに見合ったサイズのインスタンスを稼働させるのが定石です。判断のポイントは、キャパシティが制約になったとき、どちらのレバーを先に引くかです。

垂直スケーリングは実装が速く、アプリケーション側の変更も不要です。既存インスタンスにCPUとメモリを追加し、必要なら再起動するだけで完了します。分散しにくいworkload、たとえばシングルスレッドのプロセス、状態への依存が強いアプリケーション、複数インスタンス稼働を前提に作られていないレガシーシステムなどに向きます。上限は利用可能な最大インスタンスタイプであり、コストは需要に比例しません。

水平スケーリングはアプリケーション側の準備が前提です。各リクエストが必要なコンテキストをすべて持ち、リクエスト間でローカル状態を保持しないステートレスなサービスは、何台に分散してもうまく機能します。一方、セッションデータやプロセス内状態をローカルに抱えるステートフルなサービスは、フリート全体で正しく動かすために追加のアーキテクチャが必要になります。

ステートレスなアプリケーションが水平スケーリングに最適な理由は

ステートレスなアプリケーションは、どのインスタンスでもどのリクエストでも処理できるため、水平スケーリングに自然にフィットします。ロードバランサーは、可用性チェック以外のルーティングロジックを持たずに、ラウンドロビンでトラフィックを振り分けられます。トラフィックが急増すれば新規インスタンスが立ち上がってすぐ負荷を引き受け、トラフィックが落ち着けば処理中の状態を壊さずにインスタンスを終了できます。

現代のWebアプリケーション層、API層、マイクロサービスの多くは、設計段階からステートレスです。共有データベースから読み出すREST APIは、どのサーバーが処理しても結果は同じです。キューから取り出してオブジェクトストレージに書き戻すコンテナ化マイクロサービスは追加の調整なしに水平スケールでき、オートスケーリングが手動介入なしにキャパシティを需要に追従させます。

データベースやステートフルなworkloadではどんな課題が生じるか

データベースやステートフルなサービスは、そのままでは水平スケールしません。プライマリ1台で動くリレーショナルデータベースを5ノードに複製しても、書き込みスループットが5倍になるわけではありません。読み取りはリードレプリカで水平スケールできますが、書き込みはプライマリに集約されるため、書き込み中心のworkloadはレプリカ数によらずボトルネックになります。

これに対処するチームは、状態を共有層に切り出します。マネージドデータベース、Redisのような分散キャッシュ、オブジェクトストアなど、全インスタンスからアクセスできる場所です。セッションデータはRedisやDynamoDBへ、ファイルアップロードはS3やCloud Storageへ移します。この共有状態アーキテクチャによって、アプリケーション層は本当にステートレスになり、必要なデータも維持されます。

Kubernetesでは特に、永続ストレージを必要とするステートフルworkloadにはDeploymentではなくStatefulSetを使います。StatefulSetは各ポッドに安定したネットワークIDと永続ボリュームクレームを与えるため、データベース、キュー、その他の順序性を要求するステートフルサービスにとって重要です。

水平スケーリングが機能する場面、しない場面

水平スケーリングが効果を発揮するのは特定の条件下です。予測困難でスパイクのあるトラフィック、ステートレスなアプリケーション層、分散マイクロサービス、可用性要件が冗長性を要求するworkloadなどがそれにあたります。それ以外の条件では効果は薄く、ときに新たな問題を生み出します。

コンテナ化されたworkloadとマイクロサービスは、最も相性のよい領域です。各サービスは自身の需要に応じて独立してスケールするため、システムの一部で起きたスパイクが他の部分まで過剰プロビジョニングしてしまうことがありません。20個のマイクロサービスを動かすKubernetesクラスタでは、それぞれを独立してオートスケールでき、すべてをピーク負荷に合わせてサイジングする必要がなく、全体のリソース使用率を高く保てます。Kubernetes Horizontal Pod Autoscalerは、CPUやメモリに留まらないカスタムメトリクスを含め、これらのスケーリングポリシーを細かく制御できます。

イベント駆動アーキテクチャは特に水平スケールに向いています。キューを消費するワーカーのフリートは、キューの深さに応じて伸縮し、遅延なくバーストをさばき、キューが空けばインスタンスを解放できます。KEDA(Kubernetes Event-Driven Autoscaling)のようなツールはこのパターンをKubernetesにネイティブに持ち込み、SQSキューの長さやKafkaのコンシューマーラグなど、外部イベントソースに基づいてポッドをスケールします。

負荷分散とトラフィック配分で重要な判断は

ロードバランサーは水平スケールされたフリートへの全トラフィックの入口であり、その設定はアプリケーションの挙動を直接左右します。全インスタンスが等価なステートレスサービスではラウンドロビン配分で十分です。リクエスト処理時間にばらつきが大きい場合は、最少接続数ルーティングのほうが向いており、空きキャパシティの多いインスタンスへ新規接続が振られます。

ヘルスチェックは運用の要です。不健全なインスタンスにトラフィックを流すロードバランサーは、フリートを運用する意味そのものを失わせます。ヘルスチェックは、TCPで応答するかどうかだけでなく、依存先が利用可能かを確認する実際のHTTPエンドポイントなど、アプリケーションの実際の準備状態をテストすべきです。設定が緩すぎても厳しすぎても、フラッピングや不要なスケーリングイベントを招きます。

セッション管理とデータ整合性は水平スケーリングにどう影響するか

セッション管理は、水平スケーリング実装が破綻しやすい代表的なポイントです。セッションデータをローカルメモリに保持するアプリケーションは、サーバー1台なら問題なく動きます。しかしフリートに分散させると、同じユーザーの2回目のリクエストが、最初のリクエストのセッションを知らない別のインスタンスに到達し、認証失敗やカート状態の消失を引き起こすことがあります。

解決策はセッション状態の外部化です。分散セッションストレージの標準的な選択肢はRedisかMemcachedです。アプリケーション層はローカルメモリではなく共有キャッシュにセッションを読み書きする、真にステートレスな構成になります。どのインスタンスがリクエストを処理しても、全インスタンスが同じセッション状態を参照できます。セッション読み取りのたびにネットワーク往復が発生しますが、多くのアプリケーションでは水平スケーラビリティと引き換えにする価値のあるトレードオフです。

分散インスタンス間のデータ整合性は、書き込み中心のworkloadでは明示的な設計上の配慮が必要です。整合性要件に応じて、分散ロック、楽観的並行制御、イベントソーシングといったパターンで調整の問題に対処します。

モニタリングとオートスケーリング設定の成否を分けるポイントは

オートスケーリングポリシーの良し悪しは、駆動するメトリクスの良し悪しで決まります。CPU使用率はマネージドオートスケーリングサービスの既定メトリクスですが、多くのworkloadでは遅行指標です。メモリ逼迫やキューのバックログに陥ったアプリケーションは、ダウンする直前までCPU使用率が正常範囲を保つことがあります。カスタムメトリクス(リクエストキューの深さ、レスポンスレイテンシのパーセンタイル、アクティブ接続数)を使えば、オートスケーリングはより早く、より正確なシグナルを得られます。

スケールアウトポリシーは積極的であるべきです。スパイクでユーザー体験を損なうくらいなら、一時的な過剰プロビジョニングの方がましだからです。スケールインポリシーは保守的にし、クールダウン期間と段階的な縮小幅を用意して、スパイク直後にインスタンスを過剰に終了しないようにします。高負荷と通常負荷のあいだで揺れ動くトラフィックパターンで急激にスケールインするフリートは、コストをかけてインスタンスを起動・停止し続けるスラッシングを引き起こします。

Kubernetesコスト最適化ガイドでは、ネームスペース単位のリソースクォータやVPAとの統合パターンを含め、オートスケーリング設定とコスト効率を整合させる方法を詳しく解説しています。

水平スケーリングの実装パターンと、ありがちな落とし穴の回避策

実装はプラットフォームを問わず、おおむね同じ順序で進みます。アプリケーションのステートレス性を確認し、スケーリンググループを構成し、ポリシーを設定し、本番トラフィックを乗せる前にテストするという流れです。

AWSでは、EC2インスタンス(コンテナ化workloadならECSタスク)を伴うAuto Scaling Group、Application Load Balancer、スケーリングポリシーを駆動するCloudWatchアラームというスタックになります。重要な設定判断は、最小・最大インスタンス数、ターゲットとなる使用率メトリクス、スケールイン/スケールアウトのクールダウン期間です。EC2の詳細な設定リファレンスとしては、AWS EC2のコスト・メリット・ベストプラクティスガイドがインスタンス選定とコスト最適化を掘り下げて解説しています。

Google Cloudでは、オートスケーリングポリシー付きのManaged Instance GroupとGlobal External Application Load Balancerが同等のスタックを提供します。GKEクラスタではその上にKubernetesネイティブのオートスケーリングが乗り、Cluster Autoscalerがノード数を、HPAがポッド数を、それぞれ独立に管理します。

クラウドを問わず、Kubernetes上では抽象化の層がもう一段加わります。Deploymentが望ましいポッド状態を定義し、HPAがメトリクスに基づいてレプリカ数を調整し、Cluster AutoscalerまたはKarpenterがポッドのスケジューリング圧力に応じてノード数を調整します。Kubernetesアーキテクチャをゼロから構築するチームには、Kubernetesアーキテクチャ解説が基礎リファレンスとして役立ちます。

もっとも多い落とし穴は、スケーリング設定そのものではなく、分散下で破綻するアプリケーション側の前提から生じます。ハードコードされたホスト名、ローカルファイルシステムへの書き込み、インスタンス間で内容が乖離するインプロセスキャッシュ、同じレートでスケールできないサービスへの同期呼び出しなどです。こうした前提を本番投入前に洗い出しておけば、トラフィックスパイク中に発生するデバッグ作業を未然に防げます。

DoiTのForward Deployed EngineersはCloudOpsチームと直接協働し、アーキテクチャ上の前提の検証から、実際のトラフィック挙動に合ったスケーリングポリシーの構成まで、こうした実装パターンを支援します。

水平スケーリングはレジリエントなクラウド運用をどう支えるか

水平スケーリングは、多くのクラウドアプリケーションが直面しているトラフィックの現実、つまり予測しにくい需要、予告なくやって来るスパイク、単一障害点を許さない可用性要件に対応するためのインフラです。トラフィックが来れば拡張し、過ぎれば縮小するフリートは、スケーリングのたびにエンジニアが対応せずとも、この現実をさばけます。

水平スケーリングを機能させる運用上の成熟度は、単一の設定変更で得られるものではありません。ステートレスなアプリケーション設計、状態管理の外部化、メトリクス駆動のオートスケーリング、Infrastructure as Code、そして分散フリートをデバッグ可能にする可観測性ツール群といった、一連のプラクティスの積み重ねです。これらを早期に整えたチームは、騒ぎを起こさずにスケールできます。省いたチームは、インシデントへとスケールしていきます。

DoiTは、初期段階のKubernetesクラスタアーキテクチャ設計から、既存フリートのライトサイジングとオートスケーリング最適化まで、CloudOpsチームのあらゆる段階で伴走します。DoiT PerfectScale for Kubernetesはクラスタworkloadを継続的に分析し、ライトサイジングとスケーリングの推奨を提示するため、手動チューニングに費やす時間を減らし、事業を前に進める仕事により多くの時間を充てられるようになります。自社アーキテクチャへの適用可能性については、DoiTのエンジニアにご相談ください

水平スケーリングに関するよくある質問

水平スケーリングと垂直スケーリングの違いは何ですか

水平スケーリングはリソースのインスタンス(サーバー、ポッド、ノード)を追加してworkloadを分散させます。垂直スケーリングは既存インスタンスの容量(CPU、RAM)を増やします。水平スケーリングは予測困難な需要に対応し、冗長性を確保できます。垂直スケーリングは実装が容易ですが、利用可能な最大インスタンスサイズという厳格な上限があります。

CloudOpsチームはいつ垂直ではなく水平スケーリングを選ぶべきですか

水平スケーリングは、ステートレスなアプリケーション層、マイクロサービス、変動が大きく予測しづらいトラフィックを持つworkloadに最適です。垂直スケーリングは、シングルスレッドのプロセス、状態を分散できないレガシーアプリケーション、アプリケーション変更なしに迅速に容量を増やしたいworkloadに向きます。本番アーキテクチャの多くは、水平スケーリングされたフリートの内側に適切なサイズのインスタンス(垂直)を稼働させるという、両方の組み合わせで成り立っています。

水平スケーリングは自動的にコスト削減につながりますか

自動的にはつながりません。水平スケーリングは固定サイズの大型サーバーよりも需要に沿ったコストを実現できますが、それはオートスケーリングポリシーが適切にチューニングされ、ベースラインフリートにコミットメント型の価格設定が適用されている場合に限られます。トラフィックが落ちてもインスタンスを稼働させ続けるスケールインポリシーの設定ミスや、スパイク時に手動介入が要るほど慎重なスケールアウト閾値は、コストメリットを蝕みます。

Kubernetesは水平スケーリングをどう扱いますか

KubernetesはHorizontal Pod Autoscaler(HPA)を使い、CPU使用率、メモリ、またはカスタムメトリクスに基づいて稼働中のポッドレプリカ数を調整します。Cluster Autoscaler(AWSではKarpenter)はポッドのスケジューリング需要に応じてノード数を調整します。この2つのコントローラーは連携して動作し、HPAがアプリケーション層をスケールし、ノードオートスケーラーがそれを収容する基盤インフラをスケールします。

CloudOpsチームが水平スケーリングで犯す最大の実装ミスは何ですか

アプリケーションが実際にはステートレスでないのに、ステートレスだと思い込むことです。ローカルファイルシステムへの書き込み、メモリ内セッションストレージ、インプロセスキャッシュはいずれも隠れた状態を生み、同じユーザーのリクエストが別々のインスタンスに到達した瞬間に破綻します。フリートをスケールさせる前にアプリケーションをこの観点で監査しておけば、本番環境で障害として顕在化するのを防げます。