'Programmatically Stop AWS EC2 in case of inactivity

Can we stop an AWS windows server EC2 instance of a development environment when there is no activity in it, say after 2 hours of inactivity? I am having trouble identifying whether any user is connected to the server virtually.

I can easily start/stop the EC2 at a fixed time, programmatically, but in order to cut the cost of my server, I am trying to stop the EC2 when it is not being used.

My intent(or use case) is: If no user is using the EC2 till a specified amount of time, it will automatically stop. Developers can restart it as and when needed.



Solution 1:[1]

Easiest solution probably would be to set up an Alert with CloudWatch.

Have a read at the documentation, which basically describes your use case perfectly:

You can create an alarm that stops an Amazon EC2 instance when a certain threshold has been met

A condition could be the average CPU utilisation, e.g. CPU utilisation is below a certain point (which most probably correlates with no logged in users / no developer actually utilising the machine).

Solution 2:[2]

This is not a simple task.

The Amazon EC2 service provides a virtual computer that has RAM, CPU and Disk. It can view the amount of activity on the CPU, Network traffic and disk access but it cannot see into the Operating System.

So, the problem becomes how to detect 'inactivity'. This really comes down to the operating system and making some hard decisions. For example, your home computer screen turns off after a defined time of no mouse/keyboard input but the operating system is still doing activity in the background. If the system is running an application such as a web server, and there are no web requests, it is hard to know whether this is 'inactive' because there are no requests, or 'active' because the web server is running.

Bottom line: There is no out-of-the-box feature to do this. You would need to find your own definition of 'inactivity' and then trigger a shutdown in the Operating System.

If you wish to do it via schedule, this might help: Auto-Stop EC2 instances when they finish a task - DEV Community

Solution 3:[3]

UPDATE: Lambda's aren't needed anymore, see tpschmidt's answer.

Create a Lambda to turn off the EC2 that will be triggered by a Cloud Watch Alarm when for example the CPU goes under 20% average for an hour. This is fine when you're coding as you will be using more than 20%, and when you have a break for over an hour that's when you want it turned off.

Be sure to set auto save in your IDE's.

Example Python Lambda:

import boto3
region = 'eu-west-3'
instances = ['i-05be5c0c4039881ed']
ec2 = boto3.client('ec2', region_name=region)
def lambda_handler(event, context):
    #TODO getInstanceIDFromCloudWatch = event["instanceid"]
    ec2.stop_instances(InstanceIds=instances)
    print('stopped your instances: ' + str(instances))

Ref: https://www.howtoforge.com/aws-lambda-function-to-start-and-stop-ec2-instance/

In AWS Console:

  1. Goto EC2, select the EC2 instance and copy the Instance ID

  2. Goto Cloud Watch and select Metrics

  3. Under AWS Namespaces click EC2

  4. Paste the Instance ID to find it

  5. Select EC2 > Per-Instance Metrics

  6. Choose the first metric CPU utilisation

  7. Select the second tab called Graphed Metric

  8. Click the Bell icon under Actions

  9. Set a threshold, also this is the hard part, leave the default of Statistic: Average over 1 hour

  10. Set the Condition Lower/Equal and put the value as 20% (you'll need to use the machine more than 1/5th of the hour over 20% CPU otherwise it'll turn off).

  11. Next create an alarm, setup a notification if you like or remove it

  12. Once the Alarm is created

  13. In Cloud Watch select Event > Rules

  14. Add a Rule

  15. Select EC2 as the Service Name and All Event

  16. Click Target and select your Lambda.

  17. When the Alarm goes off the Lambda will turn off the instance ID

Solution 4:[4]

You are looking for adding stop action to your ec2 instance, this can be easily achieved using CloudWatch alarms. You can do this from the console using the following steps:

  1. Open the Amazon EC2 console

  2. In the navigation pane, choose Instances.

  3. Select the instance and choose Actions, Monitor and troubleshoot, Manage CloudWatch alarms.

    Alternatively, you can choose the plus sign ( ) in the Alarm status column.

  4. On the Manage CloudWatch alarms page, do the following:

    • Choose to Create an alarm.

    • To receive an email when the alarm is triggered, for Alarm notification, choose an existing Amazon SNS topic. You first need to create an Amazon SNS topic using the Amazon SNS console. For more information, see Using Amazon SNS for application-to-person (A2P) messaging in the Amazon Simple Notification Service Developer Guide.

    • Toggle on the Alarm action, and choose Stop.

    • For Group samples by and Type of data to sample, choose a statistic and a metric. In this example, choose Average and CPU utilization.

    • For Alarm When and Percent, specify the metric threshold. In this example, specify <= and 10 percent.

    • For the Consecutive period and Period, specify the evaluation period for the alarm. In this example, specify 1 consecutive period of 5 Minutes.

    • Amazon CloudWatch automatically creates an alarm name for you. To change the name, for the Alarm name, enter a new name. Alarm names must contain only ASCII characters.

    • Choose to Create.

Note You can adjust the alarm configuration based on your own requirements before creating the alarm, or you can edit them later. This includes the metric, threshold, duration, action, and notification settings. However, after you create an alarm, you cannot edit its name later.

Check this link from the documentation for terminating the instance using the same way.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 tpschmidt
Solution 2 John Rotenstein
Solution 3 Community
Solution 4 Mostafa Wael