Skip to content

Commit

Permalink
Merge pull request #1487 from professional-ian/professional-ian-featu…
Browse files Browse the repository at this point in the history
…re-eventbridge-schedule-to-ec2-terraform

New serverless pattern - EventBridge Scheduler to EC2 using Terraform
  • Loading branch information
julianwood authored Jul 10, 2023
2 parents e4402cb + cb71f21 commit e4f16c2
Show file tree
Hide file tree
Showing 4 changed files with 279 additions and 0 deletions.
55 changes: 55 additions & 0 deletions eventbridge-schedule-to-ec2-terraform/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# EventBridge Scheduler to start and stop EC2 instances
This pattern will create two EventBridge schedules that will start and stop a given array of instance-ids. You can control the start/stop time and timezone of you chosing. This example will start instances at 08:00 and stop them at 17:00 in the US/Eastern timezone.

Learn more about this pattern at Serverless Land Patterns: https://serverlessland.com/patterns/eventbridge-schedule-to-ec2-terraform.

Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example.


## Requirements

* [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources.
* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured
* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
* [Terraform](https://learn.hashicorp.com/tutorials/terraform/install-cli?in=terraform/aws-get-started) installed

## Deployment Instructions

1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository:
```
git clone https://github.com/aws-samples/serverless-patterns
```
1. Change directory to the pattern directory:
```
cd eventbridge-schedule-to-ec2-terraform
```
1. From the command line, initialize Terraform:
```
terraform init
```
1. From the commend line, apply the configuration in the main.tf file and follow the prompts:
```
terraform apply
```


## How it works

An Amazon EventBridge Schedule is used to start and stop an EC2 instance. The Terraform stack creates a VPC, EC2 instance and EventBridge Scheduler that invokes the startInstance and stopInstance API on a schedule.

## Testing

1. After deployment, view the schedule created in the Amazon EventBridge console under Scheduler>Schedules.
2. View the `ec2-start-schedule`. Navigate to the *Target* tab and note the `Payload` value which is in the format: `{"InstanceIds":["i-006c2e9f4e706bf48"]}`
3. Navigate to the EC2 console and find the EC2 instance from the `Payload` value. Check the instance is powered on during 08:00 and 17:00 in the US/Eastern timezone.

## Cleanup

1. Delete all created resources and follow prompts:
```
terraform destroy
```
----
Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.

SPDX-License-Identifier: MIT-0
54 changes: 54 additions & 0 deletions eventbridge-schedule-to-ec2-terraform/example-pattern.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"title": "EventBridge Scheduler to start and stop EC2 instances Monday to Friday",
"description": "Simple pattern that starts and stops given EC2 instances based on time of day, timezone and days of week",
"level": "300",
"framework": "Terraform",
"introBox": {
"headline": "How it works",
"text": ["Creates a schedule that turns on instances at 08:00 and turns them off at 17:00 Monday to Friday using the US/Eastern timezone."]
},
"gitHub": {
"template": {
"repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/eventbridge-schedule-to-ec2-terrafrom",
"templateURL": "serverless-patterns/eventbridge-schedule-to-ec2-terraform",
"projectFolder": "eventbridge-schedule-to-ec2-terraform",
"templateFile": "main.tf"
}
},
"resources": {
"bullets": [
{
"text": "Introducing Amazon EventBridge Scheduler",
"link": "https://aws.amazon.com/blogs/compute/introducing-amazon-eventbridge-scheduler/"
},
{
"text": "Amazon EventBridge Scheduler Docs",
"link": "https://docs.aws.amazon.com/scheduler/latest/UserGuide/what-is-scheduler.html"
}
]
},
"deploy": {
"text": [
"terraform apply"
]
},
"testing": {
"text": [
"See the Github repo for detailed testing instructions."
]
},
"cleanup": {
"text": [
"Delete the stack: <code>terraform destroy</code>."
]
},
"authors": [
{
"name": "Ian Lodge",
"image": "https://avatars.githubusercontent.com/u/135351711?v=4",
"bio": "Ian is a Solutions Architect at Amazon Web Services based in the US.",
"linkedin": "https://www.linkedin.com/in/ian-lodge"
}
]
}

147 changes: 147 additions & 0 deletions eventbridge-schedule-to-ec2-terraform/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 4.64.0"
}
}
}

provider "aws" {
region = var.region
}

locals {
project_name = "tf-test"
}


# This section creates VPC resources for the Amazon EC2 environment

resource "aws_vpc" "vpc" {
cidr_block = var.vpc_cidr
}

resource "aws_subnet" "subnet" {
vpc_id = aws_vpc.vpc.id
cidr_block = var.subnet_cidr
tags = {
Name = "private-subnet-1"
}
}

# This section creates an Amazon EC2 instance using the latest Amazon Linux AMI

data "aws_ami" "amazon-linux-2" {
most_recent = true

filter {
name = "owner-alias"
values = ["amazon"]
}

filter {
name = "name"
values = ["amzn2-ami-hvm*"]
}
}

resource "aws_instance" "test-ec2" {
ami = "${data.aws_ami.amazon-linux-2.id}"
instance_type = "t3.micro"
subnet_id = aws_subnet.subnet.id
tags = {
Name = "tf-test-ec2"
}
}

# This section creates cron schedules using Amazon EventBridge Scheduler, as well as the required IAM roles to interact with EC2

resource "aws_scheduler_schedule" "ec2-start-schedule" {
name = "ec2-start-schedule"

flexible_time_window {
mode = "OFF"
}

schedule_expression = "cron(0 8 ? * MON-FRI *)" # Scheduled startInstances at 8am EST Mon-Fri
schedule_expression_timezone = "US/Eastern" # Default is UTC
description = "Start instances event"

target {
arn = "arn:aws:scheduler:::aws-sdk:ec2:startInstances"
role_arn = aws_iam_role.scheduler-ec2-role.arn

input = jsonencode({
"InstanceIds": [
"${aws_instance.test-ec2.id}"
]
})
}
}

resource "aws_scheduler_schedule" "ec2-stop-schedule" {
name = "ec2-stop-schedule"

flexible_time_window {
mode = "OFF"
}

schedule_expression = "cron(0 17 ? * MON-FRI *)" # Scheduled stopinstances at 5pm EST Mon-Fri
schedule_expression_timezone = "US/Eastern" # Default is UTC
description = "Stop instances event"

target {
arn = "arn:aws:scheduler:::aws-sdk:ec2:stopInstances"
role_arn = aws_iam_role.scheduler-ec2-role.arn

input = jsonencode({
"InstanceIds": [
"${aws_instance.test-ec2.id}"
]
})
}
}

resource "aws_iam_policy" "scheduler_ec2_policy" {
name = "scheduler_ec2_policy"

policy = jsonencode(
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:StartInstances",
"ec2:StopInstances"
],
"Resource": [
"${aws_instance.test-ec2.arn}:*",
"${aws_instance.test-ec2.arn}"
],
}
]
}
)
}

resource "aws_iam_role" "scheduler-ec2-role" {
name = "scheduler-ec2-role"
managed_policy_arns = [aws_iam_policy.scheduler_ec2_policy.arn]

assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Sid = ""
Principal = {
Service = "scheduler.amazonaws.com"
}
},
]
})
}
23 changes: 23 additions & 0 deletions eventbridge-schedule-to-ec2-terraform/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
variable "region" {
type=string
description = "AWS Region where deploying resources"
default = "us-east-1"
}

variable "aws_profile_name" {
type=string
description = "AWS CLI credentials profile name"
default="default"
}

variable "vpc_cidr" {
type=string
description = "CIDR block for VPC"
default = "10.0.0.0/16"
}

variable "subnet_cidr" {
type=string
description = "CIDR block for the subnet"
default = "10.0.0.0/24"
}

0 comments on commit e4f16c2

Please sign in to comment.