diff --git a/api/v1beta1/gcpmachine_types.go b/api/v1beta1/gcpmachine_types.go index 7e27e7845..dc7c3c012 100644 --- a/api/v1beta1/gcpmachine_types.go +++ b/api/v1beta1/gcpmachine_types.go @@ -217,6 +217,16 @@ type CustomerEncryptionKey struct { SuppliedKey *SuppliedKey `json:"suppliedKey,omitempty"` } +// ProvisioningModel is a type for Spot VM enablement. +type ProvisioningModel string + +const ( + // ProvisioningModelStandard specifies the VM type to NOT be Spot. + ProvisioningModelStandard ProvisioningModel = "Standard" + // ProvisioningModelSpot specifies the VM type to be Spot. + ProvisioningModelSpot ProvisioningModel = "Spot" +) + // GCPMachineSpec defines the desired state of GCPMachine. type GCPMachineSpec struct { // InstanceType is the type of instance to create. Example: n1.standard-2 @@ -302,6 +312,13 @@ type GCPMachineSpec struct { // +optional Preemptible bool `json:"preemptible,omitempty"` + // ProvisioningModel defines if instance is spot. + // If set to "Standard" while preemptible is true, then the VM will be of type "Preemptible". + // If "Spot", VM type is "Spot". When unspecified, defaults to "Standard". + // +kubebuilder:validation:Enum=Standard;Spot + // +optional + ProvisioningModel *ProvisioningModel `json:"provisioningModel,omitempty"` + // IPForwarding Allows this instance to send and receive packets with non-matching destination or source IPs. // This is required if you plan to use this instance to forward routes. Defaults to enabled. // +kubebuilder:validation:Enum=Enabled;Disabled diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index 78c0f8571..3c8560ad9 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -475,6 +475,11 @@ func (in *GCPMachineSpec) DeepCopyInto(out *GCPMachineSpec) { *out = new(ServiceAccount) (*in).DeepCopyInto(*out) } + if in.ProvisioningModel != nil { + in, out := &in.ProvisioningModel, &out.ProvisioningModel + *out = new(ProvisioningModel) + **out = **in + } if in.IPForwarding != nil { in, out := &in.IPForwarding, &out.IPForwarding *out = new(IPForwarding) diff --git a/cloud/scope/machine.go b/cloud/scope/machine.go index 96f745822..ce5d02d55 100644 --- a/cloud/scope/machine.go +++ b/cloud/scope/machine.go @@ -402,6 +402,16 @@ func (m *MachineScope) InstanceSpec(log logr.Logger) *compute.Instance { Preemptible: m.GCPMachine.Spec.Preemptible, }, } + if m.GCPMachine.Spec.ProvisioningModel != nil { + switch *m.GCPMachine.Spec.ProvisioningModel { + case infrav1.ProvisioningModelSpot: + instance.Scheduling.ProvisioningModel = "SPOT" + case infrav1.ProvisioningModelStandard: + instance.Scheduling.ProvisioningModel = "STANDARD" + default: + log.Error(errors.New("Invalid value"), "Unknown ProvisioningModel value", "Spec.ProvisioningModel", *m.GCPMachine.Spec.ProvisioningModel) + } + } instance.CanIpForward = true if m.GCPMachine.Spec.IPForwarding != nil && *m.GCPMachine.Spec.IPForwarding == infrav1.IPForwardingDisabled { diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmachines.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmachines.yaml index 291043919..5dbe18c8a 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmachines.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmachines.yaml @@ -237,6 +237,15 @@ spec: description: ProviderID is the unique identifier as specified by the cloud provider. type: string + provisioningModel: + description: |- + ProvisioningModel defines if instance is spot. + If set to "Standard" while preemptible is true, then the VM will be of type "Preemptible". + If "Spot", VM type is "Spot". When unspecified, defaults to "Standard". + enum: + - Standard + - Spot + type: string publicIP: description: |- PublicIP specifies whether the instance should get a public IP. diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmachinetemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmachinetemplates.yaml index 013c01776..ece5bc8d8 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmachinetemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmachinetemplates.yaml @@ -252,6 +252,15 @@ spec: description: ProviderID is the unique identifier as specified by the cloud provider. type: string + provisioningModel: + description: |- + ProvisioningModel defines if instance is spot. + If set to "Standard" while preemptible is true, then the VM will be of type "Preemptible". + If "Spot", VM type is "Spot". When unspecified, defaults to "Standard". + enum: + - Standard + - Spot + type: string publicIP: description: |- PublicIP specifies whether the instance should get a public IP. diff --git a/docs/book/src/topics/preemptible-vms.md b/docs/book/src/topics/preemptible-vms.md index b0e9636d9..c18bb812c 100644 --- a/docs/book/src/topics/preemptible-vms.md +++ b/docs/book/src/topics/preemptible-vms.md @@ -28,3 +28,27 @@ spec: vmSize: E2 preemptible: true ``` + +## Spot VMs +[Spot VMs are the latest version of preemptible VMs.](https://cloud.google.com/compute/docs/instances/spot) + +To use a Spot VM instead of a Preemptible VM, add `provisioningModel` to `GCPMachineTemplate` and set it to `Spot`. + +```yaml +apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 +kind: GCPMachineTemplate +metadata: + name: capg-md-0 +spec: + region: us-west-1 + template: + osDisk: + diskSizeGB: 30 + managedDisk: + storageAccountType: STANDARD + osType: Linux + vmSize: E2 + provisioningModel: Spot +``` + +NOTE: specifying `preemptible: true` and `provisioningModel: Spot` is equivalent to only `provisioningModel: Spot`. Spot takes priority.