Skip to content

Commit 2a2fa48

Browse files
add descheduler
Signed-off-by: Yaroslav Borbat <yaroslav.borbat@flant.com>
1 parent 59169a6 commit 2a2fa48

23 files changed

Lines changed: 847 additions & 66 deletions

File tree

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package cvi
2+
3+
import (
4+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
5+
6+
"github.com/deckhouse/virtualization/api/core/v1alpha2"
7+
)
8+
9+
func New(options ...Option) *v1alpha2.ClusterVirtualImage {
10+
cvi := NewEmpty("")
11+
ApplyOptions(cvi, options...)
12+
return cvi
13+
}
14+
15+
func ApplyOptions(cvi *v1alpha2.ClusterVirtualImage, opts ...Option) {
16+
if cvi == nil {
17+
return
18+
}
19+
for _, opt := range opts {
20+
opt(cvi)
21+
}
22+
}
23+
24+
func NewEmpty(name string) *v1alpha2.ClusterVirtualImage {
25+
return &v1alpha2.ClusterVirtualImage{
26+
TypeMeta: metav1.TypeMeta{
27+
APIVersion: v1alpha2.SchemeGroupVersion.String(),
28+
Kind: v1alpha2.ClusterVirtualImageKind,
29+
},
30+
ObjectMeta: metav1.ObjectMeta{
31+
Name: name,
32+
},
33+
}
34+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package cvi
2+
3+
import (
4+
"github.com/deckhouse/virtualization-controller/pkg/builder/meta"
5+
"github.com/deckhouse/virtualization/api/core/v1alpha2"
6+
)
7+
8+
type Option func(vmop *v1alpha2.ClusterVirtualImage)
9+
10+
var (
11+
WithName = meta.WithName[*v1alpha2.ClusterVirtualImage]
12+
WithGenerateName = meta.WithGenerateName[*v1alpha2.ClusterVirtualImage]
13+
WithLabel = meta.WithLabel[*v1alpha2.ClusterVirtualImage]
14+
WithLabels = meta.WithLabels[*v1alpha2.ClusterVirtualImage]
15+
WithAnnotation = meta.WithAnnotation[*v1alpha2.ClusterVirtualImage]
16+
WithAnnotations = meta.WithAnnotations[*v1alpha2.ClusterVirtualImage]
17+
WithFinalizer = meta.WithFinalizer[*v1alpha2.ClusterVirtualImage]
18+
)
19+
20+
func WithDataSourceHTTP(url string, checksum *v1alpha2.Checksum, caBundle []byte) Option {
21+
return func(cvi *v1alpha2.ClusterVirtualImage) {
22+
cvi.Spec.DataSource = v1alpha2.ClusterVirtualImageDataSource{
23+
Type: v1alpha2.DataSourceTypeHTTP,
24+
HTTP: &v1alpha2.DataSourceHTTP{
25+
URL: url,
26+
Checksum: checksum,
27+
CABundle: caBundle,
28+
},
29+
}
30+
}
31+
}
32+
33+
func WithDataSourceContainerImage(image string, imagePullSecret v1alpha2.ImagePullSecret, caBundle []byte) Option {
34+
return func(cvi *v1alpha2.ClusterVirtualImage) {
35+
cvi.Spec.DataSource = v1alpha2.ClusterVirtualImageDataSource{
36+
Type: v1alpha2.DataSourceTypeContainerImage,
37+
ContainerImage: &v1alpha2.ClusterVirtualImageContainerImage{
38+
Image: image,
39+
ImagePullSecret: imagePullSecret,
40+
CABundle: caBundle,
41+
},
42+
}
43+
}
44+
}
45+
46+
func WithDataSourceObjectRef(kind v1alpha2.ClusterVirtualImageObjectRefKind, name, namespace string) Option {
47+
return func(cvi *v1alpha2.ClusterVirtualImage) {
48+
cvi.Spec.DataSource = v1alpha2.ClusterVirtualImageDataSource{
49+
Type: v1alpha2.DataSourceTypeObjectRef,
50+
ObjectRef: &v1alpha2.ClusterVirtualImageObjectRef{
51+
Kind: kind,
52+
Name: name,
53+
Namespace: namespace,
54+
},
55+
}
56+
}
57+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package vd
2+
3+
import (
4+
"github.com/deckhouse/virtualization-controller/pkg/builder/meta"
5+
"github.com/deckhouse/virtualization/api/core/v1alpha2"
6+
)
7+
8+
type Option func(vmop *v1alpha2.VirtualDisk)
9+
10+
var (
11+
WithName = meta.WithName[*v1alpha2.VirtualDisk]
12+
WithNamespace = meta.WithNamespace[*v1alpha2.VirtualDisk]
13+
WithGenerateName = meta.WithGenerateName[*v1alpha2.VirtualDisk]
14+
WithLabel = meta.WithLabel[*v1alpha2.VirtualDisk]
15+
WithLabels = meta.WithLabels[*v1alpha2.VirtualDisk]
16+
WithAnnotation = meta.WithAnnotation[*v1alpha2.VirtualDisk]
17+
WithAnnotations = meta.WithAnnotations[*v1alpha2.VirtualDisk]
18+
WithFinalizer = meta.WithFinalizer[*v1alpha2.VirtualDisk]
19+
)
20+
21+
func WithDataSourceHTTP(url string, checksum *v1alpha2.Checksum, caBundle []byte) Option {
22+
return func(vd *v1alpha2.VirtualDisk) {
23+
vd.Spec.DataSource = &v1alpha2.VirtualDiskDataSource{
24+
Type: v1alpha2.DataSourceTypeHTTP,
25+
HTTP: &v1alpha2.DataSourceHTTP{
26+
URL: url,
27+
Checksum: checksum,
28+
CABundle: caBundle,
29+
},
30+
}
31+
}
32+
}
33+
34+
func WithDataSourceContainerImage(image, imagePullSecretName string, caBundle []byte) Option {
35+
return func(vd *v1alpha2.VirtualDisk) {
36+
vd.Spec.DataSource = &v1alpha2.VirtualDiskDataSource{
37+
Type: v1alpha2.DataSourceTypeContainerImage,
38+
ContainerImage: &v1alpha2.VirtualDiskContainerImage{
39+
Image: image,
40+
ImagePullSecret: v1alpha2.ImagePullSecretName{
41+
Name: imagePullSecretName,
42+
},
43+
CABundle: caBundle,
44+
},
45+
}
46+
}
47+
}
48+
49+
func WithDataSourceObjectRef(kind v1alpha2.VirtualDiskObjectRefKind, name string) Option {
50+
return func(vd *v1alpha2.VirtualDisk) {
51+
vd.Spec.DataSource = &v1alpha2.VirtualDiskDataSource{
52+
Type: v1alpha2.DataSourceTypeObjectRef,
53+
ObjectRef: &v1alpha2.VirtualDiskObjectRef{
54+
Kind: kind,
55+
Name: name,
56+
},
57+
}
58+
}
59+
}
60+
61+
func WithDataSourceObjectRefFromCVI(cvi *v1alpha2.ClusterVirtualImage) Option {
62+
return WithDataSourceObjectRef(v1alpha2.VirtualDiskObjectRefKindClusterVirtualImage, cvi.Name)
63+
}
64+
65+
func WithDataSourceObjectRefFromVI(vi *v1alpha2.VirtualImage) Option {
66+
return WithDataSourceObjectRef(v1alpha2.VirtualDiskObjectRefKindVirtualImage, vi.Name)
67+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package vd
2+
3+
import (
4+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
5+
6+
"github.com/deckhouse/virtualization/api/core/v1alpha2"
7+
)
8+
9+
func New(options ...Option) *v1alpha2.VirtualDisk {
10+
vd := NewEmpty("", "")
11+
ApplyOptions(vd, options...)
12+
return vd
13+
}
14+
15+
func ApplyOptions(vd *v1alpha2.VirtualDisk, opts ...Option) {
16+
if vd == nil {
17+
return
18+
}
19+
for _, opt := range opts {
20+
opt(vd)
21+
}
22+
}
23+
24+
func NewEmpty(name, namespace string) *v1alpha2.VirtualDisk {
25+
return &v1alpha2.VirtualDisk{
26+
TypeMeta: metav1.TypeMeta{
27+
APIVersion: v1alpha2.SchemeGroupVersion.String(),
28+
Kind: v1alpha2.VirtualDiskKind,
29+
},
30+
ObjectMeta: metav1.ObjectMeta{
31+
Name: name,
32+
Namespace: namespace,
33+
},
34+
}
35+
}

images/virtualization-artifact/pkg/builder/vm/option.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,22 @@ func WithMemory(size resource.Quantity) Option {
4949
vm.Spec.Memory.Size = size
5050
}
5151
}
52+
53+
func WithDisks(disks ...*v1alpha2.VirtualDisk) Option {
54+
return func(vm *v1alpha2.VirtualMachine) {
55+
blockDeviceRefs := make([]v1alpha2.BlockDeviceSpecRef, 0, len(disks))
56+
for _, disk := range disks {
57+
blockDeviceRefs = append(blockDeviceRefs, v1alpha2.BlockDeviceSpecRef{
58+
Kind: v1alpha2.VirtualDiskKind,
59+
Name: disk.Name,
60+
})
61+
}
62+
vm.Spec.BlockDeviceRefs = append(vm.Spec.BlockDeviceRefs, blockDeviceRefs...)
63+
}
64+
}
65+
66+
func WithNodeSelector(nodeSelector map[string]string) Option {
67+
return func(vm *v1alpha2.VirtualMachine) {
68+
vm.Spec.NodeSelector = nodeSelector
69+
}
70+
}

openapi/config-values.yaml

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,97 @@ properties:
258258
enum:
259259
- "text"
260260
- "json"
261+
descheduler:
262+
type: object
263+
description: |
264+
Configuration for the descheduler. Enables eviction of virtual machines.
265+
properties:
266+
enabled:
267+
type: boolean
268+
description: |
269+
Enable or disable the descheduler. Set to true to activate VM eviction.
270+
x-examples: [true, false]
271+
lowNodeUtilization:
272+
type: object
273+
default: null
274+
properties:
275+
thresholds:
276+
type: object
277+
default: {}
278+
properties:
279+
cpu:
280+
type: integer
281+
minimal: 0
282+
maximal: 100
283+
description: CPU fraction in percents
284+
memory:
285+
type: integer
286+
minimal: 0
287+
maximal: 100
288+
description: Memory fraction in percents
289+
pods:
290+
type: integer
291+
minimal: 0
292+
maximal: 100
293+
description: Pods count in percents
294+
additionalProperties: true
295+
targetThresholds:
296+
type: object
297+
default: {}
298+
properties:
299+
cpu:
300+
type: integer
301+
minimal: 0
302+
maximal: 100
303+
description: CPU fraction in percents
304+
memory:
305+
type: integer
306+
minimal: 0
307+
maximal: 100
308+
description: Memory fraction in percents
309+
pods:
310+
type: integer
311+
minimal: 0
312+
maximal: 100
313+
description: Pods count in percents
314+
additionalProperties: true
315+
highNodeUtilization:
316+
type: object
317+
default: null
318+
properties:
319+
thresholds:
320+
type: object
321+
default: {}
322+
properties:
323+
cpu:
324+
type: integer
325+
minimal: 0
326+
maximal: 100
327+
description: CPU fraction in percents
328+
memory:
329+
type: integer
330+
minimal: 0
331+
maximal: 100
332+
description: Memory fraction in percents
333+
pods:
334+
type: integer
335+
minimal: 0
336+
maximal: 100
337+
description: Pods count in percents
338+
additionalProperties: true
339+
anyOf:
340+
- required: ["lowNodeUtilization"]
341+
properties:
342+
enabled:
343+
const: true
344+
not:
345+
required: ["highNodeUtilization"]
346+
- required: ["highNodeUtilization"]
347+
properties:
348+
enabled:
349+
const: true
350+
not:
351+
required: ["lowNodeUtilization"]
352+
- required: []
353+
not:
354+
required: ["highNodeUtilization", "lowNodeUtilization"]

openapi/doc-ru-config-values.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,12 @@ properties:
159159
160160
Работает для следующих компонентов:
161161
- `virtualization-controller`
162+
descheduler:
163+
type: object
164+
description: |
165+
Конфигурация для descheduler. Включает выселение виртуальных машин.
166+
properties:
167+
enabled:
168+
type: boolean
169+
description: |
170+
Включение или отключение descheduler. Установите значение true для активации выселения виртуальных машин.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{{- if .Values.virtualization.descheduler.enabled }}
2+
apiVersion: deckhouse.io/v1alpha2
3+
kind: Descheduler
4+
metadata:
5+
name: virtualization
6+
{{- include "helm_lib_module_labels" (list .) | nindent 2 }}
7+
spec:
8+
evictLocalStoragePods: true
9+
podLabelSelector:
10+
matchExpressions:
11+
- key: vm.kubevirt.internal.virtualization.deckhouse.io/name
12+
operator: Exists
13+
strategies:
14+
{{- if .Values.virtualization.descheduler.highNodeUtilization }}
15+
highNodeUtilization:
16+
enabled: true
17+
thresholds:
18+
cpu: {{ .Values.virtualization.descheduler.highNodeUtilization.thresholds.cpu }}
19+
memory: {{ .Values.virtualization.descheduler.highNodeUtilization.thresholds.memory }}
20+
pods: {{ .Values.virtualization.descheduler.highNodeUtilization.thresholds.pods }}
21+
{{- else if .Values.virtualization.descheduler.lowNodeUtilization }}
22+
lowNodeUtilization:
23+
enabled: true
24+
thresholds:
25+
cpu: {{ .Values.virtualization.descheduler.lowNodeUtilization.thresholds.cpu }}
26+
memory: {{ .Values.virtualization.descheduler.lowNodeUtilization.thresholds.memory }}
27+
pods: {{ .Values.virtualization.descheduler.lowNodeUtilization.thresholds.pods }}
28+
targetThresholds:
29+
cpu: {{ .Values.virtualization.descheduler.lowNodeUtilization.targetThresholds.cpu }}
30+
memory: {{ .Values.virtualization.descheduler.lowNodeUtilization.targetThresholds.memory }}
31+
pods: {{ .Values.virtualization.descheduler.lowNodeUtilization.targetThresholds.pods }}
32+
{{- end }}
33+
removePodsViolatingInterPodAntiAffinity:
34+
enabled: true
35+
removePodsViolatingNodeAffinity:
36+
enabled: true
37+
nodeAffinityType:
38+
- requiredDuringSchedulingIgnoredDuringExecution
39+
{{- end }}

0 commit comments

Comments
 (0)