Skip to content

Instantly share code, notes, and snippets.

@cuperman
Last active February 27, 2020 02:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cuperman/1a28588234204b495b836c67ba4d7817 to your computer and use it in GitHub Desktop.
Save cuperman/1a28588234204b495b836c67ba4d7817 to your computer and use it in GitHub Desktop.
AWS Instance Scheduler

AWS Instance Scheduler

References

Overview

What does it do?

Stops and starts EC2 and RDS instances on a schedule. This can enable cost savings by stopping resources when you know they are not being used, and starting instances automatically when they will be used.

A standard use case is to stop instances outside of normal business hours.

Interesting Features:

  • Customizable schedules and support for timezones
  • Opt-in model, allowing users to choose appropriate schedules when provisioning resources
  • Cross-account instance scheduling
  • CloudWatch metrics

Deployment

Clone the repo, so you have access to the code and CloudFormation deployment templates:

$ cd /tmp
$ git clone git@github.com:awslabs/aws-instance-scheduler.git
Cloning into 'aws-instance-scheduler'...
remote: Enumerating objects: 669, done.
remote: Total 669 (delta 0), reused 0 (delta 0), pack-reused 669
Receiving objects: 100% (669/669), 701.51 KiB | 3.26 MiB/s, done.
Resolving deltas: 100% (182/182), done.
$ cd aws-instance-scheduler

Define some environment variables that we can use throughout the build and deploy steps:

$ export AWS_PROFILE="vmxeng-tools"
$ export AWS_DEFAULT_REGION="us-east-1"
$ export SOLUTIONS_BUCKET_PREFIX="vmx-aws-solutions"
$ export SOLUTIONS_BUCKET_NAME="$SOLUTIONS_BUCKET_PREFIX-$AWS_DEFAULT_REGION"
$ export SOLUTION_NAME="aws-instance-scheduler"
$ export SOLUTION_VERSION="$(cat source/code/version.txt)"
$ echo $SOLUTION_VERSION
v1.3.0

You need an s3 bucket to deploy the CloudFormation template:

$ aws s3api create-bucket --bucket "$SOLUTIONS_BUCKET_NAME"
{
    "Location": "/vmx-aws-solutions"
}

Build s3 assets:

$ cd deployment
$ ./build-s3-dist.sh 
Please provide the base source bucket name, trademark approved solution name and version where the lambda code will eventually reside.
For example: ./build-s3-dist.sh solutions trademarked-solution-name v1.0.0
$ ./build-s3-dist.sh $SOLUTIONS_BUCKET_PREFIX $SOLUTION_NAME $SOLUTION_VERSION

Note: The build output is confusing, but if you look at the code, the 1st argument is the bucket name, the 2nd is the solution name, and the 3rd is the version string. The template automatically appends the region name to the bucket name, so I only pass in the prefix.

Note: this failed at makefile, line 57 at zip -r $(zip) pytz because there is no folder or file called pytz. I commented out this line to get the build the succeed

This creates two new directories in the current deployment subdirectory:

  • global-s3-assets - contains copies of the CloudFormation templates, and the
  • regional-s3-assets - contains lambda packages for the scheduler logic and cli
$ tree .
.
├── build-s3-dist.sh
├── global-s3-assets
│   ├── instance-scheduler-remote.template
│   └── instance-scheduler.template
├── instance-scheduler-remote.template
├── instance-scheduler.template
└── regional-s3-assets
    ├── instance-scheduler.zip
    └── scheduler-cli.zip

Copy the assets to your s3 bucket:

$ export S3_DEST="s3://$SOLUTIONS_BUCKET_NAME/$SOLUTION_NAME/$SOLUTION_VERSION/"
$ aws s3 cp global-s3-assets $S3_DEST --recursive --acl public-read
upload: global-s3-assets/instance-scheduler-remote.template ...
upload: global-s3-assets/instance-scheduler.template ...
$ aws s3 cp regional-s3-assets $S3_DEST --recursive --acl public-read
upload: regional-s3-assets/scheduler-cli.zip ...
upload: regional-s3-assets/instance-scheduler.zip ...

Create parameters.json

With minimal required params:

[
  {
    "ParameterKey": "Regions",
    "ParameterValue": "us-east-1"
  },
  {
    "ParameterKey": "CrossAccountRoles",
    "ParameterValue": ""
  },
  {
    "ParameterKey": "StartedTags",
    "ParameterValue": ""
  },
  {
    "ParameterKey": "StoppedTags",
    "ParameterValue": ""
  }
]

Note: Parameters documented in Automated Deployment, page 19

$ export TEMPLATE_URL="https://$SOLUTIONS_BUCKET_NAME.s3.amazonaws.com/$SOLUTION_NAME/$SOLUTION_VERSION/instance-scheduler.template"
$ aws cloudformation create-stack \
    --stack-name "InstanceScheduler" \
    --template-url $TEMPLATE_URL \
    --parameters "file://./parameters.json" \
    --capabilities "CAPABILITY_IAM"
{
    "StackId": "arn:aws:cloudformation:us-east-1:622230865285:stack/InstanceScheduler/cce66530-58a9-11ea-9232-120022ae60fd"
}

Configuration

Install the CLI tool

cd source/code/cli
python setup.py install

scheduler-cli --help

I was able to get it to work with pipenv:

cd source/code/cli
pipenv install .
pipenv shell

scheduler-cli --help

Configure Periods

# describe periods
scheduler-cli describe-periods \
  --stack "InstanceSchedulerConsole" \
  --region "us-east-1"

# create period for israel office
scheduler-cli create-period \
  --stack "InstanceSchedulerConsole" \
  --region "us-east-1" \
  --name "israel-office-hours" \
  --description "Office Hours in Israel" \
  --weekdays "sun-thu" \
  --begintime "09:00" \
  --endtime "17:00"

Configure Schedules

# describe schedules
scheduler-cli describe-schedules \
  --stack "InstanceSchedulerConsole" \
  --region "us-east-1"

# create us west office schedule
scheduler-cli create-schedule \
  --stack "InstanceSchedulerConsole" \
  --region "us-east-1" \
  --name "office-hours-pst" \
  --description "PST Office Hours" \
  --timezone "US/Pacific" \
  --periods "office-hours"

# create us east office schedule
scheduler-cli create-schedule \
  --stack "InstanceSchedulerConsole" \
  --region "us-east-1" \
  --name "office-hours-est" \
  --description "EST Office Hours" \
  --timezone "US/Eastern" \
  --periods "office-hours"

# create central european office schedule
scheduler-cli create-schedule \
  --stack "InstanceSchedulerConsole" \
  --region "us-east-1" \
  --name "office-hours-cet" \
  --description "CET Office Hours" \
  --timezone "Europe/Berlin" \
  --periods "office-hours"

Tagging Instances

Create an instance in the AWS console and tag with Schedule=office-hours-pst

Cross-Account Support

Refer to documentation

CloudWatch Metrics

Refer to documentation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment