Skip to content

Commit 60d5cf3

Browse files
✨ Add ability to control "EKS Auto Mode" for EKS clusters
Signed-off-by: Siarhei Rasiukevich <[email protected]>
1 parent f3c2166 commit 60d5cf3

11 files changed

+1443
-81
lines changed

config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanes.yaml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2345,6 +2345,33 @@ spec:
23452345
AssociateOIDCProvider can be enabled to automatically create an identity
23462346
provider for the controller for use with IAM roles for service accounts
23472347
type: boolean
2348+
autoMode:
2349+
description: |-
2350+
AutoMode is the EKS Auto Mode.
2351+
allows to create cluster with aws compute, ebs, elb capabilities.
2352+
properties:
2353+
compute:
2354+
description: Compute capability configuration for EKS Auto Mode.
2355+
properties:
2356+
nodePools:
2357+
description: NodePools that defines the compute resources
2358+
for your EKS Auto Mode cluster.
2359+
items:
2360+
type: string
2361+
type: array
2362+
nodeRoleArn:
2363+
description: |-
2364+
NodeRoleArn the ARN of the IAM Role EKS will assign to EC2 Managed Instances in your EKS
2365+
Auto Mode cluster. This value cannot be changed after the compute capability of
2366+
EKS Auto Mode is enabled. For more information, see the IAM Reference in the
2367+
Amazon EKS User Guide.
2368+
type: string
2369+
type: object
2370+
enabled:
2371+
default: false
2372+
description: Enabled will enable EKS Auto Mode.
2373+
type: boolean
2374+
type: object
23482375
bastion:
23492376
description: Bastion contains options to configure the bastion host.
23502377
properties:

config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanetemplates.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,34 @@ spec:
129129
AssociateOIDCProvider can be enabled to automatically create an identity
130130
provider for the controller for use with IAM roles for service accounts
131131
type: boolean
132+
autoMode:
133+
description: |-
134+
AutoMode is the EKS Auto Mode.
135+
allows to create cluster with aws compute, ebs, elb capabilities.
136+
properties:
137+
compute:
138+
description: Compute capability configuration for EKS
139+
Auto Mode.
140+
properties:
141+
nodePools:
142+
description: NodePools that defines the compute resources
143+
for your EKS Auto Mode cluster.
144+
items:
145+
type: string
146+
type: array
147+
nodeRoleArn:
148+
description: |-
149+
NodeRoleArn the ARN of the IAM Role EKS will assign to EC2 Managed Instances in your EKS
150+
Auto Mode cluster. This value cannot be changed after the compute capability of
151+
EKS Auto Mode is enabled. For more information, see the IAM Reference in the
152+
Amazon EKS User Guide.
153+
type: string
154+
type: object
155+
enabled:
156+
default: false
157+
description: Enabled will enable EKS Auto Mode.
158+
type: boolean
159+
type: object
132160
bastion:
133161
description: Bastion contains options to configure the bastion
134162
host.

controlplane/eks/api/v1beta1/conversion.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ func (r *AWSManagedControlPlane) ConvertTo(dstRaw conversion.Hub) error {
122122
dst.Spec.RolePermissionsBoundary = restored.Spec.RolePermissionsBoundary
123123
dst.Status.Version = restored.Status.Version
124124
dst.Spec.BootstrapSelfManagedAddons = restored.Spec.BootstrapSelfManagedAddons
125+
dst.Spec.AutoMode = restored.Spec.AutoMode
125126
return nil
126127
}
127128

controlplane/eks/api/v1beta1/zz_generated.conversion.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

controlplane/eks/api/v1beta2/awsmanagedcontrolplane_types.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,9 @@ type AWSManagedControlPlaneSpec struct { //nolint: maligned
206206
// +kubebuilder:default=true
207207
BootstrapSelfManagedAddons bool `json:"bootstrapSelfManagedAddons,omitempty"`
208208

209+
// +optional
210+
AutoMode *AutoMode `json:"autoMode,omitempty"`
211+
209212
// RestrictPrivateSubnets indicates that the EKS control plane should only use private subnets.
210213
// +kubebuilder:default=false
211214
RestrictPrivateSubnets bool `json:"restrictPrivateSubnets,omitempty"`
@@ -225,6 +228,29 @@ type KubeProxy struct {
225228
Disable bool `json:"disable,omitempty"`
226229
}
227230

231+
// AutoMode is the EKS Auto Mode.
232+
// allows to create cluster with aws compute, ebs, elb capabilities.
233+
type AutoMode struct {
234+
// Enabled will enable EKS Auto Mode.
235+
// +kubebuilder:default=false
236+
Enabled bool `json:"enabled,omitempty"`
237+
// Compute capability configuration for EKS Auto Mode.
238+
// +optional
239+
Compute Compute `json:"compute,omitempty"`
240+
}
241+
242+
// Compute allows to run compute capability with EKS AutoMode.
243+
type Compute struct {
244+
// NodePools that defines the compute resources for your EKS Auto Mode cluster.
245+
NodePools []string `json:"nodePools,omitempty"`
246+
// NodeRoleArn the ARN of the IAM Role EKS will assign to EC2 Managed Instances in your EKS
247+
// Auto Mode cluster. This value cannot be changed after the compute capability of
248+
// EKS Auto Mode is enabled. For more information, see the IAM Reference in the
249+
// Amazon EKS User Guide.
250+
// +optional
251+
NodeRoleArn *string `json:"nodeRoleArn,omitempty"`
252+
}
253+
228254
// VpcCni specifies configuration related to the VPC CNI.
229255
type VpcCni struct {
230256
// Disable indicates that the Amazon VPC CNI should be disabled. With EKS clusters the

controlplane/eks/api/v1beta2/awsmanagedcontrolplane_webhook.go

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/pkg/errors"
2626
apierrors "k8s.io/apimachinery/pkg/api/errors"
2727
"k8s.io/apimachinery/pkg/runtime"
28+
"k8s.io/apimachinery/pkg/util/sets"
2829
"k8s.io/apimachinery/pkg/util/validation/field"
2930
"k8s.io/apimachinery/pkg/util/version"
3031
"k8s.io/klog/v2"
@@ -52,6 +53,9 @@ const (
5253
cidrSizeMin = 16
5354
vpcCniAddon = "vpc-cni"
5455
kubeProxyAddon = "kube-proxy"
56+
57+
autoModeComputeNodePoolSystem = "system"
58+
autoModeComputeNodePoolGeneral = "general-purpose"
5559
)
5660

5761
// SetupWebhookWithManager will setup the webhooks for the AWSManagedControlPlane.
@@ -102,6 +106,7 @@ func (*awsManagedControlPlaneWebhook) ValidateCreate(_ context.Context, obj runt
102106
allErrs = append(allErrs, r.validateSecondaryCIDR()...)
103107
allErrs = append(allErrs, r.validateEKSAddons()...)
104108
allErrs = append(allErrs, r.validateDisableVPCCNI()...)
109+
allErrs = append(allErrs, r.validateAutoMode(nil)...)
105110
allErrs = append(allErrs, r.validateRestrictPrivateSubnets()...)
106111
allErrs = append(allErrs, r.validateKubeProxy()...)
107112
allErrs = append(allErrs, r.Spec.AdditionalTags.Validate()...)
@@ -144,6 +149,7 @@ func (*awsManagedControlPlaneWebhook) ValidateUpdate(ctx context.Context, oldObj
144149
allErrs = append(allErrs, r.validateAccessConfigUpdate(oldAWSManagedControlplane)...)
145150
allErrs = append(allErrs, r.validateIAMAuthConfig()...)
146151
allErrs = append(allErrs, r.validateSecondaryCIDR()...)
152+
allErrs = append(allErrs, r.validateAutoMode(oldAWSManagedControlplane)...)
147153
allErrs = append(allErrs, r.validateEKSAddons()...)
148154
allErrs = append(allErrs, r.validateDisableVPCCNI()...)
149155
allErrs = append(allErrs, r.validateRestrictPrivateSubnets()...)
@@ -472,6 +478,52 @@ func validateDisableVPCCNI(vpcCni VpcCni, addons *[]Addon, path *field.Path) fie
472478
return allErrs
473479
}
474480

481+
func (r *AWSManagedControlPlane) validateAutoMode(old *AWSManagedControlPlane) field.ErrorList {
482+
return validateAutoMode(r.Spec, old, field.NewPath("spec"))
483+
}
484+
485+
func validateAutoMode(spec AWSManagedControlPlaneSpec, old *AWSManagedControlPlane, path *field.Path) field.ErrorList {
486+
var allErrs field.ErrorList
487+
488+
if spec.AutoMode == nil {
489+
return nil
490+
}
491+
492+
if spec.AutoMode.Enabled {
493+
// EKS Auto mode is not compatible with configmap AuthenticationMode.
494+
if spec.AccessConfig.AuthenticationMode == EKSAuthenticationModeConfigMap {
495+
authConfigField := path.Child("accessConfig", "authenticationMode")
496+
allErrs = append(allErrs, field.Invalid(authConfigField, spec.AccessConfig.AuthenticationMode, "authenticationMode CONFIG_MAP couldn't be used with autoMode"))
497+
}
498+
499+
if old != nil {
500+
// nodeRoleArn cannot be changed after the compute capability of EKS Auto Mode is enabled.
501+
if old.Spec.AutoMode.Compute.NodeRoleArn != spec.AutoMode.Compute.NodeRoleArn {
502+
nodeRoleArnField := path.Child("autoMode", "compute", "nodeRoleArn")
503+
allErrs = append(allErrs, field.Invalid(nodeRoleArnField, spec.AutoMode.Compute.NodeRoleArn, "nodeRoleArn could not be changed"))
504+
}
505+
}
506+
507+
if len(spec.AutoMode.Compute.NodePools) > 0 {
508+
// nodeRoleArn should be always defined with node pools.
509+
if spec.AutoMode.Compute.NodeRoleArn == nil {
510+
nodeRoleArnField := path.Child("autoMode", "compute", "nodeRoleArn")
511+
allErrs = append(allErrs, field.Invalid(nodeRoleArnField, spec.AutoMode.Compute.NodeRoleArn, "nodeRoleArn is required when nodePools specified"))
512+
}
513+
514+
allowedPoolNames := sets.New[string](autoModeComputeNodePoolSystem, autoModeComputeNodePoolGeneral)
515+
for _, poolName := range spec.AutoMode.Compute.NodePools {
516+
nodePoolsField := path.Child("autoMode", "compute", "nodePools")
517+
if !allowedPoolNames.Has(poolName) {
518+
allErrs = append(allErrs, field.Invalid(nodePoolsField, poolName, "nodePools contains an invalid pool"))
519+
}
520+
}
521+
}
522+
}
523+
524+
return allErrs
525+
}
526+
475527
func (r *AWSManagedControlPlane) validateRestrictPrivateSubnets() field.ErrorList {
476528
return validateRestrictPrivateSubnets(r.Spec.RestrictPrivateSubnets, r.Spec.NetworkSpec, r.Spec.EKSClusterName, field.NewPath("spec"))
477529
}
@@ -620,7 +672,5 @@ func (*awsManagedControlPlaneWebhook) Default(_ context.Context, obj runtime.Obj
620672
infrav1.SetDefaults_Bastion(&r.Spec.Bastion)
621673
infrav1.SetDefaults_NetworkSpec(&r.Spec.NetworkSpec)
622674

623-
// Set default value for BootstrapSelfManagedAddons
624-
r.Spec.BootstrapSelfManagedAddons = true
625675
return nil
626676
}

controlplane/eks/api/v1beta2/awsmanagedcontrolplane_webhook_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ func TestWebhookCreate(t *testing.T) {
179179
secondaryCidr *string
180180
secondaryCidrBlocks []infrav1.VpcCidrBlock
181181
kubeProxy KubeProxy
182+
AutoMode *AutoMode
182183
accessConfig *AccessConfig
183184
}{
184185
{
@@ -364,6 +365,30 @@ func TestWebhookCreate(t *testing.T) {
364365
BootstrapClusterCreatorAdminPermissions: ptr.To(false),
365366
},
366367
},
368+
{
369+
name: "autoMode compute not allowed with authenticationMode CONFIG_MAP",
370+
eksClusterName: "default_cluster1",
371+
eksVersion: "v1.19",
372+
expectError: true,
373+
vpcCNI: VpcCni{Disable: false},
374+
AutoMode: &AutoMode{Enabled: true},
375+
},
376+
{
377+
name: "autoMode compute nodeRoleArn should be defined with nodePools",
378+
eksClusterName: "default_cluster1",
379+
eksVersion: "v1.19",
380+
expectError: true,
381+
vpcCNI: VpcCni{Disable: false},
382+
AutoMode: &AutoMode{Enabled: true, Compute: Compute{NodePools: []string{"system", "general-purpose"}}},
383+
},
384+
{
385+
name: "autoMode compute nodeRoleArn defined with nodePools",
386+
eksClusterName: "default_cluster1",
387+
eksVersion: "v1.19",
388+
expectError: false,
389+
vpcCNI: VpcCni{Disable: false},
390+
AutoMode: &AutoMode{Enabled: true, Compute: Compute{NodePools: []string{"system", "general-purpose"}, NodeRoleArn: aws.String("foo")}},
391+
},
367392
}
368393

369394
for _, tc := range tests {
@@ -411,6 +436,10 @@ func TestWebhookCreate(t *testing.T) {
411436
mcp.Spec.AccessConfig = tc.accessConfig
412437
}
413438

439+
if tc.AutoMode != nil {
440+
mcp.Spec.AutoMode = tc.AutoMode
441+
}
442+
414443
err := testEnv.Create(ctx, mcp)
415444

416445
if tc.expectError {
@@ -877,6 +906,37 @@ func TestWebhookUpdate(t *testing.T) {
877906
},
878907
expectError: true,
879908
},
909+
{
910+
name: "changing noderolearn is not allowed after it has been set",
911+
oldClusterSpec: AWSManagedControlPlaneSpec{
912+
EKSClusterName: "default_cluster1",
913+
NetworkSpec: infrav1.NetworkSpec{
914+
VPC: infrav1.VPCSpec{},
915+
},
916+
Version: ptr.To[string]("1.22"),
917+
AutoMode: &AutoMode{
918+
Compute: Compute{
919+
NodeRoleArn: aws.String("fooarn"),
920+
NodePools: []string{"pool1", "pool2"},
921+
},
922+
},
923+
},
924+
newClusterSpec: AWSManagedControlPlaneSpec{
925+
EKSClusterName: "default_cluster1",
926+
NetworkSpec: infrav1.NetworkSpec{
927+
VPC: infrav1.VPCSpec{
928+
IPv6: &infrav1.IPv6{},
929+
},
930+
},
931+
AutoMode: &AutoMode{
932+
Compute: Compute{
933+
NodeRoleArn: aws.String("bararn"),
934+
NodePools: []string{"pool1", "pool2"},
935+
},
936+
},
937+
},
938+
expectError: true,
939+
},
880940
}
881941

882942
for _, tc := range tests {

controlplane/eks/api/v1beta2/zz_generated.deepcopy.go

Lines changed: 46 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)