Skip to content

Commit 83192a7

Browse files
authored
Merge pull request #4329 from jbartosik/multi-recommender-kep-1
Adjust KEP for customized recommender
2 parents 9cb8193 + 23902ca commit 83192a7

File tree

1 file changed

+73
-41
lines changed
  • vertical-pod-autoscaler/enhancements/3919-customized-recommender-vpa

1 file changed

+73
-41
lines changed

vertical-pod-autoscaler/enhancements/3919-customized-recommender-vpa/README.md

Lines changed: 73 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@
2323

2424
Today, the current VPA recommends CPU/Mem requests based on one recommender,
2525
which recommends the future requests based on the historical usage observed in a
26-
rolling time window. As there is no universal recommendation policy that applies to all
27-
types of workload, this KEP suggests supporting multiple customized recommenders in VPA.
28-
Thus, users can run different recommenders for different workloads, as they may exhibit
29-
very distinct resource usage behaviors.
26+
rolling time window. As there is no universal recommendation policy that applies
27+
to all types of workloads, this KEP suggests supporting multiple customized
28+
recommenders in VPA. Thus, users can run different recommenders for different
29+
workloads, as they may exhibit very distinct resource usage behaviors.
3030

3131
## Motivation
3232

@@ -48,6 +48,7 @@ behaviors for workloads and applying different algorithms to improve resource ut
4848

4949
- Allow the VPA object to specify a customized recommender to use.
5050
- Allow the VPA object to use the default recommender when no recommender is specified.
51+
- Don't block future changes that will allow a VPA object to use multiple recommenders at the same time.
5152

5253
### Non-Goals
5354

@@ -84,9 +85,12 @@ VPA adopts a reactive approach so a more proactive recommender is needed for the
8485

8586
### Implementation Details
8687

87-
The following describes the details of implementing a first-citizen approach to support the customized
88-
recommender. Namely, a dedicated field `recommenderName` is added to the VPA crd definition in
89-
`deploy/vpa-v1.crd.yaml`.
88+
The following describes the details of implementing a first-citizen approach to
89+
support the customized recommender. Namely, a dedicated field `recommenders` is
90+
added to the VPA crd definition in `deploy/vpa-v1.crd.yaml`. We identify
91+
recommender to use with a struct containing name of the recommender rather than
92+
using a plain string to identify the recommender. This will allow us to pass
93+
parameters to recommenders if we need to do that in the future.
9094

9195
```yaml
9296
validation:
@@ -98,18 +102,32 @@ validation:
98102
type: object
99103
required: []
100104
properties:
101-
recommenderName:
102-
type: string
105+
recommenders:
106+
type: array
107+
items:
108+
properties:
109+
name:
110+
description: Name of the recommmender
111+
type: string
112+
type: object
103113
targetRef:
104114
type: object
105115
updatePolicy:
106116
type: object
107117
```
108118
109119
Correspondingly, the `VerticalPodAutoscalerSpec` in `pkg/apis/autoscaling.k8s.io/v1/types.go`
110-
should be updated to include the `recommenderName` field.
120+
should be updated to include the `recommenders` field.
111121

112122
```golang
123+
124+
// VerticalPodAutoscalerRecommenderSelector points to a specificic Vertical Pod Autoscaler recommender
125+
// in the future it might pass parameters to the recommender.
126+
type VerticalPodAutoscalerRecommenderSelector struct {
127+
// Name of the recommender responsible for generating recommendation for this object.
128+
Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
129+
}
130+
113131
// VerticalPodAutoscalerSpec is the specification of the behavior of the autoscaler.
114132
type VerticalPodAutoscalerSpec struct {
115133
// TargetRef points to the controller managing the set of pods for the
@@ -137,9 +155,11 @@ type VerticalPodAutoscalerSpec struct {
137155
// resources for all containers in the pod, without additional constraints.
138156
// +optional
139157
ResourcePolicy *PodResourcePolicy `json:"resourcePolicy,omitempty" protobuf:"bytes,3,opt,name=resourcePolicy"`
140-
141-
// Name of the recommender responsible for generating recommendation for this object.
142-
RecommenderName []string `json:"recommenderName,omitempty" protobuf:"bytes,4,opt,name=recommenderName"`
158+
// Recommender responsible for generating recommendation for this object.
159+
// List should be empty (then the default recommender will generate the
160+
// recommendation) or contain exactly one recommender.
161+
// +optional
162+
Recommenders []*VerticalPodAutoscalerRecommenderSelector `json:"recommenders,omitempty" protobuf:"bytes,4,opt,name=recommenders"`
143163
}
144164
```
145165

@@ -152,7 +172,7 @@ const RecommenderName = "default"
152172
recommender := routines.NewRecommender(config, *checkpointsGCInterval, useCheckpoints, RecommenderName, *vpaObjectNamespace)
153173
```
154174

155-
where the routines.NewRecommender can pass the `RecommenderName` to the clusterState object.
175+
where the `routines.NewRecommender` can pass the `RecommenderName` to the `clusterState` object.
156176

157177
```golang
158178
// NewRecommender creates a new recommender instance.
@@ -185,9 +205,24 @@ func NewClusterState(recommender_name string) *ClusterState {
185205
}
186206
```
187207

188-
Therefore, when loading VPA objects to the `clusterStateFeeder`, it can use the field selector to select VPA CRDs that
189-
have `recommenderName` equal to the current clusterState’s `RecommenderName`.
208+
Therefore, when loading VPA objects to the `clusterStateFeeder`, it should
209+
ignore VPA objects that don't have an item in the `recommenders` field with
210+
`name` equal to the current clusterState’s `RecommenderName`.
211+
190212
```golang
213+
func implicitDefaultRecommender(selectors[]*VerticalPodAutoscalerRecommenderSelector) bool {
214+
return len(selectors) == 0
215+
}
216+
217+
func selectsRecommender(selectors[]*VerticalPodAutoscalerRecommenderSelector, name *string) bool {
218+
for _, s := range(selectors) {
219+
if s.Name == *name {
220+
return true
221+
}
222+
}
223+
return false
224+
}
225+
191226
// Fetch VPA objects and load them into the cluster state.
192227
func (feeder *clusterStateFeeder) LoadVPAs() {
193228
// List VPA API objects.
@@ -200,8 +235,8 @@ func (feeder *clusterStateFeeder) LoadVPAs() {
200235
var vpaCRDs []*vpa_types.VerticalPodAutoscaler
201236
for _, vpaCRD := range allVpaCRDs {
202237
currentRecommenderName := feeder.clusterState.RecommenderName
203-
if (vpaCRD.Spec.RecommenderName != currentRecommenderName) && (vpaCRD.Spec.RecommenderName != "") {
204-
klog.V(6).Infof("Ignoring the vpaCRD as its name %v is not equal to the current recommender's name %v", vpaCRD.Spec.RecommenderName, currentRecommenderName)
238+
if (!implicitDefaultRecommender(vpaCRD.Spec.Recommenders) && !selectsRecommender(vpaCRD.Spec.Recommenders, currentRecommenderName)) {
239+
klog.V(6).Infof("Ignoring the vpaCRD as current recommender's name %v doesn't appear among its recommenders", currentRecommenderName)
205240
continue
206241
}
207242
vpaCRDs = append(vpaCRDs, vpaCRD)
@@ -216,37 +251,34 @@ func (feeder *clusterStateFeeder) LoadVPAs() {
216251
}
217252
```
218253
219-
Accordingly, the VPA object yaml should include the `recommenderName` as the default `RecommenderName`.
220-
```yaml
221-
apiVersion: "autoscaling.k8s.io/v1"
222-
kind: VerticalPodAutoscaler
223-
metadata:
224-
name: hamster-vpa
225-
Spec:
226-
recommenderName: default
227-
targetRef:
228-
apiVersion: "apps/v1"
229-
... ...
230-
```
231-
232254
### Deployment Details
233-
The customized recommender is supposed to be deployed as a separate deployment that is chosen
234-
by different sets of VPA objects.Each VPA object is supposed to choose only one recommender at a time.
235-
The way how the default recommender and the customized recommender are running and interacting with VPA objects
236-
are shown in the following drawing.
255+
The customized recommender is supposed to be deployed as a separate deployment
256+
that is chosen by different sets of VPA objects. Each VPA object is supposed to
257+
choose only one recommender at a time.
258+
The way how the default recommender and the customized recommender are running
259+
and interacting with VPA objects are shown in the following drawing.
237260
238261
<img src="images/deployment.png" alt="deployment" width="720" height="360"/>
239262
240-
Though we do not support a VPA object to use multiple recommenders in this proposal, we leave the possibility of necessary
241-
changes of using multiple recommenders in the future. Namely, we define `recommenderName` to be an array instead of a string, but we support one element only in this proposal. We modify the admission controller to validate that the array has <= 1 elements.
263+
Though we do not support a VPA object to use multiple recommenders in this
264+
proposal, we leave the possibility of necessary changes of using multiple
265+
recommenders in the future. Namely, we define `recommenders` to be an array
266+
instead of an object, but we support one element only in this proposal. We
267+
modify the admission controller to validate that the array has <= 1 elements.
242268
243-
We will add the following check in the `func validateVPA(vpa *vpa_types.VerticalPodAutoscaler, isCreate bool)` function.
244-
```
245-
if len(vpa.Spec.RecommenderName) > 1 {
246-
return fmt.Errorf("VPA object shouldn't specify more than one recommenderNames.")
269+
We will add the following check in the
270+
`func validateVPA(vpa *vpa_types.VerticalPodAutoscaler, isCreate bool)`
271+
function.
272+
273+
```golang
274+
if len(vpa.Spec.Recommenders) > 1 {
275+
return fmt.Errorf("VPA object shouldn't specify more than one recommender.")
247276
}
248277
```
249278
279+
For now we don't allow users to pass any parameters to recommenders but we leave
280+
that as a possibility for the future. We do this by using a struct (which can be
281+
extended if we need to) rather than a string.
250282
251283
## Design Details
252284

0 commit comments

Comments
 (0)