-
Notifications
You must be signed in to change notification settings - Fork 404
/
scaling.go
131 lines (101 loc) · 3.92 KB
/
scaling.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package serverless
import (
"context"
"fmt"
serverlessv1alpha2 "github.com/kyma-project/kyma/components/function-controller/pkg/apis/serverless/v1alpha2"
autoscalingv1 "k8s.io/api/autoscaling/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
apilabels "k8s.io/apimachinery/pkg/labels"
)
func stateFnCheckScaling(ctx context.Context, r *reconciler, s *systemState) stateFn {
namespace := s.instance.GetNamespace()
labels := s.internalFunctionLabels()
r.err = r.client.ListByLabel(ctx, namespace, labels, &s.hpas)
if r.err != nil {
return nil
}
if !isScalingEnabled(&s.instance) {
return stateFnCheckReplicas(ctx, r, s)
}
return stateFnCheckHPA(ctx, r, s)
}
func stateFnCheckReplicas(ctx context.Context, r *reconciler, s *systemState) stateFn {
numHpa := len(s.hpas.Items)
if numHpa > 0 {
return stateFnDeleteAllHorizontalPodAutoscalers
}
return stateFnUpdateDeploymentStatus
}
func stateFnCheckHPA(ctx context.Context, r *reconciler, s *systemState) stateFn {
if !s.hpaEqual(r.cfg.fn.TargetCPUUtilizationPercentage) {
return stateFnUpdateDeploymentStatus
}
numHpa := len(s.hpas.Items)
expectedHPA := s.buildHorizontalPodAutoscaler(r.cfg.fn.TargetCPUUtilizationPercentage)
if numHpa == 0 {
if !equalInt32Pointer(s.instance.Spec.ScaleConfig.MinReplicas, s.instance.Spec.ScaleConfig.MaxReplicas) {
return buildStateFnCreateHorizontalPodAutoscaler(expectedHPA)
}
return nil
}
if numHpa > 1 {
return stateFnDeleteAllHorizontalPodAutoscalers
}
if numHpa == 1 && !isScalingEnabled(&s.instance) {
// this case is when we previously created HPA with maxReplicas > minReplicas, but now user changed
// function spec and NOW maxReplicas == minReplicas, so hpa is not needed anymore
return stateFnDeleteAllHorizontalPodAutoscalers
}
if !s.equalHorizontalPodAutoscalers(expectedHPA) {
return buildStateFnUpdateHorizontalPodAutoscaler(expectedHPA)
}
return nil
}
func buildStateFnCreateHorizontalPodAutoscaler(hpa autoscalingv1.HorizontalPodAutoscaler) stateFn {
return func(ctx context.Context, r *reconciler, s *systemState) stateFn {
r.log.Info("Creating HorizontalPodAutoscaler")
r.err = r.client.CreateWithReference(ctx, &s.instance, &hpa)
if r.err != nil {
return nil
}
condition := serverlessv1alpha2.Condition{
Type: serverlessv1alpha2.ConditionRunning,
Status: corev1.ConditionUnknown,
LastTransitionTime: metav1.Now(),
Reason: serverlessv1alpha2.ConditionReasonHorizontalPodAutoscalerCreated,
Message: fmt.Sprintf("HorizontalPodAutoscaler %s created", hpa.GetName()),
}
return buildStatusUpdateStateFnWithCondition(condition)
}
}
func stateFnDeleteAllHorizontalPodAutoscalers(ctx context.Context, r *reconciler, s *systemState) stateFn {
r.log.Info("Deleting all HorizontalPodAutoscalers attached to function")
selector := apilabels.SelectorFromSet(s.internalFunctionLabels())
r.err = r.client.DeleteAllBySelector(ctx, &autoscalingv1.HorizontalPodAutoscaler{}, s.instance.GetNamespace(), selector)
if r.err != nil {
return nil
}
return nil
}
func buildStateFnUpdateHorizontalPodAutoscaler(expectd autoscalingv1.HorizontalPodAutoscaler) stateFn {
return func(ctx context.Context, r *reconciler, s *systemState) stateFn {
hpa := &s.hpas.Items[0]
hpa.Spec = expectd.Spec
hpa.Labels = expectd.GetLabels()
hpaName := hpa.GetName()
r.log.Info(fmt.Sprintf("Updating HorizontalPodAutoscaler %s", hpaName))
r.err = r.client.Update(ctx, hpa)
if r.err != nil {
return nil
}
condition := serverlessv1alpha2.Condition{
Type: serverlessv1alpha2.ConditionRunning,
Status: corev1.ConditionUnknown,
LastTransitionTime: metav1.Now(),
Reason: serverlessv1alpha2.ConditionReasonHorizontalPodAutoscalerUpdated,
Message: fmt.Sprintf("HorizontalPodAutoscaler %s updated", hpaName),
}
return buildStatusUpdateStateFnWithCondition(condition)
}
}