Updated: Oct 24, 2019
If like me you have 'development' boxes that are pretty much left on throughout an entire project. You can use these simple steps to switch them off on an automatic schedule. Switch them off overnight when you are not working on them and save on monthly costs.
Following on from my last blog post about the cost differences across regions in EC2. I thought I would continue with the theme of saving a few quid off of your AWS bills. Also I have a bunch of boxes full of half developed projects at the moment and I need to do this myself, so what better time to document it here.
1: Get the instance identifiers for the boxes you want to power down overnight
- Start by signing in to the AWS console. - Navigate to EC2 - Remember EC2 is not global so you need to select the region containing the boxes you want to power down overnight. For me in this case, it is Ireland. - If the column "Instance ID" is hidden, use the settings cog to turn it on. - Copy the instance ID into a text editor, mine is "i-0640aa566a666a64d"
2: Create an IAM role with permissions to start and stop EC2 instances
- Navigate to IAM from the AWS console - Select "Polocies" from the menu on the left - Click "Create policy" - Navigate to the JSON tab - Smash this in the editor window
- Click "Review Policy"
- On the review screen, add a title and a description to your liking, jot down the name in your text editor - Click "Create policy", you should now return to the IAM root page with your new policy created. - Now click "Roles" - Click "Create role" - Select "AWS Service" as the type of trusted entity - Select "Lambda" as the service that will use this role - Click "Next: Permissions" - In the search box type the name of the policy we just created - Be careful not to click the blue linked name of the policy, click the checkbox at the side of it - Click "Next: Tags" - Click "Next: Review" - Give your Role a name and description, I am going to use "LambdaEC2SchedularRole" - Click "Create role" 3. Create a Lambda that turns off instances - Navigate to Lambda from the AWS console
- Click "Create function" - Leave the default "Author from scratch" option
- Call it "OvernightInstanceSaverOff" and select Python 3.7 as the runtime
- Unfold "Choose or create an execution role" - Select "Use an existing role" - Select the Role you made in step 2 - Click "Create function" - In the function code editor bang in this code, replacing my instance id "i-0640aa566a666a64d" with your own in the script. Ensure the region in the script is also correct. My instance is in Ireland so for me it is eu-west-1
- Scroll down and edit the "Timeout" under "Basic settings" increasing it to 10 seconds
- Click "Save" at the top of the page At this point the Lambda is created, but whilst we are here we might as well test that it works. Please remember this will switch off your instance, make sure you are in a good position to do that. - Click "Test" - In the "Configure Test Event" modal, type "test" in the "Event Name" and click "Create" - Click "Test", you should get an "Execution result: succeeded" header in green - Navigate to EC2 in the AWS console - Click "Instances", observe that your instance is stopped 3. Create a Lambda that turns off instances
Ok, this time we need to make the opposite Lamba to turn instances back on. We can reuse the same IAM Role and Policy. Infact the entire process should be the same, only this time you need the Python script to start the instances not stop them. - Follow the above steps but name this Lambda "OvernightInstanceSaverOn"
- Replace line 7 ec2.stop_instances with ec2.start_instances call 4. Create Cloudwatch rules to trigger the Lambdas
Cloudwatch can be used as a scheduler, which is perfect for what we are doing here. I want my instances powered down between 11pm and 5am, as not me or any of my associate developers should be using them at those times, and represents a daily saving of 6 hours (which I will calculate the actual monetary saving at the end of this article).
- Navigate to Cloudwatch in the AWS console
- Select "Rules" from the menu on the left
- Click "Create rule"
- Select "Schedule" as the option for "Event Source"
- Select "Cron expression" and paste in this
0 22 * * ? *
- This simply says "run every day at 11pm" - On the right click "Add target"
- "Lambda Function" should be selected by default
- For "Function" select "OvernightInstanceSaverOff"
- Click "Configure details"
- Add "Overnight EC2 instance saver off" to the "Name" - Copy the exact same procedure to make "OvernightInstanceSaverOn", my cron expression for this one will be
0 05 * * ? *
This simply says "run every day at 5am"
5. Work out how much you just saved
The most important step of all! How much cost have you saved with your new fancy schedule? Well, the first 1 million invokes of a Lambda are under Free Tier so cost nothing. Cloudwatch is free for something so tiny as this. So the cost of setting this schedule up and running it is £0.00. I am powering down an on-demand EC2 instance for 6 hours per day. The box is a t2.small and currently costs $0.025 per hour. 6 * $0.025 = 15¢ per night. Lets go with 30 days in a month. 15¢ * 30 = $4.50 per month Current exchange rate is 0.77 USD to GBP 4.50 * 0.77 = £3.47 I will save £3.47 per month of my AWS bill, this is per box. I think I have around 15 or so boxes to apply this to. So I would guess I will make a saving of around £50. To add more boxes to your scheduled shutdown. You need to edit the Lambdas and add more instance id's into the array in python. Remember it is also region specific, but line 3 of the Python script is what you are after. Here is an example of shutting down two instances at once. instances = ['i-0640aa566a666a64d', ' i-0d7e5a3fafb3aa3b8']
Don't forget to add the new id to your power on script also.