From 64091031d2782e1aa910da80690211b6de9b3a72 Mon Sep 17 00:00:00 2001 From: John Hixson Date: Tue, 16 Sep 2025 21:57:14 -0700 Subject: [PATCH] AWS: Add the ability to configure throughput on GP3 volumes GP3 volumes have the ability to configure throughput from 125 MiB/s to 1000 MiB/s. This allows the ability to set this at install time in the install-config. https://issues.redhat.com/browse/CORS-4212 --- .../install.openshift.io_installconfigs.yaml | 24 +++++++++++++++++++ pkg/asset/machines/aws/awsmachines.go | 1 + pkg/asset/machines/aws/machines.go | 1 + pkg/tfvars/aws/aws.go | 4 ++++ pkg/types/aws/machinepool.go | 9 +++++++ pkg/types/aws/validation/machinepool.go | 20 ++++++++++++++++ 6 files changed, 59 insertions(+) diff --git a/data/data/install.openshift.io_installconfigs.yaml b/data/data/install.openshift.io_installconfigs.yaml index 7a4808024ec..e3844e20b14 100644 --- a/data/data/install.openshift.io_installconfigs.yaml +++ b/data/data/install.openshift.io_installconfigs.yaml @@ -221,6 +221,12 @@ spec: (GiB). minimum: 0 type: integer + throughput: + description: Throughput to provision in MiB/s supported + for the volume type. Not applicable to all types. + format: int64 + minimum: 0 + type: integer type: description: Type defines the type of the volume. type: string @@ -1661,6 +1667,12 @@ spec: gibibytes (GiB). minimum: 0 type: integer + throughput: + description: Throughput to provision in MiB/s supported + for the volume type. Not applicable to all types. + format: int64 + minimum: 0 + type: integer type: description: Type defines the type of the volume. type: string @@ -3041,6 +3053,12 @@ spec: (GiB). minimum: 0 type: integer + throughput: + description: Throughput to provision in MiB/s supported + for the volume type. Not applicable to all types. + format: int64 + minimum: 0 + type: integer type: description: Type defines the type of the volume. type: string @@ -4604,6 +4622,12 @@ spec: (GiB). minimum: 0 type: integer + throughput: + description: Throughput to provision in MiB/s supported + for the volume type. Not applicable to all types. + format: int64 + minimum: 0 + type: integer type: description: Type defines the type of the volume. type: string diff --git a/pkg/asset/machines/aws/awsmachines.go b/pkg/asset/machines/aws/awsmachines.go index 04696d7d401..023ed02a32f 100644 --- a/pkg/asset/machines/aws/awsmachines.go +++ b/pkg/asset/machines/aws/awsmachines.go @@ -107,6 +107,7 @@ func GenerateMachines(clusterID string, in *MachineInput) ([]*asset.RuntimeFile, Size: int64(mpool.EC2RootVolume.Size), Type: capa.VolumeType(mpool.EC2RootVolume.Type), IOPS: int64(mpool.EC2RootVolume.IOPS), + Throughput: ptr.To(mpool.EC2RootVolume.Throughput), Encrypted: ptr.To(true), EncryptionKey: mpool.KMSKeyARN, }, diff --git a/pkg/asset/machines/aws/machines.go b/pkg/asset/machines/aws/machines.go index b0b21c531af..561b1bb3083 100644 --- a/pkg/asset/machines/aws/machines.go +++ b/pkg/asset/machines/aws/machines.go @@ -242,6 +242,7 @@ func provider(in *machineProviderInput) (*machineapi.AWSMachineProviderConfig, e VolumeType: pointer.String(in.root.Type), VolumeSize: pointer.Int64(int64(in.root.Size)), Iops: pointer.Int64(int64(in.root.IOPS)), + Throughput: pointer.Int64(int64(in.root.Throughput)), Encrypted: pointer.Bool(true), KMSKey: machineapi.AWSResourceReference{ARN: pointer.String(in.root.KMSKeyARN)}, }, diff --git a/pkg/tfvars/aws/aws.go b/pkg/tfvars/aws/aws.go index 1d9ba7ad87d..28f448e4652 100644 --- a/pkg/tfvars/aws/aws.go +++ b/pkg/tfvars/aws/aws.go @@ -31,6 +31,7 @@ type Config struct { EdgeZonesGatewayIndex map[string]int `json:"aws_edge_parent_zones_index,omitempty"` EdgeZonesType map[string]string `json:"aws_edge_zones_type,omitempty"` IOPS int64 `json:"aws_master_root_volume_iops"` + Throughput int64 `json:"aws_master_root_volume_throughput"` Size int64 `json:"aws_master_root_volume_size,omitempty"` Type string `json:"aws_master_root_volume_type,omitempty"` Encrypted bool `json:"aws_master_root_volume_encrypted"` @@ -244,6 +245,9 @@ func TFVars(sources TFVarsSources) ([]byte, error) { if rootVolume.EBS.Iops != nil { cfg.IOPS = *rootVolume.EBS.Iops } + if rootVolume.EBS.Throughput != nil { + cfg.Throughput = *rootVolume.EBS.Throughput + } cfg.Encrypted = true if rootVolume.EBS.Encrypted != nil { diff --git a/pkg/types/aws/machinepool.go b/pkg/types/aws/machinepool.go index 60ee8d977f6..aeb0ea8e74a 100644 --- a/pkg/types/aws/machinepool.go +++ b/pkg/types/aws/machinepool.go @@ -71,6 +71,9 @@ func (a *MachinePool) Set(required *MachinePool) { if required.EC2RootVolume.IOPS != 0 { a.EC2RootVolume.IOPS = required.EC2RootVolume.IOPS } + if required.EC2RootVolume.Throughput != 0 { + a.EC2RootVolume.Throughput = required.EC2RootVolume.Throughput + } if required.EC2RootVolume.Size != 0 { a.EC2RootVolume.Size = required.EC2RootVolume.Size } @@ -107,6 +110,12 @@ type EC2RootVolume struct { // +optional IOPS int `json:"iops"` + // Throughput to provision in MiB/s supported for the volume type. Not applicable to all types. + // + // +kubebuilder:validation:Minimum=0 + // +optional + Throughput int64 `json:"throughput"` + // Size defines the size of the volume in gibibytes (GiB). // // +kubebuilder:validation:Minimum=0 diff --git a/pkg/types/aws/validation/machinepool.go b/pkg/types/aws/validation/machinepool.go index b4db532fe50..a6a1c61aeec 100644 --- a/pkg/types/aws/validation/machinepool.go +++ b/pkg/types/aws/validation/machinepool.go @@ -46,6 +46,7 @@ func ValidateMachinePool(platform *aws.Platform, p *aws.MachinePool, fldPath *fi if p.EC2RootVolume.Type != "" { allErrs = append(allErrs, validateVolumeSize(p, fldPath)...) allErrs = append(allErrs, validateIOPS(p, fldPath)...) + allErrs = append(allErrs, validateThroughput(p, fldPath)...) } if p.EC2Metadata.Authentication != "" && !validMetadataAuthValues.Has(p.EC2Metadata.Authentication) { @@ -108,6 +109,25 @@ func validateIOPS(p *aws.MachinePool, fldPath *field.Path) field.ErrorList { return allErrs } +func validateThroughput(p *aws.MachinePool, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + volumeType := strings.ToLower(p.EC2RootVolume.Type) + throughput := p.EC2RootVolume.Throughput + + switch volumeType { + case "gp3": + if throughput < 125 || throughput > 1000 { + allErrs = append(allErrs, field.Invalid(fldPath.Child("throughput"), throughput, "throughput must be between 125 MiB/s and 1000 MiB/s")) + } + default: + if throughput != 0 { + allErrs = append(allErrs, field.Invalid(fldPath.Child("throughput"), throughput, fmt.Sprintf("throughput not supported for type %s", volumeType))) + } + } + + return allErrs +} + // ValidateAMIID check the AMI ID is set for a machine pool. func ValidateAMIID(platform *aws.Platform, p *aws.MachinePool, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{}