AWS Simple Failover Setup using Elastic IP

aws

Introduction

Failover is a common technique used by high availability services. In this setup, 2 systems are set, primary and secondary. When primary system goes down because of sudden failure or scheduled maintenance, it is replaced by secondary system. In this quick article, we will see how to do such setup in AWS cloud environment. Even though code in this examples is specific for AWS, concept can be used with any cloud provider.

Concept

AWS provides static IPv4 addresses called Elastic IP addresses (Most of cloud providers provide them but under different names like Floating IPs). These IP addresses are specifically designed for dynamic assignment. So in case of failure, they can quickly be mapped to another instance. They are also useful to get internet connectivity to your isolated resource. Remember AWS also provides failover capability using route53 by setting up routing policy. (See this link for more info). But here, we are trying to setup failover at application level, instead DNS level.

Failover setup using EIP

For this to work, we need 3 components.

  • Primary EC2 instance (mandaory)
  • Secondary EC2 instance (mandatory)
  • Elastic IPv4 address to float between two instances (mandatory)

Along with 2 optional components.

  • Elastic IPv4 address to attach with primary EC2 instance (for easily ssh-ing after IPv4 addr changed)
  • Elastic IPv4 address to attach with secondary EC2 instance (for easily ssh-ing after IPv4 addr changed)

Code

See below script. We need to add instance-ids for main and failover instances. Also assign Elastic IPv4 address to fip variable.

During associating/dissociating IPv4 address, new IP addresses are assigned dynamically. This makes maintenance difficult. If we provide extra Elastic IPv4 addresses, those can be retained every time, when fip is removed.

To run script, first configure AWS command line utility. It is small python package and can be installed using below command.

pip install awscli

Then configure this utility by providing credential details which can be obtained from AWS portal.

aws configure

Copy script and make it executable to run.

#!/usr/bin/env python2.7
__author__ = "Rohit Chormale"


"""
Description - AWS Failover script to migrate traffic from one instance to another.
Dependancies - python2.7, pip2.7, awscli
Installation - pip2.7 install awscli
Usage:
    # Configure aws using below command. Required details can be found in AWS IAM service
    aws configure

    # Make script executable
    chmod ugo+x aws-failover.py

    # Add main instance-id, fallback instance-id and floating-ip below.
     Optional - If both instances have elastic ips by default, mention them below (eip1 and eip2) to retain them back, once floating ip is re-assigned.
     Make sure these default ips are allowed to reassociate when attached. 
     This can be achieved by enabling 'Allow Elastic IP to be reassociated if already attached' option in Elastic IP Settings

    # for help
    ./aws-failover.py --help
    
    # To setup fallback instance
    ./aws-failover.py --fallback

    # To setup main instance
    ./aws-failover.py --main

Supporting OS: CentOS 7
"""


import os

# main instance id
instance1 = "" 

# fallback instance id
instance2 = ""

# floating ip - This  ip will float in between both instances
fip = ""

# Optional - If both instances have elastic ips by default, mentioned them here to retain them back, once floating ip is re-assigned.
# Make sure these default ips are allowed to reassociate when attached. 
# This can be achieved by enabling 'Allow Elastic IP to be reassociated if already attached' option in Elastic IP Settings
eip1 = ""
eip2 = ""


assign_eip1_instance1 = "aws ec2 associate-address --instance-id %s --public-ip %s --allow-reassociation" %(instance1, eip1)
assign_eip2_instance2 = "aws ec2 associate-address --instance-id %s --public-ip %s --allow-reassociation" %(instance2, eip2)
assign_fip_instance1 = "aws ec2 associate-address --instance-id %s --public-ip %s --allow-reassociation" %(instance1, fip)
assign_fip_instance2 = "aws ec2 associate-address --instance-id %s --public-ip %s --allow-reassociation" %(instance2, fip)


def setup_fallback_instance():
    """Move to fallback instance"""
    os.system(assign_fip_instance2)
    if eip1:
        os.system(assign_eip1_instance1)


def setup_main_instance():
    """Move to main instance"""
    os.system(assign_fip_instance1)
    if eip2:
        os.system(assign_eip2_instance2)


if __name__ == "__main__":
    import argparse
    ap = argparse.ArgumentParser(description="AWS Failover Tool")
    ap.add_argument("--main", help="Move to main node", action="store_true", default=False)
    ap.add_argument("--fallback", help="Move to fallback node", action="store_true", default=False)
    args = vars(ap.parse_args())
    if args["fallback"]:
        setup_fallback_instance()
    if args["main"]:
        setup_main_instance()

To activate fallback instance, run script as

./aws-failover.py --fallback

To make main server active again, run script as

./aws-failover.py --main

Hope you enjoyed article ! Stay Awesome !

Leave a Reply