Skip to content

Commit b35dbe6

Browse files
Merge pull request #10132 from tthvo/CORS-4212
CORS-4212: AWS: Add the ability to configure throughput on GP3 volumes
2 parents 6901d28 + 2a98b2b commit b35dbe6

23 files changed

+496
-33
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

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ require (
8484
github.com/nutanix-cloud-native/cluster-api-provider-nutanix v1.7.0
8585
github.com/nutanix-cloud-native/prism-go-client v0.5.0
8686
github.com/onsi/gomega v1.38.2
87-
github.com/openshift/api v0.0.0-20251117165054-348370f055bf
87+
github.com/openshift/api v0.0.0-20251120220512-cb382c9eaf42
8888
github.com/openshift/assisted-image-service v0.0.0-20240607085136-02df2e56dde6
8989
github.com/openshift/assisted-service/api v0.0.0
9090
github.com/openshift/assisted-service/client v0.0.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -701,8 +701,8 @@ github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQ
701701
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
702702
github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
703703
github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
704-
github.com/openshift/api v0.0.0-20251117165054-348370f055bf h1:8VzLlQFneh4bnHA3SS+Bb9VWdVaR7WugtSeqIngMC3s=
705-
github.com/openshift/api v0.0.0-20251117165054-348370f055bf/go.mod h1:d5uzF0YN2nQQFA0jIEWzzOZ+edmo6wzlGLvx5Fhz4uY=
704+
github.com/openshift/api v0.0.0-20251120220512-cb382c9eaf42 h1:Mo2FlDdoCZ+BE2W4C0lNcxEDeIIhfsYFP6vj4Sggp8w=
705+
github.com/openshift/api v0.0.0-20251120220512-cb382c9eaf42/go.mod h1:d5uzF0YN2nQQFA0jIEWzzOZ+edmo6wzlGLvx5Fhz4uY=
706706
github.com/openshift/assisted-image-service v0.0.0-20240607085136-02df2e56dde6 h1:U6ve+dnHlHhAELoxX+rdFOHVhoaYl0l9qtxwYtsO6C0=
707707
github.com/openshift/assisted-image-service v0.0.0-20240607085136-02df2e56dde6/go.mod h1:o2H5VwQhUD8P6XsK6dRmKpCCJqVvv12KJQZBXmcCXCU=
708708
github.com/openshift/assisted-service/api v0.0.0-20250922204150-a52b83145bea h1:YhJ9iHKKT5ooAdVr8qq3BdudhTxP/WF0XYDT5gzi1ak=

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
},
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package defaults
2+
3+
import (
4+
"github.com/openshift/installer/pkg/types"
5+
"github.com/openshift/installer/pkg/types/aws"
6+
)
7+
8+
const (
9+
// defaultRootVolumeSize is the default roote volume size in GB.
10+
defaultRootVolumeSize = 120
11+
)
12+
13+
// SetMachinePoolDefaults sets the defaults for the platform.
14+
func SetMachinePoolDefaults(pool *aws.MachinePool, role string) {
15+
if pool == nil {
16+
return
17+
}
18+
19+
// Set the default volume type for machine pool.
20+
// The current default is gp3 for control plane and worker pool.
21+
// For edge pool, the current default is gp2.
22+
// See: https://github.com/openshift/installer/blob/fd5a518e4951510b82705eee8184b3dd4f2723b2/pkg/asset/machines/worker.go#L102-L117
23+
if pool.EC2RootVolume.Type == "" {
24+
defaultEBSType := aws.VolumeTypeGp3
25+
if role == types.MachinePoolEdgeRoleName {
26+
defaultEBSType = aws.VolumeTypeGp2
27+
}
28+
pool.EC2RootVolume.Type = defaultEBSType
29+
}
30+
31+
if pool.EC2RootVolume.Size == 0 {
32+
pool.EC2RootVolume.Size = defaultRootVolumeSize
33+
}
34+
}
35+
36+
// Apply sets values from the default machine platform to the machinepool.
37+
func Apply(defaultMachinePlatform, machinePool *aws.MachinePool) {
38+
// Construct a temporary machine pool so we can set the
39+
// defaults first, without overwriting the pool-sepcific values,
40+
// which have precedence.
41+
tempMP := &aws.MachinePool{}
42+
tempMP.Set(defaultMachinePlatform)
43+
tempMP.Set(machinePool)
44+
machinePool.Set(tempMP)
45+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package defaults
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
8+
"github.com/openshift/installer/pkg/types"
9+
"github.com/openshift/installer/pkg/types/aws"
10+
)
11+
12+
func TestSetMachinePoolDefaults(t *testing.T) {
13+
cases := []struct {
14+
name string
15+
pool *aws.MachinePool
16+
role string
17+
expected *aws.MachinePool
18+
}{
19+
{
20+
name: "nil pool",
21+
pool: nil,
22+
role: types.MachinePoolComputeRoleName,
23+
expected: nil,
24+
},
25+
{
26+
name: "empty pool - worker pool sets gp3",
27+
pool: &aws.MachinePool{},
28+
role: types.MachinePoolComputeRoleName,
29+
expected: &aws.MachinePool{
30+
EC2RootVolume: aws.EC2RootVolume{
31+
Type: aws.VolumeTypeGp3,
32+
Size: defaultRootVolumeSize,
33+
},
34+
},
35+
},
36+
{
37+
name: "empty pool - control plane pool sets gp3",
38+
pool: &aws.MachinePool{},
39+
role: types.MachinePoolControlPlaneRoleName,
40+
expected: &aws.MachinePool{
41+
EC2RootVolume: aws.EC2RootVolume{
42+
Type: aws.VolumeTypeGp3,
43+
Size: defaultRootVolumeSize,
44+
},
45+
},
46+
},
47+
{
48+
name: "empty pool - arbiter pool sets gp3",
49+
pool: &aws.MachinePool{},
50+
role: types.MachinePoolArbiterRoleName,
51+
expected: &aws.MachinePool{
52+
EC2RootVolume: aws.EC2RootVolume{
53+
Type: aws.VolumeTypeGp3,
54+
Size: defaultRootVolumeSize,
55+
},
56+
},
57+
},
58+
{
59+
name: "empty pool - edge pool sets gp2",
60+
pool: &aws.MachinePool{},
61+
role: types.MachinePoolEdgeRoleName,
62+
expected: &aws.MachinePool{
63+
EC2RootVolume: aws.EC2RootVolume{
64+
Type: aws.VolumeTypeGp2,
65+
Size: defaultRootVolumeSize,
66+
},
67+
},
68+
},
69+
{
70+
name: "pool with existing volume type - should not override",
71+
pool: &aws.MachinePool{
72+
EC2RootVolume: aws.EC2RootVolume{
73+
Type: aws.VolumeTypeGp2,
74+
Size: defaultRootVolumeSize,
75+
},
76+
},
77+
role: types.MachinePoolComputeRoleName,
78+
expected: &aws.MachinePool{
79+
EC2RootVolume: aws.EC2RootVolume{
80+
Type: aws.VolumeTypeGp2,
81+
Size: defaultRootVolumeSize,
82+
},
83+
},
84+
},
85+
}
86+
87+
for _, tc := range cases {
88+
t.Run(tc.name, func(t *testing.T) {
89+
SetMachinePoolDefaults(tc.pool, tc.role)
90+
assert.Equal(t, tc.expected, tc.pool, "unexpected machine pool defaults")
91+
})
92+
}
93+
}

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

0 commit comments

Comments
 (0)