Skip to content

Commit 4b7dafe

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

12 files changed

+1752
-100
lines changed

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

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2245,6 +2245,25 @@ spec:
22452245
description: AWSManagedControlPlaneSpec defines the desired state of an
22462246
Amazon EKS Cluster.
22472247
properties:
2248+
accessConfig:
2249+
description: |-
2250+
AccessConfig specifies the EKS cluster access configuration.
2251+
It defines the authentication mode and whether to bootstrap the cluster creator
2252+
as a cluster-admin.
2253+
properties:
2254+
authenticationMode:
2255+
description: |-
2256+
AuthenticationMode mode controls how Kubernetes API authentication is performed:
2257+
- CONFIG_MAP — uses only the aws-auth ConfigMap (legacy mode).
2258+
- API — uses only EKS Access Entries (aws-auth is ignored).
2259+
- API_AND_CONFIG_MAP — enables both Access Entries and aws-auth.
2260+
type: string
2261+
bootstrapAdminPermissions:
2262+
description: |-
2263+
BootstrapAdminPermissions specifies whether or not the cluster creator IAM principal was set as a cluster
2264+
admin access entry during cluster creation time.
2265+
type: boolean
2266+
type: object
22482267
additionalTags:
22492268
additionalProperties:
22502269
type: string
@@ -2298,6 +2317,31 @@ spec:
22982317
AssociateOIDCProvider can be enabled to automatically create an identity
22992318
provider for the controller for use with IAM roles for service accounts
23002319
type: boolean
2320+
autoMode:
2321+
description: |-
2322+
AutoMode is the EKS Auto Mode.
2323+
allows to create cluster with aws compute, ebs, elb capabilities.
2324+
properties:
2325+
compute:
2326+
description: Compute capability configuration for EKS Auto Mode.
2327+
properties:
2328+
nodePools:
2329+
items:
2330+
type: string
2331+
type: array
2332+
nodeRoleArn:
2333+
description: |-
2334+
NodeRoleArn the ARN of the IAM Role EKS will assign to EC2 Managed Instances in your EKS
2335+
Auto Mode cluster. This value cannot be changed after the compute capability of
2336+
EKS Auto Mode is enabled. For more information, see the IAM Reference in the
2337+
Amazon EKS User Guide.
2338+
type: string
2339+
type: object
2340+
enabled:
2341+
default: false
2342+
description: Enabled will enable EKS Auto Mode.
2343+
type: boolean
2344+
type: object
23012345
bastion:
23022346
description: Bastion contains options to configure the bastion host.
23032347
properties:

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

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,25 @@ spec:
5353
description: AWSManagedControlPlaneSpec defines the desired state
5454
of an Amazon EKS Cluster.
5555
properties:
56+
accessConfig:
57+
description: |-
58+
AccessConfig specifies the EKS cluster access configuration.
59+
It defines the authentication mode and whether to bootstrap the cluster creator
60+
as a cluster-admin.
61+
properties:
62+
authenticationMode:
63+
description: |-
64+
AuthenticationMode mode controls how Kubernetes API authentication is performed:
65+
- CONFIG_MAP — uses only the aws-auth ConfigMap (legacy mode).
66+
- API — uses only EKS Access Entries (aws-auth is ignored).
67+
- API_AND_CONFIG_MAP — enables both Access Entries and aws-auth.
68+
type: string
69+
bootstrapAdminPermissions:
70+
description: |-
71+
BootstrapAdminPermissions specifies whether or not the cluster creator IAM principal was set as a cluster
72+
admin access entry during cluster creation time.
73+
type: boolean
74+
type: object
5675
additionalTags:
5776
additionalProperties:
5877
type: string
@@ -107,6 +126,32 @@ spec:
107126
AssociateOIDCProvider can be enabled to automatically create an identity
108127
provider for the controller for use with IAM roles for service accounts
109128
type: boolean
129+
autoMode:
130+
description: |-
131+
AutoMode is the EKS Auto Mode.
132+
allows to create cluster with aws compute, ebs, elb capabilities.
133+
properties:
134+
compute:
135+
description: Compute capability configuration for EKS
136+
Auto Mode.
137+
properties:
138+
nodePools:
139+
items:
140+
type: string
141+
type: array
142+
nodeRoleArn:
143+
description: |-
144+
NodeRoleArn the ARN of the IAM Role EKS will assign to EC2 Managed Instances in your EKS
145+
Auto Mode cluster. This value cannot be changed after the compute capability of
146+
EKS Auto Mode is enabled. For more information, see the IAM Reference in the
147+
Amazon EKS User Guide.
148+
type: string
149+
type: object
150+
enabled:
151+
default: false
152+
description: Enabled will enable EKS Auto Mode.
153+
type: boolean
154+
type: object
110155
bastion:
111156
description: Bastion contains options to configure the bastion
112157
host.

controlplane/eks/api/v1beta1/conversion.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ func (r *AWSManagedControlPlane) ConvertTo(dstRaw conversion.Hub) error {
121121
dst.Spec.RolePermissionsBoundary = restored.Spec.RolePermissionsBoundary
122122
dst.Status.Version = restored.Status.Version
123123
dst.Spec.BootstrapSelfManagedAddons = restored.Spec.BootstrapSelfManagedAddons
124+
dst.Spec.AccessConfig = restored.Spec.AccessConfig
125+
dst.Spec.AutoMode = restored.Spec.AutoMode
124126
return nil
125127
}
126128

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

Lines changed: 2 additions & 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: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ type AWSManagedControlPlaneSpec struct { //nolint: maligned
131131
// +optional
132132
IAMAuthenticatorConfig *IAMAuthenticatorConfig `json:"iamAuthenticatorConfig,omitempty"`
133133

134+
// AccessConfig specifies the EKS cluster access configuration.
135+
// It defines the authentication mode and whether to bootstrap the cluster creator
136+
// as a cluster-admin.
137+
// +optional
138+
AccessConfig AccessConfig `json:"accessConfig,omitempty"`
139+
134140
// Endpoints specifies access to this cluster's control plane endpoints
135141
// +optional
136142
EndpointAccess EndpointAccess `json:"endpointAccess,omitempty"`
@@ -200,7 +206,10 @@ type AWSManagedControlPlaneSpec struct { //nolint: maligned
200206
// bare EKS cluster without EKS default networking addons
201207
// If you set this value to false when creating a cluster, the default networking add-ons will not be installed
202208
// +kubebuilder:default=true
203-
BootstrapSelfManagedAddons bool `json:"bootstrapSelfManagedAddons,omitempty"`
209+
BootstrapSelfManagedAddons *bool `json:"bootstrapSelfManagedAddons,omitempty"`
210+
211+
// +optional
212+
AutoMode *AutoMode `json:"autoMode,omitempty"`
204213

205214
// RestrictPrivateSubnets indicates that the EKS control plane should only use private subnets.
206215
// +kubebuilder:default=false
@@ -221,6 +230,42 @@ type KubeProxy struct {
221230
Disable bool `json:"disable,omitempty"`
222231
}
223232

233+
// AccessConfig is the access configuration for the cluster.
234+
type AccessConfig struct {
235+
// AuthenticationMode mode controls how Kubernetes API authentication is performed:
236+
// - CONFIG_MAP — uses only the aws-auth ConfigMap (legacy mode).
237+
// - API — uses only EKS Access Entries (aws-auth is ignored).
238+
// - API_AND_CONFIG_MAP — enables both Access Entries and aws-auth.
239+
AuthenticationMode *string `json:"authenticationMode,omitempty"`
240+
241+
// BootstrapAdminPermissions specifies whether or not the cluster creator IAM principal was set as a cluster
242+
// admin access entry during cluster creation time.
243+
// +optional
244+
BootstrapAdminPermissions *bool `json:"bootstrapAdminPermissions,omitempty"`
245+
}
246+
247+
// AutoMode is the EKS Auto Mode.
248+
// allows to create cluster with aws compute, ebs, elb capabilities.
249+
type AutoMode struct {
250+
// Enabled will enable EKS Auto Mode.
251+
// +kubebuilder:default=false
252+
Enabled bool `json:"enabled,omitempty"`
253+
// Compute capability configuration for EKS Auto Mode.
254+
// +optional
255+
Compute Compute `json:"compute,omitempty"`
256+
}
257+
258+
// Compute allows to run compute capability with EKS AutoMode.
259+
type Compute struct {
260+
NodePools []string `json:"nodePools,omitempty"`
261+
// NodeRoleArn the ARN of the IAM Role EKS will assign to EC2 Managed Instances in your EKS
262+
// Auto Mode cluster. This value cannot be changed after the compute capability of
263+
// EKS Auto Mode is enabled. For more information, see the IAM Reference in the
264+
// Amazon EKS User Guide.
265+
// +optional
266+
NodeRoleArn *string `json:"nodeRoleArn,omitempty"`
267+
}
268+
224269
// VpcCni specifies configuration related to the VPC CNI.
225270
type VpcCni struct {
226271
// Disable indicates that the Amazon VPC CNI should be disabled. With EKS clusters the

controlplane/eks/api/v1beta2/awsmanagedcontrolplane_webhook.go

Lines changed: 104 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,12 @@ import (
2222
"net"
2323

2424
"github.com/apparentlymart/go-cidr/cidr"
25+
"github.com/aws/aws-sdk-go-v2/aws"
26+
ekstypes "github.com/aws/aws-sdk-go-v2/service/eks/types"
2527
"github.com/pkg/errors"
2628
apierrors "k8s.io/apimachinery/pkg/api/errors"
2729
"k8s.io/apimachinery/pkg/runtime"
30+
"k8s.io/apimachinery/pkg/util/sets"
2831
"k8s.io/apimachinery/pkg/util/validation/field"
2932
"k8s.io/apimachinery/pkg/util/version"
3033
"k8s.io/klog/v2"
@@ -52,6 +55,9 @@ const (
5255
cidrSizeMin = 16
5356
vpcCniAddon = "vpc-cni"
5457
kubeProxyAddon = "kube-proxy"
58+
59+
autoModeComputeNodePoolSystem = "system"
60+
autoModeComputeNodePoolGeneral = "general-purpose"
5561
)
5662

5763
// SetupWebhookWithManager will setup the webhooks for the AWSManagedControlPlane.
@@ -102,6 +108,8 @@ func (*awsManagedControlPlaneWebhook) ValidateCreate(_ context.Context, obj runt
102108
allErrs = append(allErrs, r.validateSecondaryCIDR()...)
103109
allErrs = append(allErrs, r.validateEKSAddons()...)
104110
allErrs = append(allErrs, r.validateDisableVPCCNI()...)
111+
allErrs = append(allErrs, r.validateAccessConfig(nil)...)
112+
allErrs = append(allErrs, r.validateAutoMode(nil)...)
105113
allErrs = append(allErrs, r.validateRestrictPrivateSubnets()...)
106114
allErrs = append(allErrs, r.validateKubeProxy()...)
107115
allErrs = append(allErrs, r.Spec.AdditionalTags.Validate()...)
@@ -142,6 +150,8 @@ func (*awsManagedControlPlaneWebhook) ValidateUpdate(ctx context.Context, oldObj
142150
allErrs = append(allErrs, r.Spec.Bastion.Validate()...)
143151
allErrs = append(allErrs, r.validateIAMAuthConfig()...)
144152
allErrs = append(allErrs, r.validateSecondaryCIDR()...)
153+
allErrs = append(allErrs, r.validateAccessConfig(oldAWSManagedControlplane)...)
154+
allErrs = append(allErrs, r.validateAutoMode(oldAWSManagedControlplane)...)
145155
allErrs = append(allErrs, r.validateEKSAddons()...)
146156
allErrs = append(allErrs, r.validateDisableVPCCNI()...)
147157
allErrs = append(allErrs, r.validateRestrictPrivateSubnets()...)
@@ -423,6 +433,92 @@ func validateDisableVPCCNI(vpcCni VpcCni, addons *[]Addon, path *field.Path) fie
423433
return allErrs
424434
}
425435

436+
func (r *AWSManagedControlPlane) validateAccessConfig(old *AWSManagedControlPlane) field.ErrorList {
437+
return validateAccessConfig(r.Spec.AccessConfig, old, field.NewPath("spec", "accessConfig"))
438+
}
439+
440+
func validateAccessConfig(accessConfig AccessConfig, old *AWSManagedControlPlane, path *field.Path) field.ErrorList {
441+
var (
442+
allErrs field.ErrorList
443+
authModeOK bool
444+
)
445+
446+
authConfigField := path.Child("authenticationMode")
447+
448+
for _, accessMode := range ekstypes.AuthenticationMode("").Values() {
449+
if ekstypes.AuthenticationMode(*accessConfig.AuthenticationMode) == accessMode {
450+
authModeOK = true
451+
}
452+
}
453+
454+
if !authModeOK {
455+
allErrs = append(allErrs, field.Invalid(authConfigField, *accessConfig.AuthenticationMode, "unsupported authenticationMode provided"))
456+
}
457+
458+
if old != nil {
459+
if *old.Spec.AccessConfig.AuthenticationMode != *accessConfig.AuthenticationMode {
460+
if ekstypes.AuthenticationMode(*accessConfig.AuthenticationMode) == ekstypes.AuthenticationModeConfigMap {
461+
allErrs = append(allErrs, field.Invalid(authConfigField, *accessConfig.AuthenticationMode, "cannot switch authenticationMode to legacy CONFIG_MAP mode"))
462+
}
463+
}
464+
}
465+
466+
if accessConfig.BootstrapAdminPermissions != nil && *accessConfig.BootstrapAdminPermissions {
467+
if ekstypes.AuthenticationMode(*accessConfig.AuthenticationMode) == ekstypes.AuthenticationModeConfigMap {
468+
authConfigField := path.Child("bootstrapAdminPermissions")
469+
allErrs = append(allErrs, field.Invalid(authConfigField, *accessConfig.BootstrapAdminPermissions, "authenticationMode CONFIG_MAP has no effect with the bootstrapAdminPermissions parameter"))
470+
}
471+
}
472+
473+
return allErrs
474+
}
475+
476+
func (r *AWSManagedControlPlane) validateAutoMode(old *AWSManagedControlPlane) field.ErrorList {
477+
return validateAutoMode(r.Spec, old, field.NewPath("spec"))
478+
}
479+
480+
func validateAutoMode(spec AWSManagedControlPlaneSpec, old *AWSManagedControlPlane, path *field.Path) field.ErrorList {
481+
var allErrs field.ErrorList
482+
483+
if spec.AutoMode == nil {
484+
return nil
485+
}
486+
487+
if spec.AutoMode.Enabled {
488+
// EKS Auto mode is not compatible with configmap AuthenticationMode.
489+
if *spec.AccessConfig.AuthenticationMode == string(ekstypes.AuthenticationModeConfigMap) {
490+
authConfigField := path.Child("accessConfig", "authenticationMode")
491+
allErrs = append(allErrs, field.Invalid(authConfigField, spec.AccessConfig.AuthenticationMode, "authenticationMode CONFIG_MAP couldn't be used with autoMode"))
492+
}
493+
494+
if old != nil {
495+
// nodeRoleArn cannot be changed after the compute capability of EKS Auto Mode is enabled.
496+
if old.Spec.AutoMode.Compute.NodeRoleArn != spec.AutoMode.Compute.NodeRoleArn {
497+
nodeRoleArnField := path.Child("autoMode", "compute", "nodeRoleArn")
498+
allErrs = append(allErrs, field.Invalid(nodeRoleArnField, spec.AutoMode.Compute.NodeRoleArn, "nodeRoleArn could not be changed"))
499+
}
500+
}
501+
502+
if len(spec.AutoMode.Compute.NodePools) > 0 {
503+
// nodeRoleArn should be always defined with node pools.
504+
if spec.AutoMode.Compute.NodeRoleArn == nil {
505+
nodeRoleArnField := path.Child("autoMode", "compute", "nodeRoleArn")
506+
allErrs = append(allErrs, field.Invalid(nodeRoleArnField, spec.AutoMode.Compute.NodeRoleArn, "nodeRoleArn is required when nodePools specified"))
507+
}
508+
509+
allowedPoolNames := sets.New[string](autoModeComputeNodePoolSystem, autoModeComputeNodePoolGeneral)
510+
for _, poolName := range spec.AutoMode.Compute.NodePools {
511+
nodePoolsField := path.Child("autoMode", "compute", "nodePools")
512+
if !allowedPoolNames.Has(poolName) {
513+
allErrs = append(allErrs, field.Invalid(nodePoolsField, poolName, "nodePools contains an invalid pool"))
514+
}
515+
}
516+
}
517+
}
518+
519+
return allErrs
520+
}
521+
426522
func (r *AWSManagedControlPlane) validateRestrictPrivateSubnets() field.ErrorList {
427523
return validateRestrictPrivateSubnets(r.Spec.RestrictPrivateSubnets, r.Spec.NetworkSpec, r.Spec.EKSClusterName, field.NewPath("spec"))
428524
}
@@ -568,10 +664,16 @@ func (*awsManagedControlPlaneWebhook) Default(_ context.Context, obj runtime.Obj
568664
}
569665
}
570666

667+
if r.Spec.BootstrapSelfManagedAddons == nil {
668+
r.Spec.BootstrapSelfManagedAddons = aws.Bool(true)
669+
}
670+
671+
if r.Spec.AccessConfig.AuthenticationMode == nil {
672+
r.Spec.AccessConfig.AuthenticationMode = aws.String(string(ekstypes.AuthenticationModeConfigMap))
673+
}
674+
571675
infrav1.SetDefaults_Bastion(&r.Spec.Bastion)
572676
infrav1.SetDefaults_NetworkSpec(&r.Spec.NetworkSpec)
573677

574-
// Set default value for BootstrapSelfManagedAddons
575-
r.Spec.BootstrapSelfManagedAddons = true
576678
return nil
577679
}

0 commit comments

Comments
 (0)