Skip to content

Instantly share code, notes, and snippets.

@akiraak
Created December 29, 2021 20:49
Show Gist options
  • Save akiraak/9c4cb34528cab6abab837d6d76488106 to your computer and use it in GitHub Desktop.
Save akiraak/9c4cb34528cab6abab837d6d76488106 to your computer and use it in GitHub Desktop.
Terraform で AWS の普通のインフラ構築
variable "main" {
default = {
"aws_account_ids" = ["XXXXXXXXXX"]
"app_name" = "XXXX"
"region" = "ap-northeast-1"
"az_1" = "ap-northeast-1a"
"az_2" = "ap-northeast-1c"
"acm_certificate_arn" = "arn:aws:acm:ap-northeast-1:XXXXXXXXX:certificate/XXXXXXXXXXXXXXXXXXXXXXXXXXXX"
"app_public_key_path" = "XXXX.pub"
"management_public_key_path" = "XXXX.pub"
}
}
provider "aws" {
region = var.main.region
allowed_account_ids = var.main.aws_account_ids
}
/*
module "aws" {
source = "./modules"
app_name = var.main.app_name
az_1 = var.main.az_1
az_2 = var.main.az_2
}
*/
variable "vpc" {
default = {
"vpc_cidr_block" = "10.0.0.0/16"
"subnet_public_management_1_cidr_block" = "10.0.240.0/24"
"subnet_public_management_2_cidr_block" = "10.0.241.0/24"
"subnet_public_app_alb_1_cidr_block" = "10.0.0.0/24"
"subnet_public_app_alb_2_cidr_block" = "10.0.1.0/24"
"subnet_private_app_1_cidr_block" = "10.0.8.0/24"
"subnet_private_app_2_cidr_block" = "10.0.9.0/24"
"subnet_private_app_db_1_cidr_block" = "10.0.16.0/24"
"subnet_private_app_db_2_cidr_block" = "10.0.17.0/24"
}
}
# ================================================
# VPC
# ================================================
resource "aws_vpc" "main" {
cidr_block = var.vpc.vpc_cidr_block
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "${var.main.app_name}-vpc"
}
}
# ================================================
# Internet gateway & Root table to internet
# ================================================
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.main.id
tags = {
Name = "${var.main.app_name}-igw"
}
}
resource "aws_route_table" "to_internet" {
vpc_id = aws_vpc.main.id
tags = {
Name = "${var.main.app_name}-rt-to-internet"
}
}
resource "aws_route" "to_internet" {
route_table_id = aws_route_table.to_internet.id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
# ================================================
# Subnet: Public management
# ================================================
resource "aws_subnet" "public_management_1" {
vpc_id = aws_vpc.main.id
cidr_block = var.vpc.subnet_public_management_1_cidr_block
availability_zone = var.main.az_1
tags = {
Name = "${var.main.app_name}-su-public-management-1"
}
}
resource "aws_subnet" "public_management_2" {
vpc_id = aws_vpc.main.id
cidr_block = var.vpc.subnet_public_management_2_cidr_block
availability_zone = var.main.az_2
tags = {
Name = "${var.main.app_name}-sn-public-management-2"
}
}
resource "aws_route_table_association" "public_management_1" {
subnet_id = aws_subnet.public_management_1.id
route_table_id = aws_route_table.to_internet.id
}
resource "aws_route_table_association" "public_management_2" {
subnet_id = aws_subnet.public_management_2.id
route_table_id = aws_route_table.to_internet.id
}
# ================================================
# Subnet: Public app alb
# ================================================
resource "aws_subnet" "public_app_alb_1" {
vpc_id = aws_vpc.main.id
cidr_block = var.vpc.subnet_public_app_alb_1_cidr_block
availability_zone = var.main.az_1
tags = {
Name = "${var.main.app_name}-sn-public-app-alb-1"
}
}
resource "aws_subnet" "public_app_alb_2" {
vpc_id = aws_vpc.main.id
cidr_block = var.vpc.subnet_public_app_alb_2_cidr_block
availability_zone = var.main.az_2
tags = {
Name = "${var.main.app_name}-sn-public-app-alb-2"
}
}
resource "aws_route_table_association" "public_app_alb_1" {
subnet_id = aws_subnet.public_app_alb_1.id
route_table_id = aws_route_table.to_internet.id
}
resource "aws_route_table_association" "public_app_alb_2" {
subnet_id = aws_subnet.public_app_alb_2.id
route_table_id = aws_route_table.to_internet.id
}
# ================================================
# Subnet: Private app
# ================================================
resource "aws_subnet" "private_app_1" {
vpc_id = aws_vpc.main.id
cidr_block = var.vpc.subnet_private_app_1_cidr_block
availability_zone = var.main.az_1
tags = {
Name = "${var.main.app_name}-sn-private-app-1"
}
}
resource "aws_subnet" "private_app_2" {
vpc_id = aws_vpc.main.id
cidr_block = var.vpc.subnet_private_app_2_cidr_block
availability_zone = var.main.az_2
tags = {
Name = "${var.main.app_name}-sn-private-app-2"
}
}
# ================================================
# Subnet: Private app db
# ================================================
resource "aws_subnet" "private_app_db_1" {
vpc_id = aws_vpc.main.id
cidr_block = var.vpc.subnet_private_app_db_1_cidr_block
availability_zone = var.main.az_1
tags = {
Name = "${var.main.app_name}-sn-private-app-db-1"
}
}
resource "aws_subnet" "private_app_db_2" {
vpc_id = aws_vpc.main.id
cidr_block = var.vpc.subnet_private_app_db_2_cidr_block
availability_zone = var.main.az_2
tags = {
Name = "${var.main.app_name}-sn-private-app-db-2"
}
}
# ================================================
# Security group: management
# ================================================
resource "aws_security_group" "management" {
name = "${var.main.app_name}-management"
vpc_id = aws_vpc.main.id
revoke_rules_on_delete = false
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "${var.main.app_name}-sg-management"
}
}
# ssh
resource "aws_security_group_rule" "app_permit_ssh" {
security_group_id = aws_security_group.management.id
cidr_blocks = ["0.0.0.0/0"]
type = "ingress"
protocol = "tcp"
from_port = "22"
to_port = "22"
}
# ================================================
# Security group: app alb
# ================================================
resource "aws_security_group" "app_alb" {
name = "${var.main.app_name}-app-alb"
vpc_id = aws_vpc.main.id
revoke_rules_on_delete = false
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "${var.main.app_name}-sg-app-alb"
}
}
# http
resource "aws_security_group_rule" "alb_permit_from_internet_http" {
security_group_id = aws_security_group.app_alb.id
cidr_blocks = ["0.0.0.0/0"]
description = "permit from internet for http."
type = "ingress"
protocol = "tcp"
from_port = "80"
to_port = "80"
}
# https
resource "aws_security_group_rule" "alb_permit_from_internet_https" {
security_group_id = aws_security_group.app_alb.id
cidr_blocks = ["0.0.0.0/0"]
description = "permit from internet for https."
type = "ingress"
protocol = "tcp"
from_port = "443"
to_port = "443"
}
# ================================================
# Security group: app
# ================================================
resource "aws_security_group" "app" {
name = "${var.main.app_name}-app"
vpc_id = aws_vpc.main.id
revoke_rules_on_delete = false
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "${var.main.app_name}-sg-app"
}
}
# http
resource "aws_security_group_rule" "app_permit_from_app_alb_http" {
security_group_id = aws_security_group.app.id
source_security_group_id = aws_security_group.app_alb.id
description = "permit from alb."
type = "ingress"
protocol = "tcp"
from_port = "80"
to_port = "80"
}
# ssh
resource "aws_security_group_rule" "app_permit_from_management_ssh" {
security_group_id = aws_security_group.app.id
source_security_group_id = aws_security_group.management.id
description = "permit from management."
type = "ingress"
protocol = "tcp"
from_port = "22"
to_port = "22"
}
# ================================================
# Security group: app db
# ================================================
resource "aws_security_group" "app_db" {
name = "${var.main.app_name}-app-db"
vpc_id = aws_vpc.main.id
revoke_rules_on_delete = false
tags = {
Name = "${var.main.app_name}-sg-app-db"
}
}
resource "aws_security_group_rule" "app-db-sg-rule-mysql-from-app" {
security_group_id = aws_security_group.app_db.id
type = "ingress"
from_port = 3306
to_port = 3306
protocol = "tcp"
source_security_group_id = aws_security_group.app.id
}
resource "aws_security_group_rule" "app-db-sg-rule-mysql-from-management" {
security_group_id = aws_security_group.app_db.id
type = "ingress"
from_port = 3306
to_port = 3306
protocol = "tcp"
source_security_group_id = aws_security_group.management.id
}
# ALBアカウントIDを取得するために使用
data "aws_elb_service_account" "main" {}
# ================================================
# ログ格納用バケットポリシー
# ================================================
data "aws_iam_policy_document" "logging_bucket" {
statement {
sid = ""
effect = "Allow"
principals {
identifiers = [
data.aws_elb_service_account.main.arn
]
type = "AWS"
}
actions = [
"s3:PutObject"
]
resources = [
"arn:aws:s3:::${var.main.app_name}-logging",
"arn:aws:s3:::${var.main.app_name}-logging/*"
]
}
}
# ================================================
# ログ格納用バケット
# ================================================
resource "aws_s3_bucket" "logging" {
bucket = "${var.main.app_name}-logging"
policy = data.aws_iam_policy_document.logging_bucket.json ## iam.tfで設定したポリシーを使用。
force_destroy = true
versioning {
enabled = true
mfa_delete = false
}
## オブジェクトのライフサイクル設定。
lifecycle_rule {
id = "assets"
enabled = true
## オブジェクトの保存期限。
expiration {
days = "365" ## 1年
}
## 現在のオブジェクトの移行設定。
transition {
## オブジェクトが作成されてから移行するまでの日数。
days = "93" ## 3ヶ月
storage_class = "STANDARD_IA"
}
## オブジェクトの以前のバージョンの保存期限。
noncurrent_version_expiration {
days = "1095" ## 3年
}
## 古いのオブジェクトの移行設定。
noncurrent_version_transition {
## オブジェクトが古いバージョンになってから移行するまでの日数。
days = "365" ## 1年
storage_class = "GLACIER"
}
}
request_payer = "BucketOwner"
}
# S3 Public Access Block
## パブリックアクセスはしないため全て有効にする。
resource "aws_s3_bucket_public_access_block" "logging" {
bucket = aws_s3_bucket.logging.bucket
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
# ================================================
# ALB Target group: app
# ================================================
resource "aws_lb_target_group" "app" {
name = "${var.main.app_name}-tg-app"
port = 80
protocol = "HTTP"
target_type = "ip"
vpc_id = aws_vpc.main.id
# 登録解除を実行するまでの待機時間。
deregistration_delay = 300 # 処理中のリクエストの完了するのを待つためにデフォルト値を採用。
# 登録された後にリクエストを開始する猶予時間
slow_start = 0 # 登録されたらすぐに開始してよいので無効。
load_balancing_algorithm_type = "round_robin" # ラウンドロビンで平均的にリクエストを分散。
stickiness {
type = "lb_cookie"
cookie_duration = 86400 # 要件が決まっていないのでとりあえず1日を設定。
enabled = true
}
health_check {
enabled = true
interval = 30
path = "/"
port = "traffic-port" # トラフィックを受信するポートを使用。デフォルト。
protocol = "HTTP"
timeout = 5
healthy_threshold = 3
unhealthy_threshold = 3
matcher = "200-299"
}
}
# ================================================
# ALB Listener: app
# ================================================
# https
resource "aws_lb_listener" "https" {
load_balancer_arn = aws_lb.app.arn
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-2016-08"
certificate_arn = var.main.acm_certificate_arn
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.app.arn
}
}
# Listener: HTTPをHTTPSにリダイレクトするためのリスナー
resource "aws_lb_listener" "http_redirect_to_https" {
load_balancer_arn = aws_lb.app.arn
port = 80
protocol = "HTTP"
default_action {
type = "redirect"
redirect {
port = 443
protocol = "HTTPS"
status_code = "HTTP_301"
}
}
}
# ================================================
# ALB: app
# ================================================
resource "aws_lb" "app" {
name = "${var.main.app_name}-alb-app"
internal = false # 内部で使用しないため無効。
load_balancer_type = "application"
security_groups = [
aws_security_group.app_alb.id
]
access_logs {
bucket = aws_s3_bucket.logging.bucket
prefix = "elb"
enabled = true
}
subnets = [
aws_subnet.public_app_alb_1.id,
aws_subnet.public_app_alb_2.id
]
idle_timeout = 60 # デフォルトの60秒を設定。
enable_deletion_protection = false # Terraformで削除したいため無効。
enable_http2 = true
ip_address_type = "ipv4" # ipv6は使用しないためipv4を指定。
}
# ================================================
# EC2: management
# ================================================
data "aws_ami" "management" {
most_recent = true
owners = ["self"]
filter {
name = "name"
values = ["*management*"]
}
}
resource "aws_instance" "management" {
ami = "${data.aws_ami.management.id}"
vpc_security_group_ids = [aws_security_group.management.id]
subnet_id = aws_subnet.public_management_1.id
key_name = aws_key_pair.management.key_name
instance_type = "t3.micro"
associate_public_ip_address = "true"
tags = {
Name = "${var.main.app_name}-management"
}
}
resource "aws_key_pair" "management" {
key_name = "${var.main.app_name}-key-management"
public_key = file(var.main.management_public_key_path)
}
# ================================================
# EC2: app
# ================================================
data "aws_ami" "app" {
most_recent = true
owners = ["self"]
filter {
name = "name"
values = ["*docker*"]
}
}
resource "aws_instance" "app" {
ami = "${data.aws_ami.app.id}"
vpc_security_group_ids = [aws_security_group.app.id]
subnet_id = aws_subnet.private_app_1.id
key_name = aws_key_pair.app.key_name
instance_type = "t3.micro"
tags = {
Name = "${var.main.app_name}-app"
}
}
resource "aws_key_pair" "app" {
key_name = "${var.main.app_name}-key-app"
public_key = file(var.main.app_public_key_path)
}
# ================================================
# RDS: app db
# ================================================
resource "aws_db_subnet_group" "app" {
name = "${var.main.app_name}-db-sng-app"
subnet_ids = ["${aws_subnet.private_app_db_1.id}", "${aws_subnet.private_app_db_2.id}"]
tags = {
Name = "${var.main.app_name}-db-sng-app"
}
}
resource "aws_db_instance" "db" {
identifier = "${var.main.app_name}-db-app"
allocated_storage = 20
storage_type = "gp2"
engine = "mysql"
engine_version = "8.0.23"
instance_class = "db.t3.micro"
name = "${var.main.app_name}_app"
username = "root"
password = "rootroot"
skip_final_snapshot = true
vpc_security_group_ids = [aws_security_group.app_db.id]
db_subnet_group_name = aws_db_subnet_group.app.name
}
# ================================================
# Route53
# ================================================
# ================================================
# ECR
# ================================================
resource "aws_ecr_repository" "app" {
name = "${var.main.app_name}-ecr-app"
image_tag_mutability = "MUTABLE"
image_scanning_configuration {
scan_on_push = false
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment