Horizontal Pod Autoscaler

Kubernetes で Pod のレプリカ数を CPU 使用率やカスタムメトリクスに基づいて自動調整する仕組み

Kubernetesスケーリング

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 / メモリ / カスタム / 外部標準では不可
VPAPod ごとの 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 台まで落とし、メッセージ到着で起こせるのがキュー処理系での主な採用理由になる。

理論と実装の両面から学ぶなら関連書籍が参考になる。

この記事は役に立ちましたか?

関連用語

関連する記事