Closed oomichi closed 1 year ago
The code: pkg/apis/autoscaling/types.go
328 // MetricTarget defines the target value, average value, or average utilization of a specific metric
329 type MetricTarget struct {
330 // Type represents whether the metric type is Utilization, Value, or AverageValue
331 Type MetricTargetType
332 // Value is the target value of the metric (as a quantity).
333 Value *resource.Quantity
334 // TargetAverageValue is the target value of the average of the
335 // metric across all relevant pods (as a quantity)
336 AverageValue *resource.Quantity
337
338 // AverageUtilization is the target value of the average of the
339 // resource metric across all relevant pods, represented as a percentage of
340 // the requested value of the resource for the pods.
341 // Currently only valid for Resource metric source type
342 AverageUtilization *int32
343 }
344
345 // MetricTargetType specifies the type of metric being targeted, and should be either
346 // "Value", "AverageValue", or "Utilization"
347 type MetricTargetType string
348
349 const (
350 // UtilizationMetricType is a possible value for MetricTarget.Type.
351 UtilizationMetricType MetricTargetType = "Utilization"
352 // ValueMetricType is a possible value for MetricTarget.Type.
353 ValueMetricType MetricTargetType = "Value"
354 // AverageValueMetricType is a possible value for MetricTarget.Type.
355 AverageValueMetricType MetricTargetType = "AverageValue"
356 )
autoscaling v2 API ではユーザに Value
もしくは AverageValue
を指定することを許可している。
そのAPIにおいて、その二つの違いは Pods 数によってメトリックの値が割り算されるかどうかだけだ。
しかし実装面おいて、それとは少し異なる動作を行う。
Value
が与えられた場合、レプリカ数は GetObjectMetricReplicas
もしくは GetExternalMetricReplicas
関数によって計算される。
それらの関数では target value によってメトリック値が割り算されることによって usage ratio が計算される。
そして、現在 Ready な Pod 数を usage ratio によって掛け算することによって、必要となるレプリカ数が決定される。
usageRatio := float64(utilization) / float64(targetUtilization)
replicaCount = int32(math.Ceil(usageRatio * float64(readyPodCount)))
AverageValue
が与えられた場合、レプリカ数は GetObjectPerPodMetricReplicas
もしくは GetExternalPerPodMetricReplicas
関数によって計算される。
それらの関数では、最初に target value を Pod 数で掛け算し、そして metric value を割り算する。
これは想定どおりだ。
しかし、必要となるレプリカ数を計算する際、usage ratio もしくは現在のPod 数は考慮に入れない。
そのかわり、PerPod
関数内で target value のみによってメトリック値を割り算するだけだ。
replicaCount = int32(math.Ceil(float64(utilization) / float64(targetAverageUtilization)))
Value
を指定することでユーザはメトリックにおける特定の値を(オートスケールの)ターゲットにできる。
オートスケーラーは feedback loop を実装しており、指定した値になるように Pod 数を増やそうとする。
これにより、Pod 数を増やすことになる。もしもメトリック値が指定した値にならない場合、Pod 数をさらに増やそうとする。
しかしながら AverageValue
を指定することでユーザはメトリック値をそれぞれの Pod にアサインし pinning する。
feedback loop は作られない。オートスケーラーは Pod 毎のメトリック値が指定した値になるよう Pod 数を reconcile する。
この振る舞い上の違いは微細であり、ドキュメントに記載されていない。
この振る舞いは仕様だ。なぜならば大半の例では Pod 毎の理想的なメッセージが指定されている。
例えばあなたのアプリケーションが hosted queue service からタスクを進める場合、あなたは以下のセクションをあなたの HPA 設定マニュフェストに追加することで、1つの worker あたり30のタスクをやらせることができる。
公式ドキュメント、types に関するコメント、そして実装においてこの振る舞い上の違いを明確に記載するべきだ。
AverageValue
は feedback loop による良くできた実装になる可能性がある。
現状、feedback loop によって実装されていないことを説明すべきだろう。
HPA 設定において下記の設定は成功
type: AverageValue
averageValue: 500m
しかし下記は失敗
type: Utilization
averageUtilization: 50
エラーメッセージは「Required value: must specify a positive target averageValue」
上記のエラーメッセージは HPA マニフェストで spec.Pods を指定したときに実行されるチェックで出力されるもの。
一方、公式ドキュメントの type: Utilization のサンプルでは spec.Pods は含まれていない。 まずは使用中の HPA マニフェストの内容を確認の上、spec.Pods の部分が削除可能か検討する。 https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/#autoscaling-on-multiple-metrics-and-custom-metrics
元々の疑問については、マニフェストの書き方が間違えていただけに見える。
We sould be able to specify Utilization, Value and AverageValue for MetricTarget, but we can specify AverageValue only.