I can think of a few different ways to achieve this.
- First and easiest way is to create a new CloudWatch Events Rule 1, set its "Event Source" to run on a schedule and "Target" to EC2 StopInstances API call with Instance IDs provided. Look at this screenshot for clarity:
With this example, An event will start at every night at midnight and it will stop Instances by their IDs. You can change the schedule with cron expressions. See: https://crontab.guru
- You can implement any kind of custom logic with AWS Lambda functions and schedule them to be run with a variety of AWS services (including CloudWatch Events).
For example, with a Lambda function you can implement logic to find instances by a tag, like "GoodBefore=2018-08-10", and stop these instances. In fact you could even make use of API Gateway to expose an API for requesting instances, only to be terminated after a few days by their "GoodBefore" tag.
Of course, while this way is much more customizable and sophisticated, it may prove hard especially if you don't have experience in programming.
- If you don't want to implement custom logic with Lambda, but also need more than what CloudWatch Events can provide, you can make use of Instance Scheduler solution provided by AWS. It's a similar solution to what I described in previous method, but this time AWS already did the hard work for you.
1 URL for us-east-1 region: https://console.aws.amazon.com/cloudwatch/home?region=us-east-1#rules:action=create
Note: While I haven't used Instance Scheduler myself, I'm pretty sure it wouldn't decide on such things, and I think it only makes sense if it wouldn't do much more than simply making a stop call for the instance. So, on any stop event, either made by an automated solution or you, if your instances' root volume was created "EBS-backed", it will retain the data. If it is "instance store backed", it will lose the data. You can find this information from AWS EC2 console. If you want to retain data after stopping instances, make sure all volumes are EBS-backed when creating a new instance.