In recent years, Microservices got 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.
- 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.
- 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.
- 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.
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.
- 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.
public class CustomersController : ControllerBase
public class VehiclesController : ControllerBase
- I used swagger for API discovery documentation. This swagger configuration should also consider using base route path.
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:
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:
aws ecr create-repository --repository-name metadata-api
- You can also create repository by logging into AWS ECR console.
- Tag running service images with ECR repository URIs with:
docker tag metadataapi:latest
- Login to ECR to push this image to cloud. We need to run this command to generate login command.
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.
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.
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 seelect Application Load Balancer.
- Enter basic information an select VPC and subnets
- Configure Securitygrooup, with required IP address to allow access ELB.
- Enter Default Target-group name and settings. Also
- Review and Click “Create” and navigate to the ELB Dashboard.
- Navigate to Listeners tab and click on “View/edit rules” link .
- Navigate to “Edit” tab and edit default rule to return fixed response 503.
- 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”.
- Select “Network Only” option as Cluster Template. This tells ECS to use Fargate.
- Enter name and Click Create.
Step 3: ECS TaskDefination and ECS Service
- TaskDefination: Is set of instructions like image , environment varibles and memory size, ports to use while creating a container in this cluster.
- Navigate to Task Definations menu under ECS and click on Create New Task defination button.
- In the next step select Fargate as Launch type.
- Enter name and other details like Task role- if task execution role does not exist , please create one going to IAM console.
- Click on Create button under Services tab in the cluster detailed page.
- Enter all basic info like lauch type, name , task defination and number of tasks.
- Select VPC and at least two subnets(private proffered) and Security group.
- Select the Application load balancer, that we created in Step 1.
- 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.
- Unselect Route 53 , unless you have requirement to setup route 53 DNS and click Next.
- Review and Click Create Service.
- Wait for few mins to run this tasks and verify the task status by going to Task tab in the Cluster Details page.
- If you see any errors or if task never return 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.
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.