-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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: construct library for ECS #1041
Conversation
- Fix linting errors - VPC is now an argument and not created inside the cluster - Link the AutoScalingGroup up to the cluster via userData - Give the ASG instance role the required IAM permissions - Extend ECS-optimized AMI table with all regions - Add an example configuration option to deny containers access to EC2 instance metadata service.
Was getting error: lib/index.ts(7,1): error TS2308: Module './cluster' has already exported a member named 'ClusterName'. Consider explicitly re-exporting to resolve the ambiguity. lib/index.ts(7,1): error TS2308: Module './task-definition' has already exported a member named 'TaskDefinitionArn'. Consider explicitly re-exporting to resolve the ambiguity. This seemed to make npm run build happy
Sets maxSize and desiredCapabity on ASG for ECS Cluster. NOTE: Should we set minSize to 0 or 1? See ecs-cli default)
This uses the @aws-cdk/aws-applicationautoscaling library to add Task AutoScaling facilities to ECS and Fargate services.
TaskExecutionRole not being set -- lazy evaluation of executionRole on TaskDef not working on private call to generateExecutionRole? Also weird issue with importing aws-iam
Add default deployment configuration
{ | ||
"app": "node index", | ||
"context": { | ||
"availability-zones:585695036304:us-east-1": [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it normal practice in the CDK to check in account IDs? Normally we avoid publicly sharing account IDs...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope. We should definitely delete
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah this should not have been checked in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we expect customers to check this in to their repos, or should cdk.json generally be git'ignored? Should cdk init add that to a .gitignore file? Sounds like we need a separate issue to track that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fyi this stuff is online for all to see
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yay! Looking good, not much jumped out at me that has to be changed before merging. Most of my comments can be addressed in follow-up PRs
@@ -0,0 +1,3 @@ | |||
{ | |||
"app": "../node_modules/.bin/cdk-applet-js fargate-service.yml" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do I get this magical cdk-applet-js file, because it is not appearing for me locally even after a build
/** | ||
* Time after startup to ignore unhealthy load balancer checks. | ||
* | ||
* @default ??? FIXME |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nathanpeck any guidance here on a sane default?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should maybe be removed from the service properties and only added if the customer specifies a loadBalancer.
/** | ||
* Called when the image is used by a ContainerDefinition | ||
*/ | ||
public abstract bind(containerDefinition: ContainerDefinition): void; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the value of this method? It doesn't actually seem to bind to this specific image object; it just sets a flag back in the containerDefinition?
this.securityGroup = autoScalingGroup.connections.securityGroup!; | ||
|
||
// Tie instances to cluster | ||
autoScalingGroup.addUserData(`echo ECS_CLUSTER=${this.clusterName} >> /etc/ecs/ecs.config`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is so niiiiiiice
if (!props.containersAccessInstanceRole) { | ||
// Deny containers access to instance metadata service | ||
// Source: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html | ||
autoScalingGroup.addUserData('sudo iptables --insert FORWARD 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For awsvpc mode (which doesn't use docker0), you should also set ECS_AWSVPC_BLOCK_IMDS=true
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html
"ecr:BatchGetImage", | ||
"logs:CreateLogStream", | ||
"logs:PutLogEvents" | ||
).addAllResources()); // Conceivably we might do better than all resources and add targeted ARNs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 on the comment
|
||
```ts | ||
// Create an ECS cluster (backed by an AutoScaling group) | ||
const cluster = new ecs.EcsCluster(this, 'Cluster', { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need two separate constructs for ecs.EcsCluster
and ecs.FargateCluster
? I think this introduces some naming complexity (especially later down the line when we have Fargate for EKS). By having them so separate, it also hides the fact that customers can (and do) have mixed-mode clusters with some EC2 and some Fargate mode tasks.
The only real difference is how many instances (if any) are configured. Why not have a single new ecs.Cluster()
construct, that accepts an optional instanceConfiguration
prop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While it's true that we wanted to supported mixed-mode clusters, these are an extremely low percentage of customers. We wanted the construct library to provide a more opinionated way to set up infrastructure. In addition provisioning capacity in an ECS cluster, there is some differences in the networking setup as well.
Unless you know of good reasons why customers wouldn't want to have a homogeneous cluster, keeping separate cluster types seemed to streamline the design of other ECS constructs.
const cluster = new ecs.EcsCluster(this, 'Cluster', { | ||
vpc, | ||
size: 3, | ||
instanceType: new InstanceType("t2.xlarge") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instanceCount
is more descriptive than size.
I also think this API for just specifying instance type and count is too simplistic, and limits future options. For example, one nice thing we could do as a TODO is allow people to specify multiple instance types, and whether they want to use spot etc. The ECS L2 construct could then abstract away a lot of the complexity of creating this kind of diverse-bidding-strategy setup.
As above, I'd favour an instanceConfiguration
type prop that could allow expressing more advanced configurations. We could then provide some sane-default examples of instance configurations that people could drop-in, or they could create their own.
|
||
- Use the `EcsCluster`, `EcsTaskDefinition` and `EcsService` constructs to | ||
run tasks on EC2 instances running in your account. | ||
- Use the `FargateCluster`, `FargateTaskDefinition` and `FargateService` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, is this naming future-proof/correct? EcsService vs FargateService is slightly confusing as both run on ECS. Maybe ecs.EC2Service
and ecs.FargateService
?
## Service | ||
|
||
A `Service` instantiates a `TaskDefinition` on a `Cluster` a given number of | ||
times, optionally associating them with a load balnacer. Tasks that fail will |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/load balnacer/load balancer/
Task AutoScaling is powered by *Application AutoScaling*. Refer to that for | ||
more information. | ||
|
||
## Instance AutoScaling |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting up instance-autoscaling with proper draining (via lifecycle hook+lambda) is exactly the sort of undifferentiated heavy lifting that an L2 construct should be doing. From speaking to customers previously, reserved memory is normally a pretty sane default to scale on. For a drop-in example of the ASG hook/lambda function for draining, see https://github.com/aws-samples/ecs-refarch-cloudformation/blob/master/infrastructure/lifecyclehook.yaml
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aha, that is potentially more complicated than I had expected. Might hit you up next week as I'm trying to implement this.
Closing in favor of newer one |
Add an initial version of a construct library for AWS Elastic Container Service.
This construct library isn't fully feature-complete yet. This is the first iteration so
that people can use it for experimentation and put it to the test, and we can improve
on it later.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license.