Skip to content

Commit d93d030

Browse files
jhixson74tthvo
authored andcommitted
AWS: Add the ability to configure throughput on GP3 volumes
GP3 volumes have the ability to configure throughput from 125 MiB/s to 2000 MiB/s. This allows the ability to set this at install time in the install-config. https://issues.redhat.com/browse/CORS-4212
1 parent d05387a commit d93d030

File tree

9 files changed

+193
-8
lines changed

9 files changed

+193
-8
lines changed

data/data/install.openshift.io_installconfigs.yaml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,20 @@ spec:
249249
(GiB).
250250
minimum: 0
251251
type: integer
252+
throughput:
253+
description: |-
254+
Throughput to provision in MiB/s supported for the volume type. Not applicable to all types.
255+
256+
This parameter is valid only for gp3 volumes.
257+
Valid Range: Minimum value of 125. Maximum value of 2000.
258+
259+
When omitted, this means no opinion, and the platform is left to
260+
choose a reasonable default, which is subject to change over time.
261+
The current default is 125.
262+
format: int32
263+
maximum: 2000
264+
minimum: 125
265+
type: integer
252266
type:
253267
description: Type defines the type of the volume.
254268
type: string
@@ -1795,6 +1809,20 @@ spec:
17951809
gibibytes (GiB).
17961810
minimum: 0
17971811
type: integer
1812+
throughput:
1813+
description: |-
1814+
Throughput to provision in MiB/s supported for the volume type. Not applicable to all types.
1815+
1816+
This parameter is valid only for gp3 volumes.
1817+
Valid Range: Minimum value of 125. Maximum value of 2000.
1818+
1819+
When omitted, this means no opinion, and the platform is left to
1820+
choose a reasonable default, which is subject to change over time.
1821+
The current default is 125.
1822+
format: int32
1823+
maximum: 2000
1824+
minimum: 125
1825+
type: integer
17981826
type:
17991827
description: Type defines the type of the volume.
18001828
type: string
@@ -3281,6 +3309,20 @@ spec:
32813309
(GiB).
32823310
minimum: 0
32833311
type: integer
3312+
throughput:
3313+
description: |-
3314+
Throughput to provision in MiB/s supported for the volume type. Not applicable to all types.
3315+
3316+
This parameter is valid only for gp3 volumes.
3317+
Valid Range: Minimum value of 125. Maximum value of 2000.
3318+
3319+
When omitted, this means no opinion, and the platform is left to
3320+
choose a reasonable default, which is subject to change over time.
3321+
The current default is 125.
3322+
format: int32
3323+
maximum: 2000
3324+
minimum: 125
3325+
type: integer
32843326
type:
32853327
description: Type defines the type of the volume.
32863328
type: string
@@ -4960,6 +5002,20 @@ spec:
49605002
(GiB).
49615003
minimum: 0
49625004
type: integer
5005+
throughput:
5006+
description: |-
5007+
Throughput to provision in MiB/s supported for the volume type. Not applicable to all types.
5008+
5009+
This parameter is valid only for gp3 volumes.
5010+
Valid Range: Minimum value of 125. Maximum value of 2000.
5011+
5012+
When omitted, this means no opinion, and the platform is left to
5013+
choose a reasonable default, which is subject to change over time.
5014+
The current default is 125.
5015+
format: int32
5016+
maximum: 2000
5017+
minimum: 125
5018+
type: integer
49635019
type:
49645020
description: Type defines the type of the volume.
49655021
type: string

docs/user/aws/customization.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ Beyond the [platform-agnostic `install-config.yaml` properties](../customization
1818
* `rootVolume` (optional object): Defines the root volume for EC2 instances in the machine pool.
1919
* `iops` (optional integer): The amount of provisioned [IOPS][volume-iops].
2020
This is only valid for `type` `io1`.
21+
* `throughput` (optional integer): The amount of throughput in MiB/s [Throughput Performance][volume-throughput].
22+
This is only valid for `type` `gp3`.
2123
* `size` (optional integer): Size of the root volume in gibibytes (GiB).
2224
* `type` (optional string): The [type of volume][volume-type].
2325
* `kmsKeyARN` (optional string): The [ARN of KMS key][kms-key] that should be used to encrypt the EBS volume.
@@ -119,4 +121,5 @@ sshKey: ssh-ed25519 AAAA...
119121
[kms-key-default]: https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetEbsDefaultKmsKeyId.html
120122
[kms-key]: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html
121123
[volume-iops]: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-io-characteristics.html
124+
[volume-throughput]: https://docs.aws.amazon.com/ebs/latest/userguide/general-purpose.html#gp3-ebs-volume-type
122125
[volume-type]: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html

pkg/asset/machines/aws/awsmachines.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ func GenerateMachines(clusterID string, in *MachineInput) ([]*asset.RuntimeFile,
118118
}
119119
awsMachine.SetGroupVersionKind(capa.GroupVersion.WithKind("AWSMachine"))
120120

121+
if throughput := mpool.EC2RootVolume.Throughput; throughput != nil {
122+
awsMachine.Spec.RootVolume.Throughput = ptr.To(int64(*throughput))
123+
}
124+
121125
if in.Role == "bootstrap" {
122126
awsMachine.Name = capiutils.GenerateBoostrapMachineName(clusterID)
123127
awsMachine.Labels["install.openshift.io/bootstrap"] = ""

pkg/asset/machines/aws/awsmachines_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,10 @@ func TestGenerateMachines(t *testing.T) {
227227
fmt.Sprintf("%s-subnet-public-%s", stubClusterID, machineZone),
228228
}}},
229229
},
230-
SSHKeyName: ptr.To(""),
231-
RootVolume: &capa.Volume{Encrypted: ptr.To(true)},
230+
SSHKeyName: ptr.To(""),
231+
RootVolume: &capa.Volume{
232+
Encrypted: ptr.To(true),
233+
},
232234
UncompressedUserData: ptr.To(true),
233235
Ignition: &capa.Ignition{
234236
StorageType: capa.IgnitionStorageTypeOptionUnencryptedUserData,

pkg/asset/machines/aws/machines.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -242,11 +242,12 @@ func provider(in *machineProviderInput) (*machineapi.AWSMachineProviderConfig, e
242242
BlockDevices: []machineapi.BlockDeviceMappingSpec{
243243
{
244244
EBS: &machineapi.EBSBlockDeviceSpec{
245-
VolumeType: pointer.String(in.root.Type),
246-
VolumeSize: pointer.Int64(int64(in.root.Size)),
247-
Iops: pointer.Int64(int64(in.root.IOPS)),
248-
Encrypted: pointer.Bool(true),
249-
KMSKey: machineapi.AWSResourceReference{ARN: pointer.String(in.root.KMSKeyARN)},
245+
VolumeType: pointer.String(in.root.Type),
246+
VolumeSize: pointer.Int64(int64(in.root.Size)),
247+
Iops: pointer.Int64(int64(in.root.IOPS)),
248+
ThroughputMib: in.root.Throughput,
249+
Encrypted: pointer.Bool(true),
250+
KMSKey: machineapi.AWSResourceReference{ARN: pointer.String(in.root.KMSKeyARN)},
250251
},
251252
},
252253
},

pkg/types/aws/machinepool.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ func (a *MachinePool) Set(required *MachinePool) {
7979
if required.EC2RootVolume.IOPS != 0 {
8080
a.EC2RootVolume.IOPS = required.EC2RootVolume.IOPS
8181
}
82+
if required.EC2RootVolume.Throughput != nil {
83+
a.EC2RootVolume.Throughput = required.EC2RootVolume.Throughput
84+
}
8285
if required.EC2RootVolume.Size != 0 {
8386
a.EC2RootVolume.Size = required.EC2RootVolume.Size
8487
}
@@ -119,6 +122,20 @@ type EC2RootVolume struct {
119122
// +optional
120123
IOPS int `json:"iops"`
121124

125+
// Throughput to provision in MiB/s supported for the volume type. Not applicable to all types.
126+
//
127+
// This parameter is valid only for gp3 volumes.
128+
// Valid Range: Minimum value of 125. Maximum value of 2000.
129+
//
130+
// When omitted, this means no opinion, and the platform is left to
131+
// choose a reasonable default, which is subject to change over time.
132+
// The current default is 125.
133+
//
134+
// +kubebuilder:validation:Minimum:=125
135+
// +kubebuilder:validation:Maximum:=2000
136+
// +optional
137+
Throughput *int32 `json:"throughput,omitempty"`
138+
122139
// Size defines the size of the volume in gibibytes (GiB).
123140
//
124141
// +kubebuilder:validation:Minimum=0

pkg/types/aws/validation/machinepool.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ func ValidateMachinePool(platform *aws.Platform, p *aws.MachinePool, fldPath *fi
5151
if p.EC2RootVolume.Type != "" {
5252
allErrs = append(allErrs, validateVolumeSize(p, fldPath)...)
5353
allErrs = append(allErrs, validateIOPS(p, fldPath)...)
54+
allErrs = append(allErrs, validateThroughput(p, fldPath)...)
5455
}
5556

5657
if p.EC2Metadata.Authentication != "" && !validMetadataAuthValues.Has(p.EC2Metadata.Authentication) {
@@ -114,6 +115,28 @@ func validateIOPS(p *aws.MachinePool, fldPath *field.Path) field.ErrorList {
114115
return allErrs
115116
}
116117

118+
func validateThroughput(p *aws.MachinePool, fldPath *field.Path) field.ErrorList {
119+
allErrs := field.ErrorList{}
120+
121+
if p.EC2RootVolume.Throughput == nil {
122+
return allErrs
123+
}
124+
125+
volumeType := strings.ToLower(p.EC2RootVolume.Type)
126+
throughput := *p.EC2RootVolume.Throughput
127+
128+
switch volumeType {
129+
case "gp3":
130+
if throughput < 125 || throughput > 2000 {
131+
allErrs = append(allErrs, field.Invalid(fldPath.Child("throughput"), throughput, "throughput must be between 125 MiB/s and 2000 MiB/s"))
132+
}
133+
default:
134+
allErrs = append(allErrs, field.Invalid(fldPath.Child("throughput"), throughput, fmt.Sprintf("throughput not supported for type %s", volumeType)))
135+
}
136+
137+
return allErrs
138+
}
139+
117140
// ValidateAMIID check the AMI ID is set for a machine pool.
118141
func ValidateAMIID(platform *aws.Platform, p *aws.MachinePool, fldPath *field.Path) field.ErrorList {
119142
allErrs := field.ErrorList{}

pkg/types/aws/validation/machinepool_test.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,80 @@ func TestValidateMachinePool(t *testing.T) {
129129
},
130130
expected: `^test-path\.authentication: Invalid value: \"foobarbaz\": must be either Required or Optional$`,
131131
},
132+
{
133+
name: "valid root volume throughput, within allowed range",
134+
pool: &aws.MachinePool{
135+
EC2RootVolume: aws.EC2RootVolume{
136+
Type: "gp3",
137+
Size: 100,
138+
Throughput: ptr.To(int32(1200)),
139+
},
140+
},
141+
},
142+
{
143+
name: "valid root volume throughput, nil or unspecified",
144+
pool: &aws.MachinePool{
145+
EC2RootVolume: aws.EC2RootVolume{
146+
Type: "gp3",
147+
Size: 100,
148+
},
149+
},
150+
},
151+
{
152+
name: "invalid root volume throughput, below minimum",
153+
pool: &aws.MachinePool{
154+
EC2RootVolume: aws.EC2RootVolume{
155+
Type: "gp3",
156+
Size: 100,
157+
Throughput: ptr.To(int32(124)),
158+
},
159+
},
160+
expected: `^test-path\.throughput: Invalid value: 124: throughput must be between 125 MiB/s and 2000 MiB/s$`,
161+
},
162+
{
163+
name: "invalid root volume throughput, above maximum",
164+
pool: &aws.MachinePool{
165+
EC2RootVolume: aws.EC2RootVolume{
166+
Type: "gp3",
167+
Size: 100,
168+
Throughput: ptr.To(int32(2001)),
169+
},
170+
},
171+
expected: `^test-path\.throughput: Invalid value: 2001: throughput must be between 125 MiB/s and 2000 MiB/s$`,
172+
},
173+
{
174+
name: "invalid root volume throughput, zero",
175+
pool: &aws.MachinePool{
176+
EC2RootVolume: aws.EC2RootVolume{
177+
Type: "gp3",
178+
Size: 100,
179+
Throughput: ptr.To(int32(0)),
180+
},
181+
},
182+
expected: `^test-path\.throughput: Invalid value: 0: throughput must be between 125 MiB/s and 2000 MiB/s$`,
183+
},
184+
{
185+
name: "invalid root volume throughput, negative",
186+
pool: &aws.MachinePool{
187+
EC2RootVolume: aws.EC2RootVolume{
188+
Type: "gp3",
189+
Size: 100,
190+
Throughput: ptr.To(int32(-100)),
191+
},
192+
},
193+
expected: `^test-path\.throughput: Invalid value: -100: throughput must be between 125 MiB/s and 2000 MiB/s$`,
194+
},
195+
{
196+
name: "invalid root volume throughput, unsupported volume type",
197+
pool: &aws.MachinePool{
198+
EC2RootVolume: aws.EC2RootVolume{
199+
Type: "gp2",
200+
Size: 100,
201+
Throughput: ptr.To(int32(125)),
202+
},
203+
},
204+
expected: `^test-path\.throughput: Invalid value: 125: throughput not supported for type gp2$`,
205+
},
132206
}
133207
for _, tc := range cases {
134208
t.Run(tc.name, func(t *testing.T) {

pkg/types/aws/zz_generated.deepcopy.go

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)