NEW: ec2 instance scheduler

This commit is contained in:
xpk 2024-02-26 11:05:53 +08:00
parent 076bc5013c
commit 2ac422441b
Signed by: xpk
GPG Key ID: CD4FF6793F09AB86
5 changed files with 271 additions and 0 deletions

View File

@ -0,0 +1,16 @@
import boto3
import os
import json
# reference: https://aws.amazon.com/premiumsupport/knowledge-center/start-stop-lambda-eventbridge/
ec2 = boto3.client('ec2', region_name=os.environ['region_name'])
def lambda_handler(event, context):
if (event['action'] == 'start'):
resp = ec2.start_instances(InstanceIds=json.loads(os.environ['instances']))
elif (event['action'] == 'stop'):
resp = ec2.stop_instances(InstanceIds=json.loads(os.environ['instances']))
else:
resp = "Event action not provided"
return resp

View File

@ -0,0 +1,52 @@
<!-- This readme file is generated with terraform-docs -->
## Requirements
| Name | Version |
|------|---------|
| terraform | >= 1.3.0 |
| aws | >= 5.0 |
## Providers
| Name | Version |
|------|---------|
| archive | n/a |
| aws | >= 5.0 |
| random | n/a |
## Modules
No modules.
## Resources
| Name | Type |
|------|------|
| [aws_iam_role.eventscheduler](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource |
| [aws_iam_role_policy_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_lambda_function.ec2-start-stop](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource |
| [aws_lambda_permission.lambda_permission](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource |
| [aws_scheduler_schedule.start](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/scheduler_schedule) | resource |
| [aws_scheduler_schedule.stop](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/scheduler_schedule) | resource |
| [random_id.this](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource |
| [archive_file.lambda-package](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source |
| [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
## Inputs
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| description | A description of instances to be started/stopped on schedule | `string` | n/a | yes |
| instance-ids | Instances to be automatically started/stopped on schedule | `list(string)` | n/a | yes |
| instance-start-cron-expression | Cron expression for instance start schedule | `string` | n/a | yes |
| instance-stop-cron-expression | Cron expression for instance stop schedule | `string` | n/a | yes |
## Outputs
No outputs.
---
## Authorship
This module was developed by UPDATE_THIS.

View File

@ -0,0 +1,171 @@
data "aws_caller_identity" "this" {}
resource "random_id" "this" {
byte_length = 4
}
resource "aws_iam_role" "eventscheduler" {
name = "EventSchedulerRole-${random_id.this.dec}"
assume_role_policy = jsonencode(
{
"Version" : "2012-10-17",
"Statement" : [
{
"Effect" : "Allow",
"Principal" : {
"Service" : "scheduler.amazonaws.com"
},
"Action" : "sts:AssumeRole"
}
]
}
)
}
resource "aws_iam_role_policy_attachment" "this" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEventBridgeSchedulerFullAccess"
role = aws_iam_role.eventscheduler.name
}
resource "aws_iam_role" "this" {
name = "lambda-startstop-ec2-${var.description}"
assume_role_policy = jsonencode(
{
"Version" : "2012-10-17",
"Statement" : [
{
"Effect" : "Allow",
"Principal" : {
"Service" : "lambda.amazonaws.com"
},
"Action" : "sts:AssumeRole"
}
]
}
)
}
resource "aws_iam_role_policy" "this" {
policy = jsonencode(
{
"Version" : "2012-10-17",
"Statement" : [
{
"Sid" : "AllowCreationOfCloudwatchLogGroup",
"Effect" : "Allow",
"Action" : "logs:CreateLogGroup",
"Resource" : "arn:aws:logs:ap-east-1:${data.aws_caller_identity.this.account_id}:*"
},
{
"Sid" : "AllowWritingToCloudwatchLogGroup",
"Effect" : "Allow",
"Action" : [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource" : [
"arn:aws:logs:ap-east-1:${data.aws_caller_identity.this.account_id}:log-group:/aws/lambda/*"
]
},
{
"Sid" : "AllowStartingStoppingOfEc2Instance",
"Action" : [
"ec2:StopInstances",
"ec2:StartInstances",
"kms:CreateGrant"
],
"Effect" : "Allow",
"Resource" : "*"
}
]
}
)
role = aws_iam_role.this.id
name = "LambdaExecutionPolicy"
}
resource "aws_scheduler_schedule" "start" {
name = "scheduled-start-of-${var.description}-instances"
description = "Starts ${var.description} ec2 instance"
flexible_time_window {
mode = "OFF"
}
schedule_expression = var.instance-start-cron-expression
target {
arn = aws_lambda_function.ec2-start-stop.arn
role_arn = aws_iam_role.eventscheduler.arn
input = jsonencode({ "action" : "start" })
}
}
resource "aws_scheduler_schedule" "stop" {
name = "scheduled-stop-of-${var.description}-instances"
description = "Stops ${var.description} ec2 instance"
flexible_time_window {
mode = "OFF"
}
schedule_expression = var.instance-stop-cron-expression
target {
arn = aws_lambda_function.ec2-start-stop.arn
role_arn = aws_iam_role.eventscheduler.arn
input = jsonencode({ "action" : "stop" })
}
}
#
#resource "aws_cloudwatch_event_rule" "start" {
# name = "scheduled-start-of-${var.description}-instances"
# description = "Starts automation ec2 instance"
# schedule_expression = var.instance-start-cron-expression
#}
#
#resource "aws_cloudwatch_event_rule" "stop" {
# name = "scheduled-stop-of-${var.description}-instances"
# description = "Stops automation ec2 instance"
# schedule_expression = var.instance-stop-cron-expression
#}
#
#resource "aws_cloudwatch_event_target" "start" {
# rule = aws_cloudwatch_event_rule.start.name
# arn = aws_lambda_function.ec2-start-stop.arn
# input = "{\"action\": \"start\"}"
#}
#
#resource "aws_cloudwatch_event_target" "stop" {
# rule = aws_cloudwatch_event_rule.stop.name
# arn = aws_lambda_function.ec2-start-stop.arn
# input = "{\"action\": \"stop\"}"
#}
# Lambda function for instance scheduler
data "archive_file" "lambda-package" {
type = "zip"
source_file = "${path.module}/Ec2Scheduler.py"
output_path = "lambda-package.zip"
}
resource "aws_lambda_function" "ec2-start-stop" {
function_name = "${var.description}-ec2-start-stop"
filename = data.archive_file.lambda-package.output_path
source_code_hash = data.archive_file.lambda-package.output_base64sha256
handler = "Ec2Scheduler.lambda_handler"
runtime = "python3.12"
role = aws_iam_role.this.arn
timeout = 30
environment {
variables = {
instances = jsonencode(var.instance-ids)
}
}
}
resource "aws_lambda_permission" "lambda_permission" {
statement_id = "AllowCloudWatchToInvokeLambda"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.ec2-start-stop.function_name
principal = "events.amazonaws.com"
}

View File

@ -0,0 +1,19 @@
variable instance-start-cron-expression {
type = string
description = "Cron expression for instance start schedule"
}
variable instance-stop-cron-expression {
type = string
description = "Cron expression for instance stop schedule"
}
variable instance-ids {
type = list(string)
description = "Instances to be automatically started/stopped on schedule"
}
variable description {
type = string
description = "A description of instances to be started/stopped on schedule"
}

View File

@ -0,0 +1,13 @@
terraform {
required_version = ">= 1.3.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0"
}
archive = {
source = "hashicorp/archive"
}
}
}