Software Development Outsourcing
Development

Transforming a monolithic application to a micro-services oriented architecture – Part 5 – Stack for another service

We have now all we need to start splitting the monolithic application into micro-services. All we have to do from now on is:

  • Discuss about the micro-services you will create;
  • Take code apart from the big application and separate it into a new application;
  • Create APIs on the big application so both apps can continue to work in the same way as before;
  • Call the API on the big application from the mini-application if necessary, until we have a completely system based on micro-services;
  • Create stacks for each micro-service and launch it in production;
  • Finally, remove the monolithic;

So let’s say we want to launch product1 at the address tenant1.domain.com/product1. We have developed it, did all the integration (with the monolith and with other micro-services), and now we want to deploy it.

Just copy/paste the stack from the monolithic and replace the listener rules (of course, if necessary, also do changes to target group and service).

We will launch the new service and we will route the requests to tenant1.domain.com/product1 by making the following changes to the listener rules:

Listener rules for the Listener on port 80

# NOTE: this default rule is defined so the TargetGroup 
# is linked with the ALB and the Service can be created
# This fixes the problem with replacing the target group 
# when we make changes to it so the flow becomes like this:
# new target group is created - target group is linked with 
# ALB through the Listener80RuleDefault rule - new service is created
# - after the service is created the rest of the listeners 
# are created/updated, thus, we will route requests to 
# the new target group 
# only when the service is ready! 
# - we avoid 503 gateway errors with this
Listener80RuleDefault:
  Type: AWS::ElasticLoadBalancingV2::ListenerRule
  Properties:
    ListenerArn:
      Fn::ImportValue: !Sub "${BaseStackName}-Listener80"
    Priority: 3
    Conditions:
      - Field: host-header
        Values: 
          - tenant1-default-product1.domain.com
    Actions:
      - TargetGroupArn: !Ref TargetGroup
        Type: forward

Listener80Rule1:
  Type: AWS::ElasticLoadBalancingV2::ListenerRule
  DependsOn: 
    - Service
  Properties:
    ListenerArn: 
      Fn::ImportValue: !Sub "${BaseStackName}-Listener80"
    Priority: 99
    Conditions:
      - Field: host-header
        Values: 
          - tenant1.domain.cloud
      - Field: path-pattern
        Values:
          - /product1*
    Actions:
      - TargetGroupArn: !Ref TargetGroup
        Type: forward

When you define listeners, you should be careful on the Priority field. If there is already a rule with the same priority on the current listener, your stack will fail to be created.

Listeners for port 443

Listener443Rule1:
  Type: AWS::ElasticLoadBalancingV2::ListenerRule
  DependsOn: 
    - Service
  Properties:
    ListenerArn: 
      Fn::ImportValue: !Sub "${BaseStackName}-Listener443"
    Priority: 99
    Conditions:
      - Field: host-header
        Values: 
          - tenant1.domain.com
      - Field: path-pattern
        Values:
          - /product1*
    Actions:
      - TargetGroupArn: !Ref TargetGroup
        Type: forward

And that’s it. Now requests to tenant1.domain.com/product1 will be routed to your new target group  and therefore to the new containers with your new micro-service, while the others will be routed to the monolithic application.

That’s the way we did it.