Merge pull request #22171 from piosz/hpa-default

Added default cpu target for HPA
pull/6/head
Jeff Lowdermilk 2016-03-02 16:07:24 -08:00
commit 21455ab776
5 changed files with 38 additions and 10 deletions

View File

@ -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."
}
}
},

View File

@ -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"`
}

View File

@ -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 {

View File

@ -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)

View File

@ -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,