Skip to content

Commit

Permalink
Merge branch 'feature/spot-instance-support'
Browse files Browse the repository at this point in the history
  • Loading branch information
diodonfrost committed Jun 29, 2019
2 parents 92fd028 + e07db13 commit 496349d
Show file tree
Hide file tree
Showing 13 changed files with 342 additions and 59 deletions.
20 changes: 14 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,26 @@ Stop and start ec2, rds resources and autoscaling groups with lambda function.

## Features

* Aws lambda runtine Python 3.6
* Aws lambda runtine Python 3.7
* ec2 instances scheduling
* spot instances scheduling
* rds clusters scheduling
* rds instances scheduling
* autoscalings scheduling
* Aws cloudWatch logs for lambda

### Caveats
You can't stop and start an [Amazon Spot instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/how-spot-instances-work.html) (only the Spot service can stop and start a Spot Instance), but you can reboot or terminate a Spot Instance. That why this module support only scheduler action `terminate` for spot instance.

## Usage
```hcl
module "stop_ec2_instance" {
source = "diodonfrost/lambda-scheduler-stop-start/aws"
name = "ec2_stop"
cloudwatch_schedule_expression = "cron(0 00 ? * FRI *)"
schedule_action = "stop"
autoscaling_schedule = "false"
spot_schedule = "terminate"
ec2_schedule = "true"
rds_schedule = "false"
autoscaling_schedule = "false"
Expand All @@ -32,9 +38,10 @@ module "stop_ec2_instance" {

## Examples

* [EC2 scheduler](https://github.com/diodonfrost/terraform-aws-lambda-scheduler-stop-start/tree/master/examples/ec2-schedule) - Create lamnda functions to stop ec2 with tag `tostop = true` on Friday at 23:00 Gmt and start them on Monday at 07:00 GMT
* [Rds aurora - mariadb scheduler](https://github.com/diodonfrost/terraform-aws-lambda-scheduler-stop-start/tree/master/examples/rds-schedule) - Create lamnda functions to stop rds mariadb and aurora cluster with tag `tostop = true` on Friday at 23:00 Gmt and start them on Monday at 07:00 GMT
* [Autoscaling scheduler](https://github.com/diodonfrost/terraform-aws-lambda-scheduler-stop-start/tree/master/examples/autoscaling-schedule) - Create lamnda functions to suspend autoscaling group with tag `tostop = true` and terminate its ec2 instances on Friday at 23:00 Gmt and start them on Monday at 07:00 GMT
* [Autoscaling scheduler](https://github.com/diodonfrost/terraform-aws-lambda-scheduler-stop-start/tree/master/examples/autoscaling-schedule) - Create lambda functions to suspend autoscaling group with tag `tostop = true` and terminate its ec2 instances on Friday at 23:00 Gmt and start them on Monday at 07:00 GMT
* [Spot scheduler](https://github.com/diodonfrost/terraform-aws-lambda-scheduler-stop-start/tree/master/examples/spot-schedule) - Create lambda functions to stop spot instance with tag `tostop = true` on Friday at 23:00 Gmt
* [EC2 scheduler](https://github.com/diodonfrost/terraform-aws-lambda-scheduler-stop-start/tree/master/examples/ec2-schedule) - Create lambda functions to stop ec2 with tag `tostop = true` on Friday at 23:00 Gmt and start them on Monday at 07:00 GMT
* [Rds aurora - mariadb scheduler](https://github.com/diodonfrost/terraform-aws-lambda-scheduler-stop-start/tree/master/examples/rds-schedule) - Create lambda functions to stop rds mariadb and aurora cluster with tag `tostop = true` on Friday at 23:00 Gmt and start them on Monday at 07:00 GMT
* [test fixture](https://github.com/diodonfrost/terraform-aws-lambda-scheduler-stop-start/tree/master/examples/test_fixture) - Deploy environment for testing module

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Expand All @@ -47,9 +54,10 @@ module "stop_ec2_instance" {
| cloudwatch_schedule_expression | The scheduling expression | string | `"cron(0 22 ? * MON-FRI *)"` | yes |
| schedule_action | Define schedule action to apply on resources | string | `"stop"` | yes |
| resources_tag | Set the tag use for identify resources to stop or start | map | { tostop = "true" } | yes |
| ec2_schedule | Enable scheduling on ec2 resources | string | `"false"` | no |
| rds_schedule | Enable scheduling on rds resources | string | `"false"` | no |
| autoscaling_schedule | Enable scheduling on autoscaling resources | string | `"false"` | no |
| spot_schedule | Enable scheduling on spot instance resources | string | `"false"` | no |
| ec2_schedule | Enable scheduling on ec2 instance resources | string | `"false"` | no |
| rds_schedule | Enable scheduling on rds resources | string | `"false"` | no |

## Outputs

Expand Down
5 changes: 3 additions & 2 deletions examples/autoscaling-schedule/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ resource "aws_autoscaling_group" "not_scheduled" {
### Terraform modules ###

module "autoscaling-stop-friday" {
source = "diodonfrost/lambda-scheduler-stop-start/aws"
source = "../../"
name = "stop-autoscaling"
cloudwatch_schedule_expression = "cron(0 23 ? * FRI *)"
schedule_action = "stop"
Expand All @@ -89,10 +89,11 @@ module "autoscaling-stop-friday" {
}

module "autoscaling-start-monday" {
source = "diodonfrost/lambda-scheduler-stop-start/aws"
source = "../../"
name = "start-autoscaling"
cloudwatch_schedule_expression = "cron(0 07 ? * MON *)"
schedule_action = "start"
spot_schedule = "false"
ec2_schedule = "false"
rds_schedule = "false"
autoscaling_schedule = "true"
Expand Down
12 changes: 9 additions & 3 deletions examples/ec2-schedule/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ resource "aws_instance" "scheduled" {
instance_type = "t2.micro"

tags = {
tostop = "true"
Name = "shceduled"
tostop = "true"
team = "flarf"
lint = "yes"
provider = "terraform"
}
}

Expand All @@ -39,10 +43,11 @@ resource "aws_instance" "not_scheduled" {
### Terraform modules ###

module "ec2-stop-friday" {
source = "diodonfrost/lambda-scheduler-stop-start/aws"
source = "../../"
name = "stop-ec2"
cloudwatch_schedule_expression = "cron(0 23 ? * FRI *)"
schedule_action = "stop"
spot_schedule = "false"
ec2_schedule = "true"
rds_schedule = "false"
autoscaling_schedule = "false"
Expand All @@ -54,10 +59,11 @@ module "ec2-stop-friday" {
}

module "ec2-start-monday" {
source = "diodonfrost/lambda-scheduler-stop-start/aws"
source = "../../"
name = "start-ec2"
cloudwatch_schedule_expression = "cron(0 07 ? * MON *)"
schedule_action = "start"
spot_schedule = "false"
ec2_schedule = "true"
rds_schedule = "false"
autoscaling_schedule = "false"
Expand Down
6 changes: 4 additions & 2 deletions examples/rds-schedule/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,11 @@ resource "aws_db_instance" "mysql_not_scheduled" {
### Terraform modules ###

module "rds-stop-friday" {
source = "diodonfrost/lambda-scheduler-stop-start/aws"
source = "../../"
name = "stop-rds"
cloudwatch_schedule_expression = "cron(0 23 ? * FRI *)"
schedule_action = "stop"
spot_schedule = "false"
ec2_schedule = "false"
rds_schedule = "true"
autoscaling_schedule = "false"
Expand All @@ -101,10 +102,11 @@ module "rds-stop-friday" {
}

module "rds-start-monday" {
source = "diodonfrost/lambda-scheduler-stop-start/aws"
source = "../../"
name = "start-rds"
cloudwatch_schedule_expression = "cron(0 07 ? * MON *)"
schedule_action = "start"
spot_schedule = "false"
ec2_schedule = "false"
rds_schedule = "true"
autoscaling_schedule = "false"
Expand Down
127 changes: 127 additions & 0 deletions examples/spot-schedule/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# Terraform spot instance with lambda scheduler

data "aws_ami" "ubuntu" {
most_recent = true

filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"]
}

filter {
name = "virtualization-type"
values = ["hvm"]
}

owners = ["099720109477"] # Canonical
}

# Create vpc use by asg
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}

# Create subnet use bt asg
resource "aws_subnet" "main" {
vpc_id = "${aws_vpc.main.id}"
cidr_block = "10.0.1.0/24"
}

# Run spot instances that will be scheduled
resource "aws_launch_template" "scheduled" {
name_prefix = "spot-scheduled"
image_id = "${data.aws_ami.ubuntu.id}"
instance_type = "t2.micro"
}

resource "aws_autoscaling_group" "scheduled" {
desired_capacity = 3
max_size = 3
min_size = 3
vpc_zone_identifier = ["${aws_subnet.main.id}"]

mixed_instances_policy {
instances_distribution {
on_demand_percentage_above_base_capacity = "0"
}

launch_template {
launch_template_specification {
launch_template_id = "${aws_launch_template.scheduled.id}"
}

override {
instance_type = "t2.micro"
}

override {
instance_type = "t2.nano"
}
}
}

tag {
key = "tostop"
value = "true"
propagate_at_launch = true
}
}

# Run spot instances that will be not scheduled
resource "aws_launch_template" "not_scheduled" {
name_prefix = "spot-not_scheduled"
image_id = "${data.aws_ami.ubuntu.id}"
instance_type = "t2.micro"
}

resource "aws_autoscaling_group" "not_scheduled" {
desired_capacity = 2
max_size = 2
min_size = 2
vpc_zone_identifier = ["${aws_subnet.main.id}"]

mixed_instances_policy {
instances_distribution {
on_demand_percentage_above_base_capacity = "0"
}

launch_template {
launch_template_specification {
launch_template_id = "${aws_launch_template.scheduled.id}"
}

override {
instance_type = "t2.micro"
}

override {
instance_type = "t2.nano"
}
}
}

tag {
key = "tostop"
value = "false"
propagate_at_launch = true
}
}


### Terraform module ##

module "spot-terminate-friday" {
source = "../../"
name = "terminate-spot"
cloudwatch_schedule_expression = "cron(0 23 ? * FRI *)"
schedule_action = "stop"
spot_schedule = "terminate"
ec2_schedule = "false"
rds_schedule = "false"
autoscaling_schedule = "false"

resources_tag = {
key = "tostop"
value = "true"
}
}
9 changes: 9 additions & 0 deletions examples/spot-schedule/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Terraform ex2-schedule outputs

output "lambda_stop_name" {
value = "${module.spot-terminate-friday.scheduler_lambda_name}"
}

output "lambda_stop_arn" {
value = "${module.spot-terminate-friday.scheduler_lambda_arn}"
}
6 changes: 4 additions & 2 deletions examples/test_fixture/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ module "aws-stop-friday" {
name = "stop-aws"
cloudwatch_schedule_expression = "cron(0 23 ? * FRI *)"
schedule_action = "stop"
autoscaling_schedule = "true"
spot_schedule = "terminate"
ec2_schedule = "true"
rds_schedule = "true"
autoscaling_schedule = "true"

resources_tag = {
key = "tostop"
Expand All @@ -20,9 +21,10 @@ module "aws-start-monday" {
name = "start-aws"
cloudwatch_schedule_expression = "cron(0 07 ? * MON *)"
schedule_action = "start"
autoscaling_schedule = "true"
spot_schedule = "false"
ec2_schedule = "true"
rds_schedule = "true"
autoscaling_schedule = "true"

resources_tag = {
key = "tostop"
Expand Down
25 changes: 24 additions & 1 deletion main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,27 @@ EOF
}

# Create custom policy for manage ec2
resource "aws_iam_role_policy" "schedule_spot" {
name = "${var.name}-spot-custom-policy-scheduler"
role = "${aws_iam_role.scheduler_lambda.id}"

policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"ec2:TerminateSpotInstances"
],
"Resource": "*",
"Effect": "Allow"
}
]
}
EOF
}

# Create custom policy for manage ec2 instances
resource "aws_iam_role_policy" "schedule_ec2" {
name = "${var.name}-ec2-custom-policy-scheduler"
role = "${aws_iam_role.scheduler_lambda.id}"
Expand All @@ -77,7 +98,8 @@ resource "aws_iam_role_policy" "schedule_ec2" {
"ec2:DescribeInstanceStatus",
"ec2:StopInstances",
"ec2:StartInstances",
"ec2:DescribeTags"
"ec2:DescribeTags",
"ec2:TerminateSpotInstances"
],
"Resource": "*",
"Effect": "Allow"
Expand Down Expand Up @@ -167,6 +189,7 @@ resource "aws_lambda_function" "stop_start" {
EC2_SCHEDULE = "${var.ec2_schedule}"
RDS_SCHEDULE = "${var.rds_schedule}"
AUTOSCALING_SCHEDULE = "${var.autoscaling_schedule}"
SPOT_SCHEDULE = "${var.spot_schedule}"
}
}
}
Expand Down
Loading

0 comments on commit 496349d

Please sign in to comment.