Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Spot VMs #1313

Merged
merged 1 commit into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions api/v1beta1/gcpmachine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions api/v1beta1/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 cloud/scope/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,16 @@ func (m *MachineScope) InstanceSpec(log logr.Logger) *compute.Instance {
Preemptible: m.GCPMachine.Spec.Preemptible,
},
}
if m.GCPMachine.Spec.ProvisioningModel != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also explicitly set the ProvisioningModel to Standard when not null or is it implicitly set by GCP?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do believe GCP defaults to STANDARD. All documentation seems to be focused around specifying SPOT and otherwise ignoring the field.

I also figured it was lower risk to maintain the existing behavior when the field is not set, allowing the GCP default to continue to be used.

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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,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.
Expand Down
24 changes: 24 additions & 0 deletions docs/book/src/topics/preemptible-vms.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.