Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# ディレクトリ名が「.terraform」であるものを除外
**/.terraform/*
**/.idea/*
# ファイル名が「*.tfstate」にマッチしているものを除外
*.tfstate
*.tfstate.*
*.tfvars
43 changes: 43 additions & 0 deletions eventbridge-scheduler-stop-rds/env/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions eventbridge-scheduler-stop-rds/env/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
terraform {
backend "s3" {
bucket = "eventbridge-scheduler-stop-rds-terraform-prod"
key = "terraform.tfstate"
region = "us-east-2"
}
}

module "prod" {
source = "../src"
db_database = "foobar_database"
db_username = "admin"
db_exec_username = "foobar_exec_username"
}
1 change: 1 addition & 0 deletions eventbridge-scheduler-stop-rds/src/aws_caller_identity.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
data "aws_caller_identity" "self" {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//////////////////////////////////////////////////
// EventBridgeScheduler
// Aurora クラスタを起動
//////////////////////////////////////////////////
resource "aws_scheduler_schedule" "aurora_start" {
name = "aurora-start"
group_name = "default"
flexible_time_window {
// フレックスタイムウィンドウは使用しない
mode = "OFF"
}

// 平日 (MON-FRI) の 8:00 に起動
// cron(分 時 日 月 曜日 年) の順で指定
// 年の指定は * にすることで毎年有効となる
schedule_expression = "cron(0 8 ? * MON-FRI *)"
schedule_expression_timezone = "Asia/Tokyo"

target {
arn = "arn:aws:scheduler:::aws-sdk:rds:startDBCluster"
role_arn = aws_iam_role.eventbridge-scheduler-rds-start-stop-role.arn
input = jsonencode({
DbClusterIdentifier = aws_rds_cluster.default.cluster_identifier
})

retry_policy {
maximum_event_age_in_seconds = 600 // リトライする最大のイベントの経過時間:10分
maximum_retry_attempts = 1 // リトライ最大回数
}
}
}

//////////////////////////////////////////////////
// EventBridgeScheduler
// Aurora クラスタを停止
//////////////////////////////////////////////////
resource "aws_scheduler_schedule" "aurora_stop" {
name = "aurora-stop"
group_name = "default"
flexible_time_window {
// フレックスタイムウィンドウは使用しない
mode = "OFF"
}

// 平日 (MON-FRI) の 21:00 に停止
schedule_expression = "cron(0 21 ? * MON-FRI *)"
schedule_expression_timezone = "Asia/Tokyo"

target {
arn = "arn:aws:scheduler:::aws-sdk:rds:stopDBCluster"
role_arn = aws_iam_role.eventbridge-scheduler-rds-start-stop-role.arn
input = jsonencode({
DbClusterIdentifier = aws_rds_cluster.default.cluster_identifier
})

retry_policy {
maximum_event_age_in_seconds = 600 // リトライする最大のイベントの経過時間:10分
maximum_retry_attempts = 1 // リトライ最大回数
}
}
}

// 動作確認用
// (定期的: 毎日 20:20 JST)
#resource "aws_scheduler_schedule" "aurora_stop" {
# name = "aurora-stop"
# group_name = "default"
# flexible_time_window {
# mode = "OFF"
# }
#
# // 毎日 (day-of-week は問わない) 20:20 JST
# // cron(Minute Hour Day-of-month Month Day-of-week Year)
# // 日・月は「*」=毎日、曜日は「?」としています。
# schedule_expression = "cron(50 20 * * ? *)"
# schedule_expression_timezone = "Asia/Tokyo"
#
# target {
# arn = "arn:aws:scheduler:::aws-sdk:rds:stopDBCluster"
# role_arn = aws_iam_role.eventbridge-scheduler-rds-start-stop-role.arn
# input = jsonencode({
# DbClusterIdentifier = aws_rds_cluster.default.cluster_identifier
# })
#
# retry_policy {
# maximum_event_age_in_seconds = 600
# maximum_retry_attempts = 1
# }
# }
#}

21 changes: 21 additions & 0 deletions eventbridge-scheduler-stop-rds/src/iam_policy.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// RDSの起動・停止するポリシー
resource "aws_iam_policy" "rds_start_stop_base" {
name = "rds-start-stop-policy"
path = "/service-role/"
description = "start and stop RDS clusters"
policy = data.aws_iam_policy_document.rds_start_stop_base_policy.json
}

data "aws_iam_policy_document" "rds_start_stop_base_policy" {
statement {
effect = "Allow"
actions = [
"rds:StartDBCluster",
"rds:StopDBCluster"
]
// "arn:aws:rds:{リージョン名}:{アカウントID}:cluster:{クラスターID}"
resources = [
"arn:aws:rds:us-east-2:${data.aws_caller_identity.self.account_id}:cluster:${aws_rds_cluster.default.cluster_identifier}"
]
}
}
8 changes: 8 additions & 0 deletions eventbridge-scheduler-stop-rds/src/iam_policy_attachment.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// EventBridge Scheduler
resource "aws_iam_policy_attachment" "rds_start_stop_base" {
name = "rds-start-stop-base-policy-attachment"
policy_arn = aws_iam_policy.rds_start_stop_base.arn
groups = []
users = []
roles = [aws_iam_role.eventbridge-scheduler-rds-start-stop-role.name]
}
19 changes: 19 additions & 0 deletions eventbridge-scheduler-stop-rds/src/iam_role.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// EventBridge Schedulerにアタッチする
// RDSの起動・停止するIAMロール
resource "aws_iam_role" "eventbridge-scheduler-rds-start-stop-role" {
name = "eventbridge-scheduler-rds-start-stop-role"
path = "/service-role/"

assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Effect = "Allow",
Principal = {
Service = "scheduler.amazonaws.com"
},
Action = "sts:AssumeRole"
}
]
})
}
17 changes: 17 additions & 0 deletions eventbridge-scheduler-stop-rds/src/init.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.21"
}
}
}

provider "aws" {
region = "us-east-2"
}

provider "aws" {
region = "us-east-1"
alias = "use1"
}
40 changes: 40 additions & 0 deletions eventbridge-scheduler-stop-rds/src/rds_cluster.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
resource "random_password" "db_initial_password" {
length = 32
special = true
override_special = "_%?"
keepers = { // 自動生成
password_version = "1"
}
}

resource "aws_rds_cluster" "default" {
cluster_identifier = "aurora-cluster"
engine = "aurora-mysql"
engine_version = "8.0.mysql_aurora.3.08.0"
availability_zones = local.aws_az_codes
port = 3306
database_name = var.db_database
master_username = "admin"
master_password = random_password.db_initial_password.result
allow_major_version_upgrade = false
backup_retention_period = 5

preferred_backup_window = "14:00-14:30"
preferred_maintenance_window = "Sun:17:00-Sun:18:00"
apply_immediately = false
skip_final_snapshot = true
vpc_security_group_ids = [aws_security_group.db.id]
db_subnet_group_name = aws_db_subnet_group.default.name
enabled_cloudwatch_logs_exports = ["error", "slowquery"]
storage_encrypted = false
deletion_protection = false

lifecycle {
prevent_destroy = true
ignore_changes = [master_password, engine_version, availability_zones]
}

tags = {
Name = "aurora-cluster"
}
}
18 changes: 18 additions & 0 deletions eventbridge-scheduler-stop-rds/src/rds_cluster_instance.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
resource "aws_rds_cluster_instance" "cluster_instances" {
count = 2
identifier = "aurora-cluster-${count.index}"
cluster_identifier = aws_rds_cluster.default.id
instance_class = "db.t3.medium"
engine = aws_rds_cluster.default.engine
engine_version = aws_rds_cluster.default.engine_version
auto_minor_version_upgrade = false
apply_immediately = false
db_subnet_group_name = aws_db_subnet_group.default.name
// 例: 日本時間で月曜 02:00〜03:00 を想定
preferred_maintenance_window = "Sun:17:00-Sun:18:00"
monitoring_interval = 0

tags = {
Name = "aurora-instance"
}
}
8 changes: 8 additions & 0 deletions eventbridge-scheduler-stop-rds/src/rds_subnet_group.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
resource "aws_db_subnet_group" "default" {
name = "db-subnet-group"
subnet_ids = local.db_subnet_ids

tags = {
Name = "db-subnet-group"
}
}
43 changes: 43 additions & 0 deletions eventbridge-scheduler-stop-rds/src/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
variable "db_database" {
type = string
}

variable "db_username" {
type = string
}

variable "db_exec_username" {
type = string
}


variable "az_count" {
description = "使用するAZの数"
type = number
// AZ数を指定する
default = 2
}

locals {
// 利用可能なAZのリスト
aws_az_list = [
"us-east-2a",
"us-east-2b",
"us-east-2c"
]
aws_az_codes = slice(local.aws_az_list, 0, var.az_count)

// DBサーバ
db_subnet_map = {
for az in local.aws_az_codes :
"db_${az}" => aws_subnet.db[az]
}
// Private Subnets
private_subnet_map = merge(
local.db_subnet_map,
)

db_subnet_ids = [
for key, subnet in local.db_subnet_map : subnet.id
]
}
9 changes: 9 additions & 0 deletions eventbridge-scheduler-stop-rds/src/vpc.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
resource "aws_vpc" "vpc_01" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
instance_tenancy = "default"
tags = {
"Name" = "vpc-01"
}
}
16 changes: 16 additions & 0 deletions eventbridge-scheduler-stop-rds/src/vpc_security_group.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
resource "aws_security_group" "db" {
name = "db-sg"
description = "DB"
vpc_id = aws_vpc.vpc_01.id

ingress {
from_port = 3306
to_port = 3306
protocol = "tcp"
self = false
}

tags = {
"Name" = "db-sg"
}
}
20 changes: 20 additions & 0 deletions eventbridge-scheduler-stop-rds/src/vpc_subnet.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// DB subnets
resource "aws_subnet" "db" {
for_each = {
for idx, az in local.aws_az_codes :
az => {
cidr_block = cidrsubnet("10.0.0.0/16", 8, idx + 6)
availability_zone = az
name_suffix = idx + 1
}
}

vpc_id = aws_vpc.vpc_01.id
cidr_block = each.value.cidr_block
availability_zone = each.value.availability_zone
map_public_ip_on_launch = false

tags = {
"Name" = "db-subnet-${each.value.name_suffix}"
}
}