diff --git a/docs/getting_started/spot-ocean.md b/docs/getting_started/spot-ocean.md index 7caad1cbeb..767ea796f0 100644 --- a/docs/getting_started/spot-ocean.md +++ b/docs/getting_started/spot-ocean.md @@ -160,6 +160,8 @@ metadata: | `spotinst.io/ocean-instance-types` | Specify a list of instance types that should be used by the Ocean Launch Spec. | none | | `spotinst.io/autoscaler-disabled` | Specify whether the auto scaler should be disabled. | `false` | | `spotinst.io/autoscaler-default-node-labels` | Specify whether default node labels should be set for the auto scaler. | `false` | +| `spotinst.io/autoscaler-auto-config` | Specify whether headroom resources should be automatically configured and optimized. | `true` | +| `spotinst.io/autoscaler-auto-headroom-percentage` | Specify the auto headroom percentage (a number in the range [0, 200]) which controls the percentage of headroom. | none | | `spotinst.io/autoscaler-headroom-cpu-per-unit` | Specify the number of CPUs to allocate for headroom. CPUs are denoted in millicores, where 1000 millicores = 1 vCPU. | none | | `spotinst.io/autoscaler-headroom-gpu-per-unit` | Specify the number of GPUs to allocate for headroom. | none | | `spotinst.io/autoscaler-headroom-mem-per-unit` | Specify the amount of memory (MB) to allocate for headroom. | none | diff --git a/pkg/model/spotinstmodel/instance_group.go b/pkg/model/spotinstmodel/instance_group.go index f1d9789667..3a316ebdd9 100644 --- a/pkg/model/spotinstmodel/instance_group.go +++ b/pkg/model/spotinstmodel/instance_group.go @@ -92,6 +92,12 @@ const ( // the auto scaler. InstanceGroupLabelAutoScalerDefaultNodeLabels = "spotinst.io/autoscaler-default-node-labels" + // InstanceGroupLabelAutoScalerAuto* are the metadata labels used on the + // instance group to specify whether headroom resources should be + // automatically configured and optimized. + InstanceGroupLabelAutoScalerAutoConfig = "spotinst.io/autoscaler-auto-config" + InstanceGroupLabelAutoScalerAutoHeadroomPercentage = "spotinst.io/autoscaler-auto-headroom-percentage" + // InstanceGroupLabelAutoScalerHeadroom* are the metadata labels used on the // instance group to specify the headroom configuration used by the auto scaler. InstanceGroupLabelAutoScalerHeadroomCPUPerUnit = "spotinst.io/autoscaler-headroom-cpu-per-unit" @@ -580,6 +586,8 @@ func (b *InstanceGroupModelBuilder) buildLaunchSpec(c *fi.ModelBuilderContext, } if autoScalerOpts != nil { // remove unsupported options autoScalerOpts.Enabled = nil + autoScalerOpts.AutoConfig = nil + autoScalerOpts.AutoHeadroomPercentage = nil autoScalerOpts.ClusterID = nil autoScalerOpts.Cooldown = nil autoScalerOpts.Down = nil @@ -753,6 +761,7 @@ func (b *InstanceGroupModelBuilder) buildAutoScalerOpts(clusterID string, ig *ko // Enable the auto scaler for Node instance groups. opts.Enabled = fi.Bool(true) + opts.AutoConfig = fi.Bool(true) // Parse instance group labels. var defaultNodeLabels bool @@ -785,6 +794,24 @@ func (b *InstanceGroupModelBuilder) buildAutoScalerOpts(clusterID string, ig *ko opts.Cooldown = fi.Int(int(fi.Int64Value(v))) } + case InstanceGroupLabelAutoScalerAutoConfig: + { + v, err := parseBool(v) + if err != nil { + return nil, err + } + opts.AutoConfig = v + } + + case InstanceGroupLabelAutoScalerAutoHeadroomPercentage: + { + v, err := parseInt(v) + if err != nil { + return nil, err + } + opts.AutoHeadroomPercentage = fi.Int(int(fi.Int64Value(v))) + } + case InstanceGroupLabelAutoScalerHeadroomCPUPerUnit: { v, err := parseInt(v) @@ -883,6 +910,12 @@ func (b *InstanceGroupModelBuilder) buildAutoScalerOpts(clusterID string, ig *ko } } + // Toggle automatic configuration off if headroom resources are explicitly defined. + if fi.BoolValue(opts.AutoConfig) && opts.Headroom != nil { + opts.AutoConfig = fi.Bool(false) + opts.AutoHeadroomPercentage = nil + } + // Configure Elastigroup defaults to avoid state drifts. if !featureflag.SpotinstOcean.Enabled() { if opts.Cooldown == nil { diff --git a/upup/pkg/fi/cloudup/spotinsttasks/elastigroup.go b/upup/pkg/fi/cloudup/spotinsttasks/elastigroup.go index 3fa65a9cc4..ba912a72ed 100644 --- a/upup/pkg/fi/cloudup/spotinsttasks/elastigroup.go +++ b/upup/pkg/fi/cloudup/spotinsttasks/elastigroup.go @@ -81,14 +81,16 @@ type RootVolumeOpts struct { } type AutoScalerOpts struct { - Enabled *bool - ClusterID *string - Cooldown *int - Labels map[string]string - Taints []*corev1.Taint - Headroom *AutoScalerHeadroomOpts - Down *AutoScalerDownOpts - ResourceLimits *AutoScalerResourceLimitsOpts + Enabled *bool + AutoConfig *bool + AutoHeadroomPercentage *int + ClusterID *string + Cooldown *int + Labels map[string]string + Taints []*corev1.Taint + Headroom *AutoScalerHeadroomOpts + Down *AutoScalerDownOpts + ResourceLimits *AutoScalerResourceLimitsOpts } type AutoScalerHeadroomOpts struct { @@ -1399,13 +1401,14 @@ type terraformElastigroupIntegration struct { } type terraformAutoScaler struct { - Enabled *bool `json:"autoscale_is_enabled,omitempty" cty:"autoscale_is_enabled"` - AutoConfig *bool `json:"autoscale_is_auto_config,omitempty" cty:"autoscale_is_auto_config"` - Cooldown *int `json:"autoscale_cooldown,omitempty" cty:"autoscale_cooldown"` - Headroom *terraformAutoScalerHeadroom `json:"autoscale_headroom,omitempty" cty:"autoscale_headroom"` - Down *terraformAutoScalerDown `json:"autoscale_down,omitempty" cty:"autoscale_down"` - ResourceLimits *terraformAutoScalerResourceLimits `json:"resource_limits,omitempty" cty:"resource_limits"` - Labels []*terraformKV `json:"autoscale_labels,omitempty" cty:"autoscale_labels"` + Enabled *bool `json:"autoscale_is_enabled,omitempty" cty:"autoscale_is_enabled"` + AutoConfig *bool `json:"autoscale_is_auto_config,omitempty" cty:"autoscale_is_auto_config"` + AutoHeadroomPercentage *int `json:"auto_headroom_percentage,omitempty" cty:"auto_headroom_percentage"` + Cooldown *int `json:"autoscale_cooldown,omitempty" cty:"autoscale_cooldown"` + Headroom *terraformAutoScalerHeadroom `json:"autoscale_headroom,omitempty" cty:"autoscale_headroom"` + Down *terraformAutoScalerDown `json:"autoscale_down,omitempty" cty:"autoscale_down"` + ResourceLimits *terraformAutoScalerResourceLimits `json:"resource_limits,omitempty" cty:"resource_limits"` + Labels []*terraformKV `json:"autoscale_labels,omitempty" cty:"autoscale_labels"` } type terraformAutoScalerHeadroom struct { diff --git a/upup/pkg/fi/cloudup/spotinsttasks/ocean.go b/upup/pkg/fi/cloudup/spotinsttasks/ocean.go index 1d0ef536a3..b2f4479b55 100644 --- a/upup/pkg/fi/cloudup/spotinsttasks/ocean.go +++ b/upup/pkg/fi/cloudup/spotinsttasks/ocean.go @@ -293,6 +293,8 @@ func (o *Ocean) Find(c *fi.Context) (*Ocean, error) { actual.AutoScalerOpts = new(AutoScalerOpts) actual.AutoScalerOpts.ClusterID = ocean.ControllerClusterID actual.AutoScalerOpts.Enabled = ocean.AutoScaler.IsEnabled + actual.AutoScalerOpts.AutoConfig = ocean.AutoScaler.IsAutoConfig + actual.AutoScalerOpts.AutoHeadroomPercentage = ocean.AutoScaler.AutoHeadroomPercentage actual.AutoScalerOpts.Cooldown = ocean.AutoScaler.Cooldown // Headroom. @@ -521,7 +523,8 @@ func (_ *Ocean) create(cloud awsup.AWSCloud, a, e, changes *Ocean) error { if opts.Enabled != nil { autoScaler := new(aws.AutoScaler) autoScaler.IsEnabled = opts.Enabled - autoScaler.IsAutoConfig = fi.Bool(true) + autoScaler.IsAutoConfig = opts.AutoConfig + autoScaler.AutoHeadroomPercentage = opts.AutoHeadroomPercentage autoScaler.Cooldown = opts.Cooldown // Headroom. @@ -951,6 +954,8 @@ func (_ *Ocean) update(cloud awsup.AWSCloud, a, e, changes *Ocean) error { if opts.Enabled != nil { autoScaler := new(aws.AutoScaler) autoScaler.IsEnabled = e.AutoScalerOpts.Enabled + autoScaler.IsAutoConfig = e.AutoScalerOpts.AutoConfig + autoScaler.AutoHeadroomPercentage = e.AutoScalerOpts.AutoHeadroomPercentage autoScaler.Cooldown = e.AutoScalerOpts.Cooldown // Headroom. @@ -1182,9 +1187,10 @@ func (_ *Ocean) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *Oce if opts.Enabled != nil { tf.AutoScaler = &terraformAutoScaler{ - Enabled: opts.Enabled, - AutoConfig: fi.Bool(true), - Cooldown: opts.Cooldown, + Enabled: opts.Enabled, + AutoConfig: opts.AutoConfig, + AutoHeadroomPercentage: opts.AutoHeadroomPercentage, + Cooldown: opts.Cooldown, } // Headroom.