カスタムメトリクスによるKubernetesHPA:Prometheusを使った実践的オートスケーリング

Kubernetes Horizontal Pod Autoscaler (HPA) は、アプリケーションの伸縮性を管理するための基本的なコンポーネントです。CPU やメモリ使用率に基づいてスケーリングを開始するのが一般的ですが、多くの場合、最新のアプリケーションの真の負荷とパフォーマンス特性を捉えることはできません。効果的なオートスケーリングには、HTTP リクエストレート、メッセージキューの深さ、アクティブなユーザーセッションなど、アプリケーションの需要に直接関連するメトリクスが必要です。
この記事では、Prometheus Adapter を使用してカスタムメトリクスと外部メトリクスで Kubernetes HPA v2 を構成するための、実践的でコード豊富なガイドを提供します。一般的なリソース使用率を超えて、実際のアプリケーションメトリクスに基づいてデプロイメントをスケーリングする方法をデモンストレーションします。
Kubernetes HPA とメトリクスの理解
Horizontal Pod Autoscaler は、観測されたメトリクスに基づいて、デプロイメント、ステートフルセット、またはレプリカセット内の Pod の数を自動的にスケーリングします。
HPA v1 と HPA v2 の比較
- HPA v1: CPU 使用率に基づくスケーリングのみに限定されていました。
- HPA v2: リソースメトリクス(CPU、メモリ)、カスタムメトリクス、外部メトリクスを含む複数のメトリクスをサポートするようになりました。これにより、HPA の柔軟性と多様なワークロードへの適用性が大幅に向上しました。
オートスケーリングのメトリクスタイプ
-
リソースメトリクス:
- 説明: Pod によって報告される CPU およびメモリ使用率。これらは Kubernetes Metrics Server によって収集されます。
- ユースケース: CPU/メモリが負荷と直接相関するアプリケーションの汎用スケーリング。
- 制限: 実際のアプリケーション需要の間接的な指標であることが多いです。CPU バウンドなアプリケーションはうまくスケーリングできるかもしれませんが、I/O バウンドまたはレイテンシに敏感なアプリケーションはそうではないかもしれません。
-
カスタムメトリクス:
- 説明: Pod によって公開されるアプリケーション固有のメトリクス。通常、Prometheus 形式の
/metricsエンドポイントを介して公開されます。これらのメトリクスは、Kubernetes オブジェクト(例:Deployment、Service、Pod)に直接関連付けられています。 - ユースケース: HTTP リクエストレート、アクティブな接続、内部キューサイズなどのアプリケーションレベルの指標に基づくスケーリング。
- 例: Pod あたりの
http_requests_total。
- 説明: Pod によって公開されるアプリケーション固有のメトリクス。通常、Prometheus 形式の
-
外部メトリクス:
- 説明: 特定の Kubernetes オブジェクトに直接関連付けられていない外部システムから発生するメトリクス。これらのメトリクスは、グローバルであるか、共有リソースを表すことが多いです。
- ユースケース: 外部キューの深さ(例:SQS、Kafka トピックラグ)、データベース接続プールの使用率、外部 API 呼び出しレートに基づくスケーリング。
- 例: 単一の Pod に依存しない、SQS キュー内の合計メッセージ数。
HPA の仕組み
HPA コントローラーは、Kubernetes Metrics API(リソースメトリクスの場合)または Custom/External Metrics API(カスタム/外部メトリクスの場合)を継続的にクエリします。構成されたターゲット値と現在のメトリクス観測に基づいて、必要なレプリカ数を計算し、ターゲットワークロード(Deployment、ReplicaSet など)を更新します。
必要なレプリカの計算式は一般的に次のとおりです。
desiredReplicas = ceil[currentReplicas * (currentMetricValue / targetMetricValue)]
アーキテクチャ概要: カスタムメトリクス用 Prometheus Adapter
HPA が Prometheus からカスタムメトリクスと外部メトリクスを消費できるようにするために、Kubernetes エコシステムは Prometheus Adapter を提供しています。
フローは次のとおりです。
- アプリケーション: アプリケーションは、HTTP エンドポイント(
/metrics)を介して Prometheus 形式(例:http_requests_total、queue_messages_total)でメトリクスを公開します。 - Prometheus: Prometheus インスタンスは、ServiceMonitor または PodMonitor を使用して、アプリケーション Pod からこれらのメトリクスをスクレイピングします。
- Prometheus Adapter:
- Kubernetes クラスター内に API サーバーとしてデプロイされます。
custom.metrics.k8s.ioおよびexternal.metrics.k8s.ioAPI を実装します。- HPA コントローラーからのリクエストを、事前定義されたルールに基づいて Prometheus クエリに変換します。
- これらのクエリを Prometheus インスタンスに対して実行します。
- クエリ結果を期待される API 形式で HPA コントローラーに返します。
- HPA コントローラー: Prometheus Adapter によって公開される Custom/External Metrics API をクエリし、アプリケーションデプロイメントのレプリカ数を調整します。
環境設定
このセクションでは、機能する Kubernetes クラスターと kubectl が構成されていることを前提としています。
1. Prometheus Stack のインストール
Prometheus、Grafana、および Prometheus Operator を含む kube-prometheus-stack Helm チャートを使用します。
# Add the Prometheus community Helm repository
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
# Create a namespace for monitoring components
kubectl create namespace monitoring
# Install kube-prometheus-stack
helm install prometheus prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--set prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues=false \
--set prometheus.prometheusSpec.podMonitorSelectorNilUsesHelmValues=false
serviceMonitorSelectorNilUsesHelmValues と podMonitorSelectorNilUsesHelmValues フラグは非常に重要です。これらは、Prometheus が Prometheus と同じ名前空間にデプロイされた ServiceMonitor と PodMonitor、または明示的に検出されるようにラベル付けされた ServiceMonitor と PodMonitor を自動的に検出することを保証します。
2. Prometheus Adapter のインストール
Prometheus Adapter は、専用の Helm チャートを介してインストールされます。重要な部分は、Prometheus メトリクスを Kubernetes のカスタムメトリクスと外部メトリクスにマッピングする方法を定義する config.yaml を構成することです。
# Add the Prometheus Adapter Helm repository
helm repo add k8s-at-home https://k8s-at-home.com/charts/
helm repo update
# Install Prometheus Adapter with custom rules
# We'll define the rules in a values.yaml file
prometheus-adapter-values.yaml ファイルを作成します。
# prometheus-adapter-values.yaml
prometheus:
url: http://prometheus-kube-prometheus-stack-prometheus.monitoring.svc
port: 9090
# Configuration for custom and external metrics rules
config: |
rules:
- seriesQuery: '{__name__=~"^http_requests_total$"}'
resources:
overrides:
kubernetes_namespace: {resource: "namespace"}
kubernetes_pod_name: {resource: "pod"}
name:
matches: "^(.*)_total$"
as: "${1}_per_second"
metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>}[5m])) by (<<.GroupBy>>)`
- seriesQuery: '{__name__="queue_messages_total",kubernetes_namespace!="",kubernetes_pod_name!=""}'
resources:
overrides:
kubernetes_namespace: {resource: "namespace"}
kubernetes_pod_name: {resource: "pod"}
name:
matches: "^(.*)_total$"
as: "${1}_depth"
metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)`
# External metrics example for a global queue depth
- seriesQuery: '{__name__="external_queue_messages_total",queue_name!=""}'
name:
matches: "^external_(.*)_total$"
as: "${1}_depth_external"
metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>}) by (queue_name)`
external: true
次に、この values ファイルを使用して Prometheus Adapter をインストールします。
helm install prometheus-adapter k8s-at-home/prometheus-adapter \
--namespace monitoring \
-f prometheus-adapter-values.yaml
config.yaml ルールの説明:
seriesQuery: このルールによって処理されるメトリクスシリーズを識別する Prometheus ラベルセレクター。resources.overrides: Prometheus ラベル(例:kubernetes_namespace、kubernetes_pod_name)を Kubernetes リソース名にマッピングし、HPA が特定のオブジェクトをターゲットにできるようにします。name.matches/name.as: Prometheus メトリクス名が Kubernetes カスタムメトリクス名に変換される方法を定義します。http_requests_totalの場合、http_requests_per_secondになります。queue_messages_totalの場合、queue_messages_depthになります。metricsQuery: アダプターによって実行される実際の PromQL クエリ。sum(rate(<<.Series>>{<<.LabelMatchers>>}[5m])) by (<<.GroupBy>>): Pod あたりのhttp_requests_total(カウンター)の 5 分間の平均レートを計算します。<<.Series>>、<<.LabelMatchers>>、および<<.GroupBy>>は、HPA リクエストに基づいてアダプターによって置き換えられるテンプレート変数です。sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>): Pod あたりのqueue_messages_total(ゲージ)の合計を計算します。- 外部メトリクスの場合、
external
こちらもおすすめ
- Kubernetes Gateway API本番環境での利用: Ingress-NginxからEnvoyへの移行
- Kubernetes Gateway APIとEnvoy Gateway: Ingress-NGINXから最新のトラフィックルーティングへの移行
- Kubernetesにおけるゼロダウンタイムデプロイメント: Pod Disruption Budget、preStopフック、グレースフルシャットダウン
- KubernetesにおけるLinuxcgroupsv2:PSI、メモリ制限、OOMシールド
知識を確認する(インタラクティブクイズ)
重要なマイクロサービスがリアルタイムの金融取引を処理しています。CPU使用率は常に低いですが、データベースのconnection poolの枯渇により、トランザクション量のピーク時にレイテンシーの急増が発生します。このサービスをオートスケールしてレイテンシーの問題を防ぐために最も効果的なHPAメトリックタイプは何ですか、そしてその理由は何ですか?
ブラウザで動く無料の開発者ツール
AI CLIログの整形、Cron式の作成、JWTの解析、chmod権限の計算をオフラインで実行。
関連記事

PrometheusとGrafanaによるアラートとバーンレートの設計
サービスレベル目標(SLO)とエラーバジェットのために、マルチウィンドウマルチバーンレートPromQLルールを使った本番環境のPrometheusとGrafanaアラートを設計します。
続きを読む
OpenTelemetry CollectorとeBPFを本番環境で活用:コード不要のトレース、メトリクス、Prometheusパイプライン
OpenTelemetry CollectorとeBPFを本番環境で活用し、コード不要のトレース、メトリクス、Prometheusパイプラインを構築するための、本番環境レベルのアーキテクチャとコード例を含む包括的なガイドです。
続きを読む
2026年におけるKubernetesコスト最適化戦略
2026年のKubernetesコスト最適化戦略:right-sizing requests、Karpenterノード統合、Spot instances、OpenCost FinOps metricsを活用してコストを削減しましょう。
続きを読む