-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Open
Labels
@aws-cdk/aws-eksRelated to Amazon Elastic Kubernetes ServiceRelated to Amazon Elastic Kubernetes Service@aws-cdk/aws-iamRelated to AWS Identity and Access ManagementRelated to AWS Identity and Access Managementfeature-requestA feature should be added or improved.A feature should be added or improved.p2
Description
Problem Statement
The AWS CDK ServiceAccount construct currently always creates a new IAM role, even when:
- The ServiceAccount doesn't need AWS permissions (internal workloads)
- Multiple ServiceAccounts could share the same IAM role
This causes:
• IAM role limit exhaustion: AWS accounts have a default limit of 1,000 IAM roles
• Role sprawl: Duplicate roles with identical permissions
• Violates least privilege: Creates unnecessary IAM roles for Kubernetes-only workloads
Proposed Solution (Non-Breaking)
Add two new properties to control IAM role behavior:
interface ServiceAccountProps {
cluster: ICluster;
name: string;
namespace?: string;
/**
* Existing IAM role to associate with this ServiceAccount.
* If provided, no new role will be created.
*
* @default - A new role is created
*/
role?: IRole;
/**
* Whether to create an IAM role for this ServiceAccount.
* Only applicable when `role` is not provided.
*
* @default true (backward compatible)
*/
createRole?: boolean;
}Usage Examples
1. Current Behavior (Backward Compatible - Default)
const sa = new eks.ServiceAccount(this, 'S3App', {
cluster: cluster,
name: 's3-app',
namespace: 'default',
// ✅ Creates new role (default behavior, no breaking change)
});
sa.role.addManagedPolicy(/* ... */);2. No IAM Role (New - Opt-Out)
const sa = new eks.ServiceAccount(this, 'InternalApp', {
cluster: cluster,
name: 'internal-app',
namespace: 'default',
createRole: false, // NEW: Explicitly opt-out of role creation
});
// sa.role is undefined3. Use Existing IAM Role (New)
const sharedRole = iam.Role.fromRoleArn(this, 'SharedRole',
'arn:aws:iam::123456789012:role/shared-s3-reader'
);
const sa1 = new eks.ServiceAccount(this, 'App1SA', {
cluster: cluster,
name: 'app1',
namespace: 'team-a',
role: sharedRole, // NEW: Reuse existing role
});
const sa2 = new eks.ServiceAccount(this, 'App2SA', {
cluster: cluster,
name: 'app2',
namespace: 'team-b',
role: sharedRole, // Same role, different ServiceAccount
});
// When role is provided, createRole is ignored4. Multiple ServiceAccounts Share One Role
// Create one role for multiple services
const s3ReadRole = new iam.Role(this, 'S3ReadRole', {
assumedBy: new iam.ServicePrincipal('pods.eks.amazonaws.com'),
managedPolicies: [
ManagedPolicy.fromAwsManagedPolicyName('AmazonS3ReadOnlyAccess')
],
});
// Reuse same role for all services
['service-a', 'service-b', 'service-c'].forEach(name => {
new eks.ServiceAccount(this, `${name}-sa`, {
cluster: cluster,
name: name,
namespace: 'production',
role: s3ReadRole, // Shared role
});
});
// Result: 1 IAM role instead of 3 ✅Behavior Matrix
| role provided | createRole | Result |
|---|---|---|
| No | undefined (default) | ✅ Create new role (current behavior) |
| No | true | ✅ Create new role |
| No | false | ✅ No role created |
| Yes | ignored | ✅ Use provided role |
Validation Rules
// Invalid: Cannot specify both
new eks.ServiceAccount(this, 'Invalid', {
cluster: cluster,
name: 'invalid',
role: existingRole,
createRole: false, // ❌ Error: Cannot specify createRole when role is provided
});Property Access
// When role is created or provided
const sa1 = new eks.ServiceAccount(this, 'WithRole', {
cluster: cluster,
name: 'with-role',
});
sa1.role // ✅ IRole (created)
// When role is provided
const sa2 = new eks.ServiceAccount(this, 'ExistingRole', {
cluster: cluster,
name: 'existing-role',
role: myRole,
});
sa2.role // ✅ IRole (provided)
// When role creation is disabled
const sa3 = new eks.ServiceAccount(this, 'NoRole', {
cluster: cluster,
name: 'no-role',
createRole: false,
});
sa3.role // ✅ undefinedBenefits
- 100% backward compatible: Default behavior unchanged
- Reduces IAM role consumption when opted-in
- Enables role consolidation: Multiple ServiceAccounts can share one role
- Supports existing roles: Integrates with roles created outside CDK
- Follows AWS best practices: Only create IAM roles when AWS access needed
Migration Path
Users can gradually adopt the new features:
Phase 1: Continue using current behavior (no changes needed)
// Works exactly as before
const sa = new eks.ServiceAccount(this, 'App', { cluster, name: 'app' });Phase 2: Opt-out for internal workloads
// Add createRole: false for workloads that don't need AWS access
const sa = new eks.ServiceAccount(this, 'Internal', {
cluster,
name: 'internal',
createRole: false, // NEW
});Phase 3: Consolidate roles
// Share roles across multiple ServiceAccounts
const sharedRole = new iam.Role(/* ... */);
const sa1 = new eks.ServiceAccount(this, 'SA1', { cluster, name: 'sa1', role: sharedRole });
const sa2 = new eks.ServiceAccount(this, 'SA2', { cluster, name: 'sa2', role: sharedRole });Acknowledgements
- I may be able to implement this feature request
- This feature might incur a breaking change
AWS CDK Library version (aws-cdk-lib)
latest
AWS CDK CLI version
latest
Environment details (OS name and version, etc.)
all
Metadata
Metadata
Assignees
Labels
@aws-cdk/aws-eksRelated to Amazon Elastic Kubernetes ServiceRelated to Amazon Elastic Kubernetes Service@aws-cdk/aws-iamRelated to AWS Identity and Access ManagementRelated to AWS Identity and Access Managementfeature-requestA feature should be added or improved.A feature should be added or improved.p2