mirror of https://github.com/k3s-io/k3s
commit
21455ab776
|
@ -1001,7 +1001,7 @@
|
|||
"targetCPUUtilizationPercentage": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"description": "target average CPU utilization (represented as a percentage of requested CPU) over all the pods;"
|
||||
"description": "target average CPU utilization (represented as a percentage of requested CPU) over all the pods; if not specified the default autoscaling policy will be used."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -41,6 +41,7 @@ type HorizontalPodAutoscalerSpec struct {
|
|||
// upper limit for the number of pods that can be set by the autoscaler; cannot be smaller than MinReplicas.
|
||||
MaxReplicas int32 `json:"maxReplicas"`
|
||||
// target average CPU utilization (represented as a percentage of requested CPU) over all the pods;
|
||||
// if not specified the default autoscaling policy will be used.
|
||||
TargetCPUUtilizationPercentage *int32 `json:"targetCPUUtilizationPercentage,omitempty"`
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ var map_HorizontalPodAutoscalerSpec = map[string]string{
|
|||
"scaleTargetRef": "reference to scaled resource; horizontal pod autoscaler will learn the current resource consumption and will set the desired number of pods by using its Scale subresource.",
|
||||
"minReplicas": "lower limit for the number of pods that can be set by the autoscaler, default 1.",
|
||||
"maxReplicas": "upper limit for the number of pods that can be set by the autoscaler; cannot be smaller than MinReplicas.",
|
||||
"targetCPUUtilizationPercentage": "target average CPU utilization (represented as a percentage of requested CPU) over all the pods;",
|
||||
"targetCPUUtilizationPercentage": "target average CPU utilization (represented as a percentage of requested CPU) over all the pods; if not specified the default autoscaling policy will be used.",
|
||||
}
|
||||
|
||||
func (HorizontalPodAutoscalerSpec) SwaggerDoc() map[string]string {
|
||||
|
|
|
@ -39,6 +39,8 @@ const (
|
|||
// TODO: make it a flag or HPA spec element.
|
||||
tolerance = 0.1
|
||||
|
||||
defaultTargetCPUUtilizationPercentage = 80
|
||||
|
||||
HpaCustomMetricsTargetAnnotationName = "alpha/target.custom-metrics.podautoscaler.kubernetes.io"
|
||||
HpaCustomMetricsStatusAnnotationName = "alpha/status.custom-metrics.podautoscaler.kubernetes.io"
|
||||
)
|
||||
|
@ -76,11 +78,9 @@ func (a *HorizontalController) Run(syncPeriod time.Duration) {
|
|||
}
|
||||
|
||||
func (a *HorizontalController) computeReplicasForCPUUtilization(hpa extensions.HorizontalPodAutoscaler, scale *extensions.Scale) (int, *int, time.Time, error) {
|
||||
if hpa.Spec.CPUUtilization == nil {
|
||||
// If CPUTarget is not specified than we should return some default values.
|
||||
// Since we always take maximum number of replicas from all policies it is safe
|
||||
// to just return 0.
|
||||
return 0, nil, time.Time{}, nil
|
||||
targetUtilization := defaultTargetCPUUtilizationPercentage
|
||||
if hpa.Spec.CPUUtilization != nil {
|
||||
targetUtilization = hpa.Spec.CPUUtilization.TargetPercentage
|
||||
}
|
||||
currentReplicas := scale.Status.Replicas
|
||||
currentUtilization, timestamp, err := a.metricsClient.GetCPUUtilization(hpa.Namespace, scale.Status.Selector)
|
||||
|
@ -91,7 +91,7 @@ func (a *HorizontalController) computeReplicasForCPUUtilization(hpa extensions.H
|
|||
return 0, nil, time.Time{}, fmt.Errorf("failed to get cpu utilization: %v", err)
|
||||
}
|
||||
|
||||
usageRatio := float64(*currentUtilization) / float64(hpa.Spec.CPUUtilization.TargetPercentage)
|
||||
usageRatio := float64(*currentUtilization) / float64(targetUtilization)
|
||||
if math.Abs(1.0-usageRatio) > tolerance {
|
||||
return int(math.Ceil(usageRatio * float64(currentReplicas))), currentUtilization, timestamp, nil
|
||||
} else {
|
||||
|
@ -192,8 +192,9 @@ func (a *HorizontalController) reconcileAutoscaler(hpa extensions.HorizontalPodA
|
|||
desiredReplicas = 1
|
||||
} else {
|
||||
// All basic scenarios covered, the state should be sane, lets use metrics.
|
||||
cmAnnotation, cmAnnotationFound := hpa.Annotations[HpaCustomMetricsTargetAnnotationName]
|
||||
|
||||
if hpa.Spec.CPUUtilization != nil {
|
||||
if hpa.Spec.CPUUtilization != nil || !cmAnnotationFound {
|
||||
cpuDesiredReplicas, cpuCurrentUtilization, cpuTimestamp, err = a.computeReplicasForCPUUtilization(hpa, scale)
|
||||
if err != nil {
|
||||
a.updateCurrentReplicasInStatus(hpa, currentReplicas)
|
||||
|
@ -202,7 +203,7 @@ func (a *HorizontalController) reconcileAutoscaler(hpa extensions.HorizontalPodA
|
|||
}
|
||||
}
|
||||
|
||||
if cmAnnotation, cmAnnotationFound := hpa.Annotations[HpaCustomMetricsTargetAnnotationName]; cmAnnotationFound {
|
||||
if cmAnnotationFound {
|
||||
cmDesiredReplicas, cmStatus, cmTimestamp, err = a.computeReplicasForCustomMetrics(hpa, scale, cmAnnotation)
|
||||
if err != nil {
|
||||
a.updateCurrentReplicasInStatus(hpa, currentReplicas)
|
||||
|
|
|
@ -257,6 +257,19 @@ func (tc *testCase) runTest(t *testing.T) {
|
|||
tc.verifyResults(t)
|
||||
}
|
||||
|
||||
func TestDefaultScaleUp(t *testing.T) {
|
||||
tc := testCase{
|
||||
minReplicas: 2,
|
||||
maxReplicas: 6,
|
||||
initialReplicas: 4,
|
||||
desiredReplicas: 5,
|
||||
verifyCPUCurrent: true,
|
||||
reportedLevels: []uint64{900, 950, 950, 1000},
|
||||
reportedCPURequests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
}
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestScaleUp(t *testing.T) {
|
||||
tc := testCase{
|
||||
minReplicas: 2,
|
||||
|
@ -290,6 +303,19 @@ func TestScaleUpCM(t *testing.T) {
|
|||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestDefaultScaleDown(t *testing.T) {
|
||||
tc := testCase{
|
||||
minReplicas: 2,
|
||||
maxReplicas: 6,
|
||||
initialReplicas: 5,
|
||||
desiredReplicas: 4,
|
||||
verifyCPUCurrent: true,
|
||||
reportedLevels: []uint64{400, 500, 600, 700, 800},
|
||||
reportedCPURequests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")},
|
||||
}
|
||||
tc.runTest(t)
|
||||
}
|
||||
|
||||
func TestScaleDown(t *testing.T) {
|
||||
tc := testCase{
|
||||
minReplicas: 2,
|
||||
|
|
Loading…
Reference in New Issue