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): add ephemeral storage support #18106

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
140 changes: 140 additions & 0 deletions packages/@aws-cdk/aws-ecs-patterns/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,25 @@ If you need to encrypt the traffic between the load balancer and the ECS tasks,

Additionally, if more than one application target group are needed, instantiate one of the following:

On Fargate Platform Version 1.4.0 or later, you may specify up to 200GiB of [ephemeral storage](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-task-storage.html#fargate-task-storage-pv14):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you clarify here that the minimum is 21 because 20 is provided by default?


```ts
declare const cluster: ecs.Cluster;
const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', {
cluster,
memoryLimitMiB: 1024,
cpu: 512,
ephemeralStorageGiB: 100,
taskImageOptions: {
image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"),
},
});

loadBalancedFargateService.targetGroup.configureHealthCheck({
path: "/custom-health-path",
});
```

* `ApplicationMultipleTargetGroupsEc2Service`

```ts
Expand Down Expand Up @@ -125,6 +144,32 @@ const loadBalancedFargateService = new ecsPatterns.ApplicationMultipleTargetGrou
});
```

On Fargate Platform Version 1.4.0 or later, you may specify up to 200GiB of [ephemeral storage](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-task-storage.html#fargate-task-storage-pv14):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above: Can you clarify here that the minimum is 21 because 20 is provided by default?


```ts
// One application load balancer with one listener and two target groups.
declare const cluster: ecs.Cluster;
const loadBalancedFargateService = new ecsPatterns.ApplicationMultipleTargetGroupsFargateService(this, 'Service', {
cluster,
memoryLimitMiB: 1024,
cpu: 512,
ephemeralStorageGiB: 100,
taskImageOptions: {
image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"),
},
targetGroups: [
{
containerPort: 80,
},
{
containerPort: 90,
pathPattern: 'a/b/c',
priority: 10,
},
],
});
```

## Network Load Balanced Services

To define an Amazon ECS service that is behind a network load balancer, instantiate one of the following:
Expand Down Expand Up @@ -169,6 +214,21 @@ If you specify the option `recordType` you can decide if you want the construct

Additionally, if more than one network target group is needed, instantiate one of the following:

On Fargate Platform Version 1.4.0 or later, you may specify up to 200GiB of [ephemeral storage](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-task-storage.html#fargate-task-storage-pv14):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above: Can you clarify here that the minimum is 21 because 20 is provided by default?


```ts
declare const cluster: ecs.Cluster;
const loadBalancedFargateService = new ecsPatterns.NetworkLoadBalancedFargateService(this, 'Service', {
cluster,
memoryLimitMiB: 1024,
cpu: 512,
ephemeralStorageGiB: 100,
taskImageOptions: {
image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"),
},
});
```

* NetworkMultipleTargetGroupsEc2Service

```ts
Expand Down Expand Up @@ -253,6 +313,49 @@ const loadBalancedFargateService = new ecsPatterns.NetworkMultipleTargetGroupsFa
});
```

On Fargate Platform Version 1.4.0 or later, you may specify up to 200GiB of [ephemeral storage](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-task-storage.html#fargate-task-storage-pv14):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above: Can you clarify here that the minimum is 21 because 20 is provided by default?


```ts
// Two network load balancers, each with their own listener and target group.
declare const cluster: ecs.Cluster;
const loadBalancedFargateService = new ecsPatterns.NetworkMultipleTargetGroupsFargateService(this, 'Service', {
cluster,
memoryLimitMiB: 512,
ephemeralStorageGiB: 100,
taskImageOptions: {
image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"),
},
loadBalancers: [
{
name: 'lb1',
listeners: [
{
name: 'listener1',
},
],
},
{
name: 'lb2',
listeners: [
{
name: 'listener2',
},
],
},
],
targetGroups: [
{
containerPort: 80,
listener: 'listener1',
},
{
containerPort: 90,
listener: 'listener2',
},
],
});
```

## Queue Processing Services

To define a service that creates a queue and reads from that queue, instantiate one of the following:
Expand Down Expand Up @@ -299,6 +402,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.

On Fargate Platform Version 1.4.0 or later, you may specify up to 200GiB of [ephemeral storage](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-task-storage.html#fargate-task-storage-pv14):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above: Can you clarify here that the minimum is 21 because 20 is provided by default?


```ts
declare const cluster: ecs.Cluster;
const queueProcessingFargateService = new ecsPatterns.QueueProcessingFargateService(this, 'Service', {
cluster,
memoryLimitMiB: 512,
ephemeralStorageGiB: 100,
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',
});
```

## Scheduled Tasks

To define a task that runs periodically, there are 2 options:
Expand Down Expand Up @@ -336,6 +460,22 @@ const scheduledFargateTask = new ecsPatterns.ScheduledFargateTask(this, 'Schedul
});
```

On Fargate Platform Version 1.4.0 or later, you may specify up to 200GiB of [ephemeral storage](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-task-storage.html#fargate-task-storage-pv14):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above: Can you clarify here that the minimum is 21 because 20 is provided by default?


```ts
declare const cluster: ecs.Cluster;
const scheduledFargateTask = new ecsPatterns.ScheduledFargateTask(this, 'ScheduledFargateTask', {
cluster,
scheduledFargateTaskImageOptions: {
image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
memoryLimitMiB: 512,
ephemeralStorageGiB: 100,
},
schedule: appscaling.Schedule.expression('rate(1 minute)'),
platformVersion: ecs.FargatePlatformVersion.LATEST,
});
```

## Additional Examples

In addition to using the constructs, users can also add logic to customize these constructs:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ export interface ApplicationLoadBalancedFargateServiceProps extends ApplicationL
*/
readonly memoryLimitMiB?: number;

/**
* The amount (in GiB) of ephemeral storage to be allocated to the task. The maximum supported value is 200 GiB.
*
* NOTE: This parameter is only supported for tasks hosted on AWS Fargate using platform version 1.4.0 or later.
*
* This default is set in the underlying FargateTaskDefinition construct.
*
* @default 20
Copy link
Contributor

@akash1810 akash1810 Feb 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-taskdefinition-ephemeralstorage.html suggests this number should be between 21 and 200:

The total amount, in GiB, of ephemeral storage to set for the task. The minimum supported value is 21 GiB and the maximum supported value is 200 GiB.

Would 20 not create a runtime error? And/or could there be some validation of ephemeralStorageGiB with an error thrown when it is not in these bounds? That is, produce a compile (synth) time error for earlier feedback.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would 20 not create a runtime error? And/or could there be some validation of ephemeralStorageGiB with an error thrown when it is not in these bounds?

Yes, entering a value below 21 or above 200 will throw a validation exception:

https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/aws-ecs/lib/fargate/fargate-task-definition.ts#L143-L145

The default value of 20 GiB comes into play when ephemeralStorageGiB is not set. By default, Fargate provides 20 GiB of ephemeral storage. That is, users only need to add ephemeralStorageGiB to their task definition when their task needs more than 20 GiB:

https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-task-storage.html

I documented the 20 GiB default value for ephemeral storage for consistency with aws-ecs:

https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/aws-ecs/lib/fargate/fargate-task-definition.ts#L55-L62

You can see here that aws-ecs doesn't actually set the default value to 20 in the task definition, but rather sets ephemeralStorage to undefined when ephemeralStorageGiB is not set:

ephemeralStorage: this.ephemeralStorageGiB ? {
sizeInGiB: this.ephemeralStorageGiB,
} : undefined,

Copy link
Contributor

@akash1810 akash1810 Feb 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏽 thanks for the explanation and links!

Is there any reason the validation is only on FargateTaskDefinition and not TaskDefinition which it extends from?

The default value of 20 GiB comes into play when ephemeralStorageGiB is not set. By default, Fargate provides 20 GiB of ephemeral storage. That is, users only need to add ephemeralStorageGiB to their task definition when their task needs more than 20 GiB

I find this API quite confusing! You set this property if and only if you do not want the default value? If you do set it to the default of 20, a runtime error is seen? That's different from pretty much all other CloudFormation resources.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason the validation is only on FargateTaskDefinition and not TaskDefinition which it extends from?

I imagine that is because ephemeralStorage is a Fargate-specific option. It does not apply to non-Fargate tasks. So TaskDefinition defines the common properties for all ECS tasks and FargateTaskDefinition extends it to add the validation/options that are Fargate-specific.

I find this API quite confusing! You set this property if and only if you do not want the default value? If you do set it to the default of 20, a runtime error is seen?

I would agree this is confusing. It's probably this way to be backwards compatible. Before the ephemeralStorage option was added to the task definition, all Fargate tasks (on PV >= 1.4) would get 20 GiB of ephemeral storage by default. If ephemeralStorage had been added from day one, it would probably be a required option with no default value.

Maybe ECS can change their validation to not throw an error if ephemeralStorage is set to the default value (20), which would allow CloudFormation and the CDK to also set 20 as the default value and always set the property. The main downside would be having to maintain the default value in multiple places, and it being temporarily out of sync if ECS decides to change it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that having this say 20 as the the default input and then throwing an error on that value is not the way we want to go here. I realize that the aws-ecs module did it that way, but I tend to think that should be updated instead of this one following it's lead. Let's add a default of none, since we're not plugging the number 20 in anywhere on our end and add to this doc that the minimum value here is 21. If you'd like to make the same update to the aws-ecs docs, we'd welcome that but it's certainly not mandatory.

*/
readonly ephemeralStorageGiB?: number;
TheRealAmazonKendra marked this conversation as resolved.
Show resolved Hide resolved

/**
* Determines whether the service will be assigned a public IP address.
*
Expand Down Expand Up @@ -129,6 +140,7 @@ export class ApplicationLoadBalancedFargateService extends ApplicationLoadBalanc
this.taskDefinition = new FargateTaskDefinition(this, 'TaskDef', {
memoryLimitMiB: props.memoryLimitMiB,
cpu: props.cpu,
ephemeralStorageGiB: props.ephemeralStorageGiB,
executionRole: taskImageOptions.executionRole,
taskRole: taskImageOptions.taskRole,
family: taskImageOptions.family,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,17 @@ export interface ApplicationMultipleTargetGroupsFargateServiceProps extends Appl
*/
readonly memoryLimitMiB?: number;

/**
* The amount (in GiB) of ephemeral storage to be allocated to the task. The maximum supported value is 200 GiB.
*
* NOTE: This parameter is only supported for tasks hosted on AWS Fargate using platform version 1.4.0 or later.
*
* This default is set in the underlying FargateTaskDefinition construct.
*
* @default 20
*/
readonly ephemeralStorageGiB?: number;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above.


/**
* Determines whether the service will be assigned a public IP address.
*
Expand Down Expand Up @@ -125,6 +136,7 @@ export class ApplicationMultipleTargetGroupsFargateService extends ApplicationMu
this.taskDefinition = new FargateTaskDefinition(this, 'TaskDef', {
memoryLimitMiB: props.memoryLimitMiB,
cpu: props.cpu,
ephemeralStorageGiB: props.ephemeralStorageGiB,
executionRole: taskImageOptions.executionRole,
taskRole: taskImageOptions.taskRole,
family: taskImageOptions.family,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ export interface NetworkLoadBalancedFargateServiceProps extends NetworkLoadBalan
*/
readonly memoryLimitMiB?: number;

/**
* The amount (in GiB) of ephemeral storage to be allocated to the task. The maximum supported value is 200 GiB.
*
* NOTE: This parameter is only supported for tasks hosted on AWS Fargate using platform version 1.4.0 or later.
*
* This default is set in the underlying FargateTaskDefinition construct.
*
* @default 20
*/
readonly ephemeralStorageGiB?: number;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above.


/**
* Determines whether the service will be assigned a public IP address.
*
Expand Down Expand Up @@ -118,6 +129,7 @@ export class NetworkLoadBalancedFargateService extends NetworkLoadBalancedServic
this.taskDefinition = new FargateTaskDefinition(this, 'TaskDef', {
memoryLimitMiB: props.memoryLimitMiB,
cpu: props.cpu,
ephemeralStorageGiB: props.ephemeralStorageGiB,
executionRole: taskImageOptions.executionRole,
taskRole: taskImageOptions.taskRole,
family: taskImageOptions.family,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,17 @@ export interface NetworkMultipleTargetGroupsFargateServiceProps extends NetworkM
*/
readonly memoryLimitMiB?: number;

/**
* The amount (in GiB) of ephemeral storage to be allocated to the task. The maximum supported value is 200 GiB.
*
* NOTE: This parameter is only supported for tasks hosted on AWS Fargate using platform version 1.4.0 or later.
*
* This default is set in the underlying FargateTaskDefinition construct.
*
* @default 20
*/
readonly ephemeralStorageGiB?: number;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above.


/**
* Determines whether the service will be assigned a public IP address.
*
Expand Down Expand Up @@ -125,6 +136,7 @@ export class NetworkMultipleTargetGroupsFargateService extends NetworkMultipleTa
this.taskDefinition = new FargateTaskDefinition(this, 'TaskDef', {
memoryLimitMiB: props.memoryLimitMiB,
cpu: props.cpu,
ephemeralStorageGiB: props.ephemeralStorageGiB,
executionRole: taskImageOptions.executionRole,
taskRole: taskImageOptions.taskRole,
family: taskImageOptions.family,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ export interface QueueProcessingFargateServiceProps extends QueueProcessingServi
*/
readonly memoryLimitMiB?: number;

/**
* The amount (in GiB) of ephemeral storage to be allocated to the task. The maximum supported value is 200 GiB.
*
* NOTE: This parameter is only supported for tasks hosted on AWS Fargate using platform version 1.4.0 or later.
*
* This default is set in the underlying FargateTaskDefinition construct.
*
* @default 20
*/
readonly ephemeralStorageGiB?: number;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above.


/**
* The platform version on which to run your service.
*
Expand Down Expand Up @@ -116,6 +127,7 @@ export class QueueProcessingFargateService extends QueueProcessingServiceBase {
this.taskDefinition = new FargateTaskDefinition(this, 'QueueProcessingTaskDef', {
memoryLimitMiB: props.memoryLimitMiB || 512,
cpu: props.cpu || 256,
ephemeralStorageGiB: props.ephemeralStorageGiB,
family: props.family,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ export interface ScheduledFargateTaskImageOptions extends ScheduledTaskImageProp
* @default 512
*/
readonly memoryLimitMiB?: number;

/**
* The amount (in GiB) of ephemeral storage to be allocated to the task. The maximum supported value is 200 GiB.
*
* NOTE: This parameter is only supported for tasks hosted on AWS Fargate using platform version 1.4.0 or later.
*
* This default is set in the underlying FargateTaskDefinition construct.
*
* @default 20
*/
readonly ephemeralStorageGiB?: number;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above.

}

/**
Expand Down Expand Up @@ -114,6 +125,7 @@ export class ScheduledFargateTask extends ScheduledTaskBase {
this.taskDefinition = new FargateTaskDefinition(this, 'ScheduledTaskDef', {
memoryLimitMiB: taskImageOptions.memoryLimitMiB || 512,
cpu: taskImageOptions.cpu || 256,
ephemeralStorageGiB: taskImageOptions.ephemeralStorageGiB,
});
this.taskDefinition.addContainer('ScheduledContainer', {
image: taskImageOptions.image,
Expand Down
Loading