カスタムメトリクスはCPUやRAMベースの自動スケーリングよりも正確かつ有用な傾向にあります。しかし、カスタムメトリクスや外部メトリクスを使ったスケーリングはまだ未成熟な領域で、改善の余地が残されています。

Kubernetesは絶えず進化し続けるプラットフォームです。だからこそ、しばらく触れていなかった機能を私は折に触れて見直すようにしています。最近Horizontal Pod Autoscaler(HPA)で同じ作業をしたところ、知っておくと役立つにもかかわらずドキュメントが乏しく分かりにくい機能や制約がいくつかあることに気づきました。
注意したい「落とし穴」は、HPAの apiVersion: autoscaling/v2 という表記が、HPAを成熟したAPIだと印象づけてしまうことです。実際には、カスタムメトリクスや外部メトリクスを用いたスケーリングはまだ未成熟な領域で、改善の余地があります。カスタムメトリクスはCPU・RAMベースの自動スケーリングよりも正確で有用な傾向があるだけに、これは惜しい状況だと言えます。
本記事では、カスタムメトリクスがスケーラビリティを向上させるユースケースと、それを実現するためのツールを見ていきましょう。
ユースケース
カスタムメトリクスをHPAが扱える形式で公開すれば、HPAは複数のメトリクスを基にスケーリングできるようになります。Kubernetesのドキュメントには簡単な例が掲載されており、CPU使用率、秒間パケット数、秒間リクエスト数を基にスケールするHPAが構成されています。各メトリクスがそれぞれ異なる希望レプリカ数(例:3、5、8)を提示し、HPAはその中で最大の値にスケールするという仕組みです。
- Kube Prometheus Stack Helm chartは、カスタムメトリクスを提供するソリューションとして最も普及しており、サポートも充実したクラウド非依存の選択肢の一つです。スタックには複数のアプリが含まれ、その中のPrometheus Adapter for Kubernetes Metrics APIsが、PrometheusメトリクスをHPAが解釈・利用できる形式に変換して公開する役割を担います。
秒間リクエスト数やリクエスト時間/レイテンシは、Webサービスのスケーリングに適した信頼性の高いメトリクスです。
処理対象のオブジェクトがアップロードされるキューやストレージバケットを使うアーキテクチャでは、検出されたアイテム数を基に、それらを処理するサービスを自動スケールさせることもできます。
- Kubernetes Event Driven Autoscaling(KEDA)には、各種キュー(Pub/Subなど)やオブジェクトストレージバケットと連携できるscalerが用意されています。さらに、メトリクスデータベース、ログ、SQL、NoSQLデータベースへのクエリ結果からメトリクスを生成することも可能です。
可変の最小レプリカ数は、トラフィックスパイクへの対応力とコスト抑制を両立させるのに役立ちます。レプリカの起動が遅いアプリや、急激なトラフィックスパイクが発生するアプリを運用した経験があれば、サービス品質を保つために最小レプリカ数を増やす必要に迫られた場面が思い当たるはずです。
- 例えば、1レプリカで100 reqs/secを処理できるなら、100 reqs/secを超えるとエラーや遅延が発生するのを避けるため、50 reqs/secで自動スケールするよう設定できます。最小レプリカ数を10にしておけば、最小2の場合よりもスパイクへの耐性が高まります。
- この方法の難点はコストが増えることですが、アプリのトラフィックスパイクはある程度予測できるケースも多いはずです。たとえば、営業時間外は最小2、スパイクが多い時間帯は最小10、それ以外は最小5といった運用が考えられます。
- KEDAには最近、複数のメトリクスをユーザー定義の数式に組み込んで複合メトリクスを作成するオプションがマージされました。これにより、希望レプリカ数 = 自動スケーリングメトリクス + cronベースの希望レプリカ数 のような式で、可変の最小レプリカ数を実現できます。
Kubernetes上で動作するサーバーレスおよびFaaSプラットフォーム。たとえば次のようなものです。
- keda.sh
- knative.dev
- openfaas.com
制約とその影響
ここまでの内容は魅力的に映りますし、実現するためのツールも揃っています。それでは、HPAを真に優れたものにすることを阻んでいる厄介な制約とは何でしょうか。
次に挙げる制約が、UX(ユーザーエクスペリエンス)に大きな影響を及ぼしています:https://github.com/kubernetes-sigs/custom-metrics-apiserver/issues/70
制約を一言でまとめると、「カスタムメトリクスサーバーは1つしか存在できない」ということです。普及しているkube-prometheus-stackをデフォルト設定でインストールすると、Prometheus Adapterが導入されます。すると、KEDAのkeda-operator-metrics-apiserver、KnativeのKnative Pod Autoscaler、OpenFaaS Proのオートスケーラー、Datadogのオートスケーラーなどを併用できなくなります。いずれもカスタムメトリクスサーバーをホストする仕組みで動いているからです。KEDAがフィーチャークリープの代名詞かと思うほど大量のscalerを抱えているのも、これが一因ではないかと考えています。KEDAには60以上のscalerがあり、PrometheusやDatadog向けのものも含まれます。一見すると不可解ですが、その一部がこの制約を回避するために存在していると気づけば腑に落ちるはずです。
では、なぜこの制約がUXを損なうのでしょうか。まずは、優れたUXとはどのようなものかを例で示してみましょう。
Kube PrometheusスタックとHelmが人気を集めているのには理由があります。優れたUXを提供しており、その秘訣の一つは「設定より規約(convention over configuration)」というコンセプトに従っている点です。妥当なデフォルト値と、規約に沿って数百から数千のYAMLオブジェクトをあらかじめ連携させたデフォルト構成を提供することで、インストール直後から多くの機能がそのまま動くターンキーなUXを実現しているのです。
こうした魔法のようなUXを成立させる前提条件は、他のものと衝突しないネームスペースを占有できることです。これにより、自分のネームスペース内で規約を確立し、手作業の設定なしに各要素を事前連携させることができます。
この共通課題に対しては複数のPoC(概念実証)が試みられ、解決のためのKubernetes Enhancement Proposalまで作成されましたが、立ち消えとなりました。本記事がこの問題に光を当て、カスタムメトリクススケーリングAPIへの関心が再び高まるきっかけになれば幸いです。