Distributed Systems Practice Notes

Docker and Containers - Break a Monolith Application into Microservices

November 06, 2018

This lab introduces an architectural evolvement of a simple web service application, from monolith to microservice. Both architectures are containerized with Docker. The lab also shows the advantages gained in system scalability by using microservice, which could be easily achieved via changing some configurations in AWS console, and even without having to shut down the application.

Learning Outcomes

  • How to use aws-cli commands to set up host env via CloudFormation
  • How microservices work and how to deploy them as cluster in Target Groups
  • How to configure flow table entries in ALB (a software defined network)

Interaction Logic of Components

  • The Application Load Balancer (ALB) lets your service accept incoming traffic.
  • Containerized microservers work in cluster as Target Groups, and ready to handle requests.
  • ALB routes incoming requests to Target Groups based on match of path (forward or drop).

Migration of Architecture

deploy micro

  • At first (1), the web service application is monolithic, which is accessible via a generic target group api, where ALB routes all HTTP requests to.
  • Then (2) (3) we will break the application into 3 smaller but independent services, with each one containerized. 3 new target groups are created and linked to the microservices, and ALB routes requests to them according to pre-defined patterns of path.
  • Finally (4), the monolithic application is shut down, and the entire application is migrated to microservice architecture from monolithic.

Prerequisites

  • aws-cli
  • Docker ce
  • git

Operations

Module One - Containerize the Monolith

monolith

Preparations

  • Clone demo from Github
git clone https://github.com/awslabs/amazon-ecs-nodejs-microservices.git
  • Create ECS repository api in ECS console

name: api

  • Create IAM group and user to access ECS repository

Grant full access of container registry to group, then add user in group.

group policy

  • Configure AWS with User Keys

Get AWS Access Key ID and AWS Secret Access Key from last step, then

aws configure
AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name [None]: us-west-2
Default output format [None]: json
  • Docker login
aws ecr get-login --no-include-email --region [region]

See Docker login information output, copy and paste to terminal to login ECS repository

docker login -u AWS -p ...

Build and Push

  • Build Monolithic Docker Image of Service api
cd ~/amazon-ecs-nodejs-microservices/2-containerized/services/api
docker build -t api . 
  • Tag Image with v1
docker tag api:latest [account-id].dkr.ecr.[region].amazonaws.com/api:v1
  • Push Image to ECS Repository
docker push [account-id].dkr.ecr.[region].amazonaws.com/api:v1

Check in console, monolith is containerized.

ecr repo

Module Two - Deploy the Monolith

deploy monolith

Launch an ECS Cluster using AWS CloudFormation

  • Build Stack BreakTheMonolith-Demo with YAML file
aws cloudformation deploy \
--template-file ~/amazon-ecs-nodejs-microservice/2-containerized/infrastructure/ecs.yml \
--region <region> \
--stack-name BreakTheMonolith-Demo \
--capabilities CAPABILITY_NAMED_IAM

In 5 minutes, see stack ready in CloudFormation console,

create stack

Write a Task Definition

The task definition tells Amazon ECS how to deploy your application containers across the cluster.

  • Create a new task definition, remember to choose EC2 as launch type
  • Task Name, Container name: api
  • Image: [account-id].dkr.ecr.[region].amazonaws.com/api:v1
  • Port Mapping: host 0, container 3000

task type

Configure the Application Load Balancer: Target Group

The Application Load Balancer (ALB) lets your service accept incoming traffic. The ALB automatically routes traffic to container instances running on your cluster using them as a target group.

  • Create and Configure the ALB Target Group

    • Name: api
    • Protocol: HTTP
    • Port: 80
    • VPC: Use the one created by Cloud Formation, Not the default VPC

create target group

Configure the Application Load Balancer: Target Listener

The listener checks for incoming connection requests to your ALB, and routes them to service groups.

  • Add a Listener to the ALB

    • Protocol: HTTP
    • Port: 80
    • Default target group: api

create target listener

Deploy the Monolith as a Service

  • Create Service on BreakTheMonolith-Demo-ECSCluster

    • Service name: api
    • Number of tasks: 1
    • ELB Type: Application Load Balancer
    • IAM role: BreakTheMonolith-Demo-ECSServiceRole
    • Load Balancer ELB name: demo
  • Add Service to Target Group

    • Listener port 80:HTTP
    • Target group name: api

create service

Test your Monolith

  • Visit DNS name of load balancer

You should see a message ‘Ready to receive requests’.

Module Three - Break the Monolith

break down monolith

In this module, you will break the node.js application into several interconnected services and push each service’s image to an Amazon ECR repository.

ALB routes requests to 3 different target groups which are associated with microservice, whose instances are represented in Docker containers.

Provision the ECR Repositories

  • Service api is broken into 3 microservices,

    • users
    • threads
    • posts
  • Create Image Repository for Each Microservice

Build and Push Images for Each Service

  • Build and Push 3 New Images
cd ~/amazon-ecs-nodejs-microservices/3-microservices/services
docker build -t [service-name] ./[service-name] 
docker tag posts:latest [account-id].dkr.ecr.us-west-2.amazonaws.com/posts:v1
docker push [account-id].dkr.ecr.[region].amazonaws.com/[service-name]:v1

ecr 3 repos

Module Four - Deploy Microservices

In this module, you will deploy your node.js application as a set of interconnected services behind an Application Load Balancer (ALB). Then, you will use the ALB to seamlessly shift traffic from the monolith to the microservices.

Create Task Definition for Each Microservice

  • Create as in task api for,

    • users
    • threads
    • posts

Create Target Groups for Each Microservice

  • Plus a ‘dummy’ target: drop-traffic

new groups

Create Listener Rules for Each Microservice

  • Criteria: IF Path = /api/[service-name]* THEN Forward to [service-name]

5 rules

Deploy Microservices

  • Deploy on cluster as api for,

    • users
    • threads
    • posts
  • See tasks running,

running tasks

Validate Deployment

  • Same way as in testing monolith deployment

  • Visit DNS name of load balancer

You should see a message ‘Ready to receive requests’.

Official Links

AWS Tutorial: Break a Monolith Application into Microservices


Warren

Written by Warren who studies distributed systems at George Washington University. You might wanna follow him on Github