Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
10
Help us understand the problem. What is going on with this article?
@sicksixrock66

TerraformでELBとEC2とRDSのよくありそうなWebパターンを作ってみる。

More than 1 year has passed since last update.

よくありそうなこういうアーキテクチャをTerraformで練習がてら作ってみました。
変数もモジュールも考慮せず書いています。
(ALBにDNS名でアクセスするとラウンドロビンアクセスされること、
EC2からRDSに接続できることは確認していますが、セキュリティ上穴があるかもしれません。)

プレゼンテーション1.jpg

ディレクトリ構造

work/
├── alb.tf
├── ec2.tf
├── rds.tf
└── vpc.tf

Terraformの実行環境は以下の通り

$ terraform --version
Terraform v0.12.16
+ provider.aws v2.47.0

vpc.tf

##########################################################
///VPCの定義
##########################################################
resource "aws_vpc" "example" {
    cidr_block = "10.0.0.0/16"
    instance_tenancy = "default" #ハードウェア占有インスタンスを立てるかどうか
    enable_dns_hostnames = true
    enable_dns_support   = true
}
##########################################################
///パブリックサブネットの定義(マルチAZ),ALBを配置する
##########################################################
resource "aws_subnet" "public_a" {
    vpc_id                  = aws_vpc.example.id
    cidr_block              = "10.0.1.0/24"
    map_public_ip_on_launch = true   #サブネットで起動したインスタンスにパブリックIPを許可する
    availability_zone       = "ap-northeast-1a"
}

resource "aws_subnet" "public_c" {
    vpc_id                  = aws_vpc.example.id
    cidr_block              = "10.0.2.0/24"
    map_public_ip_on_launch = true
    availability_zone       = "ap-northeast-1c"
}

##########################################################
///パブリックサブネットの定義(マルチAZ),EC2(webサーバを配置する)
##########################################################
resource "aws_subnet" "public_a_web" {
    vpc_id                  = aws_vpc.example.id
    cidr_block              = "10.0.3.0/24"
    map_public_ip_on_launch = true
    availability_zone       = "ap-northeast-1a"
}

resource "aws_subnet" "public_c_web" {
    vpc_id                  = aws_vpc.example.id
    cidr_block              = "10.0.4.0/24"
    map_public_ip_on_launch = true
    availability_zone       = "ap-northeast-1c"
}
##########################################################
///インターネットゲートウェイの定義
##########################################################
resource "aws_internet_gateway" "example" {
    vpc_id                  = aws_vpc.example.id
}
##########################################################
///パブリックルートテーブルの定義
##########################################################
resource "aws_route_table" "public" {
    vpc_id = aws_vpc.example.id
}
##########################################################
///パブリックルートの定義(IGWに接続する)
##########################################################
resource "aws_route" "public" {
    route_table_id = aws_route_table.public.id
    gateway_id     = aws_internet_gateway.example.id
    destination_cidr_block = "0.0.0.0/0" 
}
##########################################################
///パブリックルートテーブルと関連付け
##########################################################
resource "aws_route_table_association" "public_a" {
    subnet_id      = aws_subnet.public_a.id
    route_table_id = aws_route_table.public.id
}
resource "aws_route_table_association" "public_c" {
    subnet_id      = aws_subnet.public_c.id
    route_table_id = aws_route_table.public.id
}
resource "aws_route_table_association" "public_a_web" {
    subnet_id      = aws_subnet.public_a_web.id
    route_table_id = aws_route_table.public.id
}
resource "aws_route_table_association" "public_c_web" {
    subnet_id      = aws_subnet.public_c_web.id
    route_table_id = aws_route_table.public.id
}
##########################################################
///プライベートサブネットの定義(マルチAZ),RDSを配置する
##########################################################
resource "aws_subnet" "private_a" {
    vpc_id                  = aws_vpc.example.id
    cidr_block              = "10.0.5.0/24"
    map_public_ip_on_launch = false   #サブネットで起動したインスタンスにパブリックIPを許可する
    availability_zone       = "ap-northeast-1a"
}

resource "aws_subnet" "private_c" {
    vpc_id                  = aws_vpc.example.id
    cidr_block              = "10.0.6.0/24"
    map_public_ip_on_launch = false
    availability_zone       = "ap-northeast-1c"
}

ec2.tf

##########################################################
///EC2
##########################################################

///publicサブネットaに配置

resource "aws_instance" "a" {
  ami                    ="ami-0c3fd0f5d33134a76"
  vpc_security_group_ids =[aws_security_group.for_webserver_ec2.id]
  instance_type          ="t2.micro"
  subnet_id              = aws_subnet.public_a_web.id
  user_data = <<EOF
  #!/bin/bash
  yum install -y httpd
  yum install -y mysql
  systemctl start httpd
  systemctl enable httpd
  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 {} \;
  echo `hostname` > /var/www/html/index.html
  EOF
}

///publicサブネットcに配置

resource "aws_instance" "c" {
  ami                    ="ami-0c3fd0f5d33134a76"
  vpc_security_group_ids =[aws_security_group.for_webserver_ec2.id]
  instance_type          ="t2.micro"
  subnet_id              = aws_subnet.public_c_web.id
  user_data = <<EOF
  #!/bin/bash
  yum update -y
  yum install -y httpd
  yum install -y mysql
  systemctl start httpd
  systemctl enable httpd
  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 {} \;
  echo `hostname` > /var/www/html/index.html
  EOF
}
##########################################################
///EC2用のSG
##########################################################

resource "aws_security_group" "for_webserver_ec2" {
    name ="for-ec2"
    vpc_id= aws_vpc.example.id
    ingress{
        from_port = 80
        to_port   = 80
        protocol  = "tcp"
        security_groups =[aws_security_group.alb.id]
    }
   egress{
       from_port  = 0
       to_port    = 0
       protocol   = "-1"
       cidr_blocks=["0.0.0.0/0"]
   }
}

alb.tf

##########################################################
///ALBの定義
##########################################################
resource "aws_lb" "for_webserver" {
  name               = "webserver-alb"
  internal           = false             #falseを指定するとインターネット向け,trueを指定すると内部向け
  load_balancer_type = "application"

  security_groups    = [
    aws_security_group.alb.id
  ]

  subnets            = [
      aws_subnet.public_a.id,
      aws_subnet.public_c.id,
  ]
}
##########################################################
///ALBに付与するセキュリティグループの定義
##########################################################

resource "aws_security_group" "alb" {
    name ="alb"
    vpc_id= aws_vpc.example.id
    ingress{
        from_port = 80
        to_port   = 80
        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"]
   }
}
##########################################################
///ALBのリスナーの定義
##########################################################

resource "aws_lb_listener" "for_webserver" {
  load_balancer_arn = aws_lb.for_webserver.arn
  port              = "80"
  protocol          = "HTTP"

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.for_webserver.arn
  }

}

///リスナールールの定義

resource "aws_lb_listener_rule" "forward" {
  listener_arn = aws_lb_listener.for_webserver.arn
  priority     = 99

  action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.for_webserver.arn
  }

  condition {
      path_pattern{
        values = ["/*"]
      }
  }
}


##########################################################
///ALBのターゲットグループの定義
##########################################################
resource "aws_lb_target_group" "for_webserver" {
  name        = "for-webserver-lb-tg"
  port        = 80
  protocol    = "HTTP"
  vpc_id      = aws_vpc.example.id

  health_check {
        path        = "/index.html"
  }
}

///ターゲットグループをインスタンスに紐づける

resource "aws_lb_target_group_attachment" "for_webserver_a" {
  target_group_arn = aws_lb_target_group.for_webserver.arn
  target_id        = aws_instance.a.id
  port             = 80
}

resource "aws_lb_target_group_attachment" "for_webserver_c" {
  target_group_arn = aws_lb_target_group.for_webserver.arn
  target_id        = aws_instance.c.id
  port             = 80
}

rds.tf

##########################################################
///RDSの定義
##########################################################
resource "aws_db_instance" "default" {
  allocated_storage      = 20
  storage_type           = "gp2"
  engine                 = "mysql"
  engine_version         = "5.7"
  instance_class         = "db.t2.micro"
  name                   = "mydb"
  username               = "foo"
  password               = "foobarbaz"
  parameter_group_name   = "default.mysql5.7"
  multi_az               = true
  db_subnet_group_name   = aws_db_subnet_group.dbsubnet.name
  skip_final_snapshot    = true
  vpc_security_group_ids = [aws_security_group.for_rds.id]
}
##########################################################
///DBサブネットグループの定義
##########################################################
resource "aws_db_subnet_group" "dbsubnet" {
  name       = "main"
  subnet_ids = [aws_subnet.private_a.id, aws_subnet.private_c.id]

  tags = {
    Name = "My DB subnet group"
  }
}
##########################################################
///RDS用のSG
##########################################################

resource "aws_security_group" "for_rds" {
    name ="for-rds"
    vpc_id= aws_vpc.example.id
    ingress{
        from_port = 3306
        to_port   = 3306
        protocol  = "tcp"
        cidr_blocks = [aws_vpc.example.cidr_block]
    }
   egress{
       from_port  = 0
       to_port    = 0
       protocol   = "-1"
       cidr_blocks = ["0.0.0.0/0"]
   }
}

改善点

変数化・モジュール化
AMI作成

ALBをパブリックサブネット、EC2をプライベートサブネットに配置するようにする
→作成しようとしたらunhealthyでBadGatewayになってしまったので要検証

参考にさせていただいた書籍・ページ

実践Terraform AWSにおけるシステム設計とベストプラクティス
https://dx.nissho-ele.co.jp/blog/aws-beginner-ec2-elb_20190410.html
https://www.terraform.io/

10
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
sicksixrock66
AWSを理解したいインフラエンジニア

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
10
Help us understand the problem. What is going on with this article?