Skip to content

Commit 30c579c

Browse files
committed
feat: add cube and gpu support via templates
1 parent fa77f69 commit 30c579c

5 files changed

Lines changed: 131 additions & 21 deletions

File tree

api/v1alpha1/ionoscloudmachine_types.go

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ const (
9898
ServerTypeEnterprise ServerType = "ENTERPRISE"
9999
// ServerTypeVCPU server of type VCPU.
100100
ServerTypeVCPU ServerType = "VCPU"
101+
// ServerTypeCUBE server of type CUBE.
102+
ServerTypeCUBE ServerType = "CUBE"
103+
// ServerTypeGPU server of type GPU.
104+
ServerTypeGPU ServerType = "GPU"
101105
)
102106

103107
// String returns the string representation of the ServerType.
@@ -107,6 +111,8 @@ func (a ServerType) String() string {
107111

108112
// IonosCloudMachineSpec defines the desired state of IonosCloudMachine.
109113
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.networkID) || has(self.networkID)", message="networkID is required once set"
114+
// +kubebuilder:validation:XValidation:rule="(self.type != 'CUBE' && self.type != 'GPU') || self.templateID != ''",message="templateID is required when type is CUBE or GPU"
115+
// +kubebuilder:validation:XValidation:rule="(self.type == 'CUBE' || self.type == 'GPU') || !has(self.templateID) || self.templateID == ''",message="templateID must only be used with CUBE or GPU type"
110116
type IonosCloudMachineSpec struct {
111117
// ProviderID is the IONOS Cloud provider ID
112118
// will be in the format ionos://ee090ff2-1eef-48ec-a246-a51a33aa4f3a
@@ -118,7 +124,17 @@ type IonosCloudMachineSpec struct {
118124
//+kubebuilder:validation:Format=uuid
119125
DatacenterID string `json:"datacenterID"`
120126

127+
// TemplateID is the ID of the template for creating CUBE or GPU servers.
128+
// If a template has GPU cards assigned, then it can only be used to create GPU servers,
129+
// otherwise it can only be used for CUBE servers.
130+
// NumCores, MemoryMB, CPUFamily and the size parameter of the first volume (boot Disk) are ignored when this is set.
131+
// Available TemplateIDs can be listed using the cloud api.
132+
//+kubebuilder:validation:Format=uuid
133+
//+optional
134+
TemplateID string `json:"templateID,omitempty"`
135+
121136
// NumCores defines the number of cores for the VM.
137+
// Ignored when TemplateID is specified.
122138
//+kubebuilder:validation:Minimum=1
123139
//+kubebuilder:default=1
124140
//+optional
@@ -133,6 +149,7 @@ type IonosCloudMachineSpec struct {
133149
// MemoryMB is the memory size for the VM in MB.
134150
// Size must be specified in multiples of 256 MB with a minimum of 1024 MB
135151
// which is required as we are using hot-pluggable RAM by default.
152+
// Ignored when TemplateID is specified.
136153
//+kubebuilder:validation:MultipleOf=1024
137154
//+kubebuilder:validation:Minimum=2048
138155
//+kubebuilder:default=3072
@@ -144,6 +161,7 @@ type IonosCloudMachineSpec struct {
144161
//
145162
// If not specified, the cloud will select a suitable CPU family
146163
// based on the availability in the data center.
164+
// Ignored when TemplateID is specified.
147165
//+kubebuilder:example=AMD_OPTERON
148166
//+optional
149167
CPUFamily *string `json:"cpuFamily,omitempty"`
@@ -180,9 +198,10 @@ type IonosCloudMachineSpec struct {
180198
// +kubebuilder:validation:MinLength=1
181199
NetworkID *string `json:"networkID,omitempty"`
182200

183-
// Type is the server type of the VM. Can be either ENTERPRISE or VCPU.
201+
// Type is the server type of the VM. Can be either ENTERPRISE, VCPU, CUBE or GPU.
202+
// Use the types CUBE or GPU together with TemplateID.
184203
//+kubebuilder:validation:XValidation:rule="self == oldSelf",message="type is immutable"
185-
//+kubebuilder:validation:Enum=ENTERPRISE;VCPU
204+
//+kubebuilder:validation:Enum=ENTERPRISE;VCPU;CUBE;GPU
186205
//+kubebuilder:default=ENTERPRISE
187206
//+optional
188207
Type ServerType `json:"type,omitempty"`
@@ -216,12 +235,14 @@ type Volume struct {
216235
Name string `json:"name,omitempty"`
217236

218237
// DiskType defines the type of the hard drive.
238+
// Ignored when TemplateID of IonosCloudMachineSpec is specified (for the boot volume).
219239
//+kubebuilder:validation:Enum=HDD;SSD Standard;SSD Premium
220240
//+kubebuilder:default=HDD
221241
//+optional
222242
DiskType VolumeDiskType `json:"diskType,omitempty"`
223243

224-
// SizeGB defines the size of the volume in GB
244+
// SizeGB defines the size of the volume in GB.
245+
// Ignored when TemplateID of IonosCloudMachineSpec is specified (for the boot volume).
225246
//+kubebuilder:validation:Minimum=10
226247
//+kubebuilder:default=20
227248
//+optional
@@ -392,7 +413,7 @@ type IonosCloudMachine struct {
392413
metav1.TypeMeta `json:",inline"`
393414
metav1.ObjectMeta `json:"metadata,omitempty"`
394415

395-
//+kubebuilder:validation:XValidation:rule="self.type != 'VCPU' || !has(self.cpuFamily)",message="cpuFamily must not be specified when using VCPU"
416+
//+kubebuilder:validation:XValidation:rule="(self.type != 'VCPU' && self.type != 'CUBE' && self.type != 'GPU') || !has(self.cpuFamily)",message="cpuFamily must not be specified when using VCPU, CUBE or GPU"
396417
Spec IonosCloudMachineSpec `json:"spec,omitempty"`
397418
Status IonosCloudMachineStatus `json:"status,omitempty"`
398419
}

config/crd/bases/infrastructure.cluster.x-k8s.io_ionoscloudmachines.yaml

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ spec:
164164
165165
If not specified, the cloud will select a suitable CPU family
166166
based on the availability in the data center.
167+
Ignored when TemplateID is specified.
167168
example: AMD_OPTERON
168169
type: string
169170
datacenterID:
@@ -189,7 +190,9 @@ spec:
189190
type: string
190191
diskType:
191192
default: HDD
192-
description: DiskType defines the type of the hard drive.
193+
description: |-
194+
DiskType defines the type of the hard drive.
195+
Ignored when TemplateID of IonosCloudMachineSpec is specified (for the boot volume).
193196
enum:
194197
- HDD
195198
- SSD Standard
@@ -242,7 +245,9 @@ spec:
242245
type: string
243246
sizeGB:
244247
default: 20
245-
description: SizeGB defines the size of the volume in GB
248+
description: |-
249+
SizeGB defines the size of the volume in GB.
250+
Ignored when TemplateID of IonosCloudMachineSpec is specified (for the boot volume).
246251
minimum: 10
247252
type: integer
248253
required:
@@ -325,6 +330,7 @@ spec:
325330
MemoryMB is the memory size for the VM in MB.
326331
Size must be specified in multiples of 256 MB with a minimum of 1024 MB
327332
which is required as we are using hot-pluggable RAM by default.
333+
Ignored when TemplateID is specified.
328334
format: int32
329335
minimum: 2048
330336
multipleOf: 1024
@@ -343,7 +349,9 @@ spec:
343349
rule: self == oldSelf
344350
numCores:
345351
default: 1
346-
description: NumCores defines the number of cores for the VM.
352+
description: |-
353+
NumCores defines the number of cores for the VM.
354+
Ignored when TemplateID is specified.
347355
format: int32
348356
minimum: 1
349357
type: integer
@@ -352,13 +360,25 @@ spec:
352360
ProviderID is the IONOS Cloud provider ID
353361
will be in the format ionos://ee090ff2-1eef-48ec-a246-a51a33aa4f3a
354362
type: string
363+
templateID:
364+
description: |-
365+
TemplateID is the ID of the template for creating CUBE or GPU servers.
366+
If a template has GPU cards assigned, then it can only be used to create GPU servers,
367+
otherwise it can only be used for CUBE servers.
368+
NumCores, MemoryMB, CPUFamily and the size parameter of the first volume (boot Disk) are ignored when this is set.
369+
Available TemplateIDs can be listed using the cloud api.
370+
format: uuid
371+
type: string
355372
type:
356373
default: ENTERPRISE
357-
description: Type is the server type of the VM. Can be either ENTERPRISE
358-
or VCPU.
374+
description: |-
375+
Type is the server type of the VM. Can be either ENTERPRISE, VCPU, CUBE or GPU.
376+
Use the types CUBE or GPU together with TemplateID.
359377
enum:
360378
- ENTERPRISE
361379
- VCPU
380+
- CUBE
381+
- GPU
362382
type: string
363383
x-kubernetes-validations:
364384
- message: type is immutable
@@ -368,10 +388,17 @@ spec:
368388
- disk
369389
type: object
370390
x-kubernetes-validations:
371-
- message: cpuFamily must not be specified when using VCPU
372-
rule: self.type != 'VCPU' || !has(self.cpuFamily)
391+
- message: cpuFamily must not be specified when using VCPU, CUBE or GPU
392+
rule: (self.type != 'VCPU' && self.type != 'CUBE' && self.type != 'GPU')
393+
|| !has(self.cpuFamily)
373394
- message: networkID is required once set
374395
rule: '!has(oldSelf.networkID) || has(self.networkID)'
396+
- message: templateID is required when type is CUBE or GPU
397+
rule: (self.type != 'CUBE' && self.type != 'GPU') || self.templateID
398+
!= ''
399+
- message: templateID must only be used with CUBE or GPU type
400+
rule: (self.type == 'CUBE' || self.type == 'GPU') || !has(self.templateID)
401+
|| self.templateID == ''
375402
status:
376403
description: IonosCloudMachineStatus defines the observed state of IonosCloudMachine.
377404
properties:

config/crd/bases/infrastructure.cluster.x-k8s.io_ionoscloudmachinetemplates.yaml

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ spec:
184184
185185
If not specified, the cloud will select a suitable CPU family
186186
based on the availability in the data center.
187+
Ignored when TemplateID is specified.
187188
example: AMD_OPTERON
188189
type: string
189190
datacenterID:
@@ -209,7 +210,9 @@ spec:
209210
type: string
210211
diskType:
211212
default: HDD
212-
description: DiskType defines the type of the hard drive.
213+
description: |-
214+
DiskType defines the type of the hard drive.
215+
Ignored when TemplateID of IonosCloudMachineSpec is specified (for the boot volume).
213216
enum:
214217
- HDD
215218
- SSD Standard
@@ -264,8 +267,9 @@ spec:
264267
type: string
265268
sizeGB:
266269
default: 20
267-
description: SizeGB defines the size of the volume in
268-
GB
270+
description: |-
271+
SizeGB defines the size of the volume in GB.
272+
Ignored when TemplateID of IonosCloudMachineSpec is specified (for the boot volume).
269273
minimum: 10
270274
type: integer
271275
required:
@@ -349,6 +353,7 @@ spec:
349353
MemoryMB is the memory size for the VM in MB.
350354
Size must be specified in multiples of 256 MB with a minimum of 1024 MB
351355
which is required as we are using hot-pluggable RAM by default.
356+
Ignored when TemplateID is specified.
352357
format: int32
353358
minimum: 2048
354359
multipleOf: 1024
@@ -367,8 +372,9 @@ spec:
367372
rule: self == oldSelf
368373
numCores:
369374
default: 1
370-
description: NumCores defines the number of cores for the
371-
VM.
375+
description: |-
376+
NumCores defines the number of cores for the VM.
377+
Ignored when TemplateID is specified.
372378
format: int32
373379
minimum: 1
374380
type: integer
@@ -377,13 +383,25 @@ spec:
377383
ProviderID is the IONOS Cloud provider ID
378384
will be in the format ionos://ee090ff2-1eef-48ec-a246-a51a33aa4f3a
379385
type: string
386+
templateID:
387+
description: |-
388+
TemplateID is the ID of the template for creating CUBE or GPU servers.
389+
If a template has GPU cards assigned, then it can only be used to create GPU servers,
390+
otherwise it can only be used for CUBE servers.
391+
NumCores, MemoryMB, CPUFamily and the size parameter of the first volume (boot Disk) are ignored when this is set.
392+
Available TemplateIDs can be listed using the cloud api.
393+
format: uuid
394+
type: string
380395
type:
381396
default: ENTERPRISE
382-
description: Type is the server type of the VM. Can be either
383-
ENTERPRISE or VCPU.
397+
description: |-
398+
Type is the server type of the VM. Can be either ENTERPRISE, VCPU, CUBE or GPU.
399+
Use the types CUBE or GPU together with TemplateID.
384400
enum:
385401
- ENTERPRISE
386402
- VCPU
403+
- CUBE
404+
- GPU
387405
type: string
388406
x-kubernetes-validations:
389407
- message: type is immutable
@@ -395,6 +413,12 @@ spec:
395413
x-kubernetes-validations:
396414
- message: networkID is required once set
397415
rule: '!has(oldSelf.networkID) || has(self.networkID)'
416+
- message: templateID is required when type is CUBE or GPU
417+
rule: (self.type != 'CUBE' && self.type != 'GPU') || self.templateID
418+
!= ''
419+
- message: templateID must only be used with CUBE or GPU type
420+
rule: (self.type == 'CUBE' || self.type == 'GPU') || !has(self.templateID)
421+
|| self.templateID == ''
398422
required:
399423
- spec
400424
type: object

docs/custom-image.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,15 @@ export PACKER_FLAGS="--var 'kubernetes_rpm_version=1.28.3' --var 'kubernetes_sem
3232

3333
Now you can build the image:
3434
```sh
35-
make build-qemu-ubuntu-2204
35+
make build-qemu-ubuntu-2404
3636
```
37-
In this case, for Ubuntu 22.04. Works also for `1804` or `2004`.
37+
38+
For efi support (required to use GPUs) build the image like this:
39+
```sh
40+
make build-qemu-ubuntu-2404-efi
41+
```
42+
43+
In this case, for Ubuntu 24.04. Works also for `2204`.
3844
The image creation takes quite some time, so be patient.
3945

4046
The image will be created in the `output` directory.
@@ -71,6 +77,20 @@ You can also do that via Cloud API:
7177
ionosctl img update --image-id <image-id> --cloudinit V1 --licence-type LINUX
7278
```
7379

80+
### Enabling efi support for your image
81+
82+
Important: you **must** build your image with EFI support for this to work!
83+
To enable UEFI functionality for your image, you need to make an adjustment in DCD:
84+
85+
1. Go to Management -> Images & Snapshots -> select your image.
86+
2. Set UEFI Support to "Image is UEFI-compatible" and save your changes.
87+
88+
You can also do that via Cloud API:
89+
90+
```sh
91+
ionosctl img update --image-id <image-id> --require-legacy-bios=false
92+
```
93+
7494
### Enabling disk serial exposure
7595

7696
The disk serial number is required for dynamic volume provisioning plugins like a CSI driver to function properly.

internal/service/cloud/server.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,10 @@ func (s *Service) deleteServer(ctx context.Context, ms *scope.Machine, server *s
246246

247247
deleteVolumes := ms.ClusterScope.IsDeleted()
248248
bootVolumeID := server.GetProperties().GetBootVolume().GetId()
249-
if !deleteVolumes && bootVolumeID != nil {
249+
250+
// when using templates (cubes or gpu servers) we cannot delete the boot volume
251+
// the whole server must be deleted at once
252+
if !deleteVolumes && bootVolumeID != nil && (server.Properties != nil && server.Properties.TemplateUuid == nil) {
250253
// We need to make sure to only delete volumes if the cluster is being deleted.
251254
// If a node is being replaced, we only delete the boot volume and keep all other volumes.
252255
// The CSI will take care of re-attaching the existing volumes to the new node.
@@ -381,6 +384,15 @@ func (*Service) buildServerProperties(
381384
Type: ptr.To(machineSpec.Type.String()),
382385
}
383386

387+
if machineSpec.TemplateID != "" {
388+
props.TemplateUuid = &machineSpec.TemplateID
389+
390+
// cores, ram and cpuFamily cannot be set when using a template
391+
props.Cores = nil
392+
props.Ram = nil
393+
props.CpuFamily = nil
394+
}
395+
384396
return props
385397
}
386398

@@ -404,6 +416,12 @@ func (s *Service) buildServerEntities(ms *scope.Machine, params serverEntityPara
404416
},
405417
}
406418

419+
// size and type of the boot volume cannot be set when using a template
420+
if machineSpec.TemplateID != "" {
421+
bootVolume.Properties.Size = nil
422+
bootVolume.Properties.Type = nil
423+
}
424+
407425
if params.imageID != "" {
408426
bootVolume.Properties.Image = &params.imageID
409427
}

0 commit comments

Comments
 (0)