Tuesday, July 26, 2016

IaC with AWS Lambda: Automate infra optimization


   Almost every staging and/or development environment need to be shutdown  during the Off-hours and startup again next day for the cost optimization. the same can be automated multiple ways (Cron, Data pipeline, or 3rd party tools) . These tools either have single point of failure, higher execution time (Data pipeline) or cost.

  AWS Lambda provides server less compute (fast, cost effective, SLA based up time). It provide boots to new generation application and new way of writing infrastructure as code.

 In order to demonstrate the same i have written function in python boto3 with cloudwatch scheduler for automating shutdown and startup job.

   Since the complexity level is low I am skipping  the lambda function creation step.
A tag need to be created in each EC2 instances which need to be automated. I have used following tag value which you can replace.

  Auto Stop:
         Tag name: AutoStop
         Tag Value: True

   Auto Start:
         Tag name: AutoStart
         Tag Value: True
 
-------------------------------------------Auto shutdown function Begin-----------------------------------------
import boto3
import logging

#setup simple logging for INFO
logger = logging.getLogger()
logger.setLevel(logging.INFO)

#define the connection and set the region
ec2 = boto3.resource('ec2', region_name='ap-southeast-1')

def lambda_handler(event, context):

    # all running EC2 instances with tag filters.
    filters = [{
            'Name': 'tag:AutoStop,
            'Values': ['True']
        },
        {
            'Name': 'instance-state-name', 
            'Values': ['running']
        }
    ]
    
    #filter the instances which are stopped
    instances = ec2.instances.filter(Filters=filters)

    #locate all running instances
    RunningInstances = [instance.id for instance in instances]
    
    #print the instances for logging purposes
    print RunningInstances 
    
    if len(RunningInstances) > 0:
        #perform the shutdown
        shuttingDown = ec2.instances.filter(InstanceIds=RunningInstances).stop()
        print shuttingDown
    else:
        print "All the tagged instances are off"

-------------------------------------------Auto shutdown function End-----------------------------------------

     The same function can be converted as startup with minor modification as follows

-------------------------------------------Auto startup function Begin-----------------------------------------
import boto3
import logging

#setup simple logging for INFO
logger = logging.getLogger()
logger.setLevel(logging.INFO)

#define the connection and set region name
ec2 = boto3.resource('ec2', region_name='ap-southeast-1')
def lambda_handler(event, context):

    # all stopped EC2 instances and tag filters.
    filters = [{
            'Name': 'tag:AutoStart',
            'Values': ['True']
        },
        {
            'Name': 'instance-state-name', 
            'Values': ['stopped']
        }
    ]
    
    #filter the instances
    instances = ec2.instances.filter(Filters=filters)

    #locate all stopped instances 
    StoppedInstances = [instance.id for instance in instances]
 
    #print the instances for logging purposes
    print StoppedInstances  
 
    if len(StoppedInstances) > 0:
        #perform the startup
        AutoStarting = ec2.instances.filter(InstanceIds=StoppedInstances).start()
        print AutoStarting
    else:
        print "All the tagged instances are already running"

-------------------------------------------Auto startup function End-----------------------------------------


  NOTE: Post the function creation, lambda function can be tested with proper test case modification.

Create the cloudwatch rule with cron setup and add the target function as follows.
 
     -> Create cloudwatch schedule rule


 -> Configure cron settings and add lambda function target


-> Create rule and complete configuration