- HPAの理解のためにHorizontal Pod Autoscaler Walkthroughを翻訳しました。
- 2018,10,09(ver1.12.1)現在の内容の素人翻訳なので間違いなどあると思います。
- 原文と対応させたいので各セクションの見出しや用語は原文ママにしています。
Horizontal Pod Autoscaler
Horizontal Pod Autoscaler
(以下HPA
)はReplication Controller
, Deployment
, Replica Set
のPod数をCPU使用率(もしくは他のアプリケーションから提供されるカスタムメトリクス)に基づいて自動的にスケールします。
ただし、Deamon Sets
のようなリソースは対象外であることは留意してください。
HPA
はk8s Apiリソースとコントローラとして実装されています。
それはコントローラの動作を定義します。
コントローラはユーザによって設定された平均CPU使用率にマッチするように定期的にReplication Controller
, Deployment
内のレプリカ数を調整します。
- How does the Horizontal Pod Autoscaler work?
- API Object
- Support for Horizontal Pod Autoscaler in kubectl
- Autoscaling during rolling update
- Support for cooldown/delay
- Support for multiple metrics
- Support for custom metrics
- Support for metrics APIs
- What's next
How does the Horizontal Pod Autoscaler work?

HPA
はコントローラーマネージャーの--horizontal-pod-autoscaler-sync-period
フラグ(デフォルト30秒)でコントロールされる期間ごとに繰り返しコントロールするものとして実装されています。
それぞれの期間、コントローラマネージャーはそれぞれのHPA
に定義された指定されたメトリクスに対してリソースの利用量を問い合わせます。
コントローラマネージャーはリソースのメトリクスAPI(podごとのリソースメトリクス)かカスタムメトリクス(他のメトリクス)どちらかからメトリクスを獲得します。
-
pod単位のリソースメトリクス(CPUなど)の場合、コントローラは
HPA
で指定された各podのメトリクスAPIからメトリックをフェッチします。次に目標使用率が設定されている場合、コントローラは各podのリソース要求に対して目標利用率がどういうパーセンテージなのかを計算します。
ターゲットの生の値がセットされている場合、直接生のメトリクス値が使用されます。
次にコントローラは利用率か生の値(指定されたターゲットのタイプに応じた)の平均値を指定された全てのpodから取得します。
そして要求レプリカ数をスケールするための比率を生成します。
要求リソースがpodのrequest
にない場合、podのCPU使用率は定義されず、オートスケーラはメトリックに対して何もしません。
オートスケーリングのアルゴリズムの詳細はalgorithm detailsをみてください。
-
podごとのカスタムメトリックの場合、リソースメトリックと同様に動作しますが、利用率を使わずに生の値を使います。
-
オブジェクトメトリックと外部メトリックでは、まず1つのメトリックをフェッチします。このメトリックは目標値と比較されて前述の比率を生成します。
autoscaling/v2beta2
では比較される前にpod数で分割した値にするということをオプションで選択できます。
HPA
は普通は集計API(metrics.k8s.io
, custom.metrics.k8s.io
, external.metrics.k8s.io
)からメトリックをフェッチします。
metrics.k8s.io
APIは各nodeごとにローンチされているはずのmetrics-server
から提供されています。
metrics-serverの説明はみておいてください。
HPA
はHeapster
から直接メトリックを取ることもできます。
HPA
が直接Heapster
からメトリックを取得するのはk8s 1.11から非推奨になりました
metrics API
のサポートについてもっと知りたい場合はここ参照
多分GKEとかマネージドだったら特に気にしなくていい情報だと思われ
オートスケーラはScale sub resource
を使ってスケール可能なコントローラ(RC
,Deployment
, RS
)にアクセスします。
Scale
はレプリカ数をセットすることと、各レプリカの状態を調査することを許可します。
Scale sub-resource
についてはここを参照ください。
Algorithm Details
最も基本的な観点として、HPA
コントローラは目標値と、現在のメトリック値の間の比率で動いています。
desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )]
(例)
現在のメトリックが200mで、目標値が100mだった場合、200/100 == 2.0
なのでレプリカ数は2倍になります。
現在値が50mだったら50/100 == 0.5
なので半分にします。
比率が1.0に十分に近かったら、スケーリングはされません。
このしきい値(耐性)は--horizontal-pod-autoscaler-tolerance
フラグで設定できます。デフォルトは0.1
です。
つまりデフォルトだと current/desire == 1.1の場合はスケールしないということ*
targetAverageValue
かtargetAverageUtilization
が指定されている場合、currentMetricValue
はHPA
で指定された全てのPodのメトリックの平均を取得して計算されます。
削除タイムスタンプがついたpod(シャットダウンされているプロセス中のpod)と失敗してるpodは全て削除されます。
メトリックが無いpodも存在します。そのpodは一旦置いておかれます。最終的にスケーリングするpod数の最終調整時の辻褄合わせに使用されます。
CPUでスケーリングする場合、まだpodが準備段階(初期化中)かpodの最新メトリックポイント(メトリックするタイミング?)が準備完了になった時点でとり置かれます。
技術的な制約により、特定のCPUメトリクスを脇に取り置くかどうか決めるときは、HPA
コントローラはpodが準備完了になる最初の時間を正確に決めることはできません。
その代わりに、ポッドは、まだ準備ができていない場合は「準備ができていない」とみなされ、開始されてから短い設定可能な時間内に未使用に移行します。
この設定可能な時間
は--horizontal-pod-autoscaler-initial-readiness-delay
フラグで設定され、デフォルトは30秒です。ポッドが準備完了状態になると、開始されてから設定可能な時間が長くなると、ポッドが最初になる準備が整ったとみなされます。この値は--horizontal-pod-autoscaler-cpu-initialization-period
フラグで設定され、デフォルトは5分です。
currentMetricValue / desiredMetricValue
ベーススケールはそのあと、脇にとり置かれたり、前述のように削除されたpodを使用して計算されます。
取得できなかったメトリックがある場合、スケールダウンの時は100%、スケールアップ(スケールアウトのが正しいのでは?)の場合は0%を消費する仮定をし、より保守的に平均値の消費量を計算し直します。
これにより潜在的なスケールの振れ幅を小さくします。
さらに、準備未完了のpodがあり、欠落したメトリックや準備未完了のpodがある事実を考慮せずにスケールアップしてしまっている場合、保守的に準備未完了のpodは目標メトリックに対して0%消費していると想定し、さらにスケールの振れ幅を小さくします。
欠落したメトリック、準備未完了のpodを判明させた後、使用率を再計算します。
そうしてできた新しい比率が先ほどのスケールの決定事項を覆したり、しきい値(耐性)の範囲内である場合は、スケールをスキップします。
言い換えれば、新しい比率を使うということです。
Note: 新しい使用率が使われても、平均利用値のオリジナル値は準備未完了pod、欠落メトリックを考慮しない状態でHPAのステータスを通して報告されます。
HPAで複数のメトリックが指定されている場合、各メトリックの計算がされ、一番目標レプリカ数の大きいものが採用されます。
もし、それらのメトリックをレプリカ数に変換できない場合(例: メトリックAPIからエラーが返された場合)はスケールがスキップされます。
最後に(ようやく)HPAがスケールをする直前に、スケールのリコメンデーションが記録されます。
(リコメンデーションは複数溜まっていて)HPAコントローラは設定可能なウィンドウの最高推奨値を選択し、そのウィンドウ内の全てのリコメンデーションを考慮します。
最高推奨は--horizontal-pod-autoscaler-downscale-stabilization-window
フラグで設定できます。デフォルトは5分です。
これにより、スケールダウンが徐々に発生し、急激なメトリック変化の影響によるインパクトを抑えます。
API Object
HPAはk8sのautoscaling
API groupのAPIリソースです。
現在のstableバージョンautoscaling/v1
ではCPUのオートスケールのみサポートします。
autoscaling/v2beta2
ではmemory, custom metricsを選択することが可能です。
autoscaling/v2beta2
の記述をautoscaling/v1
で動かす場合は単に注釈として保存されます。
詳細はHorizontalPodAutoscaler Objectを参照ください。
Support for Horizontal Pod Autoscaler in kubectl
HPA
をはじめとして全てのAPIリソースはkubectl
でサポートされます。
kubectl create
コマンドで新しいオートスケーラーを作ることができます。
kubectl get hpa
でリスト表示、kubectl describe hpa
で詳細を取得できます。
kubectl delete hpa
で削除できます。
加えてkubectl autoscale
コマンドで簡単にHPAを作成できます。
おもむろにkubectl autoscale rs foo --min=2 --max=5 --cpu-percent=80
を実行すれば、fooというRSに目標CPU使用率、2〜5のレプリカ数でHPAを設定することができます。
詳細はここを見てください。
Autoscaling during rolling update
現在、k8sはReplication Controllerを直に管理するか、RSを管理するDeploymentオブジェクトを使用してrolling updateを実行することができます。
HPAは後者のアプローチをサポートします。
つまり、HPAはDeploymentにバインドされ、Deploymentはそれが持つReplica Setのサイズを設定します。
HPAはReplication Controllerの直接操作のrolling updateでは動作しません。
つまり、Replication ControllerはHPAにバインドされないのでkubectl rolling-update
を使ってください。
上記のようにReplication Controllerのrolling-updateでHPAが動かないのは、rolling-updateが新しいReplication Controllerを作るという挙動によるものです。HPAは新しいReplication Controllerにバインドされません。
Support for cooldown/delay
HPAを使ってレプリカのグループのスケールを管理するとき、動的に発生するメトリック評価値によって頻繁にレプリカ数の増減が起こり続く可能性があります。
これはthrashing
と呼ばれます。
v1.6〜では、kube-controller-manager
コンポーネントに用意されているフラグとして公開されているHPAグローバル設定をチューニングすることでこの問題を緩和できます。
v1.12〜では、新しいアルゴリズムによりアップスケール遅延をする必要がなくなりました。
--horizontal-pod-autoscaler-downscale-delay
このオプションは現在のスケーリング処理が完了してから他のダウンスケール処理をはじめるのに待つ期間を設定するものです。
Note: これらのパラメタをチューニングする際はクラスタのオペレータ担当者は発生しうる結果に注意しないといけません。
クールダウンの遅延が長すぎればワークロードの変化にHPAが反応しなくなり、逆に短すぎるとスラッシングが発生します。
Support for multiple metrics
k8sはmultiple metrics
によるスケーリングをサポートしています。
autoscaling/v2beta2
APIバージョンを使い、HPAに複数のメトリックを設定し、それに則ってスケールすることができます。
HPAコントローラは各メトリックを評価し、そのメトリックに則った新しいスケーリングを提案します。
一番大きいレプリカ数の提案が採用されます。
Support for custom metrics
k8s1.2でalphaサポートされました。特別なannotations
を使うことでアプリケーション固有のメトリックに基づきスケーリングすることができるようになりました。
ただし、それらのannotations
はk8s1.6でオートスケーリングapiから廃止されました。
従来の方法でのカスタムメトリックの収集はまだ可能です。
ただし、HPAでは使えません。そして、前者のどのカスタムメトリックかを指定するアノテーションをHPAでは使えなくなりました。
k8s1.6はHPAでカスタムメトリックを使うためのサポートを追加しました。
autoscaling/v2beta2
apiを使ってカスタムメトリクスをHPAに追加できます。
k8sは最適なメトリックを使うために新しいカスタムメトリックapi
詳しくはSupport for metrics APIsを参照すること
Support for metrics APIs
デフォルトでは、HPAは一連のapiメトリックapiを検索します。
それらのapiを検索するために、クラスターの管理担当者は下記をしておく必要があります。
- apiの集約レイヤが有効であること
- 対応するapiが登録済みであること
-
metrics.k8s.io
: 通常、metric-server
により提供されています。クラスターのアドオンとしてローンチされます。 -
custom.metrics.k8s.io
: "アダプター"apiサーバーによって提供されます。アダプターはメトリックのソリューションベンダーによって提供されます。
メトリックのパイプラインをチェックするか、よく知られたソリューションをご活用ください。 -
external.metrics.k8s.io
: 前述のカスタムメトリクスのアダプターによって提供されると思います。
-
-
--horizontal-pod-autoscaler-use-rest-clients
はtrueもしくはセットされていない状態です。このフラグによりHeapsterベースのオートスケーリングに切り替わりますが、現在は非推奨です。
(metrics-serverサポートにより?)
What's next
- Design documentation: Horizontal Pod Autoscaling.
- kubectl autoscale command: kubectl autoscale.
- Usage example of Horizontal Pod Autoscaler.