#本記事の目的
Terraformを用いて、AWS上でよく見るシステムパターンを作成し、アウトプットとして記録する。
今回は基本的なWeb3層構成を作成してみる。
#設計
###システム要件
・Web/APサーバー及びDBサーバを各2台ずつ構築し、ロードバランサーで通信を振り分ける。
・ロードバランサーはパブリックサブネットに配置し、https通信でアクセスできるようにする。
・Web/APサーバー及びDBサーバはプライベートサブネットに配置し、ロードバランサーを介してアクセスできるようにする。
・ロードバランサーのアクセスログは、別途専用ストレージに保存する。
#事前準備
###ソフトウェア要件
※1 今回はTerraform用のAWS CLIプロファイルを、tf-demo
という名前で作成し使用する。
※2 Terraform実施時に出力されるjsonデータ加工用のコマンド。
###EC2キーペア用の公開鍵/秘密鍵の作成
$ ssh-keygen -t rsa -f ~/.ssh/web3_configuration.pem
###ホストゾーンの作成
Route53等で、事前にドメインを購入する。
$ aws route53 create-hosted-zone --name <購入したドメイン名> --caller-reference $(date +%Y-%m-%d_%H-%M-%S)
#ファイル構成
$ tree
web3_configuration/
├── certificate.tf
├── compute.tf
├── config.tf
├── dns.tf
├── firewall.tf
├── lb.tf
├── network.tf
├── output.tf
├── rd.tf
├── storage.tf
├── variable.tf
└── src
└── user_data.sh
#ファイル内容
###certificateファイル
ALB用のSSL証明書の設定を定義する。
# ====================
#
# ACM Certificate
#
# ====================
resource "aws_acm_certificate" "example_cert" {
domain_name = "*.${var.registered_domain}"
subject_alternative_names = ["${var.registered_domain}"]
validation_method = "DNS"
tags = {
Name = "${var.project}-${var.environment}-wildcard-sslcert"
}
lifecycle {
create_before_destroy = true
}
depends_on = [
data.aws_route53_zone.example_route53_zone
]
}
# ====================
#
# ACM DNS Verifycation
#
# ====================
resource "aws_route53_record" "example_route53_acm_dns_resolve" {
for_each = {
for dvo in aws_acm_certificate.example_cert.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
type = dvo.resource_record_type
record = dvo.resource_record_value
}
}
allow_overwrite = true
zone_id = data.aws_route53_zone.example_route53_zone.zone_id
name = each.value.name
type = each.value.type
ttl = 600
records = [each.value.record]
}
resource "aws_acm_certificate_validation" "cert_valid" {
certificate_arn = aws_acm_certificate.example_cert.arn
validation_record_fqdns = [for record in aws_route53_record.example_route53_acm_dns_resolve : record.fqdn]
}
###computeファイル
AMI、EC2インスタンス、EC2キーペアの設定を定義する。
# ====================
#
# AMI
#
# ====================
# 最新版のAmazonLinux2のAMI情報
data "aws_ami" "example_ami" {
most_recent = true
owners = ["amazon"]
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "root-device-type"
values = ["ebs"]
}
filter {
name = "name"
values = ["amzn2-ami-hvm-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "block-device-mapping.volume-type"
values = ["gp2"]
}
filter {
name = "state"
values = ["available"]
}
}
# ====================
#
# EC2 Instance
#
# ====================
resource "aws_instance" "example_instance_1a" {
ami = data.aws_ami.example_ami.image_id
instance_type = var.instance_type
subnet_id = aws_subnet.example_subnet_1.id
associate_public_ip_address = true
vpc_security_group_ids = [aws_security_group.example_sg_ec2.id]
root_block_device {
volume_type = var.volume_type
volume_size = var.volume_size
delete_on_termination = true
}
key_name = aws_key_pair.example_key.id
user_data = file(var.user_data_file)
tags = {
Name = "${var.project}-${var.environment}-ec2-1a"
Project = var.project
Env = var.environment
}
}
resource "aws_instance" "example_instance_1c" {
ami = data.aws_ami.example_ami.image_id
instance_type = var.instance_type
subnet_id = aws_subnet.example_subnet_2.id
associate_public_ip_address = true
vpc_security_group_ids = [aws_security_group.example_sg_ec2.id]
root_block_device {
volume_type = var.volume_type
volume_size = var.volume_size
delete_on_termination = true
}
key_name = aws_key_pair.example_key.id
user_data = file(var.user_data_file)
tags = {
Name = "${var.project}-${var.environment}-ec2-1c"
Project = var.project
Env = var.environment
}
}
# ====================
#
# Key Pair
#
# ====================
resource "aws_key_pair" "example_key" {
key_name = var.key_name
public_key = file(var.public_key_file)
tags = {
Name = "${var.project}-${var.environment}-keypair"
Project = var.project
Env = var.environment
}
}
###dnsファイル
Route53の設定を定義する。
# ====================
#
# Route53
#
# ====================
data "aws_route53_zone" "example_route53_zone" {
name = var.registered_domain
}
resource "aws_route53_record" "example_route53_record" {
zone_id = data.aws_route53_zone.example_route53_zone.id
name = "www.example.${var.domain}"
type = "A"
alias {
name = aws_lb.example_alb.dns_name
zone_id = aws_lb.example_alb.zone_id
evaluate_target_health = true
}
}
###firewallファイル
セキュリティグループの設定を定義する。
# ====================
#
# Security Group
#
# ====================
# ALB用セキュリティグループ
resource "aws_security_group" "example_sg_alb" {
name = "example_sg_alb"
vpc_id = aws_vpc.example_vpc.id
tags = {
Name = "${var.project}-${var.environment}-sg-alb"
Project = var.project
Env = var.environment
}
}
# インバウンドルール(http接続用)
resource "aws_security_group_rule" "in_http_alb" {
security_group_id = aws_security_group.example_sg_alb.id
type = "ingress"
cidr_blocks = ["0.0.0.0/0"]
from_port = 80
to_port = 80
protocol = "tcp"
}
# インバウンドルール(https接続用)
resource "aws_security_group_rule" "in_https_alb" {
security_group_id = aws_security_group.example_sg_alb.id
type = "ingress"
cidr_blocks = ["0.0.0.0/0"]
from_port = 443
to_port = 443
protocol = "tcp"
}
# アウトバウンドルール(全開放)
resource "aws_security_group_rule" "out_all_alb" {
security_group_id = aws_security_group.example_sg_alb.id
type = "egress"
cidr_blocks = ["0.0.0.0/0"]
from_port = 0
to_port = 0
protocol = "-1"
}
# EC2用セキュリティグループ
resource "aws_security_group" "example_sg_ec2" {
name = "example_sg_ec2"
vpc_id = aws_vpc.example_vpc.id
tags = {
Name = "${var.project}-${var.environment}-sg-ec2"
Project = var.project
Env = var.environment
}
}
# インバウンドルール(ssh接続用)
resource "aws_security_group_rule" "in_ssh_ec2" {
security_group_id = aws_security_group.example_sg_ec2.id
type = "ingress"
cidr_blocks = ["0.0.0.0/0"]
from_port = 22
to_port = 22
protocol = "tcp"
}
# インバウンドルール(http接続用)
resource "aws_security_group_rule" "in_http_ec2" {
security_group_id = aws_security_group.example_sg_ec2.id
type = "ingress"
cidr_blocks = ["0.0.0.0/0"]
from_port = 80
to_port = 80
protocol = "tcp"
}
# インバウンドルール(https接続用)
resource "aws_security_group_rule" "in_https_ec2" {
security_group_id = aws_security_group.example_sg_ec2.id
type = "ingress"
cidr_blocks = ["0.0.0.0/0"]
from_port = 443
to_port = 443
protocol = "tcp"
}
# アウトバウンドルール(全開放)
resource "aws_security_group_rule" "out_all_ec2" {
security_group_id = aws_security_group.example_sg_ec2.id
type = "egress"
cidr_blocks = ["0.0.0.0/0"]
from_port = 0
to_port = 0
protocol = "-1"
}
# RDS用セキュリティグループ
resource "aws_security_group" "example_sg_rds" {
name = "example_sg_rds"
vpc_id = aws_vpc.example_vpc.id
tags = {
Name = "${var.project}-${var.environment}-sg-rds"
Project = var.project
Env = var.environment
}
}
# インバウンドルール(mysql接続用)
resource "aws_security_group_rule" "in_mysql_rds" {
security_group_id = aws_security_group.example_sg_rds.id
type = "ingress"
cidr_blocks = ["0.0.0.0/0"]
from_port = 3306
to_port = 3306
protocol = "tcp"
}
# アウトバウンドルール(全開放)
resource "aws_security_group_rule" "out_all_rds" {
security_group_id = aws_security_group.example_sg_rds.id
type = "egress"
cidr_blocks = ["0.0.0.0/0"]
from_port = 0
to_port = 0
protocol = "-1"
}
###lbファイル
ALBの設定を定義する。
# ====================
#
# ALB
#
# ====================
resource "aws_lb" "example_alb" {
name = "${var.project}-${var.environment}-app-alb"
internal = false #falseを指定するとインターネット向け,trueを指定すると内部向け
load_balancer_type = "application"
idle_timeout = var.idle_timeout
enable_deletion_protection = false
access_logs {
bucket = aws_s3_bucket.example_log_bucket.id
enabled = true
}
subnets = [
aws_subnet.example_subnet_1.id,
aws_subnet.example_subnet_2.id,
]
security_groups = [
aws_security_group.example_sg_alb.id
]
}
# ====================
#
# Listener
#
# ====================
resource "aws_lb_listener" "example_alb_lsnr_http" {
load_balancer_arn = aws_lb.example_alb.arn
port = 80
protocol = "HTTP"
default_action {
type = "redirect"
redirect {
port = 443
protocol = "HTTPS"
status_code = "HTTP_301"
}
}
}
resource "aws_lb_listener" "example_alb_lsnr_https" {
load_balancer_arn = aws_lb.example_alb.arn
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-2016-08"
certificate_arn = aws_acm_certificate.example_cert.arn
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.example_alb_tg.arn
}
}
# ====================
#
# Target Group
#
# ====================
resource "aws_lb_target_group" "example_alb_tg" {
name = "${var.project}-${var.environment}-alp-tg"
target_type = "instance"
port = 80
protocol = "HTTP"
vpc_id = aws_vpc.example_vpc.id
deregistration_delay = var.deregistration_delay
health_check {
path = "/"
healthy_threshold = var.healthy_threshold
unhealthy_threshold = var.unhealthy_threshold
timeout = var.timeout
interval = var.interval
matcher = var.matcher
port = "traffic-port"
protocol = "HTTP"
}
depends_on = [
aws_lb.example_alb
]
tags = {
Name = "${var.project}-${var.environment}-alp-tg"
Project = var.project
Env = var.environment
}
}
resource "aws_lb_target_group_attachment" "example_alb_tgec2_1a" {
target_group_arn = aws_lb_target_group.example_alb_tg.arn
target_id = aws_instance.example_instance_1a.id
}
resource "aws_lb_target_group_attachment" "example_alb_tgec2_1c" {
target_group_arn = aws_lb_target_group.example_alb_tg.arn
target_id = aws_instance.example_instance_1c.id
}
data "aws_elb_service_account" "example_log_service_account" {}
###networkファイル
VPC/サブネット/インターネットゲートウェイ/Elastic IP/Natゲートウェイ/ルーティングの設定を定義する。
# ====================
#
# VPC
#
# ====================
resource "aws_vpc" "example_vpc" {
cidr_block = var.vpc_cidr_block
enable_dns_support = true # DNS解決有効化
enable_dns_hostnames = true # DNSホスト名有効化
tags = {
Name = "${var.project}-${var.environment}-vpc"
Project = var.project
Env = var.environment
}
}
# ====================
#
# Public Subnet
#
# ====================
resource "aws_subnet" "example_subnet_1" {
vpc_id = aws_vpc.example_vpc.id
cidr_block = var.subnet_cidr_block_1
map_public_ip_on_launch = true #インスタンス起動時におけるパブリックIPアドレスの自動割り当ての有効化
availability_zone = var.availability_zone_1
tags = {
Name = "${var.project}-${var.environment}-subnet-1"
Project = var.project
Env = var.environment
}
}
resource "aws_subnet" "example_subnet_2" {
vpc_id = aws_vpc.example_vpc.id
cidr_block = var.subnet_cidr_block_2
map_public_ip_on_launch = true #インスタンス起動時におけるパブリックIPアドレスの自動割り当ての有効化
availability_zone = var.availability_zone_2
tags = {
Name = "${var.project}-${var.environment}-subnet-2"
Project = var.project
Env = var.environment
}
}
# ====================
#
# Private Subnet
#
# ====================
resource "aws_subnet" "example_subnet_3" {
vpc_id = aws_vpc.example_vpc.id
cidr_block = var.subnet_cidr_block_3
map_public_ip_on_launch = false #インスタンス起動時におけるパブリックIPアドレスの自動割り当ての無効化
availability_zone = var.availability_zone_1
tags = {
Name = "${var.project}-${var.environment}-subnet-3"
Project = var.project
Env = var.environment
}
}
resource "aws_subnet" "example_subnet_4" {
vpc_id = aws_vpc.example_vpc.id
cidr_block = var.subnet_cidr_block_4
map_public_ip_on_launch = false #インスタンス起動時におけるパブリックIPアドレスの自動割り当ての無効化
availability_zone = var.availability_zone_2
tags = {
Name = "${var.project}-${var.environment}-subnet-4"
Project = var.project
Env = var.environment
}
}
resource "aws_subnet" "example_subnet_5" {
vpc_id = aws_vpc.example_vpc.id
cidr_block = var.subnet_cidr_block_5
map_public_ip_on_launch = false #インスタンス起動時におけるパブリックIPアドレスの自動割り当ての無効化
availability_zone = var.availability_zone_1
tags = {
Name = "${var.project}-${var.environment}-subnet-5"
Project = var.project
Env = var.environment
}
}
resource "aws_subnet" "example_subnet_6" {
vpc_id = aws_vpc.example_vpc.id
cidr_block = var.subnet_cidr_block_6
map_public_ip_on_launch = false #インスタンス起動時におけるパブリックIPアドレスの自動割り当ての無効化
availability_zone = var.availability_zone_2
tags = {
Name = "${var.project}-${var.environment}-subnet-6"
Project = var.project
Env = var.environment
}
}
# ====================
#
# Internet Gateway
#
# ====================
resource "aws_internet_gateway" "example_igw" {
vpc_id = aws_vpc.example_vpc.id
tags = {
Name = "${var.project}-${var.environment}-igw"
Project = var.project
Env = var.environment
}
}
# ====================
#
# Elastic IP
#
# ====================
resource "aws_eip" "example_eip_1a" {
vpc = true
depends_on = [aws_internet_gateway.example_igw]
tags = {
Name = "${var.project}-${var.environment}-eip-1a"
Project = var.project
Env = var.environment
}
}
resource "aws_eip" "example_eip_1c" {
vpc = true
depends_on = [aws_internet_gateway.example_igw]
tags = {
Name = "${var.project}-${var.environment}-eip-1c"
Project = var.project
Env = var.environment
}
}
# ====================
#
# Nat Gateway
#
# ====================
resource "aws_nat_gateway" "example_ngw_1a" {
allocation_id = aws_eip.example_eip_1a.id
subnet_id = aws_subnet.example_subnet_3.id
depends_on = [aws_eip.example_eip_1a]
tags = {
Name = "${var.project}-${var.environment}-ngw-1a"
}
}
resource "aws_nat_gateway" "example_ngw_1c" {
allocation_id = aws_eip.example_eip_1c.id
subnet_id = aws_subnet.example_subnet_3.id
depends_on = [aws_eip.example_eip_1c]
tags = {
Name = "${var.project}-${var.environment}-ngw-1c"
}
}
# ====================
#
# Public Route Table
#
# ====================
resource "aws_route_table" "example_public_rt" {
vpc_id = aws_vpc.example_vpc.id
tags = {
Name = "${var.project}-${var.environment}-public-rt"
Project = var.project
Env = var.environment
}
}
resource "aws_route" "example_public_route" {
route_table_id = aws_route_table.example_public_rt.id
gateway_id = aws_internet_gateway.example_igw.id
destination_cidr_block = "0.0.0.0/0"
}
resource "aws_route_table_association" "example_public_subrt_1" {
subnet_id = aws_subnet.example_subnet_1.id
route_table_id = aws_route_table.example_public_rt.id
}
resource "aws_route_table_association" "example_public_subrt_2" {
subnet_id = aws_subnet.example_subnet_2.id
route_table_id = aws_route_table.example_public_rt.id
}
# ====================
#
# Private Route Table
#
# ====================
resource "aws_route_table" "example_private_rt_1a" {
vpc_id = aws_vpc.example_vpc.id
tags = {
Name = "${var.project}-${var.environment}-private-rt-1a"
Project = var.project
Env = var.environment
}
}
resource "aws_route" "example_private_route_1a" {
route_table_id = aws_route_table.example_private_rt_1a.id
gateway_id = aws_nat_gateway.example_ngw_1a.id
destination_cidr_block = "0.0.0.0/0"
}
resource "aws_route_table_association" "example_private_subrt_3" {
subnet_id = aws_subnet.example_subnet_3.id
route_table_id = aws_route_table.example_private_rt_1a.id
}
resource "aws_route_table" "example_private_rt_1c" {
vpc_id = aws_vpc.example_vpc.id
tags = {
Name = "${var.project}-${var.environment}-private-rt-1c"
Project = var.project
Env = var.environment
}
}
resource "aws_route" "example_private_route_1c" {
route_table_id = aws_route_table.example_private_rt_1c.id
gateway_id = aws_nat_gateway.example_ngw_1c.id
destination_cidr_block = "0.0.0.0/0"
}
resource "aws_route_table_association" "example_private_subrt_4" {
subnet_id = aws_subnet.example_subnet_4.id
route_table_id = aws_route_table.example_private_rt_1c.id
}
###rdファイル
RDSの設定を定義する。
# ====================
#
# RDS Parameter Group
#
# ====================
resource "aws_db_parameter_group" "example_db_parametergroup" {
name = "${var.project}-${var.environment}-db-parametergroup"
family = "mysql8.0"
parameter {
name = "character_set_database"
value = "utf8mb4"
}
parameter {
name = "character_set_server"
value = "utf8mb4"
}
}
# ====================
#
# RDS Option Group
#
# ====================
resource "aws_db_option_group" "example_db_optiongroup" {
name = "${var.project}-${var.environment}-db-optiongroup"
engine_name = "mysql"
major_engine_version = "8.0"
}
# ====================
#
# RDS Subnet Group
#
# ====================
resource "aws_db_subnet_group" "example_db_subnetgroup" {
name = "${var.project}-${var.environment}-db-subnetgroup"
subnet_ids = [
aws_subnet.example_subnet_5.id,
aws_subnet.example_subnet_6.id
]
tags = {
Name = "${var.project}-${var.environment}-db-subnetgroup"
Project = var.project
Env = var.environment
}
}
# ====================
#
# RDS instance
#
# ====================
resource "aws_db_instance" "example_db" {
engine = "mysql"
engine_version = "8.0.20"
identifier = "${var.project}-${var.environment}-db"
username = "admin"
password = var.db_password
instance_class = var.instance_class
storage_type = var.storage_type
allocated_storage = var.allocated_storage
max_allocated_storage = var.max_allocated_storage
storage_encrypted = false
multi_az = true
db_subnet_group_name = aws_db_subnet_group.example_db_subnetgroup.name
vpc_security_group_ids = [aws_security_group.example_sg_rds.id]
publicly_accessible = false
port = 3306
name = "${var.project}${var.environment}db"
parameter_group_name = aws_db_parameter_group.example_db_parametergroup.name
option_group_name = aws_db_option_group.example_db_optiongroup.name
backup_window = var.backup_window
backup_retention_period = var.backup_retention_period
maintenance_window = var.maintenance_window
auto_minor_version_upgrade = false
deletion_protection = false
skip_final_snapshot = true
apply_immediately = true
tags = {
Name = "${var.project}-${var.environment}-db"
Project = var.project
Env = var.environment
}
}
###storageファイル
S3バケットの設定を定義する。
resource "random_string" "example_unique_key" {
length = 6
upper = false
lower = true
number = true
special = false
}
# ====================
#
# S3 log bucket
#
# ====================
resource "aws_s3_bucket" "example_log_bucket" {
bucket = "${var.project}-${var.environment}-log-bucket-${random_string.example_unique_key.result}"
force_destroy = true
lifecycle_rule {
enabled = true
expiration {
days = var.expiration_days
}
}
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
tags = {
Name = "${var.project}-${var.environment}-log-bucket"
Project = var.project
Env = var.environment
}
}
resource "aws_s3_bucket_public_access_block" "example_log_bucket_access_block" {
bucket = aws_s3_bucket.example_log_bucket.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
depends_on = [aws_s3_bucket_policy.example_log_bucket_policy]
}
resource "aws_s3_bucket_policy" "example_log_bucket_policy" {
bucket = aws_s3_bucket.example_log_bucket.id
policy = data.aws_iam_policy_document.example_log_bucket_policy_document.json
}
data "aws_iam_policy_document" "example_log_bucket_policy_document" {
statement {
effect = "Allow"
actions = ["s3:PutObject"]
resources = ["${aws_s3_bucket.example_log_bucket.arn}/*"]
principals {
type = "AWS"
identifiers = [data.aws_elb_service_account.example_log_service_account.id]
}
}
}
###variableファイル
Terraform実施時のグローバル変数を定義する。必要に応じてterraform.tfvarsファイルを作成する。
# ====================
#
# Variables
#
# ====================
variable "aws_region" {
default = "ap-northeast-1"
}
variable "project" {
default = "availability"
}
variable "environment" {
default = "test"
}
# IAM #
variable "aws_profile" {
default = "tf-demo" # AWSプロファイル
}
# EC2 #
variable "instance_type" {
default = "t2.micro"
}
variable "volume_type" {
default = "gp2"
}
variable "volume_size" {
default = "8"
}
variable "user_data_file" {
default = "./src/user_data.sh"
}
variable "key_name" {
default = "availability"
}
variable "public_key_file" {
default = "~/.ssh/availability.pem.pub"
}
# VPC #
variable "vpc_cidr_block" {
default = "10.0.0.0/16"
}
variable "subnet_cidr_block_1" {
default = "10.0.1.0/24"
}
variable "subnet_cidr_block_2" {
default = "10.0.2.0/24"
}
variable "subnet_cidr_block_3" {
default = "10.0.3.0/24"
}
variable "subnet_cidr_block_4" {
default = "10.0.4.0/24"
}
variable "subnet_cidr_block_5" {
default = "10.0.5.0/24"
}
variable "subnet_cidr_block_6" {
default = "10.0.6.0/24"
}
variable "availability_zone_1" {
default = "ap-northeast-1a"
}
variable "availability_zone_2" {
default = "ap-northeast-1c"
}
# RDS #
variable "db_password" {}
variable "instance_class" {
default = "db.t2.micro"
}
variable "storage_type" {
default = "gp2"
}
variable "allocated_storage" {
default = 20
}
variable "max_allocated_storage" {
default = 50
}
variable "backup_window" {
default = "04:00-05:00"
}
variable "backup_retention_period" {
default = 7
}
variable "maintenance_window" {
default = "Mon:05:00-Mon:08:00"
}
# ALB #
variable "idle_timeout" {
default = 60
}
variable "deregistration_delay" {
default = 300
}
variable "healthy_threshold" {
default = 5
}
variable "unhealthy_threshold" {
default = 2
}
variable "timeout" {
default = 5
}
variable "interval" {
default = 30
}
variable "matcher" {
default = 200
}
# Route53 #
variable "registered_domain" {}
# S3 #
variable "expiration_days" {
default = 10
}
###outputファイル
terraform apply
コマンド実行時の出力内容を定義する。
# ====================
#
# Output
#
# ====================
output "domain_name" {
value = aws_route53_record.example_route53_record.name
}
output "instance_1a_private_ip" {
value = aws_instance.example_instance_1a.private_ip
}
output "instance_1c_private_ip" {
value = aws_instance.example_instance_1c.private_ip
}
output "rds_endpoint" {
value = aws_db_instance.example_db.endpoint
}
output "db_password" {
value = var.db_password
}
###configファイル
Terraformのプロバイダー及びバージョン設定を定義する。
# ====================
#
# Terraform
#
# ====================
terraform {
required_version = ">=1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.0"
}
}
}
# ====================
#
# Provider
#
# ====================
provider "aws" {
profile = var.aws_profile
region = var.aws_region
}
###user_dataファイル
EC2(Web/APサーバ)用ユーザデータの内容を記述する。
今回は例としてapacheを導入し、ホスト名が記載された静的コンテンツを表示させる。
またMySQLクライアントを導入し、RDSに接続できるようにする。
必要に応じてtomcat等も合わせて導入する。
#!/bin/bash
yum update -y
#Apacheインストール
yum install -y httpd
#Apache権限設定
usermod -a -G apache ec2-user
chown -R ec2-user:apache /var/www
chmod 2775 /var/www
find /var/www -type d -exec chmod 2775 {} \;
find /var/www -type f -exec chmod 0664 {} \;
#Apache用indexファイル書き換え
echo $(hostname) > /var/www/html/index.html
#Apache起動
systemctl enable httpd
systemctl start httpd
#mysqlクライアントインストール
yum install -y mysql
#リソース作成
###Terraform実施
$ terraform init
$ terraform plan
$ terraform apply
###ドメイン名を使用したALBへのhttpsアクセス
$ curl https://`terraform output -json | jq -r .domain_name.value` --insecure
###EC2からRDSへの接続(踏み台サーバ上で実施)
$ ssh -i ~/.ssh/web3_configuration.pem ec2-user@<instance_1a_private_ip/instance_1c_private_ip>
$ mysql -u admin -p <db_password> -h <rds_endpoint>
※対象のインスタンスはプライベートサブネットに存在するため、パプリックサブネットに踏み台サーバを別途起動し、踏み台サーバを介してssh接続する。
#感想
今回は基本的なWeb3層構成を作成してみた。
クラウドの場合、PaaSを使用する事でロードバランサーやデータベースサーバを容易に構築/冗長化する事ができ、オンプレミスと比較して手軽に構築できるのは大きなメリットであると感じた。
次回はコンテナオーケストレーション基盤構成を構築する予定である。
#GitHub
https://github.com/kuraboshi/iac/tree/main/terraform/web3_configuration
#参考文献