Using AWS CDK to create an ECS Service definition

Paulo Siecola
4 min readJan 13, 2021
Defining infrastructure with AWS Cloud Development Kit

Infrastructure as Code, or IaC, its not something new, but it's getting more attention from most of cloud developers in the past few years. If you don't know what IaC is, this is the main concept:

IaC is the process of model and provisioning cloud infrastructure using high-level programming languages.

In this article you'll learn how to create an ECS service with AWS Fargate, using the AWS Cloud Development Kit, or CDK, including other features, such as:

  • The ECS task and service definitions, including its CPU, memory and number of instances to be used;
  • How to pass environment variables to the service execution;
  • The CloudWatch log group definition;
  • How to grant permissions to the service to access other AWS resources;
  • The application load balancer definition;
  • And how to configure the target group to monitor our instances.

The most important here: using AWS CDK, there is no need to create YAML or JSON CloudFormation templates. All of the infrastructure will be create using, guess what, Java!

Of course, those templates still exist, in some part of the AWS CDK background process, but the developer just need to write the Java code to define the AWS ECS service infrastructure.

If you need to prepare your development environment to use the CDK, here is a good step-by-step tutorial.

So, let's assume we already have the AWS Cluster created in another stack, which of course it's a required parameter to create the ECS service.

Stack creation:

Everything starts with a new stack definition, which can be made by a new class extending from Stack:

Note that the cluster is one of the parameters in the new service stack constructor. This constructor also has a queue, which we will use here just as an example, about how to grant permission to this new service to access some other AWS resource.

Defining the environment variables:

Inside the second constructor, let's create a map to be used as the environment variable to be passed to our service:

Here we are defining the AWS region where the service belongs and the SQS queue name, which it will consume some messages. This variable will be used in the service creation.

CloudWatch log parameters:

As mentioned before, we want to define some CloudWatch log parameters to this new service, such as the log group name. To do this, create a LogDriver definition:

This LogDriver will be used in the task definition below.

Here we are defining the CloudWatch log group name as Service01. In this way, all the logs generated by this service will be under this log group. This is a good strategy to locate the service logs in the CloudWatch Insights, for example.

Also, we are defining the removal policy to DESTROY, which won't preserve the logs if the stack is destroyed.

Creating the task definition:

And now the task definition, which of course defines where the container image is, should be create. To define it, we can use ApplicationLoadBalancedTaskImageOptions builder:

Here we are defining the following parameters to the task:

  • the container name as aws_project01;
  • where the Docker image is, which in this case is one of my DockerHub repositories;
  • the container port to be exposed;
  • the LogDriver created above;
  • and the environment variables to be passed to the application, as mentioned above.

Creating the service definition:

Now, let's create the service itself. Thanks to the CDK default values, we can create all the stuff, and believe me, it's a lot of resources to be create, with a few lines of code:

Actually, this is the application load balancer definition, which include the ECS service. Here we are defining the following parameters:

  • the service name as service-01;
  • the AWS Cluster where it belongs;
  • 512 CPU units to be allocated to the service;
  • 1024 MB of RAM to be allocated to the service;
  • 2 desired instances of the service;
  • the 8080 HTTP port, to expose the service to receive requests from the Internet;
  • the task image options, created above;
  • and finally exposing the application load balancer to the entire Internet.

Defining the target group health check mechanism:

With the service01 variable created above, it's possible to configure the target group with the proper values to monitor our application:

Here we are configuring the health check mechanism, to always keep healthy instances of our service running. It's point to an special endpoint in our application and to the container port.

Granting permissions to the service:

And finally, we can grant to our service a permission to access the SQS passed as parameter to this stack:

This is made giving the consuming permission to the task role definition.

Conclusion:

AWS Cloud Development Kit is definitely a good way to model complex AWS resources, like an ECS service. With a few lines of code it's possible to create it, thanks to the AWS CDK default values.

I would say that, to create such an infrastructure like this one, it's necessary a huge CloudFormation template file, perhaps with more than 500 lines of code. Actually, there is a folder named cdk.out inside the CDK project, where all of these files are generated, during the deployment process, so it's easy to compare with the Java code created here.

If you liked this post and want to contribute to my work, writing content like this, take a look at this online course, about this topic and other subjects related to AWS service development using ECS, Fargate and CDK!

--

--

Paulo Siecola

Backend and mobile developer. Author of books about cloud computing development. Professor in cloud computing. Udemy instructor.