-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Open
Labels
@aws-cdk/aws-ecsRelated to Amazon Elastic ContainerRelated to Amazon Elastic ContainerbugThis issue is a bug.This issue is a bug.effort/mediumMedium work item – several days of effortMedium work item – several days of effortp2
Description
Describe the bug
This example uses a managed instances capacity provider with an Ec2Service. It fails to synth because the cluster lacks EC2 capacity providers.
https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs-readme.html#managed-instances-capacity-providers
Regression Issue
- Select this option if this issue appears to be a regression.
Last Known Working CDK Library Version
No response
Expected Behavior
Examples work. Examples are tested in integration tests. (This one is not, the integ test only tests managed instances capacity provider with a Fargate Service.)
Current Behavior
λ npx cdk synth
/private/tmp/foo/node_modules/aws-cdk-lib/core/lib/private/synthesis.js:3
`);throw new(errors_1()).UnscopedValidationError(`Validation failed with the following errors:
^
UnscopedValidationError: Validation failed with the following errors:
[FooStack/EC2Service] Cluster for this service needs Ec2 capacity. Call addXxxCapacity() on the cluster.
at path [undefined]
[FooStack/EC2Service] Cluster for this service needs Ec2 capacity. Call addXxxCapacity() on the cluster.
at validateTree (/private/tmp/foo/node_modules/aws-cdk-lib/core/lib/private/synthesis.js:3:12)
at synthesize (/private/tmp/foo/node_modules/aws-cdk-lib/core/lib/private/synthesis.js:1:1893)
at App.synth (/private/tmp/foo/node_modules/aws-cdk-lib/core/lib/stage.js:1:2912)
at process.<anonymous> (/private/tmp/foo/node_modules/aws-cdk-lib/core/lib/app.js:1:2041)
at Object.onceWrapper (node:events:633:26)
at process.emit (node:events:518:28)
at process.emit (node:domain:489:12)
at process.emit.sharedData.processEmitHook.installedValue [as emit] (/private/tmp/foo/node_modules/@cspotcode/source-map-support/source-map-support.js:745:40)
npx ts-node --prefer-ts-exts bin/foo.ts: Subprocess exited with error 1
Reproduction Steps
I ran npx cdk init app --language typescript, put that example in the stack, and filled in the "blanks" of the declare consts in the example.
Resulting stack:
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import { Size } from 'aws-cdk-lib';
export class FooStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const managedInstancesInstanceProfile = new iam.InstanceProfile(
this,
"ManagedInstancesInstanceProfile",
);
managedInstancesInstanceProfile.role?.addManagedPolicy(
iam.ManagedPolicy.fromAwsManagedPolicyName(
"AmazonECSInstanceRolePolicyForManagedInstances",
),
);
const managedInstancesInfrastructureRole = new iam.Role(
this,
"ManagedInstancesInfrastructureRole",
{
assumedBy: new iam.ServicePrincipal("ecs.amazonaws.com"),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName(
"AmazonECSInfrastructureRolePolicyForManagedInstances",
),
],
},
);
managedInstancesInstanceProfile.role?.grantPassRole(
managedInstancesInfrastructureRole,
);
const cluster = new ecs.Cluster(this, 'Cluster',);
// Create a Managed Instances Capacity Provider
const miCapacityProvider = new ecs.ManagedInstancesCapacityProvider(this, 'MICapacityProvider', {
infrastructureRole: managedInstancesInfrastructureRole,
ec2InstanceProfile: managedInstancesInstanceProfile,
subnets: cluster.vpc.privateSubnets,
securityGroups: [new ec2.SecurityGroup(this, 'MISecurityGroup', { vpc: cluster.vpc })],
instanceRequirements: {
vCpuCountMin: 1,
memoryMin: Size.gibibytes(2),
cpuManufacturers: [ec2.CpuManufacturer.INTEL],
acceleratorManufacturers: [ec2.AcceleratorManufacturer.NVIDIA],
},
propagateTags: ecs.PropagateManagedInstancesTags.CAPACITY_PROVIDER,
});
// Add the capacity provider to the cluster
cluster.addManagedInstancesCapacityProvider(miCapacityProvider);
const taskDefinition = new ecs.Ec2TaskDefinition(this, 'TaskDef');
taskDefinition.addContainer('web', {
image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
memoryReservationMiB: 256,
});
new ecs.Ec2Service(this, 'EC2Service', {
cluster,
taskDefinition,
minHealthyPercent: 100,
capacityProviderStrategies: [
{
capacityProvider: miCapacityProvider.capacityProviderName,
weight: 1,
},
],
});
}
}Possible Solution
No response
Additional Information/Context
No response
AWS CDK Library version (aws-cdk-lib)
2.220.0
AWS CDK CLI version
N/A
Node.js Version
N/A
OS
N/A
Language
TypeScript
Language Version
No response
Other information
While I've got your attention:
- I wish the documentation would explain the tradeoffs between using Ec2Service and FargateService. Why did this feature not gets its own ManagedInstancesService? Why do we have to use one of these other constructs instead?
- Why does the user have to explicitly grant required iam permissions to the relevant infrastructure/instance profile roles? CDK typically provides these kinds of things automatically.
- I don't see why managed instances capacity providers have to drive creation of ClusterCapacityProviderAssociations: https://github.com/aws/aws-cdk/blame/cfbc6fbc1d6e4b960b48613b97ffd8dc79727882/packages/aws-cdk-lib/aws-ecs/lib/cluster.ts#L1966. Managed Instances capacity providers do not use capacity provider associations.
- Why doesn't ManagedInstancesCapacityProvider implement things like IConnectable? Most CDK L2 constructs don't require users to "drop down" to raw SecurityGroups.
- Similar question about subnets. Most L2 constructs accept
ec2.SubnetSelectioninstead of a raw array of subnets.
Metadata
Metadata
Assignees
Labels
@aws-cdk/aws-ecsRelated to Amazon Elastic ContainerRelated to Amazon Elastic ContainerbugThis issue is a bug.This issue is a bug.effort/mediumMedium work item – several days of effortMedium work item – several days of effortp2