From 1caf425174490799789bd7d745b0f38b6e2db806 Mon Sep 17 00:00:00 2001 From: Doug-AWS Date: Tue, 13 Nov 2018 07:32:34 -0800 Subject: [PATCH 01/17] ECS example WIP --- docs/src/examples.rst | 272 +++++++++++++++++++----------------------- 1 file changed, 125 insertions(+), 147 deletions(-) diff --git a/docs/src/examples.rst b/docs/src/examples.rst index 4269ac53ab6fa..1621eb9361217 100644 --- a/docs/src/examples.rst +++ b/docs/src/examples.rst @@ -14,205 +14,183 @@ |cdk| Examples ############## -This topic contains some usage examples to help you get started understanding -the |cdk|. +This topic contains some examples to help you get started using some of the advanced constructs +offered by the |cdk|. -.. We'll include this if we ever implement DeploymentPipeline - _multiple_stacks_example: +.. _creating_ecs_l2_example: - Creating an App with Multiple Stacks - ==================================== +Creating an |ECS| Construct +=========================== - The following example creates the following stacks and one deployment pipeline: +|ECSlong| (|ECS|) is a highly scalable, fast, container management service +that makes it easy to run, stop, and manage Docker containers on a cluster. +You can host your cluster on a serverless infrastructure that is managed by +|ECS| by launching your services or tasks using the Fargate launch type. +For more control you can host your tasks on a cluster of +|EC2long| (|EC2|) instances that you manage by using the EC2 launch type. - - **Dev** uses the default environment - - **PreProd** in the **us-west-2** Region - - **NAEast** in the **us-east-1** Region - - **NAWest** in the **us-west-2** Region - - **EU** in the **eu-west-1** Region - - **DeploymentPipeline** in the **us-east-1** Region +Since |ECS| can be used with a number of AWS services, +you should understand how the |ECS| construct that we use in this example +gives you a leg up on using these AWS services: - Implement the class **MyStack** in the *my-stack* sub-folder, - that extends the |stack-class| class - (this is the same code as shown in the :doc:`concepts` topic). - code-block:: js - import { Stack, StackProps } from '@aws-cdk/cdk' +* Automatic security group opening for LBs +* Automatic ordering dependency between service and LB attaching to target group +* Automatic userdata configuration on ASG +* Early validation of some tricky param combinations, which saves you deployment time in CFN to discover issues +* Automatic permissions added for ECR if you use an image from ECR +* convenient api for autoscaling +* Asset support, so deploying source from yer machine to ECS in one go - interface MyStackProps extends StackProps { - encryptedStorage: boolean; - } - export class MyStack extends Stack { - constructor(parent: Construct, name: string, props?: MyStackProps) { - super(parent, name, props); - new MyStorageLayer(this, 'Storage', { encryptedStorage: props.encryptedStorage }); - new MyControlPlane(this, 'CPlane'); - new MyDataPlane(this, 'DPlane'); - } - } +- |IAM| +- |EC2| +- |ELB| +- |ECR| +- |CFN| - Implement the class **DeploymentPipeline** in the *my-deployment* sub-folder, - that extends the |stack-class| class - (this is the same code as shown in the :doc:`concepts` topic). - code-block:: js +.. _creating_ecs_l2_example_1: - Use **MyStack** and **DeploymentPipeline** to create the stacks and deployment pipeline. +Step 1: Create the Directory and Initialze the |cdk| +---------------------------------------------------- - code-block:: js +Let's start with creating a new directory to hold our |cdk| code +and create a new app in that directory. - import { App } from '@aws-cdk/cdk' - import { MyStack } from './my-stack' - import { DeploymentPipeline } from './my-deployment' +.. code-block:: sh - const app = new App(); + mkdir MyEcsConstruct + cd MyEcsConstruct + +.. tabs:: - // Use the default environment - new MyStack(app, { name: 'Dev' }); + .. group-tab:: TypeScript - // Pre-production stack - const preProd = new MyStack(app, { - name: 'PreProd', - env: { region: 'us-west-2' }, - preProd: true - }); + .. code-block:: sh - // Production stacks - const prod = [ - new MyStack(app, { - name: 'NAEast', - env: { region: 'us-east-1' } - }), + cdk init --language typescript - new MyStack(app, { - name: 'NAWest', - env: { region: 'us-west-2' } - }), + Update *my_ecs_construct.ts* in the *bin* directory to only contain the following code: - new MyStack(app, { - name: 'EU', - env: { region: 'eu-west-1' }, - encryptedStorage: true - }) - ] + .. code-block:: ts - // CI/CD pipeline stack - new DeploymentPipeline(app, { - env: { region: 'us-east-1' }, - strategy: DeploymentStrategy.Waved, - preProdStages: [ preProd ], - prodStages: prod - }); + #!/usr/bin/env node + import cdk = require('@aws-cdk/cdk'); - app.run(); + class MyWidgetServiceStack extends cdk.Stack { + constructor(parent: cdk.App, name: string, props?: cdk.StackProps) { + super(parent, name, props); -.. _dynamodb_example: -Creating a |DDB| Table -====================== + } + } -The following example creates a -|DDB| table with the partition key **Alias** -and sort key **Timestamp**. + // Create a new CDK app + const app = new cdk.App(); -.. code-block:: js + // Add your stack to it + new MyWidgetServiceStack(app, 'MyWidgetServiceStack'); - import dynamodb = require('@aws-cdk/aws-dynamodb'); - import cdk = require('@aws-cdk/cdk'); + app.run(); - class MyStack extends cdk.Stack { - constructor(parent: cdk.App, name: string, props?: cdk.StackProps) { - super(parent, name, props); + Save it and make sure it builds and creates an empty stack. - const table = new dynamodb.Table(this, 'Table', { - tableName: 'MyAppTable', - readCapacity: 5, - writeCapacity: 5 - }); + .. code-block:: sh - table.addPartitionKey({ name: 'Alias', type: dynamodb.AttributeType.String }); - table.addSortKey({ name: 'Timestamp', type: dynamodb.AttributeType.String }); - } - } + npm run build + cdk synth - const app = new cdk.App(); + You should see a stack like the following, + where CDK-VERSION is the version of the CDK. - new MyStack(app, 'MyStack'); + .. code-block:: sh - app.run(); + Resources: + CDKMetadata: + Type: 'AWS::CDK::Metadata' + Properties: + Modules: >- + @aws-cdk/cdk=CDK-VERSION,@aws-cdk/cx-api=CDK-VERSION,my_widget_service=0.1.0 -.. _creating_rds_example: -Creating an |RDS| Database -========================== + .. group-tab:: Java -The following example creates the Aurora database **MyAuroraDatabase**. + .. code-block:: sh -.. code-block:: js + cdk init --language java - import ec2 = require('@aws-cdk/aws-ec2'); - import rds = require('@aws-cdk/aws-rds'); - import cdk = require('@aws-cdk/cdk'); +.. _creating_ecs_l2_example_2: - class MyStack extends cdk.Stack { - constructor(parent: cdk.App, name: string, props?: cdk.StackProps) { - super(parent, name, props); +Step 2: Add the |ECS| Package and ??? +------------------------------------- - const vpc = new ec2.VpcNetwork(this, 'VPC'); +Install support for |EC2| and |ECS|. - new rds.DatabaseCluster(this, 'MyRdsDb', { - defaultDatabaseName: 'MyAuroraDatabase', - masterUser: { - username: 'admin', - password: '123456' - }, - engine: rds.DatabaseClusterEngine.Aurora, - instanceProps: { - instanceType: new ec2.InstanceTypePair(ec2.InstanceClass.Burstable2, ec2.InstanceSize.Small), - vpc: vpc, - vpcPlacement: { - subnetsToUse: ec2.SubnetType.Public - } - } - }); - } - } +.. tabs:: - const app = new cdk.App(); + .. group-tab:: TypeScript - new MyStack(app, 'MyStack'); + .. code-block:: sh - app.run(); + npm install @aws-cdk/aws-ec2 @aws-cdk/aws-ecs -.. _creating_s3_example: +Create an |ECS| Fargate construct. +Fargate ??? -Creating an |S3| Bucket -======================= +.. tabs:: -The following example creates the |S3| bucket **MyS3Bucket** with server-side KMS -encryption provided by |S3|. + .. group-tab:: TypeScript -.. code-block:: js + Add the following import statements: - import s3 = require('@aws-cdk/aws-s3'); - import cdk = require('@aws-cdk/cdk'); + .. code-block:: typescript - class MyStack extends cdk.Stack { - constructor(parent: cdk.App, name: string, props?: cdk.StackProps) { - super(parent, name, props); + import ec2 = require('@aws-cdk/aws-ec2'); + import ecs = require('@aws-cdk/aws-ecs'); - new s3.Bucket(this, 'MyBucket', { - bucketName: 'MyS3Bucket', - encryption: s3.BucketEncryption.KmsManaged - }); - } - } + Add the following code to the end of the constructor: - const app = new cdk.App(); + .. code-block:: typescript - new MyStack(app, 'MyStack'); + // Create a VPC + const vpc = new ec2.VpcNetwork(this, 'VPC');const vpc = new ec2.VpcNetwork(this, 'TheVPC', { + cidr: '10.0.0.0/21', + subnetConfiguration: [ + { + cidrMask: 24, + name: 'Ingress', + subnetType: ec2.SubnetType.Public, + }, + { + cidrMask: 24, + name: 'Application', + subnetType: ec2.SubnetType.Private, + }, + { + cidrMask: 28, + name: 'Database', + subnetType: ec2.SubnetType.Isolated, + } + ], + }); - app.run() + // Create an ECS cluster + const cluster = new ecs.Cluster(this, 'Cluster', { + vpc: vpc, + }); + + // Add capacity to the cluster + cluster.addDefaultAutoScalingGroupCapacity({ + instanceType: new ec2.InstanceType("t2.xlarge"), + instanceCount: 3, + }); + + // Instantiate an ECS Service with an automatic load balancer + const ecsService = new ecs.LoadBalancedEc2Service(this, 'Service', { + cluster, + memoryLimitMiB: 512, + image: ecs.ContainerImage.fromDockerHub("amazon/amazon-ecs-sample"), + }); From 8c8be92a35dbe138220fcd2102e08de66894ef24 Mon Sep 17 00:00:00 2001 From: Doug-AWS Date: Wed, 14 Nov 2018 05:55:01 -0800 Subject: [PATCH 02/17] ECS example WIP --- docs/src/examples.rst | 89 +++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 46 deletions(-) diff --git a/docs/src/examples.rst b/docs/src/examples.rst index 1621eb9361217..681a6ae327c54 100644 --- a/docs/src/examples.rst +++ b/docs/src/examples.rst @@ -37,10 +37,10 @@ gives you a leg up on using these AWS services: * Automatic security group opening for LBs * Automatic ordering dependency between service and LB attaching to target group -* Automatic userdata configuration on ASG +* Automatic userdata configuration on ASG * Early validation of some tricky param combinations, which saves you deployment time in CFN to discover issues * Automatic permissions added for ECR if you use an image from ECR -* convenient api for autoscaling +* convenient api for autoscaling * Asset support, so deploying source from yer machine to ECS in one go @@ -64,7 +64,7 @@ and create a new app in that directory. mkdir MyEcsConstruct cd MyEcsConstruct - + .. tabs:: .. group-tab:: TypeScript @@ -77,10 +77,9 @@ and create a new app in that directory. .. code-block:: ts - #!/usr/bin/env node import cdk = require('@aws-cdk/cdk'); - class MyWidgetServiceStack extends cdk.Stack { + class MyEcsConstructStack extends cdk.Stack { constructor(parent: cdk.App, name: string, props?: cdk.StackProps) { super(parent, name, props); @@ -88,11 +87,9 @@ and create a new app in that directory. } } - // Create a new CDK app const app = new cdk.App(); - // Add your stack to it - new MyWidgetServiceStack(app, 'MyWidgetServiceStack'); + new MyEcsConstructStack(app, 'MyEcsConstructStack'); app.run(); @@ -112,9 +109,7 @@ and create a new app in that directory. CDKMetadata: Type: 'AWS::CDK::Metadata' Properties: - Modules: >- - @aws-cdk/cdk=CDK-VERSION,@aws-cdk/cx-api=CDK-VERSION,my_widget_service=0.1.0 - + Modules: @aws-cdk/cdk=CDK-VERSION,@aws-cdk/cx-api=CDK-VERSION,my_ecs_construct=0.1.0 .. group-tab:: Java @@ -124,8 +119,8 @@ and create a new app in that directory. .. _creating_ecs_l2_example_2: -Step 2: Add the |ECS| Package and ??? -------------------------------------- +Step 2: Add the |EC2| and |ECS| Packages +---------------------------------------- Install support for |EC2| and |ECS|. @@ -137,8 +132,8 @@ Install support for |EC2| and |ECS|. npm install @aws-cdk/aws-ec2 @aws-cdk/aws-ecs -Create an |ECS| Fargate construct. -Fargate ??? +Create a FargateService. +This requires a VPC, cluster, task definition, and security group. .. tabs:: @@ -155,42 +150,44 @@ Fargate ??? .. code-block:: typescript - // Create a VPC - const vpc = new ec2.VpcNetwork(this, 'VPC');const vpc = new ec2.VpcNetwork(this, 'TheVPC', { - cidr: '10.0.0.0/21', - subnetConfiguration: [ - { - cidrMask: 24, - name: 'Ingress', - subnetType: ec2.SubnetType.Public, - }, - { - cidrMask: 24, - name: 'Application', - subnetType: ec2.SubnetType.Private, - }, - { - cidrMask: 28, - name: 'Database', - subnetType: ec2.SubnetType.Isolated, - } - ], + const vpc = new ec2.VpcNetwork(this, 'MyVpc', { + maxAZs: 2 // Default is all AZs in region }); // Create an ECS cluster - const cluster = new ecs.Cluster(this, 'Cluster', { - vpc: vpc, + const cluster = new ecs.Cluster(this, 'MyCluster', { + vpc: vpc + }); + + const taskDefinition = new ecs.FargateTaskDefinition(this, 'MyFargateTaskDefinition', { + cpu: '256', // Default + memoryMiB: '2048' // Default is 512 }); - // Add capacity to the cluster - cluster.addDefaultAutoScalingGroupCapacity({ - instanceType: new ec2.InstanceType("t2.xlarge"), - instanceCount: 3, + // The task definition must have at least one container. + // Otherwise you cannot synthesize or deploy your app. + taskDefinition.addContainer('MyContainer', { + image: ecs.DockerHub.image('MyDockerImage') // Required }); - // Instantiate an ECS Service with an automatic load balancer - const ecsService = new ecs.LoadBalancedEc2Service(this, 'Service', { - cluster, - memoryLimitMiB: 512, - image: ecs.ContainerImage.fromDockerHub("amazon/amazon-ecs-sample"), + const securityGroup = new ec2.SecurityGroup(this, 'MySecurityGroup', { + vpc: vpc }); + + new ecs.FargateService(this, 'MyFargateService', { + taskDefinition: taskDefinition, // Required + cluster: cluster, // Required + desiredCount: 6, // Default is 1 + securityGroup: securityGroup, // Required + platformVersion: ecs.FargatePlatformVersion.Latest // Default + }); + + Save it and make sure it builds and creates a stack. + + .. code-block:: sh + + npm run build + cdk synth + +You should see a stack of about 300 lines, so we won't show it here. + From c6bc455c8ebe2d30b1b654c98a30e7302df65cde Mon Sep 17 00:00:00 2001 From: Doug-AWS Date: Wed, 14 Nov 2018 06:49:33 -0800 Subject: [PATCH 03/17] Fixed TypeScript formatting --- docs/src/examples.rst | 85 +++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 47 deletions(-) diff --git a/docs/src/examples.rst b/docs/src/examples.rst index 681a6ae327c54..18b04de53941c 100644 --- a/docs/src/examples.rst +++ b/docs/src/examples.rst @@ -31,26 +31,17 @@ For more control you can host your tasks on a cluster of Since |ECS| can be used with a number of AWS services, you should understand how the |ECS| construct that we use in this example -gives you a leg up on using these AWS services: - - - -* Automatic security group opening for LBs -* Automatic ordering dependency between service and LB attaching to target group -* Automatic userdata configuration on ASG -* Early validation of some tricky param combinations, which saves you deployment time in CFN to discover issues -* Automatic permissions added for ECR if you use an image from ECR -* convenient api for autoscaling -* Asset support, so deploying source from yer machine to ECS in one go - - - -- |IAM| -- |EC2| -- |ELB| -- |ECR| -- |CFN| - +gives you a leg up on using AWS services: + +* Automatic security group opening for load balancers +* Automatic ordering dependency between service and load balancer attaching to a target group +* Automatic userdata configuration on auto-scaling group +* Early validation of parameter combinations, + which exposes |CFN| issues earlier, + thus saving you deployment time +* Automatically adds permissions for |ECR| if you use an image from |ECR| +* Convenient API for autoscaling +* Asset support, so that you can deploy source from your machine to |ECS| in one step .. _creating_ecs_l2_example_1: @@ -73,43 +64,43 @@ and create a new app in that directory. cdk init --language typescript - Update *my_ecs_construct.ts* in the *bin* directory to only contain the following code: + Update *my_ecs_construct.ts* in the *bin* directory to only contain the following code: - .. code-block:: ts + .. code-block:: ts - import cdk = require('@aws-cdk/cdk'); + import cdk = require('@aws-cdk/cdk'); - class MyEcsConstructStack extends cdk.Stack { - constructor(parent: cdk.App, name: string, props?: cdk.StackProps) { - super(parent, name, props); + class MyEcsConstructStack extends cdk.Stack { + constructor(parent: cdk.App, name: string, props?: cdk.StackProps) { + super(parent, name, props); - } - } + } + } - const app = new cdk.App(); + const app = new cdk.App(); - new MyEcsConstructStack(app, 'MyEcsConstructStack'); + new MyEcsConstructStack(app, 'MyEcsConstructStack'); - app.run(); + app.run(); - Save it and make sure it builds and creates an empty stack. + Save it and make sure it builds and creates an empty stack. - .. code-block:: sh + .. code-block:: sh - npm run build - cdk synth + npm run build + cdk synth - You should see a stack like the following, - where CDK-VERSION is the version of the CDK. + You should see a stack like the following, + where CDK-VERSION is the version of the CDK. - .. code-block:: sh + .. code-block:: sh - Resources: - CDKMetadata: - Type: 'AWS::CDK::Metadata' - Properties: - Modules: @aws-cdk/cdk=CDK-VERSION,@aws-cdk/cx-api=CDK-VERSION,my_ecs_construct=0.1.0 + Resources: + CDKMetadata: + Type: 'AWS::CDK::Metadata' + Properties: + Modules: @aws-cdk/cdk=CDK-VERSION,@aws-cdk/cx-api=CDK-VERSION,my_ecs_construct=0.1.0 .. group-tab:: Java @@ -182,12 +173,12 @@ This requires a VPC, cluster, task definition, and security group. platformVersion: ecs.FargatePlatformVersion.Latest // Default }); - Save it and make sure it builds and creates a stack. + Save it and make sure it builds and creates a stack. - .. code-block:: sh + .. code-block:: sh - npm run build - cdk synth + npm run build + cdk synth You should see a stack of about 300 lines, so we won't show it here. From f342d3bb2b6cdbb1c02f8759cd60f61f715b9ee0 Mon Sep 17 00:00:00 2001 From: Doug-AWS Date: Wed, 14 Nov 2018 07:21:16 -0800 Subject: [PATCH 04/17] WIP; explained the two launch types --- docs/src/examples.rst | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/docs/src/examples.rst b/docs/src/examples.rst index 18b04de53941c..060bba5305d1c 100644 --- a/docs/src/examples.rst +++ b/docs/src/examples.rst @@ -123,8 +123,19 @@ Install support for |EC2| and |ECS|. npm install @aws-cdk/aws-ec2 @aws-cdk/aws-ecs -Create a FargateService. -This requires a VPC, cluster, task definition, and security group. +.. _creating_ecs_l2_example_3: + +Step 3: Create a Fargate Service +-------------------------------- + +There are two different ways of creating a serverless infrastructure with |ECS|: + +- Using the **Fargate** launch type, where |ECS| manages your cluster resources +- Using the **EC2** launch type, where you manage your cluster resources + +This example creates a Fargate service, +which requires a VPC, a cluster, a task definition, and a security group. +Later on we'll show you how to launch an EC2 service. .. tabs:: @@ -181,4 +192,3 @@ This requires a VPC, cluster, task definition, and security group. cdk synth You should see a stack of about 300 lines, so we won't show it here. - From 29dfa0b62a6c977cd1f39038e3b94c1c25f63e2f Mon Sep 17 00:00:00 2001 From: Doug-AWS Date: Wed, 14 Nov 2018 11:37:16 -0800 Subject: [PATCH 05/17] Fixed ECS example --- docs/src/examples.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/examples.rst b/docs/src/examples.rst index 060bba5305d1c..0ded2e22480b6 100644 --- a/docs/src/examples.rst +++ b/docs/src/examples.rst @@ -169,7 +169,7 @@ Later on we'll show you how to launch an EC2 service. // The task definition must have at least one container. // Otherwise you cannot synthesize or deploy your app. taskDefinition.addContainer('MyContainer', { - image: ecs.DockerHub.image('MyDockerImage') // Required + image: ecs.ContainerImage.fromDockerHub('MyDockerImage') // Required }); const securityGroup = new ec2.SecurityGroup(this, 'MySecurityGroup', { From 5cb3d900d4fecc0401987199a3aba3806c9963a8 Mon Sep 17 00:00:00 2001 From: Doug-AWS Date: Fri, 16 Nov 2018 08:16:41 -0800 Subject: [PATCH 06/17] Removed lingering Java tab --- docs/src/examples.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/docs/src/examples.rst b/docs/src/examples.rst index 0ded2e22480b6..828c2cc418dea 100644 --- a/docs/src/examples.rst +++ b/docs/src/examples.rst @@ -102,12 +102,6 @@ and create a new app in that directory. Properties: Modules: @aws-cdk/cdk=CDK-VERSION,@aws-cdk/cx-api=CDK-VERSION,my_ecs_construct=0.1.0 - .. group-tab:: Java - - .. code-block:: sh - - cdk init --language java - .. _creating_ecs_l2_example_2: Step 2: Add the |EC2| and |ECS| Packages From 908f28a973745865348294a12b0965c1c6a5d312 Mon Sep 17 00:00:00 2001 From: Doug Date: Mon, 19 Nov 2018 06:33:12 -0800 Subject: [PATCH 07/17] Update examples.rst --- docs/src/examples.rst | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/docs/src/examples.rst b/docs/src/examples.rst index 828c2cc418dea..c90e44837a84a 100644 --- a/docs/src/examples.rst +++ b/docs/src/examples.rst @@ -19,7 +19,7 @@ offered by the |cdk|. .. _creating_ecs_l2_example: -Creating an |ECS| Construct +Creating an |ECS| |cdk| App =========================== |ECSlong| (|ECS|) is a highly scalable, fast, container management service @@ -31,7 +31,7 @@ For more control you can host your tasks on a cluster of Since |ECS| can be used with a number of AWS services, you should understand how the |ECS| construct that we use in this example -gives you a leg up on using AWS services: +gives you a leg up on using AWS services by providing the following benefits: * Automatic security group opening for load balancers * Automatic ordering dependency between service and load balancer attaching to a target group @@ -122,14 +122,14 @@ Install support for |EC2| and |ECS|. Step 3: Create a Fargate Service -------------------------------- -There are two different ways of creating a serverless infrastructure with |ECS|: +There are two different ways of running your container tasks with |ECS|: - Using the **Fargate** launch type, where |ECS| manages your cluster resources - Using the **EC2** launch type, where you manage your cluster resources This example creates a Fargate service, which requires a VPC, a cluster, a task definition, and a security group. -Later on we'll show you how to launch an EC2 service. +Later on we'll show you how to launch |EC2| instances that you manage. .. tabs:: @@ -147,7 +147,7 @@ Later on we'll show you how to launch an EC2 service. .. code-block:: typescript const vpc = new ec2.VpcNetwork(this, 'MyVpc', { - maxAZs: 2 // Default is all AZs in region + maxAZs: 3 // Default is all AZs in region }); // Create an ECS cluster @@ -160,22 +160,15 @@ Later on we'll show you how to launch an EC2 service. memoryMiB: '2048' // Default is 512 }); - // The task definition must have at least one container. - // Otherwise you cannot synthesize or deploy your app. + // The task definition for the container. taskDefinition.addContainer('MyContainer', { - image: ecs.ContainerImage.fromDockerHub('MyDockerImage') // Required - }); - - const securityGroup = new ec2.SecurityGroup(this, 'MySecurityGroup', { - vpc: vpc + image: ecs.ContainerImage.fromDockerHub('amazon/amazon-ecs-sample') // Required }); new ecs.FargateService(this, 'MyFargateService', { taskDefinition: taskDefinition, // Required cluster: cluster, // Required desiredCount: 6, // Default is 1 - securityGroup: securityGroup, // Required - platformVersion: ecs.FargatePlatformVersion.Latest // Default }); Save it and make sure it builds and creates a stack. From b5b3dd420e3a7e127230463cd745fd662a24d797 Mon Sep 17 00:00:00 2001 From: Doug-AWS Date: Tue, 20 Nov 2018 05:12:25 -0800 Subject: [PATCH 08/17] WIP on ECS example --- docs/src/examples.rst | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/docs/src/examples.rst b/docs/src/examples.rst index c90e44837a84a..a6fbf00939562 100644 --- a/docs/src/examples.rst +++ b/docs/src/examples.rst @@ -156,7 +156,7 @@ Later on we'll show you how to launch |EC2| instances that you manage. }); const taskDefinition = new ecs.FargateTaskDefinition(this, 'MyFargateTaskDefinition', { - cpu: '256', // Default + cpu: '512', // Default is 256 memoryMiB: '2048' // Default is 512 }); @@ -178,4 +178,34 @@ Later on we'll show you how to launch |EC2| instances that you manage. npm run build cdk synth -You should see a stack of about 300 lines, so we won't show it here. + You should see a stack of about 300 lines, so we won't show it here. + The stack should contain one default instance, two public subnets, + and a security group. + + Deploy the stack. + + .. code-block:: sh + + cdk deploy + +.. _creating_ecs_l2_example_4: + +Step 4: Adding to the Fargate Service +------------------------------------- + +We've created about the simplest Fargate service, +but it isn't very robust and might not be able to handle +larger loads, so let's add an auto-scaling group. + +Add the following code just after you declare a cluster, +but before you create the service. +This code extends the |ECS| cluster with three t2.xlarge instances, +instead of default of one ??? instance. + +.. code-block:: ts + + // Add capacity to it + cluster.addDefaultAutoScalingGroupCapacity({ + instanceType: new ec2.InstanceType('t2.xlarge'), + instanceCount: 3 // default is 1 + }); From 9105f9732f7275cb88bc2404e2e75f30be92bb76 Mon Sep 17 00:00:00 2001 From: Doug-AWS Date: Tue, 20 Nov 2018 10:15:55 -0800 Subject: [PATCH 09/17] Update list of AWS service benefits; WIP --- docs/src/examples.rst | 56 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 11 deletions(-) diff --git a/docs/src/examples.rst b/docs/src/examples.rst index a6fbf00939562..fac396f709ef1 100644 --- a/docs/src/examples.rst +++ b/docs/src/examples.rst @@ -29,20 +29,48 @@ You can host your cluster on a serverless infrastructure that is managed by For more control you can host your tasks on a cluster of |EC2long| (|EC2|) instances that you manage by using the EC2 launch type. +This example shows you how to launch some services using the Fargate launch type, +similar to the `AWS ECS tutorial on creating a cluster and launching a sample web application `_. +This example replicates that tutorial in |cdk| code. +Then we'll show you how to update the web app to be a simple greeting server. +The front facing greeter service fetches a random greeting and a random name from two backend services. + Since |ECS| can be used with a number of AWS services, you should understand how the |ECS| construct that we use in this example gives you a leg up on using AWS services by providing the following benefits: -* Automatic security group opening for load balancers -* Automatic ordering dependency between service and load balancer attaching to a target group -* Automatic userdata configuration on auto-scaling group -* Early validation of parameter combinations, - which exposes |CFN| issues earlier, - thus saving you deployment time +* Automatic security group opening for load balancers, + which enables load balancers to communicate with instances + without you explictly creating a security group. + +* Automatic ordering dependency between service and load balancer attaching to a target group, + where the |cdk| enforces the correct order of creating the listener before an instance is created + +* Automatic userdata configuration on auto-scaling group, + which creates the correct configuration to associate a cluster to AMI(s). + +* Early validation of parameter combinations, which exposes |CFN| issues earlier, thus saving you deployment time. + For example, depending upon the task, it is easy to mis-configure the memory settings. + Previously you would not encounter an error until you deployed your app, + but now the |cdk| can detect a misconfiguration and emit an error when you synthesize your app. + * Automatically adds permissions for |ECR| if you use an image from |ECR| + When you use an image from |ECR|, the |cdk| adds the correct permissions. + * Convenient API for autoscaling -* Asset support, so that you can deploy source from your machine to |ECS| in one step + The |cdk| supplies a method so you can autoscaling instances when you use an |EC2| cluster; + this functionality is done automatically when you use an instance in a Fargate cluster. + + In addition, the |cdk| will prevent instances from being deleted when + autoscaling tries to kill an instance, + but either a task is running or is scheduled on that instance. + Previously, you had to create a Lambda function to have this functionality. + +* Asset support, so that you can deploy source from your machine to |ECS| in one step + Previously, to use application source you had to perform a number of manual steps + (upload to |ECR|, create Docker image, etc.). + .. _creating_ecs_l2_example_1: Step 1: Create the Directory and Initialze the |cdk| @@ -128,8 +156,11 @@ There are two different ways of running your container tasks with |ECS|: - Using the **EC2** launch type, where you manage your cluster resources This example creates a Fargate service, -which requires a VPC, a cluster, a task definition, and a security group. -Later on we'll show you how to launch |EC2| instances that you manage. +which requires a VPC, a cluster, and a task definition. +You can read information about the Docker image **amazon/amazon-ecs-sample** +at + +.. Todo task: Later on we'll show you how to launch |EC2| instances that you manage. .. tabs:: @@ -188,10 +219,13 @@ Later on we'll show you how to launch |EC2| instances that you manage. cdk deploy + |CFN| displays information abvout the 30 or so steps that + it makes as it deploys your app. + .. _creating_ecs_l2_example_4: -Step 4: Adding to the Fargate Service -------------------------------------- +Step 4: Adding to the Service +----------------------------- We've created about the simplest Fargate service, but it isn't very robust and might not be able to handle From 6b36eb703a0c556579119ddbafa3d461711a20d0 Mon Sep 17 00:00:00 2001 From: Doug-AWS Date: Tue, 20 Nov 2018 12:23:57 -0800 Subject: [PATCH 10/17] Updated intro text for ECS example; WIP --- docs/src/examples.rst | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/docs/src/examples.rst b/docs/src/examples.rst index fac396f709ef1..4cbc1ed1cd4e1 100644 --- a/docs/src/examples.rst +++ b/docs/src/examples.rst @@ -29,9 +29,19 @@ You can host your cluster on a serverless infrastructure that is managed by For more control you can host your tasks on a cluster of |EC2long| (|EC2|) instances that you manage by using the EC2 launch type. -This example shows you how to launch some services using the Fargate launch type, -similar to the `AWS ECS tutorial on creating a cluster and launching a sample web application `_. -This example replicates that tutorial in |cdk| code. +This example shows you how to launch some services using the Fargate launch type. +If you've ever used the console to create a Fargate service, +you know that there are many steps you must follow to accomplish that task. +AWS has a number of tutorials and documentation topics that walk you through +creating a Fargate service, +including: + +* `How to Deploy Docker Containers - AWS `_ + +* `Setting up with Amazon ECS `_ and +`Getting Started with Amazon ECS using Fargate `_ + +This example creates a similar Fargate service in |cdk| code. Then we'll show you how to update the web app to be a simple greeting server. The front facing greeter service fetches a random greeting and a random name from two backend services. From 8e783eacdb023c96a0a49a46305989ae8b7d0d09 Mon Sep 17 00:00:00 2001 From: Doug-AWS Date: Tue, 20 Nov 2018 13:34:20 -0800 Subject: [PATCH 11/17] Removed info about future content in examples --- docs/src/examples.rst | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/docs/src/examples.rst b/docs/src/examples.rst index 4cbc1ed1cd4e1..de2bbf3785e85 100644 --- a/docs/src/examples.rst +++ b/docs/src/examples.rst @@ -39,11 +39,11 @@ including: * `How to Deploy Docker Containers - AWS `_ * `Setting up with Amazon ECS `_ and -`Getting Started with Amazon ECS using Fargate `_ + `Getting Started with Amazon ECS using Fargate `_ This example creates a similar Fargate service in |cdk| code. -Then we'll show you how to update the web app to be a simple greeting server. -The front facing greeter service fetches a random greeting and a random name from two backend services. +.. Then we'll show you how to update the web app to be a simple greeting server. + The front facing greeter service fetches a random greeting and a random name from two backend services. Since |ECS| can be used with a number of AWS services, you should understand how the |ECS| construct that we use in this example @@ -219,9 +219,9 @@ at npm run build cdk synth - You should see a stack of about 300 lines, so we won't show it here. - The stack should contain one default instance, two public subnets, - and a security group. + You should see a stack of a couple hundred lines, so we won't show it here. + The stack should contain one default instance, a private subnet and a public subnet + for the three availability zones, and a security group. Deploy the stack. @@ -229,7 +229,7 @@ at cdk deploy - |CFN| displays information abvout the 30 or so steps that + |CFN| displays information about the dozens of steps that it makes as it deploys your app. .. _creating_ecs_l2_example_4: @@ -243,8 +243,7 @@ larger loads, so let's add an auto-scaling group. Add the following code just after you declare a cluster, but before you create the service. -This code extends the |ECS| cluster with three t2.xlarge instances, -instead of default of one ??? instance. +This code creates a cluster that scales out to up to three **t2.xlarge** instances. .. code-block:: ts From 675b8a82ed93c22c7944efde675bb0a646ca0954 Mon Sep 17 00:00:00 2001 From: Doug-AWS Date: Tue, 20 Nov 2018 13:53:05 -0800 Subject: [PATCH 12/17] First cut at ECS example for re:Invent --- docs/src/examples.rst | 48 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/docs/src/examples.rst b/docs/src/examples.rst index de2bbf3785e85..474ce2ad24915 100644 --- a/docs/src/examples.rst +++ b/docs/src/examples.rst @@ -241,14 +241,46 @@ We've created about the simplest Fargate service, but it isn't very robust and might not be able to handle larger loads, so let's add an auto-scaling group. -Add the following code just after you declare a cluster, -but before you create the service. +Add the following code just after you declare a cluster. This code creates a cluster that scales out to up to three **t2.xlarge** instances. -.. code-block:: ts +.. tabs:: + + .. group-tab:: TypeScript + + Add the following import statements: + + .. code-block:: typescript + + .. code-block:: ts + + // Add capacity to it + cluster.addDefaultAutoScalingGroupCapacity({ + instanceType: new ec2.InstanceType('t2.xlarge'), + instanceCount: 3 // default is 1 + }); + + Save it and make sure it builds and creates a stack. + + .. code-block:: sh + + npm run build + cdk synth + + Another awesome |cdk| feature is being able to see what you've changed + in comparison to what you've already deployed: + + .. code-block:: sh + + cdk diff + + You should see about a dozen resource changes, including the new auto-scaling resources, + such as a new **LifecycleHook**. + + Deploy the stack. + + .. code-block:: sh + + cdk deploy - // Add capacity to it - cluster.addDefaultAutoScalingGroupCapacity({ - instanceType: new ec2.InstanceType('t2.xlarge'), - instanceCount: 3 // default is 1 - }); +That's how easy it is to create a Fargate service to run a Docker image with autoscaling. From 0f8713b6048bfbc2556c41d6c76002545fa1aa15 Mon Sep 17 00:00:00 2001 From: Doug-AWS Date: Tue, 20 Nov 2018 14:00:34 -0800 Subject: [PATCH 13/17] Removed mentions of greeter service(s) --- docs/src/examples.rst | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/docs/src/examples.rst b/docs/src/examples.rst index 474ce2ad24915..1a6e286eca517 100644 --- a/docs/src/examples.rst +++ b/docs/src/examples.rst @@ -42,8 +42,6 @@ including: `Getting Started with Amazon ECS using Fargate `_ This example creates a similar Fargate service in |cdk| code. -.. Then we'll show you how to update the web app to be a simple greeting server. - The front facing greeter service fetches a random greeting and a random name from two backend services. Since |ECS| can be used with a number of AWS services, you should understand how the |ECS| construct that we use in this example @@ -167,10 +165,6 @@ There are two different ways of running your container tasks with |ECS|: This example creates a Fargate service, which requires a VPC, a cluster, and a task definition. -You can read information about the Docker image **amazon/amazon-ecs-sample** -at - -.. Todo task: Later on we'll show you how to launch |EC2| instances that you manage. .. tabs:: @@ -230,16 +224,14 @@ at cdk deploy |CFN| displays information about the dozens of steps that - it makes as it deploys your app. + it takes as it deploys your app. .. _creating_ecs_l2_example_4: Step 4: Adding to the Service ----------------------------- -We've created about the simplest Fargate service, -but it isn't very robust and might not be able to handle -larger loads, so let's add an auto-scaling group. +Let's add auto-scaling to our cluster. Add the following code just after you declare a cluster. This code creates a cluster that scales out to up to three **t2.xlarge** instances. From 307b34ae51376f2d6e4b905d76af1f92f758cfba Mon Sep 17 00:00:00 2001 From: Doug Date: Wed, 21 Nov 2018 07:28:47 -0800 Subject: [PATCH 14/17] Update examples.rst --- docs/src/examples.rst | 59 ++++--------------------------------------- 1 file changed, 5 insertions(+), 54 deletions(-) diff --git a/docs/src/examples.rst b/docs/src/examples.rst index 1a6e286eca517..b5d42bf9e426b 100644 --- a/docs/src/examples.rst +++ b/docs/src/examples.rst @@ -81,8 +81,8 @@ gives you a leg up on using AWS services by providing the following benefits: .. _creating_ecs_l2_example_1: -Step 1: Create the Directory and Initialze the |cdk| ----------------------------------------------------- +Step 1: Create the Directory and Initialize the |cdk| +----------------------------------------------------- Let's start with creating a new directory to hold our |cdk| code and create a new app in that directory. @@ -160,8 +160,8 @@ Step 3: Create a Fargate Service There are two different ways of running your container tasks with |ECS|: -- Using the **Fargate** launch type, where |ECS| manages your cluster resources -- Using the **EC2** launch type, where you manage your cluster resources +- Using the **Fargate** launch type, where |ECS| manages the physical machines that your containers are running on for you +- Using the **EC2** launch type, where you do the managing, such as specifying autoscaling This example creates a Fargate service, which requires a VPC, a cluster, and a task definition. @@ -226,53 +226,4 @@ which requires a VPC, a cluster, and a task definition. |CFN| displays information about the dozens of steps that it takes as it deploys your app. -.. _creating_ecs_l2_example_4: - -Step 4: Adding to the Service ------------------------------ - -Let's add auto-scaling to our cluster. - -Add the following code just after you declare a cluster. -This code creates a cluster that scales out to up to three **t2.xlarge** instances. - -.. tabs:: - - .. group-tab:: TypeScript - - Add the following import statements: - - .. code-block:: typescript - - .. code-block:: ts - - // Add capacity to it - cluster.addDefaultAutoScalingGroupCapacity({ - instanceType: new ec2.InstanceType('t2.xlarge'), - instanceCount: 3 // default is 1 - }); - - Save it and make sure it builds and creates a stack. - - .. code-block:: sh - - npm run build - cdk synth - - Another awesome |cdk| feature is being able to see what you've changed - in comparison to what you've already deployed: - - .. code-block:: sh - - cdk diff - - You should see about a dozen resource changes, including the new auto-scaling resources, - such as a new **LifecycleHook**. - - Deploy the stack. - - .. code-block:: sh - - cdk deploy - -That's how easy it is to create a Fargate service to run a Docker image with autoscaling. +That's how easy it is to create a Fargate service to run a Docker image. From aa359ac86b1aa2f9f943bf7fdfd318a71c0256b8 Mon Sep 17 00:00:00 2001 From: Doug-AWS Date: Mon, 3 Dec 2018 12:48:03 -0800 Subject: [PATCH 15/17] Updated FargateService to LoadBalancedFargateService --- docs/src/examples.rst | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/src/examples.rst b/docs/src/examples.rst index b5d42bf9e426b..d4cfb93a6f4ca 100644 --- a/docs/src/examples.rst +++ b/docs/src/examples.rst @@ -160,11 +160,12 @@ Step 3: Create a Fargate Service There are two different ways of running your container tasks with |ECS|: -- Using the **Fargate** launch type, where |ECS| manages the physical machines that your containers are running on for you +- Using the **Fargate** launch type, + where |ECS| manages the physical machines that your containers are running on for you - Using the **EC2** launch type, where you do the managing, such as specifying autoscaling -This example creates a Fargate service, -which requires a VPC, a cluster, and a task definition. +The following example creates a Fargate service running on an ECS cluster fronted by an internet-facing +application load balancer. .. tabs:: @@ -185,25 +186,24 @@ which requires a VPC, a cluster, and a task definition. maxAZs: 3 // Default is all AZs in region }); - // Create an ECS cluster const cluster = new ecs.Cluster(this, 'MyCluster', { vpc: vpc }); - const taskDefinition = new ecs.FargateTaskDefinition(this, 'MyFargateTaskDefinition', { - cpu: '512', // Default is 256 - memoryMiB: '2048' // Default is 512 + // Add capacity to it + cluster.addDefaultAutoScalingGroupCapacity({ + instanceType: new ec2.InstanceType('t2.xlarge'), + instanceCount: 3 // default is 1 }); - - // The task definition for the container. - taskDefinition.addContainer('MyContainer', { - image: ecs.ContainerImage.fromDockerHub('amazon/amazon-ecs-sample') // Required - }); - - new ecs.FargateService(this, 'MyFargateService', { - taskDefinition: taskDefinition, // Required + + // Create a load-balanced Fargate service and make it public + new ecs.LoadBalancedFargateService(this, 'MyFargateService', { cluster: cluster, // Required + cpu: '512', // Default is 256 desiredCount: 6, // Default is 1 + image: ecs.ContainerImage.fromDockerHub('amazon/amazon-ecs-sample'), // Required + memoryMiB: '2048', // Default is 512 + publicLoadBalancer: true // Default is false }); Save it and make sure it builds and creates a stack. From d0e2aa2f8655d7e3d5083a56599b4041f0869a7e Mon Sep 17 00:00:00 2001 From: Doug-AWS Date: Thu, 6 Dec 2018 08:17:48 -0800 Subject: [PATCH 16/17] Updated ECS example using CDK 0.19.0; removed autoscaling --- docs/src/examples.rst | 38 +++++++------------------------------- 1 file changed, 7 insertions(+), 31 deletions(-) diff --git a/docs/src/examples.rst b/docs/src/examples.rst index d4cfb93a6f4ca..523eefb9e952a 100644 --- a/docs/src/examples.rst +++ b/docs/src/examples.rst @@ -47,6 +47,8 @@ Since |ECS| can be used with a number of AWS services, you should understand how the |ECS| construct that we use in this example gives you a leg up on using AWS services by providing the following benefits: +* Automatically configures a load balancer. + * Automatic security group opening for load balancers, which enables load balancers to communicate with instances without you explictly creating a security group. @@ -65,7 +67,7 @@ gives you a leg up on using AWS services by providing the following benefits: * Automatically adds permissions for |ECR| if you use an image from |ECR| When you use an image from |ECR|, the |cdk| adds the correct permissions. -* Convenient API for autoscaling +* Automatic autoscaling The |cdk| supplies a method so you can autoscaling instances when you use an |EC2| cluster; this functionality is done automatically when you use an instance in a Fargate cluster. @@ -100,27 +102,7 @@ and create a new app in that directory. cdk init --language typescript - Update *my_ecs_construct.ts* in the *bin* directory to only contain the following code: - - .. code-block:: ts - - import cdk = require('@aws-cdk/cdk'); - - class MyEcsConstructStack extends cdk.Stack { - constructor(parent: cdk.App, name: string, props?: cdk.StackProps) { - super(parent, name, props); - - - } - } - - const app = new cdk.App(); - - new MyEcsConstructStack(app, 'MyEcsConstructStack'); - - app.run(); - - Save it and make sure it builds and creates an empty stack. + Build the app and confirm that it creates an empty stack. .. code-block:: sh @@ -171,14 +153,14 @@ application load balancer. .. group-tab:: TypeScript - Add the following import statements: + Add the following import statements to *lib/my_ecs_construct-stack.ts*: .. code-block:: typescript import ec2 = require('@aws-cdk/aws-ec2'); import ecs = require('@aws-cdk/aws-ecs'); - Add the following code to the end of the constructor: + Replace the comment at the end of the constructor with the following code: .. code-block:: typescript @@ -190,12 +172,6 @@ application load balancer. vpc: vpc }); - // Add capacity to it - cluster.addDefaultAutoScalingGroupCapacity({ - instanceType: new ec2.InstanceType('t2.xlarge'), - instanceCount: 3 // default is 1 - }); - // Create a load-balanced Fargate service and make it public new ecs.LoadBalancedFargateService(this, 'MyFargateService', { cluster: cluster, // Required @@ -213,7 +189,7 @@ application load balancer. npm run build cdk synth - You should see a stack of a couple hundred lines, so we won't show it here. + The stack is hundreds of lines, so we won't show it here. The stack should contain one default instance, a private subnet and a public subnet for the three availability zones, and a security group. From 34275d913c6102b0231054f0306a37fc9a0a7a3b Mon Sep 17 00:00:00 2001 From: Doug-AWS Date: Fri, 7 Dec 2018 06:39:57 -0800 Subject: [PATCH 17/17] Reverted autoscaling blurb --- docs/src/examples.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/examples.rst b/docs/src/examples.rst index 523eefb9e952a..6ca6eaa1ffdeb 100644 --- a/docs/src/examples.rst +++ b/docs/src/examples.rst @@ -67,8 +67,8 @@ gives you a leg up on using AWS services by providing the following benefits: * Automatically adds permissions for |ECR| if you use an image from |ECR| When you use an image from |ECR|, the |cdk| adds the correct permissions. -* Automatic autoscaling - The |cdk| supplies a method so you can autoscaling instances when you use an |EC2| cluster; +* Convenient API for autoscaling + The |cdk| supplies a method so you can autoscale instances when you use an |EC2| cluster; this functionality is done automatically when you use an instance in a Fargate cluster. In addition, the |cdk| will prevent instances from being deleted when