$ git clone https://github.com/okeeffed/using-the-aws-cdk-with-localstack-and-aws-cdk-local deploying-a-fargate-cluster-with-localstack-and-the-aws-cdk
$ cd deploying-a-fargate-cluster-with-localstack-and-the-aws-cdk
$ npm i
# if install fails, remove the lockfile and try again
At this stage, we will have the app in a basic working state.
In order to create the CDN stack, we will require the following AWS CDK libraries:
npm i @aws-cdk/core @aws-cdk/aws-ec2 @aws-cdk/aws-ecs @aws-cdk/aws-ecs-patterns
The repository that we cloned already has a upgrade script supplied. We can use this to ensure our CDK packages are at parity:
npm run upgrade
We are now at a stage add a pattern construct to a stack.
Create a Fargate cluster
Update lib/aws-cdk-with-typescript-foundations-stack.ts to the following:
import * as cdk from "@aws-cdk/core";
import * as ec2 from "@aws-cdk/aws-ec2";
import * as ecs from "@aws-cdk/aws-ecs";
import * as ecs_patterns from "@aws-cdk/aws-ecs-patterns";
export class AwsCdkWithTypescriptFoundationsStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// The code that defines your stack goes here
const vpc = new ec2.Vpc(this, "MyVpc");
const cluster = new ecs.Cluster(this, "MyCluster", {
vpc: vpc,
});
// Create a load-balanced Fargate service and make it public
new ecs_patterns.ApplicationLoadBalancedFargateService(
this,
"MyFargateService",
{
cluster: cluster, // Required
cpu: 256, // Default is 256
desiredCount: 1, // Default is 1
taskImageOptions: {
image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"),
},
memoryLimitMiB: 512, // Default is 512
publicLoadBalancer: true, // Default is false
}
);
}
}
At this stage, we are ready to deploy to LocalStack.
Deploying to LocalStack
The docker-compose.yml file already has what is required for us to startup LocalStack.
Run docker compose up for LocalStack to start on Docker.
Once that is started, we can go through our usual lifecycle of the AWS CDK by synthesizing and deploying our app.
$ npm run local synth
# ... output omitted
We can then deploy our stack:
$ npm run local deploy
> aws-cdk-with-typescript-foundations@0.1.0 local
> cdklocal "deploy"
This deployment will make potentially sensitive changes according to your current security approval level (--require-approval broadening).
Please confirm you intend to make the following modifications:
IAM Statement Changes
┌───┬───────────────┬────────┬───────────────┬───────────────┬───────────┐
│ │ Resource │ Effect │ Action │ Principal │ Condition │
├───┼───────────────┼────────┼───────────────┼───────────────┼───────────┤
│ + │ ${MyFargateSe │ Allow │ sts:AssumeRol │ Service:ecs-t │ │
│ │ rvice/TaskDef │ │ e │ asks.amazonaw │ │
│ │ /ExecutionRol │ │ │ s.com │ │
│ │ e.Arn} │ │ │ │ │
├───┼───────────────┼────────┼───────────────┼───────────────┼───────────┤
│ + │ ${MyFargateSe │ Allow │ sts:AssumeRol │ Service:ecs-t │ │
│ │ rvice/TaskDef │ │ e │ asks.amazonaw │ │
│ │ /TaskRole.Arn │ │ │ s.com │ │
│ │ } │ │ │ │ │
├───┼───────────────┼────────┼───────────────┼───────────────┼───────────┤
│ + │ ${MyFargateSe │ Allow │ logs:CreateLo │ AWS:${MyFarga │ │
│ │ rvice/TaskDef │ │ gStream │ teService/Tas │ │
│ │ /web/LogGroup │ │ logs:PutLogEv │ kDef/Executio │ │
│ │ .Arn} │ │ ents │ nRole} │ │
└───┴───────────────┴────────┴───────────────┴───────────────┴───────────┘
Security Group Changes
┌───┬────────────────────────┬─────┬────────────┬────────────────────────┐
│ │ Group │ Dir │ Protocol │ Peer │
├───┼────────────────────────┼─────┼────────────┼────────────────────────┤
│ + │ ${MyFargateService/LB/ │ In │ TCP 80 │ Everyone (IPv4) │
│ │ SecurityGroup.GroupId} │ │ │ │
│ + │ ${MyFargateService/LB/ │ Out │ TCP 80 │ ${MyFargateService/Ser │
│ │ SecurityGroup.GroupId} │ │ │ vice/SecurityGroup.Gro │
│ │ │ │ │ upId} │
├───┼────────────────────────┼─────┼────────────┼────────────────────────┤
│ + │ ${MyFargateService/Ser │ In │ TCP 80 │ ${MyFargateService/LB/ │
│ │ vice/SecurityGroup.Gro │ │ │ SecurityGroup.GroupId} │
│ │ upId} │ │ │ │
│ + │ ${MyFargateService/Ser │ Out │ Everything │ Everyone (IPv4) │
│ │ vice/SecurityGroup.Gro │ │ │ │
│ │ upId} │ │ │ │
└───┴────────────────────────┴─────┴────────────┴────────────────────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)
Do you wish to deploy these changes (y/n)? y
AwsCdkWithTypescriptFoundationsStack: deploying...
AwsCdkWithTypescriptFoundationsStack: creating CloudFormation changeset...
✅ AwsCdkWithTypescriptFoundationsStack
Outputs:
AwsCdkWithTypescriptFoundationsStack.MyFargateServiceLoadBalancerDNS704F6391 = 50dc6c495c0c9188.elb.localhost.localstack.cloud
AwsCdkWithTypescriptFoundationsStack.MyFargateServiceServiceURL4CF8398A = http://50dc6c495c0c9188.elb.localhost.localstack.cloud
Stack ARN:
arn:aws:cloudformation:us-east-1:000000000000:stack/AwsCdkWithTypescriptFoundationsStack/7c56b074
The output includes a public URL that we can now visit at http://50dc6c495c0c9188.elb.localhost.localstack.cloud/.
The container running locally
Updating our test
We can update our test by running npm t and copying the resources output and adding it to our stack.
Running our test again will yield the following output:
$ npm t
> aws-cdk-with-typescript-foundations@0.1.0 test
> jest
PASS test/aws-cdk-with-typescript-foundations.test.ts
✓ Fargate Stack (294 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 4.407 s, estimated 6 s
Ran all test suites.
Tear down
I had an issue with the teardown on LocalStack for this one, but stopping Docker will do the trick.
Summary
Today's post demonstrated how to deploy a Fargate cluster locally to LocalStack using the AWS CDK.