Skip to content

Commit

Permalink
Migrate task sets example template to CDK
Browse files Browse the repository at this point in the history
  • Loading branch information
clareliguori committed Jan 7, 2021
1 parent 6cef496 commit 92be98f
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 295 deletions.
25 changes: 21 additions & 4 deletions trivia-backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ There are multiple options in the [infra](infra/) folder for provisioning and de
1. ECS on Fargate, deployed via CloudFormation using [ECS task set deployments](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/deployment-type-external.html)
1. ECS on Fargate, deployed via CloudFormation using [CodeDeploy blue-green deployments](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/blue-green.html)
1. ECS on Fargate, deployed using [CodeDeploy blue-green deployments](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/deployment-type-bluegreen.html) outside of CloudFormation
1. EKS on Fargate, deployed via CloudFormation using a [CloudFormation custom resource to run kubectl](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-eks-legacy.KubernetesResource.html)
1. EKS on Fargate, deployed via CloudFormation using a [CloudFormation custom resource to run kubectl](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-eks.KubernetesManifest.html)

### ECS on Fargate (rolling update deployments)

The [cdk](infra/cdk/) folder contains an example of how to model this service with the [AWS Cloud Development Kit (AWS)](https://github.com/awslabs/aws-cdk) and deploy the service with CloudFormation, using [ECS rolling update deployments](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/deployment-type-ecs.html).
The [cdk](infra/cdk/) folder contains the example 'ecs-service' for how to model this service with the [AWS Cloud Development Kit (AWS)](https://github.com/awslabs/aws-cdk) and deploy the service with CloudFormation, using [ECS rolling update deployments](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/deployment-type-ecs.html).

To deploy the Typescript example, run the following.
```
Expand All @@ -66,9 +66,26 @@ cdk deploy --app ecs-service.js TriviaBackendProd

See the 'api-service-pipeline' example in the [pipelines](../pipelines/) folder for instructions on how to continuously deploy this example with CodePipeline's [CloudFormation deploy action](https://docs.aws.amazon.com/codepipeline/latest/userguide/integrations-action-type.html#integrations-deploy-CloudFormation).

### ECS on Fargate (task set deployments)

The [cdk](infra/cdk/) folder contains the example 'ecs-task-sets' for how to model this service with the [AWS Cloud Development Kit (AWS)](https://github.com/awslabs/aws-cdk) and deploy the service with CloudFormation, using [ECS task set deployments](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/deployment-type-external.html). Note that this example does not currently have a continuous deployment pipeline example in this repo.

To deploy the Typescript example, run the following.
```
npm install -g aws-cdk
npm install
npm run build
cdk synth -o build --app 'node ecs-task-sets.js'
cdk deploy --app ecs-task-sets.js TriviaBackendTaskSets
```

### ECS on Fargate (CodeDeploy blue-green deployments, outside of CloudFormation)

The [codedeploy-blue-green](infra/codedeploy-blue-green/) folder contains examples of the configuration needed to setup and execute a [blue-green deployment with CodeDeploy](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/deployment-type-bluegreen.html) directly: CodeDeploy appspec file, ECS task definition file, ECS service, CodeDeploy application definition, and CodeDeploy deployment group.
The [codedeploy-blue-green](infra/codedeploy-blue-green/) folder contains an example of the configuration needed to setup and execute a [blue-green deployment with CodeDeploy](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/deployment-type-bluegreen.html) directly: CodeDeploy appspec file, ECS task definition file, ECS service, CodeDeploy application definition, and CodeDeploy deployment group.

The non-service infrastructure (load balancer, security groups, roles, etc) is modeled and provisioned with the AWS CDK and CloudFormation. A sample pre-traffic CodeDeploy hook is modeled and provisioned with CloudFormation. In this example, the ECS service is initially created outside of CloudFormation, and all future deployments are done directly with CodeDeploy outside of CloudFormation.

Expand All @@ -83,7 +100,7 @@ See the 'api-service-codedeploy-pipeline' example in the [pipelines](../pipeline

### EKS on Fargate

The [cdk](infra/cdk/) folder contains examples of how to model this service with the [AWS Cloud Development Kit (AWS)](https://github.com/awslabs/aws-cdk) and deploy it to EKS on Fargate, using a [CloudFormation custom resource to run kubectl](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-eks-legacy.KubernetesResource.html). Note that this example does not currently have a continuous deployment pipeline example.
The [cdk](infra/cdk/) folder contains the example 'eks-service' for how to model this service with the [AWS Cloud Development Kit (AWS)](https://github.com/awslabs/aws-cdk) and deploy it to EKS on Fargate, using a [CloudFormation custom resource to run kubectl](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-eks-legacy.KubernetesResource.html)). Note that this example does not currently have a continuous deployment pipeline example in this repo.

First, install [kubectl](https://github.com/kubernetes/kubectl) and [eksctl](https://github.com/weaveworks/eksctl).

Expand Down
114 changes: 114 additions & 0 deletions trivia-backend/infra/cdk/ecs-task-sets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#!/usr/bin/env node
import { Port, SecurityGroup, Vpc } from '@aws-cdk/aws-ec2';
import { Repository } from '@aws-cdk/aws-ecr';
import * as ecs from '@aws-cdk/aws-ecs';
import { ApplicationLoadBalancer, ApplicationProtocol, ApplicationTargetGroup, IApplicationLoadBalancerTarget, LoadBalancerTargetProps, TargetType, Protocol } from '@aws-cdk/aws-elasticloadbalancingv2';
import cdk = require('@aws-cdk/core');

class TriviaBackendStack extends cdk.Stack {
constructor(parent: cdk.App, name: string, props: cdk.StackProps) {
super(parent, name, props);

// Configuration parameters
const imageRepo = Repository.fromRepositoryName(this, 'Repo', 'reinvent-trivia-backend');
const tag = (process.env.IMAGE_TAG) ? process.env.IMAGE_TAG : 'latest';
const image = ecs.ContainerImage.fromEcrRepository(imageRepo, tag)

// Look up existing network infrastructure (default VPC)
const vpc = Vpc.fromLookup(this, 'Vpc', {
isDefault: true,
});
const subnets = vpc.publicSubnets;
const cluster = ecs.Cluster.fromClusterAttributes(this, 'Cluster', {
clusterName: 'default',
vpc,
securityGroups: [],
});

// Create load balancer and security group resources
const serviceSG = new SecurityGroup(this, 'ServiceSecurityGroup', { vpc });

const loadBalancer = new ApplicationLoadBalancer(this, 'LB', {
vpc,
internetFacing: true,
});
serviceSG.connections.allowFrom(loadBalancer, Port.tcp(80));
new cdk.CfnOutput(this, 'ServiceURL', { value: 'http://' + loadBalancer.loadBalancerDnsName });

const listener = loadBalancer.addListener('PublicListener', {
protocol: ApplicationProtocol.HTTP,
port: 80,
open: true,
});
const targetGroup = listener.addTargets('ECS', {
protocol: ApplicationProtocol.HTTP,
deregistrationDelay: cdk.Duration.seconds(5),
healthCheck: {
interval: cdk.Duration.seconds(5),
path: '/',
protocol: Protocol.HTTP,
healthyThresholdCount: 2,
unhealthyThresholdCount: 3,
timeout: cdk.Duration.seconds(4)
},
targets: [ // empty to begin with, set the target type to be 'IP'
new (class EmptyIpTarget implements IApplicationLoadBalancerTarget {
attachToApplicationTargetGroup(_: ApplicationTargetGroup): LoadBalancerTargetProps {
return { targetType: TargetType.IP };
}
})()
],
});

// Create Fargate resources: task definition, service, task set, etc
const taskDefinition = new ecs.FargateTaskDefinition(this, 'TaskDefinition', {});
const container = taskDefinition.addContainer('web', {
image,
logging: new ecs.AwsLogDriver({ streamPrefix: 'Service' }),
});
container.addPortMappings({ containerPort: 80 });

const service = new ecs.CfnService(this, 'Service', {
cluster: cluster.clusterName,
desiredCount: 2,
deploymentController: { type: ecs.DeploymentControllerType.EXTERNAL },
});
service.node.addDependency(targetGroup);
service.node.addDependency(listener);

const taskSet = new ecs.CfnTaskSet(this, 'TaskSet', {
cluster: cluster.clusterName,
service: service.attrName,
scale: { unit: 'PERCENT', value: 100 },
taskDefinition: taskDefinition.taskDefinitionArn,
launchType: ecs.LaunchType.FARGATE.toString(),
loadBalancers: [
{
containerName: 'web',
containerPort: 80,
targetGroupArn: targetGroup.targetGroupArn,
}
],
networkConfiguration: {
awsVpcConfiguration: {
assignPublicIp: 'ENABLED',
securityGroups: [ serviceSG.securityGroupId ],
subnets: subnets.map(subnet => subnet.subnetId),
}
},
});

new ecs.CfnPrimaryTaskSet(this, 'PrimaryTaskSet', {
cluster: cluster.clusterName,
service: service.attrName,
taskSetId: taskSet.attrId,
});

}
}

const app = new cdk.App();
new TriviaBackendStack(app, 'TriviaBackendTaskSets', {
env: { account: process.env['CDK_DEFAULT_ACCOUNT'], region: 'us-east-1' }
});
app.synth();
28 changes: 0 additions & 28 deletions trivia-backend/infra/cfn-task-sets/README.md

This file was deleted.

Loading

0 comments on commit 92be98f

Please sign in to comment.