feat: add fallback support for value metric type #6655
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Since the constraint on having fallback only for
AverageValue
seems to me kinda unwarranted, it's here relaxed a bit, and can be removed altogether if we opt for another implementation.The constraint now becomes that the
scaleTargetRef
object has a field.status.readyReplicas
that its controller updates with the number of ready replicas, so that we can directly use that. This is de facto the case withDeployments
/StatefulSets
/Replicasets
/ArgoRollouts
.We can then generically fetch the object as
unstructured
and access the value of the field to divide by it. A brief math illustration starting with the HPA's equationdesiredReplicas = ceil [currentReplicas * (currentMetricValue/desiredMetricValue) ]
By passing
currentMetricValue = desiredMetricValue * fallbackReplicas / currentReplicas
We end up with
desiredReplicas = ceil [currentReplicas * (( desiredMetricValue * fallbackReplicas / currentReplicas )/desiredMetricValue) ]
desiredReplicas = ceil [currentReplicas * (fallbackReplicas / currentReplicas ) ] = ceil [fallbackReplicas] = fallbackReplicas
Emphasis: currentReplicas in HPA's equation is the number of ready replicas.
I preferred this approach to the other one (which would remove the
.status.readyReplicas
field constraint) which is manually counting the number of ready pods (similar to what HPA does here), since it'd be quite involved. If it seems a better approach to you, I can implement it.For full clarity, a problematic nit with this: is that we're dependent on the object's controller updating the
.status.readyReplicas
in a timely manner.If there had been a lag, then the
currentReplicas
the HPA multiplies by (which it gets by manually counting pods) would deviate from thecurrentReplicas
value we divide by.If ours is less, then we'd scale higher than
fallbackReplicas
for a brief while; if ours is more, then we'd scale less thanfallbackReplicas
. Either way we should eventually stabilize atfallbackReplicas
exactly.Final unrelated small change for correctness sake (that I think should be fixed regardless of this PR), the line
Value: *resource.NewMilliQuantity(normalisationValue*1000*replicas, resource.DecimalSI),
has been changed to
Value: *resource.NewMilliQuantity(int64(normalisationValue*1000*replicas), resource.DecimalSI),
with
normalizationValue
beingfloat64
instead of int.This prevents early casting to int, which would discard fractions in
normalizationValue
early on, that would have been already rounded when multiplying by 1000 below.Imagine
normalisationValue=2.5
andfallbackReplicas=10
, previously,Value = 2*1000*10 = 20000
.Now,
Value = 2.5*1000*10 = int64(25000.0) = 2500
.Obviously the former will cause HPA to not scale to fallbackReplicas exactly.
For the unchecked list item, if this looks good, I'll open a PR to the docs repo.
Checklist