0

The goal i am trying to achieve is I have around 8 test instances that i want to stop when i am not at work to save cost. then start them back up again when i get back to work.

I have a function that achieves exactly what i need

import boto3
region = 'cn-north-1'
instances = ['i-xxxxxx', 'i-xxxxxxx', 'i-xxxxxx', 'i-xxxxxx', 'i-xxxxxxxx']
ec2 = boto3.client('ec2', region_name=region)

def lambda_handler(event, context):
    ec2.stop_instances(InstanceIds=instances)
    print('stopped your instances: ' + str(instances))

The problem is I have immutable deployment policy on all of my instances so instances is constantly changing and i will have to update the function everyday.

Is there anyway that I can target by tag or something more versatile so i don't have to update the function everyday?

I've looked through documentation but it's pretty unclear to me https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ec2.html

2

Most people should use the instance scheduler, but you can't in the China region.

Alternate Solution

There are dozens of samples on the internet that will help you achieve this. One of them is here. Basically, instead of hard coding instance IDs you use the boto3 API to find instances by tag.

This function also lets you change the start / stop time using tags. You can take parts of this code and modify yours (which came from here I think) to incorporate it.

import boto3
import time

##
# First function will try to filter for EC2 instances that contain a tag named `Scheduled` which is set to `True`
# If that condition is meet function will compare current time (H:M) to a value of the additional tags which defines the trigger `ScheduleStop` or `ScheduleStart`.
# Value of the `ScheduleStop` or `ScheduleStart` must be in the following format `H:M` - example `09:00`  
# 
# In order to trigger this function make sure to setup CloudWatch event which will be executed every minute. 
# Following Lambda Function needs a role with permission to start and stop EC2 instances and writhe to CloudWatch logs.
# 
# Example EC2 Instance tags: 
# 
# Scheduled     : True
# ScheduleStart : 06:00
# ScheduleStop  : 18:00
##

#define boto3 the connection
ec2 = boto3.resource('ec2')

def lambda_handler(event, context):

    # Get current time in format H:M
    current_time = time.strftime("%H:%M")

    # Find all the instances that are tagged with Scheduled:True
    filters = [{
            'Name': 'tag:Scheduled',
            'Values': ['True']
        }
    ]

    # Search all the instances which contains scheduled filter 
    instances = ec2.instances.filter(Filters=filters)

    stopInstances = []   
    startInstances = []   

    # Locate all instances that are tagged to start or stop.
    for instance in instances:

        for tag in instance.tags:

            if tag['Key'] == 'ScheduleStop':

                if tag['Value'] == current_time:

                    stopInstances.append(instance.id)

                    pass

                pass

            if tag['Key'] == 'ScheduleStart':

                if tag['Value'] == current_time:

                    startInstances.append(instance.id)

                    pass

                pass

            pass

        pass

    print current_time

    # shut down all instances tagged to stop. 
    if len(stopInstances) > 0:
        # perform the shutdown
        stop = ec2.instances.filter(InstanceIds=stopInstances).stop()
        print stop
    else:
        print "No instances to shutdown."

    # start instances tagged to stop. 
    if len(startInstances) > 0:
        # perform the start
        start = ec2.instances.filter(InstanceIds=startInstances).start()
        print start
    else:
        print "No instances to start."

Standard Solution

This is the best solution for most people.

Use the AWS instance scheduler, as per this tutorial. It starts and stops instances based on tags, on a schedule you define.

I'm not going to copy and paste an article in here, as the information changes occasionally and AWS keeps their documentation up to date quite well.

  • Unfortunately this is not available in the cn-north-1 region:( – NooBskie Oct 22 '19 at 6:38
  • I have added another option for you to the answer – Tim Oct 22 '19 at 7:03
  • Nice Tim! this looks like the proper solution for me – NooBskie Oct 22 '19 at 7:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.