Skip to content

Commit

Permalink
allow to customize VM devices
Browse files Browse the repository at this point in the history
Signed-off-by: Marcin Franczyk <[email protected]>
  • Loading branch information
mfranczy committed Oct 15, 2020
1 parent ba68218 commit aa5304a
Show file tree
Hide file tree
Showing 16 changed files with 540 additions and 36 deletions.
4 changes: 4 additions & 0 deletions charts/internal/machine-class/templates/machine-class.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ providerSpec:
resources:
{{ toYaml $machineClass.resources | indent 4 }}
{{- end }}
{{- if $machineClass.devices }}
devices:
{{ toYaml $machineClass.devices | indent 4 }}
{{- end }}
{{- if $machineClass.rootVolume }}
rootVolume:
{{ toYaml $machineClass.rootVolume | indent 4 }}
Expand Down
5 changes: 5 additions & 0 deletions charts/internal/machine-class/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ machineClasses:
cpu: "300m"
memory: "4Gi"
overcommitGuestOverhead: true
devices:
disks:
- name: "root-disk"
cache: "none"
networkInterfaceMultiQueue: true
rootVolume:
pvc:
storageClassName: standard
Expand Down
23 changes: 23 additions & 0 deletions docs/usage-as-end-user.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,29 @@ An example `WorkerConfig` for the KubeVirt extension looks as follows:
```yaml
apiVersion: kubevirt.provider.extensions.gardener.cloud/v1alpha1
kind: WorkerConfig
devices:
# disks allow to customize disks attached to KubeVirt VM
# check [link](https://kubevirt.io/user-guide/#/creation/disks-and-volumes?id=disks-and-volumes) for full specification and options
disks:
# name must match defined dataVolume name
# to modify root volume the name must be equal to 'root-disk'
- name: root-disk # modify root-disk
# disk type, check [link](https://kubevirt.io/user-guide/#/creation/disks-and-volumes?id=disks) for more types
disk:
# bus indicates the type of disk device to emulate.
bus: virtio
# set disk device cache
cache: writethrough
# dedicatedIOThread indicates this disk should have an exclusive IO Thread
dedicatedIOThread: true
- name: volume-1 # modify dataVolume named volume-1
disk: {}
# whether to have random number generator from host
rng: {}
# whether or not to enable virtio multi-queue for block devices
blockMultiQueue: true
# if specified, virtual network interfaces configured with a virtio bus will also enable the vhost multiqueue feature
networkInterfaceMultiQueue: true
cpu:
# number of cores inside the VMI
cores: 1
Expand Down
81 changes: 81 additions & 0 deletions hack/api-reference/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,20 @@ string
</tr>
<tr>
<td>
<code>devices</code></br>
<em>
<a href="#kubevirt.provider.extensions.gardener.cloud/v1alpha1.Devices">
Devices
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Devices allows to customize devices attached to KubeVirt VM</p>
</td>
</tr>
<tr>
<td>
<code>cpu</code></br>
<em>
kubevirt.io/client-go/api/v1.CPU
Expand Down Expand Up @@ -375,6 +389,73 @@ map[string]bool
</tr>
</tbody>
</table>
<h3 id="kubevirt.provider.extensions.gardener.cloud/v1alpha1.Devices">Devices
</h3>
<p>
(<em>Appears on:</em>
<a href="#kubevirt.provider.extensions.gardener.cloud/v1alpha1.WorkerConfig">WorkerConfig</a>)
</p>
<p>
<p>Devices allows to fine-tune devices attached to KubeVirt VM</p>
</p>
<table>
<thead>
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>disks</code></br>
<em>
[]kubevirt.io/client-go/api/v1.Disk
</em>
</td>
<td>
<em>(Optional)</em>
<p>Disks allows to customize disks attached to KubeVirt VM</p>
</td>
</tr>
<tr>
<td>
<code>rng</code></br>
<em>
kubevirt.io/client-go/api/v1.Rng
</em>
</td>
<td>
<em>(Optional)</em>
<p>Whether to have random number generator from host</p>
</td>
</tr>
<tr>
<td>
<code>blockMultiQueue</code></br>
<em>
bool
</em>
</td>
<td>
<em>(Optional)</em>
<p>Whether or not to enable virtio multi-queue for block devices</p>
</td>
</tr>
<tr>
<td>
<code>networkInterfaceMultiqueue</code></br>
<em>
bool
</em>
</td>
<td>
<em>(Optional)</em>
<p>If specified, virtual network interfaces configured with a virtio bus will also enable the vhost multiqueue feature</p>
</td>
</tr>
</tbody>
</table>
<h3 id="kubevirt.provider.extensions.gardener.cloud/v1alpha1.InfrastructureStatus">InfrastructureStatus
</h3>
<p>
Expand Down
47 changes: 29 additions & 18 deletions pkg/admission/validator/shoot.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,18 @@ var (
workerConfigPath = func(index int) *field.Path { return workersPath.Index(index).Child("providerConfig") }
)

type workerConfigContext struct {
workerConfig *apiskubevirt.WorkerConfig
dataVolumes []core.DataVolume
}

type validationContext struct {
shoot *core.Shoot
infrastructureConfig *apiskubevirt.InfrastructureConfig
controlPlaneConfig *apiskubevirt.ControlPlaneConfig
workerConfigs []*apiskubevirt.WorkerConfig
cloudProfile *gardencorev1beta1.CloudProfile
cloudProfileConfig *apiskubevirt.CloudProfileConfig
shoot *core.Shoot
infrastructureConfig *apiskubevirt.InfrastructureConfig
controlPlaneConfig *apiskubevirt.ControlPlaneConfig
workerConfigsContexts []*workerConfigContext
cloudProfile *gardencorev1beta1.CloudProfile
cloudProfileConfig *apiskubevirt.CloudProfileConfig
}

func (s *shoot) validateContext(valContext *validationContext) field.ErrorList {
Expand All @@ -111,8 +116,8 @@ func (s *shoot) validateContext(valContext *validationContext) field.ErrorList {
allErrors = append(allErrors, validation.ValidateInfrastructureConfig(valContext.infrastructureConfig, infrastructureConfigPath)...)
allErrors = append(allErrors, validation.ValidateControlPlaneConfig(valContext.controlPlaneConfig, controlPlaneConfigPath)...)
allErrors = append(allErrors, validation.ValidateWorkers(valContext.shoot.Spec.Provider.Workers, workersPath)...)
for i, workerConfig := range valContext.workerConfigs {
allErrors = append(allErrors, validation.ValidateWorkerConfig(workerConfig, workerConfigPath(i))...)
for i, workerConfigContext := range valContext.workerConfigsContexts {
allErrors = append(allErrors, validation.ValidateWorkerConfig(workerConfigContext.workerConfig, workerConfigContext.dataVolumes, workerConfigPath(i))...)
}

return allErrors
Expand Down Expand Up @@ -158,8 +163,10 @@ func (s *shoot) validateUpdate(ctx context.Context, oldShoot, shoot *core.Shoot)

allErrors = append(allErrors, validation.ValidateWorkersUpdate(oldValContext.shoot.Spec.Provider.Workers, currentValContext.shoot.Spec.Provider.Workers, workersPath)...)

for i, currentWorkerConfig := range currentValContext.workerConfigs {
for j, oldWorkerConfig := range oldValContext.workerConfigs {
for i, currentContext := range currentValContext.workerConfigsContexts {
currentWorkerConfig := currentContext.workerConfig
for j, oldContext := range oldValContext.workerConfigsContexts {
oldWorkerConfig := oldContext.workerConfig
if shoot.Spec.Provider.Workers[i].Name == oldShoot.Spec.Provider.Workers[j].Name && !reflect.DeepEqual(oldWorkerConfig, currentWorkerConfig) {
allErrors = append(allErrors, validation.ValidateWorkerConfigUpdate(currentWorkerConfig, oldWorkerConfig, workerConfigPath(i))...)
}
Expand Down Expand Up @@ -191,7 +198,7 @@ func (s *shoot) newValidationContext(ctx context.Context, shoot *core.Shoot) (*v
}
}

var workerConfigs []*apiskubevirt.WorkerConfig
var workerConfigsContexts []*workerConfigContext
for _, worker := range shoot.Spec.Provider.Workers {
workerConfig := &apiskubevirt.WorkerConfig{}
if worker.ProviderConfig != nil {
Expand All @@ -201,7 +208,11 @@ func (s *shoot) newValidationContext(ctx context.Context, shoot *core.Shoot) (*v
return nil, errors.Wrapf(err, "could not decode providerConfig of worker %q", worker.Name)
}
}
workerConfigs = append(workerConfigs, workerConfig)

workerConfigsContexts = append(workerConfigsContexts, &workerConfigContext{
workerConfig: workerConfig,
dataVolumes: worker.DataVolumes,
})
}

cloudProfile := &gardencorev1beta1.CloudProfile{}
Expand All @@ -218,12 +229,12 @@ func (s *shoot) newValidationContext(ctx context.Context, shoot *core.Shoot) (*v
}

return &validationContext{
shoot: shoot,
infrastructureConfig: infrastructureConfig,
controlPlaneConfig: controlPlaneConfig,
workerConfigs: workerConfigs,
cloudProfile: cloudProfile,
cloudProfileConfig: cloudProfileConfig,
shoot: shoot,
infrastructureConfig: infrastructureConfig,
controlPlaneConfig: controlPlaneConfig,
workerConfigsContexts: workerConfigsContexts,
cloudProfile: cloudProfile,
cloudProfileConfig: cloudProfileConfig,
}, nil
}

Expand Down
15 changes: 14 additions & 1 deletion pkg/apis/kubevirt/types_worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ import (
type WorkerConfig struct {
metav1.TypeMeta

// Devices allows to customize devices attached to KubeVirt VM
Devices *Devices
// CPU allows specifying the CPU topology of KubeVirt VM.
// +optional
CPU *kubevirtv1.CPU
// Memory allows specifying the VirtualMachineInstance memory features like huge pages and guest memory settings.
// Each feature might require appropriate FeatureGate enabled.
Expand All @@ -54,6 +55,18 @@ type WorkerConfig struct {
OvercommitGuestOverhead bool
}

// Devices allows to fine-tune devices attached to KubeVirt VM
type Devices struct {
// Disks allows to customize disks attached to KubeVirt VM
Disks []kubevirtv1.Disk
// Whether to have random number generator from host
Rng *kubevirtv1.Rng
// Whether or not to enable virtio multi-queue for block devices
BlockMultiQueue bool
// If specified, virtual network interfaces configured with a virtio bus will also enable the vhost multiqueue feature
NetworkInterfaceMultiQueue bool
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// WorkerStatus contains information about created worker resources.
Expand Down
19 changes: 19 additions & 0 deletions pkg/apis/kubevirt/v1alpha1/types_worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ import (
type WorkerConfig struct {
metav1.TypeMeta `json:",inline"`

// Devices allows to customize devices attached to KubeVirt VM
// +optional
Devices *Devices `json:"devices,omitempty"`
// CPU allows specifying the CPU topology of KubeVirt VM.
// +optional
CPU *kubevirtv1.CPU `json:"cpu,omitempty"`
Expand Down Expand Up @@ -60,6 +63,22 @@ type WorkerConfig struct {
OvercommitGuestOverhead bool `json:"overcommitGuestOverhead,omitempty"`
}

// Devices allows to fine-tune devices attached to KubeVirt VM
type Devices struct {
// Disks allows to customize disks attached to KubeVirt VM
// +optional
Disks []kubevirtv1.Disk `json:"disks,omitempty"`
// Whether to have random number generator from host
// +optional
Rng *kubevirtv1.Rng `json:"rng,omitempty"`
// Whether or not to enable virtio multi-queue for block devices
// +optional
BlockMultiQueue bool `json:"blockMultiQueue,omitempty"`
// If specified, virtual network interfaces configured with a virtio bus will also enable the vhost multiqueue feature
// +optional
NetworkInterfaceMultiQueue bool `json:"networkInterfaceMultiqueue,omitempty"`
}

// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

Expand Down
38 changes: 38 additions & 0 deletions pkg/apis/kubevirt/v1alpha1/zz_generated.conversion.go

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

Loading

0 comments on commit aa5304a

Please sign in to comment.