From eea30bda5a9d8cc5afe88770a58afde10270c975 Mon Sep 17 00:00:00 2001 From: Rafael Fonseca Date: Sun, 5 May 2024 18:24:35 +0200 Subject: [PATCH 1/3] aws: terraform: add spot instance support for masters Spot instances can result on savings for short-lived clusters. --- data/data/aws/bootstrap/main.tf | 10 ++++++++++ data/data/aws/cluster/main.tf | 1 + data/data/aws/cluster/master/main.tf | 10 ++++++++++ data/data/aws/cluster/master/variables.tf | 5 +++++ data/data/aws/variables-aws.tf | 6 ++++++ 5 files changed, 32 insertions(+) diff --git a/data/data/aws/bootstrap/main.tf b/data/data/aws/bootstrap/main.tf index 963b662cf9a..e3a0954892d 100644 --- a/data/data/aws/bootstrap/main.tf +++ b/data/data/aws/bootstrap/main.tf @@ -163,6 +163,16 @@ resource "aws_instance" "bootstrap" { vpc_security_group_ids = [var.master_sg_id, aws_security_group.bootstrap.id] associate_public_ip_address = local.public_endpoints && var.aws_public_ipv4_pool == "" + dynamic "instance_market_options" { + for_each = var.aws_master_use_spot_instance ? [1] : [] + content { + market_type = "spot" + spot_options { + spot_instance_type = "one-time" + } + } + } + lifecycle { # Ignore changes in the AMI which force recreation of the resource. This # avoids accidental deletion of nodes whenever a new OS release comes out. diff --git a/data/data/aws/cluster/main.tf b/data/data/aws/cluster/main.tf index e6ebcf6b81a..5912484aef8 100644 --- a/data/data/aws/cluster/main.tf +++ b/data/data/aws/cluster/main.tf @@ -55,6 +55,7 @@ module "masters" { user_data_ign = var.ignition_master publish_strategy = var.aws_publish_strategy iam_role_name = var.aws_master_iam_role_name + use_spot_instance = var.aws_master_use_spot_instance } module "iam" { diff --git a/data/data/aws/cluster/master/main.tf b/data/data/aws/cluster/master/main.tf index 6a61e831c6e..22c198327c1 100644 --- a/data/data/aws/cluster/master/main.tf +++ b/data/data/aws/cluster/master/main.tf @@ -146,6 +146,16 @@ resource "aws_instance" "master" { device_index = 0 } + dynamic "instance_market_options" { + for_each = var.use_spot_instance ? [1] : [] + content { + market_type = "spot" + spot_options { + spot_instance_type = "one-time" + } + } + } + lifecycle { # Ignore changes in the AMI which force recreation of the resource. This # avoids accidental deletion of nodes whenever a new CoreOS Release comes diff --git a/data/data/aws/cluster/master/variables.tf b/data/data/aws/cluster/master/variables.tf index 1d785767aff..34638960e7e 100644 --- a/data/data/aws/cluster/master/variables.tf +++ b/data/data/aws/cluster/master/variables.tf @@ -101,3 +101,8 @@ variable "iam_role_name" { type = string description = "The name of the existing role to use for the instance profile" } + +variable "use_spot_instance" { + type = bool + description = "Whether to use Spot instances for masters" +} diff --git a/data/data/aws/variables-aws.tf b/data/data/aws/variables-aws.tf index 57c9c0262f3..8a8a9a842f8 100644 --- a/data/data/aws/variables-aws.tf +++ b/data/data/aws/variables-aws.tf @@ -239,3 +239,9 @@ EOF default = "" } + +variable "aws_master_use_spot_instance" { + type = bool + description = "(optional) Whether to use instances from the Spot market for masters" + default = false +} From 4b9b06ab5bdc51776e628b784421d4044ee7f96c Mon Sep 17 00:00:00 2001 From: Rafael Fonseca Date: Sun, 5 May 2024 18:32:24 +0200 Subject: [PATCH 2/3] tfvars: aws: enable spot instance for master if set If the control plane machine manifests have been edited with spot instance information, enable the use of spot instances in the terraform config. Notice that max price information is ignored, since it's not advised for it to be set. --- pkg/tfvars/aws/aws.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkg/tfvars/aws/aws.go b/pkg/tfvars/aws/aws.go index 2c2280b7b6d..1d9ba7ad87d 100644 --- a/pkg/tfvars/aws/aws.go +++ b/pkg/tfvars/aws/aws.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/pkg/errors" + "github.com/sirupsen/logrus" machinev1beta1 "github.com/openshift/api/machine/v1beta1" "github.com/openshift/installer/pkg/asset/ignition/bootstrap" @@ -50,6 +51,7 @@ type Config struct { PreserveBootstrapIgnition bool `json:"aws_preserve_bootstrap_ignition"` MasterSecurityGroups []string `json:"aws_master_security_groups,omitempty"` PublicIpv4Pool string `json:"aws_public_ipv4_pool"` + MasterUseSpotInstance bool `json:"aws_master_use_spot_instance,omitempty"` } // TFVarsSources contains the parameters to be converted into Terraform variables @@ -187,6 +189,11 @@ func TFVars(sources TFVarsSources) ([]byte, error) { return nil, errors.New("EBS IOPS must be configured for the io1 root volume") } + useSpotInstances := masterConfig.SpotMarketOptions != nil + if useSpotInstances { + logrus.Warn("Found Spot instance configuration. Please be warned, this is not advised.") + } + cfg := &Config{ CustomEndpoints: endpoints, Region: masterConfig.Placement.Region, @@ -211,6 +218,7 @@ func TFVars(sources TFVarsSources) ([]byte, error) { PreserveBootstrapIgnition: sources.PreserveBootstrapIgnition, MasterSecurityGroups: sources.MasterSecurityGroups, PublicIpv4Pool: sources.PublicIpv4Pool, + MasterUseSpotInstance: useSpotInstances, } stubIgn, err := bootstrap.GenerateIgnitionShimWithCertBundleAndProxy(sources.IgnitionPresignedURL, sources.AdditionalTrustBundle, sources.Proxy) From 8ec547f84f77df19c38c7378ff33f14f6c83b06a Mon Sep 17 00:00:00 2001 From: Rafael Fonseca Date: Thu, 23 May 2024 19:17:14 +0200 Subject: [PATCH 3/3] CORS-3524: cmd: add a way to list hidden features For now this will be use to detect installer versions that support Spot instance features. The command is marked as `hidden` since it's supposed to be used only internally. --- cmd/openshift-install/features.go | 42 +++++++++++++++++++++++++++++++ cmd/openshift-install/main.go | 1 + 2 files changed, 43 insertions(+) create mode 100644 cmd/openshift-install/features.go diff --git a/cmd/openshift-install/features.go b/cmd/openshift-install/features.go new file mode 100644 index 00000000000..2b5650f73a8 --- /dev/null +++ b/cmd/openshift-install/features.go @@ -0,0 +1,42 @@ +package main + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +var ( + outputJSON = false + hiddenFeatures = []string{ + "terraform-spot-masters", + } +) + +func newListFeaturesCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "list-hidden-features", + Short: "List supported hidden features", + Long: "", + Hidden: true, + Args: cobra.ExactArgs(0), + Run: func(_ *cobra.Command, _ []string) { + var out string + if outputJSON { + outb, err := json.Marshal(hiddenFeatures) + if err != nil { + logrus.Fatalf("failed to marshal output: %s", err.Error()) + } + out = string(outb) + } else { + out = strings.Join(hiddenFeatures, "\n") + } + fmt.Println(out) + }, + } + cmd.PersistentFlags().BoolVar(&outputJSON, "json", false, "print output in json format") + return cmd +} diff --git a/cmd/openshift-install/main.go b/cmd/openshift-install/main.go index 97228eaab8c..b147ea604b8 100644 --- a/cmd/openshift-install/main.go +++ b/cmd/openshift-install/main.go @@ -55,6 +55,7 @@ func installerMain() { newCompletionCmd(), newExplainCmd(), newAgentCmd(ctx), + newListFeaturesCmd(), } { rootCmd.AddCommand(subCmd) }