Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / containers / docker

Deploying ASP.NET Core Microservices in AWS ECS using Fargate

4.33/5 (4 votes)
17 Apr 2019CPOL8 min read 20.3K  
In this article, we will learn how to deploy ASP.NET Core Microservices in AWS ECS using Fargate with Cloudformation template and AWS Console.

Introduction

Image 1

In recent years, Microservices gained a lot of popularity and most of the systems are adopting this new architecture to develop Line of business applications. However, Microservices might not be a single solution for everyone or every problem. Let’s say if you got an independent team to build and manage independent modules in your system, then it might be an ideal approach. Having said that, it could be a better architecture even for single team projects to develop complex distributed applications and deploy it in any cloud environment.

You can find good resources to learn more about Microservices here.

In this series, I am going to take you on a ride, how to deploy dotnet core Microservices in AWS using ECS Fargate.

Why ECS Fargate?

I love serverless frameworks like AWS lambda and Azure functions. However, they got few limitations around memory, timeout and framework versions. Let's say you got a component which requires more than 3 GB Memory to process its work and/or it might take more than 10 mins and/or it uses an older .NET Core Framework or Node js framework. AWS fargate is a serverless framework to deploy apps on ECS containers, without requiring us to maintain Host machine. We have the freedom to choose framework and memory allocation for these containers.

Prerequisites

  • I am assuming you have already worked with ASP.NET Core apps.
  • You need to have some basic understanding of AWS services such as EC2, ECS, ELB, ECR, IAM and AWS configuration.
  • Dotnet core SDK, AWS CLI, Docker and Visual Studio code or any IDE should be installed in the development machine.

Application Architecture

Image 2

  • I created one application for Vehicle insurance use case. Any client can make REST calls to Metadata service to create/update customer, vehicles information and requests for vehicle insurance quotations. Quote will be generated on server and sent back to clients. Once you pick a quote, the client should call policy service to process and create policy.
  • I created two simple ASP.NET Core webapi projects for these services, one to manage basic information like customer, vehicle and quotes. And the other one to manage policies.
  • Each service will interact with its own database to make these services purely independent.
  • Data between these databases can be synced or changed using Event patterns, which will be out of scope for this demo.

AWS Infrastructure Architecture

We will deploy this simple micro-services to AWS ECS cluster using Fargate.

Image 3

  • Every request from clients can come to a single Application load balancer and then the request will be forwarded to respective target groups by matching URL pattern.
  • The idea is to create a unique Target group for each service, so that they will forward the requests to service Containers, that are launched in ECS cluster using Fargate.
  • APIs running in ECS containers should be able to communicate with database services such as SQL Server RDS, Elasticache and DynamoDB in the same VPC.

Readiness of ASP.NET Core WebAPI

Let's first understand the necessary parts in ASP.NET Core webapi services to be able to deploy in ECS cluster.

  • All lookup data and session related data should be stored in a single instance redis cache or some common database, so that all service instances should be able to access data from single repository.
    JavaScript
    services.AddStackExchangeRedisCache(options =>
    {
       options.Configuration = Configuration["Cache:AWSRedisEndPoint"];
    });
  • Every service should have a health check route configured, to check service is running in container from ELB. I used built in middleware to configure this.
    JavaScript
    //this line in ConfigureServices method of Startup.cs
    services.AddHealthChecks();
    //this line in Configure method of Startup.cs
    app.UseHealthChecks("/health");
  • All routes in a service should have a common base route path, so that requests from ELB should be able to send to this service target group by matching the base route path.
    JavaScript
    [Route("metadataapi/[controller]")]
    public class CustomersController : ControllerBase
    [Route("metadataapi/[controller]")]
    public class VehiclesController : ControllerBase
  • I used swagger for API discovery documentation. This swagger configuration should also consider using base route path.
    JavaScript
    app.UseSwagger(c =>
    {
     c.RouteTemplate="policyapi/swagger/{documentName}/swagger.json";\
    });
    app.UseSwaggerUI(c =>
    { 
     c.SwaggerEndpoint("/policyapi/swagger/v1/swagger.json","APIdoc");
     c.RoutePrefix = "policyapi/swagger";
    });

Docker Image to Run Container on ECS

  • Docker is a platform to create and deploy application containers on Host machine. If you have not worked on Docker earlier, please consider going through some basics. I loved this pluralsight course.
  • I created docker file for each service with basic instructions to build API image.
  • I also created a docker-compose file to build and run these containers in local host machine.
  • You will require to create a .env file setup environment variables to service
  • Build and run images in containers by using this command in terminal:
    BAT
    docker-compose up -d --build
  • Make sure the API services are running fine in container by navigating to swagger URLs http://localhost:8080/metadataapi/swagger
  • Create image Repositories for each service using this command:
    BAT
    aws ecr create-repository --repository-name metadata-api
  • You can also create repository by logging into AWS ECR console.

    Image 4

  • Tag running service images with ECR repository URIs with:
    BAT
    docker tag metadataapi:latest
    875373411184.dkr.ecr.us-west1.amazonaws.com/insurancemetadata:latest
  • Login to ECR to push this image to cloud. We need to run this command to generate login command.
    BAT
    aws ecr get-login --no-include-email --region us-west-2
  • Copy and paste the output from the above command in the terminal to perform actual login.
  • Once you login successfully, push these service images to Cloud.
    BAT
    docker push 
    875373411184.dkr.ecr.us-west-1.amazonaws.com/insurancemetadata

Deploy Service Images in ECS Cluster using Cloudformation

Once docker images are pushed to ECR repository, then we can deploy the services using the following two cloud-formation templates.

  • First one to create common resources like Load balancer, securitygroups and Cluster.
  • Second one to configure service in containers using Fargate and also creates necessary IAM roles, target groups, Task definition and ECS Service.

We need to create one stack for each service in our application by passing the necessary parameters.

  • You can use either AWS console to create stacks for these cloudformation templates or execute them from the command line.

    Image 5

    BAT
    aws cloudformation deploy 
       --template-file /path_to_template/microservice-cluster-elb.yaml 
    --stack-name my-new-stack
    --parameter-overrides EnvironmentName=mycluster vpcid=<vpcid> ...
  • Once the first stack completed successfully, we need to create stack for each service. This time, we need to find output from first stack to pass to the service stack like elbruleid, securitygroupname and clustername.
  • Before creating service, make sure all necessary environment variables are defined in the template.
  • Once the second stack is created, you can find the ELB load balancer DNS entry in AWS console.
  • Browse each service swagger URL to make sure APIs are deployed successfully.

    Image 6

  • These cloud-formation templates are reusable for CI/CD tool integration as well.
  • Other option to deploy these microservices is to use AWS Web console.

Deploy Service Images in ECS Cluster using AWS Console

We learned how to deploy dotnet microservices in AWS ECS Fargate using cloudformation. In this section, we will deploy the same application using AWS Console to understand each AWS service.

Step 1: Application Load Balancer -ELB

  • We use ELB to distribute http requests to all ECS containers equally. ELB is fully manager load balancer in AWS

  • Once the API images are pushed to AWS ECR Repository, just verify they exist in AWS console.

  • Navigate to EC2 Service, click on Load balancers, Select Create Load Balancer and select Application Load Balancer.

    Image 7

  • Enter basic information an select VPC and subnets:

    Image 8

    Image 9

  • Configure Securitygroup, with required IP address to allow access ELB.

    Image 10

  • Enter Default Target-group name and settings. Also:

    Image 11

    Image 12

  • Review and click Create and navigate to the ELB Dashboard.
  • Navigate to Listeners tab and click on View/edit rules link .

    Image 13

  • Navigate to Edit tab and edit default rule to return fixed response 503.

    Image 14

  • Click on Update button and Find the DNS Name of ELB and browse.

Step 2: ECS Cluster

  • ECS is an AWS custom orchestration for containers in Cloud.
  • Navigate to ECS, select Cluster and click on Create Cluster.

    Image 15

  • Select Network Only option as Cluster Template. This tells ECS to use Fargate.

    Image 16

  • Enter name and click Create.

    Image 17

Step 3: ECS TaskDefinition and ECS Service

  • TaskDefinition: Is set of instructions like image, environment varibles and memory size, ports to use while creating a container in this cluster.
  • Navigate to Task Definitions menu under ECS and click on Create New Task definition button.

    Image 18

  • In the next step, select Fargate as Launch type.

    Image 19

  • Enter name and other details like Task role - if task execution role does not exist , please create one going to IAM console.

    Image 20

    Image 21

  • Add containers to this task by clicking Add Container button at the bottom.
    • Fill the information like name, image url of this service and ports in the Container popup. You can leave the remaining settings to default, unless you have specific requirements.

      Image 22

  • After adding containers , just click on Create button and navigate to Task details page to confirm.
  • ECS Service is a mechanism in ECS to execute the task definitions with desired number of containers in one environment. And also, you can configure the ELB target group for these containers to be available to Load balancer.

  • Navigate to Clusters dashboard and select the cluster we created.

    Image 23

  • Click on Create button under Services tab in the cluster detailed page.

    Image 24

  • Enter all basic info like lauch type, name, task definition and number of tasks.

    Image 25

  • Select VPC and at least two subnets (private proffered) and Security group.

    Image 26

  • Select the Application load balancer, that we created in Step 1.

    Image 27

  • Click on Add Load balancer button and and fill the information to create a separate Target group for this service. Also, make sure you enter the path pattern same as your API base root path- /metadataapi* and health route.

    Image 28

  • Unselect Route 53, unless you have requirement to setup route 53 DNS and click Next.

    Image 29

  • Review and click Create Service.
  • Wait for few minutes to run this task and verify the task status by going to Task tab in the Cluster Details page.

    Image 30

  • If you see any errors or if task never returns the Running status, just navigate to executing task page by clicking first link in the above page. You should be able to see details error and logs.
  • Now browse the ELB DNS name along with swagger route to verify service is running successfully.

    Image 31

Conclusion

Repeat Step 3 for all other services in your micro service application and they should be available on the same ELB DNS URL with different routes.

With this approach, you can deploy micro services without affecting other services. Obviously, this UI approach is just to understand the various services. Mostly, we should use some type of infrastructure as code technology like Cloud-formation or Terraform or AWS Code Deploy to integrate with our CI/CD tools.

References

History

  • 18th April, 2019: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)