Horizontal Pod Autoscaler
Kubernetes で Pod のレプリカ数を CPU 使用率やカスタムメトリクスに基づいて自動調整する仕組み
Horizontal Pod Autoscaler とは
Horizontal Pod Autoscaler (HPA) は、Kubernetes で Pod のレプリカ数を CPU 使用率、メモリ使用率、カスタムメトリクスに基づいて自動的にスケールイン/スケールアウトする仕組みである。トラフィックの増減に応じて Pod 数を動的に調整し、リソース効率とパフォーマンスを両立する。
基本的な設定
CPU とメモリの 2 つを目標にした最小構成を示す。
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-server-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-server
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70 # CPU 使用率 70% を目標
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
メトリクスを複数指定した場合、コントローラーは各メトリクスについて必要レプリカ数を個別に算出し、その最大値を採用する。したがって CPU が 70% を下回っていても、メモリ側がより多くのレプリカを要求している間は縮小しない。さらに目標値との比が 1.0 に十分近い範囲 (既定の許容幅 0.1 = 目標の ±10%) では調整をスキップするため、CPU 使用率が 71% になった程度では Pod は増えない。
スケーリングの仕組み
スケーリングの仕組みを図で示す。
desiredReplicas = ceil(currentReplicas × (currentMetric / targetMetric))
例: 現在 3 Pod、CPU 使用率 90%、目標 70%
desiredReplicas = ceil(3 × (90 / 70)) = ceil(3.86) = 4
HPA コントローラーは連続監視ではなく間欠的な制御ループで、kube-controller-manager の --horizontal-pod-autoscaler-sync-period (既定 15 秒) ごとにメトリクスを取得してレプリカ数を調整する。判定に使うのは対象 Pod 群の平均値である。
ここで実務上つまずくのが、使用率の分母が Pod の resources.requests だという点だ。コンテナのいずれかに該当リソースの requests が設定されていないと Pod の使用率が未定義になり、コントローラーはそのメトリクスについて何もしない。HPA が「動かない」ときの原因として requests 未設定は最初に疑う価値がある。CPU でのスケーリングでは、起動直後でまだ Ready になっていない Pod や Ready 直前のメトリクスも計算から外されるため、スケールアウト直後は新しい Pod が平均値に寄与するまで数十秒の遅れが出る。
カスタムメトリクスによるスケーリング
CPU/メモリだけでなく、アプリケーション固有のメトリクス (リクエスト数、キューの深さ) でスケーリングできる。
metrics:
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: 100 # Pod あたり 100 req/s を目標
Prometheus Adapter や KEDA (Kubernetes Event-Driven Autoscaling) を使って、外部メトリクスソースと連携する。
スケーリングの安定化
メトリクスの揺れでレプリカ数が振動するのを防ぐ仕組みが behavior の安定化ウィンドウとレート制限ポリシーである。安定化ウィンドウは過去の推奨値を遡って参照し、スケールダウン時はその区間の最大値を採る (ローリング最大)。
behavior:
scaleDown:
stabilizationWindowSeconds: 300 # 5分間の安定化期間
policies:
- type: Percent
value: 10 # 1回で最大10%削減
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 0 # スケールアップは即座に
policies:
- type: Percent
value: 100 # 1回で最大100%追加
periodSeconds: 60
上の例は既定値を意図的に絞ったものだ。behavior を書かない場合の既定は、スケールダウンが安定化ウィンドウ 300 秒 + 15 秒ごとに現レプリカ数の 100% まで削減、スケールアップが安定化ウィンドウ 0 秒 + 15 秒ごとに 4 Pod または 100% の大きい方まで追加である。つまり「下げは慎重・上げは即座」は既定の挙動そのもので、例のように 60 秒あたり 10% へ絞ると縮小がさらに緩慢になる。
許容幅は本来 kube-controller-manager の --horizontal-pod-autoscaler-tolerance (既定 0.1) でクラスター全体に効く設定だが、2026 年 8 月時点の Kubernetes 1.35 では behavior 配下の tolerance フィールドでスケールアップ・スケールダウン別に指定できる (ベータ・既定で有効)。
メモリを目標に使うときは縮小しにくい点に注意する。JVM や Node.js のようにヒープを確保したまま OS へ返さないランタイムでは、負荷が去っても使用量が下がらず、スケールダウン条件を満たさないまま Pod 数が張り付く。メモリは上限側の保険として使い、増減の主軸は CPU かリクエスト数系のメトリクスに置くのが扱いやすい。
VPA・KEDA との住み分け
同じ「自動スケール」でも役割が異なる 3 者を整理する。
| ツール | 調整対象 | 主なメトリクス | 0 台への縮小 |
|---|---|---|---|
| HPA | レプリカ数 (水平) | CPU / メモリ / カスタム / 外部 | 標準では不可 |
| VPA | Pod ごとの requests / limits (垂直) | CPU / メモリ | 対象外 |
| KEDA | レプリカ数 (水平・内部で HPA を生成) | キュー長やイベント数などの外部指標 | 可 |
VPA は HPA の代わりではなく、1 Pod あたりの適正なリソース要求を決める役である。公式の既知の制限では、VPA を HPA と同一のリソースメトリクス (CPU または メモリ) で併用してはならないとされている。逆に、VPA をメモリ・HPA を CPU のように別のリソースメトリクスへ振り分ける構成や、HPA をカスタム/外部メトリクスで動かす構成は併用できる。VPA が推奨値を適用する際は Pod が作り直され、別ノードへ再スケジュールされることもある点も設計時に織り込む。
KEDA も HPA の対抗ではない。KEDA はイベントソースを監視して指標を Kubernetes へ供給し、1 台から N 台への調整は結局ビルトインの HPA コントローラーが行う。KEDA 独自の領分は 0 台と 1 台の間の切り替え (アクティベーション) で、待ち行列が空のときにワークロードを 0 台まで落とし、メッセージ到着で起こせるのがキュー処理系での主な採用理由になる。
理論と実装の両面から学ぶなら関連書籍が参考になる。
この記事は役に立ちましたか?
関連用語
Kubernetes
コンテナのデプロイ、スケーリング、管理を自動化するオープンソースのオーケストレーションプラットフォーム
オートスケーリング
トラフィックや負荷に応じてコンピュートリソースを自動的に増減させる仕組み
ロードバランシング
複数のサーバーにトラフィックを分散し、可用性とスケーラビリティを向上させる仕組み
CloudWatch
AWS のモニタリング / ログ管理サービスで、メトリクス収集、ログ分析、アラートを提供する
テレメトリ
システムの状態をメトリクス、ログ、トレースの 3 本柱で収集・送信する仕組み
時系列データベース
タイムスタンプ付きのデータを効率的に保存・クエリするために最適化されたデータベース