Kubernetes Horizontal Pod Autoscaler(HPA)チューニング実践ガイド
リソースリクエスト、メトリクス、スケール動作、安定化ウィンドウ、検証コマンドを使ってKubernetes HPAをチューニングします。
Kubernetes Horizontal Pod Autoscaler(HPA)チューニング実践ガイド
Kubernetes Horizontal Pod Autoscaler(HPA)は、メトリクスと制限がアプリの動作を反映していれば、トラフィック急増時にもアプリの応答性を維持できます。チューニングが不十分なHPAは、スケールアップが遅すぎたり、スケールダウンが速すぎたり、リソースリクエストが不足しているためにまったくスケールしない可能性があります。
このガイドでは、CPU、メモリ、カスタムメトリクス、外部メトリクス、スケール動作制御を使用してKubernetes HPAをチューニングする方法を説明します。
Horizontal Pod Autoscaler(HPA)の理解
HPAは、現在の需要に合わせてアプリケーションのPod数を自動的に増減します。指定されたメトリクスを継続的に監視し、目標値と比較します。観測されたメトリクスが目標を超えると、HPAはスケールアップイベントを開始し、下回るとスケールダウンをトリガーします。この動的な調整により、過剰プロビジョニングを防ぎながら、アプリケーションが最適に動作するための十分なリソースを確保します。
HPAは以下に基づいてスケールできます:
- リソースメトリクス:主にCPU使用率とメモリ使用率(
metrics.k8s.ioAPI経由で利用可能。通常はKubernetes Metrics Serverが提供)。 - カスタムメトリクス:
custom.metrics.k8s.ioAPI経由で公開されるアプリケーション固有のメトリクス(例:1秒あたりのリクエスト数、キュー深度、アクティブ接続数)。通常はprometheus-adapterのようなアダプターが必要。 - 外部メトリクス:クラスター外部のソースから
external.metrics.k8s.ioAPI経由で公開されるメトリクス(例:Google Cloud Pub/Subキューサイズ、AWS SQSキュー長)。外部メトリクスを取得できるカスタムメトリクスAPIサーバーも必要。
効果的なHPAチューニングの前提条件
HPA設定に入る前に、以下の基本要素が整っていることを確認してください:
1. 正確なリソースリクエストと制限の定義
これはおそらく最も重要な前提条件です。 HPAは、使用率のパーセンテージを計算するために、正しく定義されたCPUとメモリのリクエストに大きく依存します。PodにCPUリクエストが定義されていない場合、HPAはCPU使用率を計算できず、CPUベースのスケーリングは不可能になります。
- リクエスト:コンテナに保証される最小リソースを定義します。HPAはこれらの値を使用して、Podあたりの目標使用率を決定します。
- 制限:コンテナが消費できる最大リソースを定義します。制限により、単一のPodが過剰なリソースを消費し、同じノード上の他のPodに影響を与えるのを防ぎます。
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: my-image:latest
resources:
requests:
cpu: "200m" # CPUコアの20%
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
2. Kubernetes Metrics Serverのインストール
HPAがCPUおよびメモリ使用率メトリクスを使用するには、クラスターにKubernetes Metrics Serverがインストールされている必要があります。これはKubeletからリソースメトリクスを収集し、metrics.k8s.io API経由で公開します。
3. アプリケーションの可観測性
カスタムメトリクスまたは外部メトリクスの場合、アプリケーションは関連メトリクスを公開し(例:Prometheusエンドポイント経由)、これらのメトリクスを収集してKubernetes APIに公開する方法(通常はPrometheusアダプターまたはカスタムメトリクスAPIサーバーを使用)が必要です。
HPAの設定:コアパラメータ
HPAマニフェストの基本構造を見てみましょう:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
namespace: default
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
主要パラメータ:
scaleTargetRef:HPAがスケールするターゲットリソース(例:Deployment)を定義します。apiVersion、kind、nameを指定します。minReplicas:HPAがスケールダウンする最小Pod数。ゼロ負荷時でも高可用性のために少なくとも1または2に設定することをお勧めします。maxReplicas:HPAがスケールアップする最大Pod数。これは暴走スケーリングに対する安全策として機能し、コストを制限します。metrics:HPAが監視するメトリクスを定義する配列。type:Resource、Pods、Object、またはExternalを指定できます。resource.name:Resourceタイプの場合、cpuまたはmemoryを指定します。target.type:Resourceタイプの場合、Utilization(リクエストされたリソースのパーセンテージ)またはAverageValue(絶対値)。averageUtilization:Utilizationタイプの場合、目標パーセンテージ。HPAは現在の使用率 / 目標使用率 * 現在のPod数に基づいて希望するPod数を計算します。
応答性と安定性のためのHPAチューニング
基本設定に加えて、HPAは特にautoscaling/v2(または古いバージョンではv2beta2)で、スケーリング動作をより細かく管理するための高度なチューニングオプションを提供します。
1. CPUおよびメモリターゲット(averageUtilization / averageValue)
適切な目標使用率を設定することが重要です。目標が低いと早期スケーリング(応答性が高いがコストがかかる可能性あり)になり、目標が高いと後期スケーリング(応答性が低いが安価でパフォーマンス低下のリスクあり)になります。
- 最適な目標の決定方法:負荷テストとプロファイリングが最善の方法です。アプリケーションに徐々に負荷をかけながら、リソース使用率とパフォーマンスメトリクス(レイテンシ、エラー率)を監視します。アプリケーションのパフォーマンスが低下し始めるCPU/メモリ使用率を特定します。HPAターゲットをこのしきい値より低く設定します。通常はCPUで60〜80%の範囲です。
- バランス:予期しないスパイクに備えて十分な余裕を残しつつ、過剰プロビジョニングにならないような目標を目指します。
2. スケーリング動作(behaviorフィールド)
HPA autoscaling/v2で導入されたbehaviorフィールドは、スケールアップおよびスケールダウンイベントを細かく制御し、「スラッシング」(急速なスケールアップとスケールダウンのサイクル)を防ぎます。
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
behavior:
scaleUp:
stabilizationWindowSeconds: 60 # 再スケールアップまで60秒待機
policies:
- type: Pods
value: 4
periodSeconds: 15 # 15秒ごとに最大4Pod追加
- type: Percent
value: 100
periodSeconds: 15 # または15秒ごとに現在のPod数を2倍(制限の少ない方)
scaleDown:
stabilizationWindowSeconds: 300 # スケールダウンまで5分待機
policies:
- type: Percent
value: 50
periodSeconds: 60 # 60秒ごとに最大50%のPodを削除
selectPolicy: Max # 最大のスケールダウン変更を許可するポリシーを選択
scaleUp設定:
stabilizationWindowSeconds:最近の時間枠でスケーリング推奨を平滑化します。スケールアップは通常、アプリが迅速に反応できるように短いウィンドウを使用します。policies:スケールアップイベント中にPodを追加する方法を定義します。複数のポリシーを定義でき、HPAは最も多くのPodを許可するポリシー(最も積極的なスケールアップ)を使用します。type: Pods:固定数のPodでスケールアップ。valueは追加するPod数。periodSecondsはこのポリシーが適用される時間枠を定義。type: Percent:現在のPod数のパーセンテージでスケールアップ。valueはパーセンテージ。
scaleDown設定:
stabilizationWindowSeconds:scaleDownではより重要で、HPAがスケールダウンを検討する前にメトリクスが目標を下回っているのを観測する時間を指定します。長いウィンドウ(例:300〜600秒)は、一時的な落ち込み時の早期スケールダウンを防ぎ、「コールドスタート」やパフォーマンス低下を回避します。これは安定した環境にとって重要な設定です。policies:scaleUpと同様に、Podの削除方法を定義します。selectPolicyがMinの場合、HPAは最も少ないPod数(最も積極的なスケールダウン)になるポリシーを使用し、Maxの場合は最も多いPod数になるポリシーを使用します。type: Pods:固定数のPodを削除。type: Percent:現在のPod数のパーセンテージを削除。
selectPolicy:複数のscaleDownポリシーが定義されている場合に適用するポリシーを決定します。デフォルトはMaxで、最大のスケール変更を許可するポリシーを選択します。より保守的なダウンスケーリングが必要な場合はMinを使用します。警告:積極的な
scaleDownポリシーや短いstabilizationWindowSecondsには注意してください。アプリケーションの初期化時間が長い場合やステートフル接続を処理する場合、急速なダウンスケーリングはサービス中断やユーザー遅延の増加につながる可能性があります。
高度なHPAメトリクスと戦略
CPUとメモリは一般的ですが、多くのアプリケーションは実際のワークロードを反映するカスタムメトリクスや外部メトリクスでより適切にスケールします。
1. カスタムメトリクス
CPUやメモリがアプリケーションの負荷やパフォーマンスボトルネックの直接的な指標でない場合にカスタムメトリクスを使用します。例:HTTPリクエスト/秒(QPS)、アクティブ接続数、メッセージキュー長、バッチジョブバックログ。
カスタムメトリクスを使用するには:
- アプリケーションがこれらのメトリクスを公開する必要があります(例:Prometheusエクスポーター経由)。
- これらのメトリクスをスクレイピングし、
custom.metrics.k8s.ioAPI経由で公開できるカスタムメトリクスアダプター(例:prometheus-adapter)をデプロイします。
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa-qps
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 15
metrics:
- type: Pods # メトリクスがデプロイメント全体の場合はObject
pods:
metric:
name: http_requests_per_second # アプリケーション/アダプターが公開するメトリクス名
target:
type: AverageValue
averageValue: "10k" # Podあたり1秒あたり10,000リクエストを目標
2. 外部メトリクス
外部メトリクスは、アプリケーションのワークロードがKubernetes上で直接実行されていない外部システムによって駆動される場合に便利です。例:AWS SQSキュー深度、Kafkaトピックラグ、Pub/Subサブスクリプションバックログ。
外部メトリクスを使用するには:
- 外部システムからメトリクスを取得できるカスタムメトリクスAPIサーバー(例:AWS CloudWatchやGCP Monitoring用の特定のアダプター)が必要です。
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-worker-hpa-sqs
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-worker
minReplicas: 1
maxReplicas: 20
metrics:
- type: External
external:
metric:
name: aws_sqs_queue_messages_visible # 外部ソースからのメトリクス名
selector:
matchLabels:
queue: my-queue-name
target:
type: AverageValue
averageValue: "100" # Podあたりキューに表示されるメッセージ100件を目標
3. 複数メトリクス
HPAは複数のメトリクスを同時に監視するように設定できます。複数のメトリクスが指定されている場合、HPAは各メトリクスに対して希望するレプリカ数を個別に計算し、これらの希望レプリカ数の最大値を選択します。これにより、アプリケーションが観測されたすべての負荷次元に対して十分にスケールすることが保証されます。
# ... (HPA定型文)
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "10k"
監視と検証
効果的なHPAチューニングは、継続的な監視と検証を必要とする反復プロセスです:
- HPAイベントの観察:
kubectl describe hpa <hpa-name>を使用して、HPAのステータス、イベント、スケーリング決定を確認します。これにより、HPAがスケールアップまたはダウンした理由に関する貴重な洞察が得られます。 - メトリクスとレプリカの監視:可観測性スタック(例:Prometheus、Grafana)を使用して、アプリケーションのリソース使用率(CPU、メモリ)、カスタム/外部メトリクス、および実際のPodレプリカ数を経時的に可視化します。これらを受信負荷の変化と関連付けます。
- 負荷テスト:予想される負荷とピーク負荷をシミュレートして、HPAの応答性を検証し、ストレス下でアプリケーションが期待どおりに動作することを確認します。これらのテストに基づいてHPAパラメータを調整します。
HPAチューニングのベストプラクティス
- 適切に定義されたリソースリクエスト/制限から始める:これらは正確なリソースベースのHPAの基盤です。これらがないと、HPAはCPU/メモリに対して効果的に機能できません。
- 現実的な
minReplicasとmaxReplicasを設定する:minReplicasは可用性のベースラインを提供し、maxReplicasは暴走コストとリソース枯渇に対する安全策として機能します。 - 目標使用率を徐々に調整する:やや控えめなCPU目標(例:60〜70%)から始めて、反復します。100%使用率を目指さないでください。レイテンシや処理スパイクのバッファがなくなります。
stabilizationWindowSecondsを活用する:急速なスケーリング変動を防ぐために不可欠です。scaleDownにはscaleUpよりも長いウィンドウ(例:5〜10分)を使用して、安定性を確保します。- アプリケーション固有のメトリクスを優先する:CPUやメモリがアプリケーションのパフォーマンスボトルネックと直接相関しない場合は、カスタムメトリクスまたは外部メトリクスを使用して、より正確で効率的なスケーリングを実現します。
- 監視、テスト、反復:HPAチューニングは一度きりの設定ではありません。アプリケーションの動作、トラフィックパターン、基盤となるインフラストラクチャは変化する可能性があります。定期的にHPAのパフォーマンスを確認し、必要に応じて設定を調整します。
- アプリケーションのスケーリング特性を理解する:リクエストに比例して線形にスケールしますか?起動時間は長いですか?ステートフルですか?これらの特性はHPA戦略に影響を与えます。
最終的なポイント
HPAチューニングをフィードバックループとして扱います。正確なリソースリクエストから始め、現実的なminReplicasとmaxReplicasを設定し、実際の需要を追跡するメトリクスを選択し、本番トラフィックが依存する前に負荷テストでスケールアップおよびスケールダウン動作を検証します。