Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ecs-patterns): support disabling CPU-based scaling and custom target utilization #28315

Merged
merged 26 commits into from
Dec 22, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
81d3235
Adding property to allow consumer to disable Cpu based scaling
AnuragMohapatra Dec 9, 2023
918174d
Fix PR review comments
AnuragMohapatra Dec 15, 2023
b4da8f6
Merge pull request #1 from AnuragMohapatra/main
AnuragMohapatra Dec 15, 2023
785ed03
Merge pull request #2 from AnuragMohapatra/fix/issue-20706-allowtosto…
AnuragMohapatra Dec 15, 2023
2606c19
Fix integration testing
AnuragMohapatra Dec 15, 2023
5d16287
Merge branch 'aws:main' into fix/issue-20706-fixforcpubasedautoscaler…
AnuragMohapatra Dec 15, 2023
8a08738
Merge branch 'fix/issue-20706-fixforcpubasedautoscaleracecondition' o…
AnuragMohapatra Dec 15, 2023
1476dc0
Fix the integration test failure
AnuragMohapatra Dec 16, 2023
1161013
Merge branch 'main' into fix/issue-20706-fixforcpubasedautoscaleracec…
AnuragMohapatra Dec 16, 2023
41cfbee
Fix typo in readme
AnuragMohapatra Dec 16, 2023
fecca49
Merge branch 'fix/issue-20706-fixforcpubasedautoscaleracecondition' o…
AnuragMohapatra Dec 16, 2023
ca9390b
Update clean ups as per PR review
mohapatraanurag Dec 17, 2023
4edfc9e
fixing linting issues
AnuragMohapatra Dec 17, 2023
419a956
Fix indentation
AnuragMohapatra Dec 17, 2023
99a4d75
Update more PR Review comments
mohapatraanurag Dec 18, 2023
e27634a
Fix PR review comments
mohapatraanurag Dec 19, 2023
652985f
Update readme
mohapatraanurag Dec 19, 2023
ea0fcf3
Merge branch 'main' into fix/issue-20706-fixforcpubasedautoscaleracec…
AnuragMohapatra Dec 19, 2023
a6b1113
Update readme
AnuragMohapatra Dec 20, 2023
1d20c8e
Merge branch 'fix/issue-20706-fixforcpubasedautoscaleracecondition' o…
AnuragMohapatra Dec 20, 2023
80db0af
Merge branch 'main' into fix/issue-20706-fixforcpubasedautoscaleracec…
AnuragMohapatra Dec 20, 2023
1d5cbbd
make the properties private in base class
AnuragMohapatra Dec 21, 2023
8a2d795
Merge branch 'fix/issue-20706-fixforcpubasedautoscaleracecondition' o…
AnuragMohapatra Dec 21, 2023
d544f31
Merge branch 'main' into fix/issue-20706-fixforcpubasedautoscaleracec…
AnuragMohapatra Dec 21, 2023
33efe97
Apply suggestions from code review
kaizencc Dec 22, 2023
dd0b470
Merge branch 'main' into fix/issue-20706-fixforcpubasedautoscaleracec…
mergify[bot] Dec 22, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions packages/aws-cdk-lib/aws-ecs-patterns/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,27 @@ const queueProcessingFargateService = new ecsPatterns.QueueProcessingFargateServ

when queue not provided by user, CDK will create a primary queue and a dead letter queue with default redrive policy and attach permission to the task to be able to access the primary queue.

NOTE: This construct add a CPU Based scaling strategy by default, if this is not required in any solution please disable this by setting `disableCpuBasedScaling` to `true`.

```ts
declare const cluster: ecs.Cluster;
const queueProcessingFargateService = new ecsPatterns.QueueProcessingFargateService(this, 'Service', {
cluster,
memoryLimitMiB: 512,
image: ecs.ContainerImage.fromRegistry('test'),
command: ["-c", "4", "amazon.com"],
enableLogging: false,
desiredTaskCount: 2,
environment: {
TEST_ENVIRONMENT_VARIABLE1: "test environment variable 1 value",
TEST_ENVIRONMENT_VARIABLE2: "test environment variable 2 value",
},
maxScalingCapacity: 5,
containerName: 'test',
disableCpuBasedScaling: true,
});
```

AnuragMohapatra marked this conversation as resolved.
Show resolved Hide resolved
## Scheduled Tasks

To define a task that runs periodically, there are 2 options:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,20 @@ export interface QueueProcessingServiceBaseProps {
* @default - false
*/
readonly enableExecuteCommand?: boolean;

/**
* Flag to disable CPU based auto scaling strategy on the service.
*
* @default - false
*/
readonly disableCpuBasedScaling?: boolean
AnuragMohapatra marked this conversation as resolved.
Show resolved Hide resolved

/**
* The target CPU utilization percentage for CPU based scaling strategy when enabled.
*
* @default - 50
*/
readonly targetUtilizationPercent?: number
AnuragMohapatra marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand Down Expand Up @@ -279,6 +293,18 @@ export abstract class QueueProcessingServiceBase extends Construct {
* The AwsLogDriver to use for logging if logging is enabled.
*/
public readonly logDriver?: LogDriver;
/**
* Flag to disable CPU based auto scaling strategy on the service.
*
* @default - false
*/
public readonly disableCpuBasedScaling: boolean = false
/**
* The target CPU utilization percentage for CPU based scaling strategy when enabled.
*
* @default - 50
*/
public readonly targetUtilizationPercent: number = 50
AnuragMohapatra marked this conversation as resolved.
Show resolved Hide resolved

/**
* Constructs a new instance of the QueueProcessingServiceBase class.
Expand Down Expand Up @@ -325,6 +351,8 @@ export abstract class QueueProcessingServiceBase extends Construct {
// Add the queue name to environment variables
this.environment = { ...(props.environment || {}), QUEUE_NAME: this.sqsQueue.queueName };
this.secrets = props.secrets;
this.disableCpuBasedScaling = props.disableCpuBasedScaling ?? false;
this.targetUtilizationPercent = props.targetUtilizationPercent ?? 50;

this.desiredCount = props.desiredTaskCount ?? 1;

Expand Down Expand Up @@ -357,9 +385,12 @@ export abstract class QueueProcessingServiceBase extends Construct {
*/
protected configureAutoscalingForService(service: BaseService) {
const scalingTarget = service.autoScaleTaskCount({ maxCapacity: this.maxCapacity, minCapacity: this.minCapacity });
scalingTarget.scaleOnCpuUtilization('CpuScaling', {
targetUtilizationPercent: 50,
});

if (!this.disableCpuBasedScaling) {
scalingTarget.scaleOnCpuUtilization('CpuScaling', {
targetUtilizationPercent: this.targetUtilizationPercent,
});
}
scalingTarget.scaleOnMetric('QueueMessagesVisibleScaling', {
metric: this.sqsQueue.metricApproximateNumberOfMessagesVisible(),
scalingSteps: this.scalingSteps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,98 @@ testDeprecated('test Fargate queue worker service construct - with optional prop
});
});

testDeprecated('test Fargate queue worker service construct - with cpu scaling strategy disabled', () => {
// GIVEN
const stack = new cdk.Stack();
const vpc = new ec2.Vpc(stack, 'VPC');
const cluster = new ecs.Cluster(stack, 'Cluster', { vpc });
cluster.addAsgCapacityProvider(new AsgCapacityProvider(stack, 'DefaultAutoScalingGroupProvider', {
autoScalingGroup: new AutoScalingGroup(stack, 'DefaultAutoScalingGroup', {
vpc,
instanceType: new ec2.InstanceType('t2.micro'),
machineImage: MachineImage.latestAmazonLinux(),
}),
}));
const queue = new sqs.Queue(stack, 'fargate-test-queue', {
queueName: 'fargate-test-sqs-queue',
});

// WHEN
new ecsPatterns.QueueProcessingFargateService(stack, 'Service', {
cluster,
memoryLimitMiB: 512,
image: ecs.ContainerImage.fromRegistry('test'),
command: ['-c', '4', 'amazon.com'],
enableLogging: false,
environment: {
TEST_ENVIRONMENT_VARIABLE1: 'test environment variable 1 value',
TEST_ENVIRONMENT_VARIABLE2: 'test environment variable 2 value',
},
queue,
maxScalingCapacity: 5,
minHealthyPercent: 60,
maxHealthyPercent: 150,
serviceName: 'fargate-test-service',
family: 'fargate-task-family',
platformVersion: ecs.FargatePlatformVersion.VERSION1_4,
circuitBreaker: { rollback: true },
disableCpuBasedScaling: true,
});

// THEN - QueueWorker is of FARGATE launch type, an SQS queue is created and all optional properties are set.
Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', {
DeploymentConfiguration: {
MinimumHealthyPercent: 60,
MaximumPercent: 150,
DeploymentCircuitBreaker: {
Enable: true,
Rollback: true,
},
},
LaunchType: 'FARGATE',
ServiceName: 'fargate-test-service',
PlatformVersion: ecs.FargatePlatformVersion.VERSION1_4,
DeploymentController: {
Type: 'ECS',
},
});

Template.fromStack(stack).hasResourceProperties('AWS::SQS::Queue', { QueueName: 'fargate-test-sqs-queue' });

Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', {
ContainerDefinitions: [
Match.objectLike({
Command: [
'-c',
'4',
'amazon.com',
],
Environment: [
{
Name: 'TEST_ENVIRONMENT_VARIABLE1',
Value: 'test environment variable 1 value',
},
{
Name: 'TEST_ENVIRONMENT_VARIABLE2',
Value: 'test environment variable 2 value',
},
{
Name: 'QUEUE_NAME',
Value: {
'Fn::GetAtt': [
'fargatetestqueue28B43841',
'QueueName',
],
},
},
],
Image: 'test',
}),
],
Family: 'fargate-task-family',
});
AnuragMohapatra marked this conversation as resolved.
Show resolved Hide resolved
AnuragMohapatra marked this conversation as resolved.
Show resolved Hide resolved
});

test('can set custom containerName', () => {
// GIVEN
const stack = new cdk.Stack();
Expand Down
Loading