水平スケーリングの制御理論(HPA/オートスケール)
オートスケールが暴れる・遅れる理由を制御理論で腑分け。HPAの比例制御、振動を抑えるヒステリシス、reactiveとpredictiveの違いを原理から理解し、安定したスケール設定を組めます。
- 1.HPAは『現在のメトリクスと目標値の比』でレプリカ数を一発算出する比例制御。desired = ceil(current × 観測値/目標値) が中核で、積分・微分項を持たない純Pコントローラに近い。
- 2.制御ループには測定・反映・効果発現の遅延(むだ時間)があり、ゲインが高い/許容幅が狭いと振動する。安定化の鍵はヒステリシス(スケールイン安定化窓)と許容デッドバンド。
- 3.reactiveは観測後に追従するため負荷急増に必ず遅れる。predictiveは予測でリードタイムを先回りするが、外れると過剰/過少プロビジョンを招く。両者は併用が定石。
オートスケールはなぜ暴れ、なぜ遅れるのか
水平オートスケール(HPA: Horizontal Pod Autoscaler に代表される機構)は、ひと言で言えば 負荷を測ってレプリカ数を増減するフィードバック制御 です。だが現場では二つの厄介が起きます。ひとつは 振動——レプリカ数が増えては減りを繰り返し落ち着かない。もうひとつは 遅れ——負荷スパイクに追従できず、増設が間に合った頃にはピークが過ぎている。
この二つは設定ミスではなく、フィードバック制御に普遍的な性質の現れです。本記事では HPA が内部で解いている式を制御理論の言葉で分解し、なぜ振動するのか、ヒステリシスがどう効くのか、そして reactive(事後追従)と predictive(予測先行)が制御上どう違うのかを原理から説明します。
HPAの中核:比例制御としてのレプリカ算出
HPA が毎周期おこなう計算は、驚くほど単純です。目標とするメトリクス値(例:Pod あたり CPU 使用率 50%)と現在の観測平均から、必要レプリカ数を一発で求めます。
desiredReplicas = ceil( currentReplicas × (currentMetric / targetMetric) )
例: 現在4レプリカ、目標CPU 50%、実測平均が 80% のとき
desired = ceil( 4 × (80 / 50) ) = ceil(6.4) = 7
これは制御理論でいう 比例制御(P制御) とほぼ同型です。誤差(観測値と目標値のズレ)に比例して操作量(レプリカ数)を決め、積分項(過去の誤差の蓄積)も微分項(誤差の変化率)も持ちません。比 currentMetric / targetMetric が実質的な比例ゲインの役割を果たし、しかも 逆問題を直接解いて新しい絶対値を出す ため、P制御に付き物の定常偏差(オフセット)が原理的に出ないのが特徴です。理想的には、レプリカを desired に合わせれば次周期の観測値は目標へ収束します。
なぜ目標値「未満」に過剰増設しないかというと、HPA には 許容率(tolerance) というデッドバンドがあるからです。比が 1 から一定幅(既定で約10%)以内なら「目標どおり」とみなし、レプリカを動かしません。これは制御で言う 不感帯 で、測定ノイズによる無用な増減を抑える最初の安定化策です。
この一発算出が成り立つのは「レプリカ数を2倍にすれば1台あたり負荷が半分になる」という 線形のスケーラビリティ仮定 に依ります。共有DBのロック競合や調整オーバーヘッドがあると、レプリカを増やしても1台あたり負荷が期待ほど下がらず、HPAは目標へ収束しきれません。この収穫逓減はアムダール/ユニバーサルスケーラビリティ則そのものです(/devops/amdahl-gustafson-scalability/)。
むだ時間とゲイン:振動が生まれる構造
P制御が一発で目標に収束するなら、なぜ振動するのか。原因は 制御ループに無視できない遅延(むだ時間, dead time)がある ことです。フィードバック制御は、誤差を測り→操作し→効果が現れる、というループを回しますが、HPA の各段に時間がかかります。
[負荷変化] →(a)→ [メトリクス採取・集約] →(b)→ [HPA評価周期] →(c)→ [Pod起動] →(d)→ [効果反映]
(a) メトリクスパイプラインの遅延(採取間隔・集約ウィンドウ)
(b) HPAの評価間隔(既定で約15秒ごと)
(c) スケジューリング+イメージ取得+起動+ウォームアップ
(d) 新Podがトラフィックを受け、平均メトリクスに反映されるまで
制御理論の鉄則として、ループにむだ時間があり、かつ比例ゲインが高いと系は振動し、ある限界を超えると発散する。HPA で「ゲインが高い」状況とは、観測ウィンドウが短くノイズに敏感、許容率が狭い、起動が遅い、といった条件です。典型的な振動はこう進みます。
1. 負荷スパイク → 実測CPUが急上昇 → HPAが大量増設を指示
2. 新Podの起動中、まだ効果が出ない → 次の評価でも高負荷のまま → さらに増設
3. ようやく全Podが立ち上がり負荷が分散 → 今度はCPUが目標を大きく下回る
4. HPAが過剰とみなし一気にスケールイン → 残ったPodの負荷が再上昇 → 1へ
これは制御対象の応答遅れに対してコントローラが先走った結果の オーバーシュート → アンダーシュート の往復で、まさに振動(ハンチング)です。Pod の起動が遅い(c が大きい)ほど、また増設量が大胆(ゲインが高い)ほど顕著になります。同じ「効果が出る前に追加投入してしまう」構造は、輻輳崩壊やリトライストームと地続きです(/devops/congestion-collapse-backpressure/)。
ヒステリシス:上げと下げで閾値をずらす
振動を抑える最も効く手が ヒステリシス(履歴依存) です。要点は スケールアウトとスケールインで判断基準を非対称にする こと。とくに「下げ」を鈍くします。HPA は既定で、スケールインに対して 安定化ウィンドウ(stabilization window, 既定約300秒) を設けます。直近一定時間で計算された desired のうち 最大値 を採用するため、瞬間的な負荷の谷では縮まず、谷が一定時間続いて初めて縮みます。
| 手法 | 効く方向 | やること | 副作用 |
|---|---|---|---|
| 許容率(デッドバンド) | 上下両方 | 比が1±10%以内なら動かさない | 小さな恒常的ズレを放置 |
| スケールイン安定化窓 | 下げを鈍化 | 過去N秒のdesired最大値を採用 | 縮小が遅れ余剰コスト |
| スケール速度ポリシー | 上下を制限 | 周期あたりの増減率/数に上限 | 急増への追従が鈍る |
| クールダウン | 再動作を抑制 | 直近の操作後しばらく静止 | 連続調整ができない |
非対称にする理由は明快です。増設の取り返しは効くが、誤った縮小は即障害になる からです。負荷が一瞬下がっただけで縮め、直後に戻って過負荷に陥るより、「下げは慎重に、上げは機敏に」が安全側に倒れます。安定化窓は系の応答遅れ(むだ時間)より十分長く取るのが原則で、これにより「効果が反映される前に次の操作を打つ」リスクを構造的に減らせます。
安定化窓やクールダウンを長くすれば振動は確実に収まりますが、その分 応答が鈍く なります。制御理論の言う安定性と応答性のトレードオフそのもので、無料の安定化はありません。窓を Pod 起動時間の数倍まで縮め、代わりにスケールアウト側の安定化窓は短く(または0に)して上げの俊敏さを残す、という非対称チューニングが実務の落とし所です。
reactive と predictive:制御の構え方の違い
ここまでの HPA は本質的に reactive(フィードバック制御) です。「実際に負荷が上がってから」測って追従するため、むだ時間ぶんは必ず後手に回る。これは制御構造上の限界で、どれだけチューニングしても観測→反映の遅延はゼロにできません。
これを補うのが predictive(フィードフォワード制御) です。過去の周期性(毎朝9時に負荷が立つ等)や先行指標(キュー長・上流のリクエスト到着率)から 将来の負荷を予測し、上がる前に増設 します。誤差を見てから動く reactive と違い、外乱(負荷変化)そのものを予測して先回りするのがフィードフォワードの発想です。
| 観点 | reactive(フィードバック) | predictive(フィードフォワード) |
|---|---|---|
| トリガ | 実測メトリクスが目標を逸脱 | 予測モデル/スケジュール/先行指標 |
| 遅れ | むだ時間ぶん必ず後手 | リードタイムを先取りでき遅れを相殺 |
| 外れたとき | 保守的に実測へ収束 | 過剰または過少プロビジョンが残る |
| 前提 | メトリクスが取れれば動く | 負荷に予測可能な構造が要る |
| 典型例 | CPU/RPSベースのHPA | 時間帯スケジュール・ML予測スケーラ |
predictive の弱点は 予測誤差がそのままコストとリスクになる ことです。外れて過剰に増やせば資源を遊ばせ、過少なら過負荷を招く。フィードフォワードは外乱モデルの精度に全面的に依存し、モデルが現実とズレた瞬間に補正が効きません。そこで実務では 両者を併用 します——predictive でベースラインを先回り確保し、予測誤差を reactive な HPA が事後に吸収する、という二段構えです。フィードフォワードで大まかに当て、残差をフィードバックで詰めるのは制御の常套手段です。
レプリカを増やしても改善しないボトルネック——単一の書き込みマスタDB、グローバルロック、ライセンス上限のある外部依存——は、水平オートスケールの守備範囲外です。HPAはステートレスで線形にスケールする層にのみ有効で、増設が逆に共有資源の競合を悪化させる場合すらあります。どこがスケールするかの見極めは容量計画の領域です(/devops/capacity-planning/)。
メトリクス選びと安定性
何を制御入力(観測メトリクス)にするかも安定性を左右します。CPU 使用率は手軽ですが 遅行指標 で、しかもガベージコレクションやノイジーネイバーで揺れやすい。一方、キュー長や同時実行数、リクエスト到着率(RPS) はより 先行的 で、リトル則(L = λ × W)を介して負荷と直結するため制御入力として素直です。待ち行列が深いほどテイルレイテンシが発散する関係を踏まえると、レイテンシそのものを目標にするのは難しい——目標レイテンシ未満に保とうとすると、飽和点近傍で 1/(1−ρ) が急峻になりゲインが暴れるためです(/devops/queueing-theory-tail-latency/)。
実務の指針はこうです。揺れの少ない先行指標を選ぶほど制御は安定し、観測ウィンドウを適度に長く取るほどノイズに強くなる(が応答は鈍る)。複数メトリクスを併用する場合、HPA は各メトリクスから個別に desired を算出し その最大値 を採るため、最も逼迫した次元が支配します。これは安全側だが、ノイズの多いメトリクスを1本混ぜるだけで全体が暴れうる点に注意が要ります。新Podが起動直後に過大な負荷を計上されないよう、起動猶予(メトリクス安定までの待ち)を設けるのも振動抑制に効きます。
まとめ
- HPA の中核は
desired = ceil(current × 観測値/目標値)という比例制御。比がゲイン、許容率がデッドバンドとして働き、逆問題を直接解くためオフセットが出にくい。 - 振動の正体はむだ時間×高ゲイン。測定・評価・起動・反映の各遅延がループに乗り、効果が出る前に追加操作を打つとオーバーシュートとアンダーシュートを往復する。
- ヒステリシスで上げと下げを非対称に。スケールイン安定化窓・クールダウン・速度制限で「下げを鈍く、上げを機敏に」する。安定化と応答性はトレードオフ。
- reactive は必ず後手、predictive は予測誤差がコスト/リスク。フィードバック(事後追従)とフィードフォワード(予測先行)は併用が定石で、predictive でベースを先取りし残差を HPA が吸収する。
- メトリクスは揺れの少ない先行指標を選ぶ。CPU は遅行で暴れやすく、キュー長・RPS の方が制御入力として素直。複数指標は最大値支配なのでノイズ源を混ぜない。
DevOps/インフラ Article
水平スケーリングの制御理論(HPA/オートスケール)を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
オートスケール
比較で見る軸
難易度: advanced / カテゴリ: DevOps/インフラ / タグ数: 6
導入後に効く点
制御ループには測定・反映・効果発現の遅延(むだ時間)があり、ゲインが高い/許容幅が狭いと振動する。安定化の鍵はヒステリシス(スケールイン安定化窓)と許容デッドバンド。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- DevOps/インフラ
- タグ数
- 6
判断チェックリスト
- 自社の用途が「オートスケール / HPA」に近いか確認する。
- 強みである「HPAは『現在のメトリクスと目標値の比』でレプリカ数を一発算出する比例制御。desired = ceil(current × 観測値/目標値) が中核で、積分・微分項を持たない純Pコントローラに近い。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。