目次
- 垂直スケールと水平スケール:まず「増やす方向」を理解する
- 垂直スケール(スケールアップ):1台を大きくする
- 水平スケール(スケールアウト/イン):台数を増減する
- スケールの判断に使うメトリクスを選ぶ
- 「ターゲット追従」で考える
- クールダウンとフラッピング:増減が暴れる理由
- フラッピングはなぜ起きるか
- クールダウンと非対称な設定で抑える
- 起動時間とウォームアップ:増えた台がすぐ役に立つとは限らない
- 起動時間はスケールの「反応速度」を決める
- ウォームアップ:起動直後の台に全力を出させない
- 前提条件:ステートレスと「スケールしても効かないボトルネック」
- ステートレスでなければ台数は増やせない
- アプリを増やしてもDBは増えない
- コスト上限:無制限のスケールは事故になる
- トラブル事例:TV放映後のアクセス集中にスケールが間に合わなかった
- 症状
- 原因
- 対処
- まとめ
「オートスケーリングを設定したのに、アクセス集中時に間に合わずエラーが出た」「台数が増えたり減ったりを繰り返して落ち着かない」「スケールアウトしたら今度はDBが悲鳴を上げた」――オートスケーリングは「設定すれば自動で何とかしてくれる機能」と思われがちですが、実際には設計の前提を満たしていないと期待どおりに動きません。
この記事では、垂直スケールと水平スケールの違いから始めて、スケールの判断に使うメトリクス(CPU・リクエスト数・キュー長)の選び方、クールダウンとフラッピングの関係、起動時間とウォームアップの考え方、ステートレスという前提条件、スケールしても効かないボトルネック(DB)、そしてコスト上限の決め方までを、仕組みから順に解説します。読み終えると、自社のアプリにオートスケーリングを「効かせる」ために何を整えるべきかが判断できるようになります。
垂直スケールと水平スケール:まず「増やす方向」を理解する
垂直スケール(スケールアップ):1台を大きくする
垂直スケールは、サーバーのCPU・メモリを増やして1台の処理能力を上げる方法です。アプリの改修が不要で、DBのように分散が難しいものにも適用できます。一方で、インスタンスタイプの変更には通常再起動が必要で、上限(最大サイズのインスタンス)があり、1台なので冗長性は増えません。「自動化」との相性も悪く、オートスケーリングと言うときは基本的に水平スケールを指します。
水平スケール(スケールアウト/イン):台数を増減する
水平スケールは、同じ構成のサーバーを増やしてロードバランサーで分散する方法です。理論上は上限なく増やせ、1台落ちても他がカバーするため可用性も上がります。ただし、「どの台にリクエストが行っても同じ結果になる」ことが前提で、アプリ側にステートレスという条件が課されます。ロードバランサーの動作はロードバランサーとはを参照してください。
オートスケーリングは、この水平スケールを「メトリクスに応じて自動で行う」仕組みです。AWSではEC2 Auto Scaling GroupやECS Service Auto Scaling、KubernetesではHorizontal Pod Autoscaler(HPA)、Cloud RunやApp Serviceではプラットフォームに組み込まれています。
スケールの判断に使うメトリクスを選ぶ
「何を見て増やすか」がオートスケーリング設計の中心です。代表的な3つを比較します。
| メトリクス | 向いているワークロード | 長所 | 注意点 |
|---|---|---|---|
| CPU使用率 | CPU負荷が支配的なAPI、画像処理 | どの環境でも取れる。設定が簡単 | I/O待ちが多いアプリではCPUが上がらないまま遅くなる。メモリ枯渇も検知できない |
| リクエスト数/台(ALBのRequestCountPerTargetなど) | 一般的なWebアプリ・API | 「1台あたり何リクエストまでさばけるか」という負荷試験の結果をそのまま閾値にできる | リクエストの重さがばらつくと精度が落ちる |
| キュー長(SQSのメッセージ数など) | 非同期ワーカー、バッチ | 「溜まっている仕事の量」を直接見られる。最も直感的 | ワーカー1台あたりの処理速度から必要台数を逆算する設計(バックログ/台数)が必要 |
「ターゲット追従」で考える
現在の主流は「メトリクスを目標値に保つように台数を調整する」ターゲット追従型(Target Tracking)です。例えば「CPU使用率を平均50%に保つ」と設定すれば、80%になれば増やし、20%が続けば減らします。目標値を50〜60%程度に置くのは、スケールアウトが完了するまでの間(数分)に急増するトラフィックを吸収する余裕を残すためです。目標値を90%にすると、増設が間に合う前に飽和します。
# ECS Service Auto Scaling:ALBのターゲットあたりリクエスト数で追従
aws application-autoscaling register-scalable-target \
--service-namespace ecs \
--resource-id service/my-cluster/my-api \
--scalable-dimension ecs:service:DesiredCount \
--min-capacity 2 --max-capacity 10
aws application-autoscaling put-scaling-policy \
--service-namespace ecs \
--resource-id service/my-cluster/my-api \
--scalable-dimension ecs:service:DesiredCount \
--policy-name req-per-target \
--policy-type TargetTrackingScaling \
--target-tracking-scaling-policy-configuration '{
"TargetValue": 500,
"PredefinedMetricSpecification": {
"PredefinedMetricType": "ALBRequestCountPerTarget",
"ResourceLabel": "app/my-alb/xxxx/targetgroup/my-tg/yyyy"
},
"ScaleOutCooldown": 60,
"ScaleInCooldown": 300
}'
ここでTargetValueの500は「1タスクあたり毎分500リクエストまでなら十分な速度で返せる」という負荷試験の結果に基づいて決めます。試験なしに勘で置いた値は、ほぼ確実に高すぎるか低すぎます。1台のさばける同時接続数の考え方は同時接続数とワーカー数の見積もりを参照してください。
クールダウンとフラッピング:増減が暴れる理由
フラッピングはなぜ起きるか
台数を増やした直後は、新しいサーバーが起動途中でまだ負荷を受けていないため、平均メトリクスはすぐには下がりません。ここで「まだ高い」と判断してさらに増やすと、数分後に全台が稼働した時点で過剰になり、今度は「低すぎる」と判断して減らし、減らしすぎてまた増やす…という振動(フラッピング)が起きます。増減のたびに起動コストとエラーが発生し、コストも安定しません。
クールダウンと非対称な設定で抑える
クールダウンは、スケール操作の後、次の操作までに待つ時間です。スケールアウトのクールダウンは「新しいサーバーが起動してメトリクスに反映されるまでの時間」より少し長く設定します。スケールインは慎重にすべきなので、より長く(例:5〜10分)取るのが定石です。「増やすのは速く、減らすのは遅く」という非対称が基本原則です。KubernetesのHPAでもbehaviorで同じ考え方を設定できます。
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
behavior:
scaleUp:
stabilizationWindowSeconds: 0 # 増やすときは即断
policies:
- type: Percent
value: 100 # 一度に最大2倍まで
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300 # 5分間高い値が続かなければ減らさない
policies:
- type: Pods
value: 1 # 1分に1台ずつしか減らさない
periodSeconds: 60
起動時間とウォームアップ:増えた台がすぐ役に立つとは限らない
起動時間はスケールの「反応速度」を決める
スケールアウトを決めてから新しいサーバーがリクエストをさばき始めるまでには、インスタンスの起動、コンテナイメージの取得、アプリの初期化、ヘルスチェックの成功、という段階があります。EC2でAMIから起動すると数分、コンテナでもイメージが大きければ1〜2分かかります。この間にトラフィックが急増すれば、既存の台が飽和します。起動時間を短くすることは、オートスケーリングの精度を上げることと同義です。
- コンテナイメージを小さくする(マルチステージビルド、不要な依存の削除)
- 起動時の重い初期化(大きなキャッシュの構築、マイグレーション)を避けるか非同期化する
- ヘルスチェックの間隔と閾値を、起動完了を素早く検知できる値にする(ヘルスチェック設計入門)
ウォームアップ:起動直後の台に全力を出させない
起動直後のサーバーは、JITコンパイルが済んでいない、コネクションプールが空、ローカルキャッシュが空、といった理由で本来の性能が出ません。ここにいきなり均等にリクエストを振ると、その台だけ遅くなります。ALBのターゲットグループには「スロースタート」という設定があり、登録直後の台に段階的にトラフィックを増やせます。また、Auto Scaling Groupの「インスタンスウォームアップ」は、起動直後の台をメトリクス集計から除外して、フラッピングの原因になる「まだ負荷を受けていない台」の影響を減らします。
# ALBターゲットグループのスロースタート(新しい台に30秒かけて徐々に振る)
aws elbv2 modify-target-group-attributes \
--target-group-arn arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/my-tg/yyyy \
--attributes Key=slow_start.duration_seconds,Value=30
前提条件:ステートレスと「スケールしても効かないボトルネック」
ステートレスでなければ台数は増やせない
オートスケーリングが「勝手に台数を増減する」ということは、「どの台がいつ消えても困らない」設計が必要だということです。セッションをメモリに持っている、アップロードファイルをローカルディスクに書いている、台ごとに設定が違う、といった状態は、スケールインで台が消えた瞬間に問題を起こします。セッションはRedisやDBへ、ファイルはオブジェクトストレージへ追い出す必要があります。ストレージの選び方はオブジェクト・ブロック・ファイルストレージの違いで解説しています。
アプリを増やしてもDBは増えない
オートスケーリングでもっとも多い落とし穴は、「アプリサーバーを増やしたら、DBへの接続数と負荷がその分増えて、DBが先に限界を迎える」というものです。アプリを2台から10台にすれば、コネクションプールも5倍になり、DBのmax_connectionsを超えて接続エラーが出ることもあります。DBは水平スケールが難しいため、対策は次の順で考えます。
- アプリ1台あたりのコネクションプールのサイズを、最大台数×プールサイズがDBの接続上限を超えないように決める。必要ならPgBouncerなどのプーラーを挟む(データベースのコネクションプーリング入門)。
- 読み取りをレプリカに逃がし、キャッシュ(Redis)でDBへの問い合わせ自体を減らす。
- それでも足りなければDBの垂直スケール(インスタンスサイズ変更)を検討する。
「スケールアウトのテストをするなら、DBのメトリクスも同時に見る」を習慣にしてください。アプリ側の台数が増えてもレスポンスが改善しないなら、ボトルネックはアプリではなくその先にあります。
コスト上限:無制限のスケールは事故になる
オートスケーリングは「必要なときだけ増やす」ことでコストを抑える仕組みですが、上限を設けなければ、バグによるリトライループやDDoS的なアクセスで台数が跳ね上がり、月末の請求で気づくことになります。
- 最大台数(max):負荷試験で確認した「これ以上増やしてもDBが先に詰まる」台数と、月額予算から逆算した台数の小さい方に設定する。
- 最小台数(min):可用性のため2以上が基本。1台だと、その台の障害やデプロイ時に無停止で入れ替えられない。
- 予算アラート:AWS Budgetsなどで、日次コストが想定を超えたら通知する。
- スケジュールスケーリング:営業時間中は最小4台、夜間は2台、のように予測できる変動はメトリクスに頼らず時間で設定した方が安定する。
必要台数の見積もり方法はキャパシティプランニング入門を参照してください。
トラブル事例:TV放映後のアクセス集中にスケールが間に合わなかった
症状
自社サービスがTV番組で紹介された直後、通常の20倍のアクセスが数分で流入しました。オートスケーリングは設定されていたにもかかわらず、最初の10分間は5xxエラーが多発し、その後ようやく安定しました。安定後は台数が最大まで増えていましたが、DBのCPUは100%に張り付いていました。
原因
3つの問題が重なっていました。第一に、スケールアウトの閾値がCPU80%と高く、判定に3分の連続超過を要求していたため、増設の判断そのものが遅れました。第二に、EC2のAMIにアプリが含まれておらず、起動後にgit pullと依存インストールを行う構成だったため、1台の起動に7分かかっていました。第三に、アプリ台数が最大に達した時点でDBの接続数が上限に達し、それ以降はアプリを増やしてもDBが処理できない状態でした。
対処
- 閾値をターゲット追従(CPU50%)に変更し、判定期間を1分に短縮した。
- アプリと依存をすべて焼き込んだAMI(コンテナ化後はイメージ)を用意し、起動時間を1分未満にした。
- PgBouncerを導入してDB接続を多重化し、読み取り系クエリをリードレプリカに分離した。
- 放映などイベントが事前にわかる場合は、開始1時間前に最小台数を引き上げるスケジュールスケーリングを運用ルールにした。
再度の放映時には、事前のスケジュール増設と速い起動により、エラーなしで乗り切れました。オートスケーリングは「事後に反応する仕組み」であり、予測できる急増は事前に増やす方が確実です。
まとめ
オートスケーリングを機能させるには、設定より前に前提を整える必要があります。アプリをステートレスにし、負荷試験で1台あたりの処理能力を把握したうえでメトリクスと目標値を決め、「増やすのは速く・減らすのは遅く」の非対称なクールダウンでフラッピングを抑え、起動時間を短くしてウォームアップで新しい台を保護する。そしてアプリを増やしてもDBは増えないことを前提に、コネクションプールとキャッシュで先回りし、最大台数と予算アラートで上限を決める。この一連の設計があって初めて、「自動で何とかしてくれる」状態になります。
オートスケーリングの導入や、アクセス集中に備えた構成の見直し・負荷試験の実施でお困りの場合は、Harmonic Societyのシステム開発・インフラ支援にご相談ください。
Harmonic Society
この記事の内容、自社の業務でも活かせそうですか?
ローカルLLM・AI・クラウドなどの技術導入を、要件整理からPoC・社内展開まで代表エンジニアが伴走します。オンライン対応・全国OK。まずは30分の無料相談から。売り込みはしません。
関連記事
Related / 9 articles
Notes & Insights
- プログラミング
DDoS攻撃の仕組みと対策入門|レイヤー別の防御とCDN・クラウドの活用
DDoS攻撃をボリューム型・プロトコル型・アプリ層に分けて仕組みを解説し、自前サーバーで防げない理由、CloudflareやAWS Shieldの標準防御、オリジンIPの隠し方、レートリミットとBot対策、攻撃を受けたときの初動、費用が跳ね上がるDenial of Walletへの備えまでわかります。
- プログラミング
WAFとは?仕組み・導入パターン・誤検知対策|Webアプリを攻撃から守る実践ガイド
WAFがファイアウォールやIDSと何が違うのか、シグネチャとマネージドルールの仕組み、Cloudflare WAF・AWS WAF・ModSecurityの比較、フォーム送信がブロックされる誤検知の調査と例外設定、ログ監視、WAFが代替できないことまで実践的に解説します。
- プログラミング
セキュリティヘッダー入門|CSP・HSTS・X-Frame-Optionsの設定と効果を実践解説
CSP・HSTS・X-Frame-Options・X-Content-Type-Optionsなど主要セキュリティヘッダーが防ぐ攻撃と、CSPのReport-Onlyからの段階導入、nonce/hash、HSTS preloadの不可逆リスク、Nginx・Next.js・Astroでの設定例、確認方法を解説します。
- プログラミング
クラウドの通信費(Egress)入門|データ転送量課金の仕組みと転送コストを抑える設計
クラウドの「受信無料・送信有料」の原則、AZ間・リージョン間・インターネット向けの単価差、NATゲートウェイ処理料の罠、CDNで転送量を減らす方法、バックアップやログ転送の見落とし、請求書で転送料を特定する手順を解説。想定外の請求を防げます。
- プログラミング
秘密情報をGitに入れない仕組み|.gitignore・git-secrets・履歴から漏れた鍵の削除
APIキーや.envをGitにコミットしてしまう典型経路と、.gitignore・.env.exampleの運用、pre-commitでのgitleaks検知、GitHub secret scanningの活用、漏れた鍵の無効化と履歴書き換え(git filter-repo)の手順を解説。仕組みで再発を防げます。
- プログラミング
開発・ステージング・本番環境の分離設計|環境差分をなくす構成とアクセス制御
開発・ステージング・本番それぞれの目的と、構成をコードで揃える方法、環境別の設定注入、本番データを使わないテストデータ戦略、ステージングの保護(Basic認証・IP制限・noindex)、コストを抑える運用までを解説。環境差分による本番障害を防げます。
- プログラミング
ngrok・Cloudflare Tunnelでローカルを公開|Webhook開発とデモ環境の作り方
NAT内のローカル環境にStripeやLINEのWebhookを届けるトンネリングの仕組みを解説。ngrok・Cloudflare Tunnel・localtunnelの比較、固定ドメインと認証、リクエスト検査、公開時のセキュリティ、自宅サーバー公開への応用までわかります。
- プログラミング
ローカル開発環境のHTTPS化|mkcert・hostsファイル・自己署名証明書の正しい使い方
ローカル開発をHTTPS前提にすべき理由(Secure Cookie・Service Worker・OAuth)と、mkcertでローカルCAを作りhostsで独自ドメインを割り当ててVite・Next.js・Dockerで使う手順を解説。証明書警告を無視する癖の危険も理解できます。
- プログラミング
localhost・0.0.0.0・127.0.0.1の違い|ポートとUnixソケットを理解して「つながらない」を解決
localhost・127.0.0.1・0.0.0.0の意味の違い、Dockerで外から接続できない原因、host.docker.internal、ポート競合の調べ方、Unixソケットの利点と権限、1024未満ポートの制約を解説。「つながらない」を仕組みから解決できます。
Harmonic Society
「読んで終わり」にせず、自社の業務で試してみませんか?
AI・ローカルLLM・クラウドの導入を、要件整理からPoC・社内展開まで代表エンジニアが伴走します。オンライン対応・全国OK・売り込みなし。
無料・30分・オンラインOK|1営業日以内に返信します