Skip to content

Commit

Permalink
neonvm-controller: add spec.cpuArchitecture field
Browse files Browse the repository at this point in the history
Add spec.cpuArchitecture to use for scheduling
pods instead of relying on spec.affinity.
Add new field to the kubectl output.
  • Loading branch information
mikhail-sakhnov committed Feb 10, 2025
1 parent 0e9d1fa commit 8ace4b1
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 30 deletions.
13 changes: 13 additions & 0 deletions neonvm/apis/neonvm/v1/virtualmachine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ type VirtualMachineSpec struct {

ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"`

// +kubebuilder:default:=amd64
// +optional
TargetArchitecture *CPUArchitecture `json:"targetArchitecture,omitempty"`

Guest Guest `json:"guest"`

// Running init containers is costly, so InitScript field should be preferred over ExtraInitContainers
Expand Down Expand Up @@ -170,6 +174,14 @@ func (spec *VirtualMachineSpec) Resources() VirtualMachineResources {
}
}

// +kubebuilder:validation:Enum=amd64;arm64
type CPUArchitecture string

const (
CPUArchitectureAMD64 CPUArchitecture = "amd64"
CPUArchitectureARM64 CPUArchitecture = "arm64"
)

// +kubebuilder:validation:Enum=QmpScaling;SysfsScaling
type CpuScalingMode string

Expand Down Expand Up @@ -639,6 +651,7 @@ func (p VmPhase) IsAlive() bool {
// +kubebuilder:printcolumn:name="Node",type=string,priority=1,JSONPath=`.status.node`
// +kubebuilder:printcolumn:name="Image",type=string,priority=1,JSONPath=`.spec.guest.rootDisk.image`
// +kubebuilder:printcolumn:name="CPUScalingMode",type=string,priority=1,JSONPath=`.spec.cpuScalingMode`
// +kubebuilder:printcolumn:name="TargetArchitecture",type=string,priority=1,JSONPath=`.spec.targetArchitecture`
type VirtualMachine struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Expand Down
20 changes: 17 additions & 3 deletions neonvm/apis/neonvm/v1/virtualmachine_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,25 @@ func (r *VirtualMachine) ValidateUpdate(old runtime.Object) (admission.Warnings,
}
}

// allow to change CPU scaling mode only if it's not set
if before.Spec.CpuScalingMode != nil && (r.Spec.CpuScalingMode == nil || *r.Spec.CpuScalingMode != *before.Spec.CpuScalingMode) {
return nil, fmt.Errorf(".spec.cpuScalingMode is not allowed to be changed once it's set")
fieldsAllowedToChangeFromNullOnly := []struct {
fieldName string
getter func(*VirtualMachine) any
}{
{".spec.cpuScalingMode", func(v *VirtualMachine) any { return v.Spec.CpuScalingMode }},
{".spec.targetArchitecture", func(v *VirtualMachine) any { return v.Spec.TargetArchitecture }},
}

for _, info := range fieldsAllowedToChangeFromNullOnly {
if info.getter(before) != nil && (info.getter(r) == nil || info.getter(r) != info.getter(before)) {
return nil, fmt.Errorf("%s is is not allowed to be changed once it's set", info.fieldName)
}
}

// allow to change CPU scaling mode only if it's not set
// if before.Spec.CpuScalingMode != nil && (r.Spec.CpuScalingMode == nil || *r.Spec.CpuScalingMode != *before.Spec.CpuScalingMode) {
// return nil, fmt.Errorf(".spec.cpuScalingMode is not allowed to be changed once it's set")
// }

// validate .spec.guest.cpu.use
if r.Spec.Guest.CPUs.Use < r.Spec.Guest.CPUs.Min {
return nil, fmt.Errorf(".cpus.use (%v) should be greater than or equal to the .cpus.min (%v)",
Expand Down
5 changes: 5 additions & 0 deletions neonvm/apis/neonvm/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions neonvm/config/crd/bases/vm.neon.tech_virtualmachines.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ spec:
name: CPUScalingMode
priority: 1
type: string
- jsonPath: .spec.targetArchitecture
name: TargetArchitecture
priority: 1
type: string
name: v1
schema:
openAPIV3Schema:
Expand Down Expand Up @@ -2942,6 +2946,12 @@ spec:
type: boolean
serviceAccountName:
type: string
targetArchitecture:
default: amd64
enum:
- amd64
- arm64
type: string
targetRevision:
description: |-
TargetRevision is the identifier set by external party to track when changes to the spec
Expand Down
34 changes: 20 additions & 14 deletions pkg/neonvm/controllers/vm_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (
"fmt"
"os"
"reflect"
sysruntime "runtime"
"strconv"
"time"

Expand Down Expand Up @@ -1136,6 +1135,7 @@ func annotationsForVirtualMachine(vm *vmv1.VirtualMachine) map[string]string {

func affinityForVirtualMachine(vm *vmv1.VirtualMachine) *corev1.Affinity {
a := vm.Spec.Affinity

if a == nil {
a = &corev1.Affinity{}
}
Expand All @@ -1145,23 +1145,29 @@ func affinityForVirtualMachine(vm *vmv1.VirtualMachine) *corev1.Affinity {
if a.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution == nil {
a.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution = &corev1.NodeSelector{}
}
// if NodeSelectorTerms list is empty - add default values (arch==amd64 or os==linux)

// if NodeSelectorTerms list is empty - add default values (arch==vm.Spec.Affinity or os==linux)
if len(a.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms) == 0 {
matches := []corev1.NodeSelectorRequirement{
{
Key: "kubernetes.io/os",
Operator: "In",
Values: []string{"linux"},
},
}

if vm.Spec.TargetArchitecture != nil {
matches = append(matches, corev1.NodeSelectorRequirement{
Key: "kubernetes.io/arch",
Operator: "In",
Values: []string{string(*vm.Spec.TargetArchitecture)},
})
}

a.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms = append(
a.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms,
corev1.NodeSelectorTerm{
MatchExpressions: []corev1.NodeSelectorRequirement{
{
Key: "kubernetes.io/arch",
Operator: "In",
Values: []string{sysruntime.GOARCH},
},
{
Key: "kubernetes.io/os",
Operator: "In",
Values: []string{"linux"},
},
},
MatchExpressions: matches,
})
}
return a
Expand Down
12 changes: 12 additions & 0 deletions tests/e2e/default-values/00-assert.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: kuttl.dev/v1beta1
kind: TestAssert
timeout: 10
---
apiVersion: vm.neon.tech/v1
kind: VirtualMachine
metadata:
name: example
# default values for cpuScalingMode and cpuArchitecture
spec:
cpuScalingMode: QmpScaling
targetArchitecture: amd64
File renamed without changes.
13 changes: 0 additions & 13 deletions tests/e2e/tmp-default-cpu-scaling-mode/00-assert.yaml

This file was deleted.

0 comments on commit 8ace4b1

Please sign in to comment.