Go x Next.js(SPA) な環境をTerraformでAWSに構築してみます!
バックエンドのGoには、ECS Fargateで。
フロントエンドのSPAには、CloudFront・S3を使用して静的ホスティングをしてます。
また、System エージェントをインストールすることでFargateコンテナ内に接続できるようにしています。
はじめに
連載記事でこの環境を構築していきます。
本記事では、API用のドメインhttps化・アプリケーションロードバランサー構築・RDSの構築を行います!
フォルダ構成とか書き方、モージュル化などは、【ネットワーク環境構築】terraform AWS環境構築 第1回この記事とほぼ同じなので気になる方は御覧ください!
全体のソースコード:github
環境は以下です。
| OS | Cataline 10.15.6 |
| Terraform | 0.14.4 |
| Go | 1.16.3 |
| React | 17.0.2 |
基本構文などこちらにまとめてますので、よかったらみてください!
AWS Terraform 基本コード まとめ
連載一覧
- Go x Next.js(SPA) をTerraformでさっさと構築 1/3
- Go x Next.js(SPA) をTerraformでさっさと構築 2/3 ←ここ
- Go x Next.js(SPA) をTerraformでさっさと構築 3/3
やること
以下の定義と作成をします。
API用のドメインACM証明書発行
【ドメインhttps化・ACM(SSL)証明書発行】terraform AWS環境構築 第2回
こことほぼ同じですが、発行するドメインに「api.」を付け加えます。
./main.tf
module "network" {
source = "./network"
app_name = var.app_name
}
module "acm" {
source = "./acm"
domain = var.domain
}
module "spa" {
source = "./spa"
app_name = var.app_name
domain = var.domain
acm_id = module.acm.acm_id
}
#追記
module "subdomain_acm" {
source = "./subdomain_acm"
domain = var.domain
}
./subdomain_acm/main.tf
resource "aws_acm_certificate" "this" {
domain_name = "api.${var.domain}"
validation_method = "DNS"
lifecycle {
create_before_destroy = true
}
}
resource "aws_route53_record" "this" {
depends_on = [aws_acm_certificate.this]
for_each = {
for dvo in aws_acm_certificate.this.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
}
}
zone_id = data.aws_route53_zone.this.zone_id
name = each.value.name
records = [each.value.record]
ttl = 60
type = each.value.type
}
resource "aws_acm_certificate_validation" "this" {
certificate_arn = aws_acm_certificate.this.arn
validation_record_fqdns = [for record in aws_route53_record.this : record.fqdn]
}
./subdomain_acm/variables.tf
variable "domain" {}
./subdomain_acm/data.tf
data "aws_route53_zone" "this" {
name = var.domain
private_zone = false
}
./subdomain_acm/outputs.tf
output "sub_acm_id" {
value = aws_acm_certificate.this.id
}
[terraform] $ terraform plan
作成されるリソースの確認。
[terraform] $ terraform apply
リソースの作成。

api.<your domain> のACM証明書が発行されているのが確認できましたね。
アプリケーションロードバランサー
【ロードバランサー構築】terraform AWS環境構築 第3回
こことほぼ同じです。
./main.tf
module "network" {
source = "./network"
app_name = var.app_name
}
module "acm" {
source = "./acm"
domain = var.domain
}
module "spa" {
source = "./spa"
app_name = var.app_name
domain = var.domain
acm_id = module.acm.acm_id
}
module "subdomain_acm" {
source = "./subdomain_acm"
domain = var.domain
}
#追記
module "elb" {
source = "./elb"
app_name = var.app_name
vpc_id = module.network.vpc_id
public_subnet_ids = module.network.public_subnet_ids
sub_acm_id = module.subdomain_acm.sub_acm_id
domain = var.domain
}
./elb/main.tf
resource "aws_security_group" "this" {
vpc_id = var.vpc_id
dynamic "ingress" {
for_each = var.ingress_ports
iterator = port
content {
from_port = port.value
to_port = port.value
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "${var.app_name}-sg"
}
}
resource "aws_lb" "this" {
name = "${var.app_name}-alb"
load_balancer_type = "application"
security_groups = [aws_security_group.this.id]
subnets = var.public_subnet_ids
}
resource "aws_lb_listener" "http" {
port = "80"
protocol = "HTTP"
load_balancer_arn = aws_lb.this.arn
default_action {
type = "redirect"
redirect {
port = "443"
protocol = "HTTPS"
status_code = "HTTP_301"
}
}
}
resource "aws_lb_listener" "https" {
port = "443"
protocol = "HTTPS"
load_balancer_arn = aws_lb.this.arn
certificate_arn = var.sub_acm_id
default_action {
type = "fixed-response"
fixed_response {
content_type = "text/plain"
status_code = "200"
message_body = "ok"
}
}
}
resource "aws_route53_record" "this" {
type = "A"
name = "api.${var.domain}"
zone_id = data.aws_route53_zone.this.id
alias {
name = aws_lb.this.dns_name
zone_id = aws_lb.this.zone_id
evaluate_target_health = true
}
}
./elb/variables.tf
variable "app_name" {}
variable "vpc_id" {}
variable "ingress_ports" {
description = "list of ingress ports"
default = [80, 443]
}
variable "public_subnet_ids" {}
variable "sub_acm_id" {}
variable "domain" {}
./elb/data.tf
data "aws_route53_zone" "this" {
name = var.domain
private_zone = false
}
./elb/outputs.tf
output "http_listener_arn" {
value = aws_lb_listener.http.arn
}
output "https_listener_arn" {
value = aws_lb_listener.https.arn
}
output "alb_security_group_id" {
value = aws_security_group.this.id
}
RDSの構築
【RDS構築】terraform AWS環境構築 第5回
ここと同じです。
./main.tf
module "network" {
source = "./network"
app_name = var.app_name
}
module "acm" {
source = "./acm"
domain = var.domain
}
module "spa" {
source = "./spa"
app_name = var.app_name
domain = var.domain
acm_id = module.acm.acm_id
}
module "subdomain_acm" {
source = "./subdomain_acm"
domain = var.domain
}
module "elb" {
source = "./elb"
app_name = var.app_name
vpc_id = module.network.vpc_id
public_subnet_ids = module.network.public_subnet_ids
sub_acm_id = module.subdomain_acm.sub_acm_id
domain = var.domain
}
# 追記
module "rds" {
source = "./rds"
app_name = var.app_name
db_name = var.db_name
db_user = var.db_user
db_password = var.db_password
vpc_id = module.network.vpc_id
alb_security_group_id = module.elb.alb_security_group_id
private_subnet_ids = module.network.private_subnet_ids
}
./terraform.tfvars
domain = "<your domain>" db_name = "go-next_db" db_user = "root" db_password = "password"
./rds/main.tf
resource "aws_security_group" "this" {
vpc_id = var.vpc_id
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "${var.app_name}-rds-sg"
}
}
resource "aws_security_group_rule" "this" {
security_group_id = aws_security_group.this.id
type = "ingress"
from_port = 3306
to_port = 3306
protocol = "tcp"
source_security_group_id = var.alb_security_group_id
}
resource "aws_db_subnet_group" "this" {
name = var.db_name
description = "db subent group of ${var.db_name}"
subnet_ids = var.private_subnet_ids
}
resource "aws_db_instance" "this" {
allocated_storage = 10
storage_type = "gp2"
engine = var.engine
engine_version = var.engine_version
instance_class = var.db_instance
identifier = "${var.app_name}-rds"
username = var.db_user
password = var.db_password
skip_final_snapshot = true
enabled_cloudwatch_logs_exports = [
"error",
"general",
"slowquery"
]
vpc_security_group_ids = [aws_security_group.this.id]
db_subnet_group_name = aws_db_subnet_group.this.name
}
./rds/variables.tf
variable "app_name" {}
variable "db_name" {}
variable "db_user" {}
variable "db_password" {}
variable "vpc_id" {}
variable "alb_security_group_id" {}
variable "engine" {
type = string
default = "mysql"
}
variable "engine_version" {
type = string
default = "8.0.20"
}
variable "db_instance" {
type = string
default = "db.t2.micro"
}
variable "private_subnet_ids" {}
./rds/outputs.tf
output "db_address" {
value = aws_db_instance.this.address
}
おわり
これで、ロードバランサーの構築・DB構築が完了しました。
次回は、ECSクラスター・ECSサービス・SSMアクティベーションの作成を行います。
最後までご覧いただきありがとうございます!
何か疑問に思うことがあれば、何でもいいのでコメントくれれば精一杯答えさせていただきます。
Twitterとかフォローしてくれると嬉しいです。では、次回お会いしましょう!

コメント