2023-03-08 · 6

Terraform の基本的な使い方

cloudterraform

この記事は公開から2年以上経過しています。

Terraform docs : aws_lb_listener | Resources | hashicorp/aws | Terraform | Terraform Registry

VPC

vpc & endpoints

# Create VPC
resource "aws_vpc" "Web_Service_Provisioning" {
  cidr_block = "10.0.0.0/16"
  enable_dns_hostnames = true
  tags = {
    Name = "Web_Service_Provisioning"
  }
}

# VPC Endpoint for ECR
resource "aws_vpc_endpoint" "Wsp-ECR-dkr" {
  vpc_id = aws_vpc.Web_Service_Provisioning.id
  service_name = "com.amazonaws.ap-northeast-2.ecr.dkr"
  vpc_endpoint_type = "Interface"
  private_dns_enabled = true
  security_group_ids = [aws_security_group.WSP_Default_SG.id]
  subnet_ids = [aws_subnet.Private_Subnet_AZ_B.id]
  tags = {
    Name = "WSP_ECR"
  }
}

resource "aws_vpc_endpoint" "Wsp-ECR-api" {
  vpc_id = aws_vpc.Web_Service_Provisioning.id
  service_name = "com.amazonaws.ap-northeast-2.ecr.api"
  vpc_endpoint_type = "Interface"
  private_dns_enabled = true
  security_group_ids = [aws_security_group.WSP_Default_SG.id]
  subnet_ids = [aws_subnet.Private_Subnet_AZ_B.id]
  tags = {
    Name = "WSP_ECR"
  }
}

subnet

# Public Subnet-AZ-A
resource "aws_subnet" "Public_Subnet_AZ_A" {
  vpc_id = aws_vpc.Web_Service_Provisioning.id
  availability_zone = "ap-northeast-2a"
  cidr_block = "10.0.1.0/24"
  tags = {
    Name = "Public_Subnet_AZ_A"
  }
}

# Private Subent-AZ-A
resource "aws_subnet" "Private_Subnet_AZ_A" {
  vpc_id = aws_vpc.Web_Service_Provisioning.id
  availability_zone = "ap-northeast-2a"
  cidr_block = "10.0.3.0/24"
  tags = {
    Name = "Private_Subnet_AZ_A"
  }
}

IGW

resource "aws_internet_gateway" "Web_Service_Provisioning_Internet_Gateway" {
  vpc_id = aws_vpc.Web_Service_Provisioning.id
  tags = {
    Name = "WSP_Internet_Gateway"
  }
}

Nat Gateway

resource "aws_eip" "Web_Service_Provisioning_EIP" {
  vpc = true
  tags = {
    Name = "WSP_NAT_EIP"
  }
}

Route tables

resource "aws_route_table" "Web_Service_Provisioning_Public_RT" {
  vpc_id = aws_vpc.Web_Service_Provisioning.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.Web_Service_Provisioning_Internet_Gateway.id
  }
  tags = {
    Name = "Public_Route_Table"
  }
}

resource "aws_route_table" "Web_Service_Provisioning_Private_RT_AZ_A" {
  vpc_id = aws_vpc.Web_Service_Provisioning.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_nat_gateway.Web_Service_Provisioning_NAT_Gateway.id
  }
  tags = {
    Name = "Private_Route_Table_AZ_A"
  }
}

Route table association

resource "aws_route_table_association" "Public_Subnet_AZ_A" {
  subnet_id = aws_subnet.Public_Subnet_AZ_A.id
  route_table_id = aws_route_table.Web_Service_Provisioning_Public_RT.id
}

resource "aws_route_table_association" "Private_Subnet_AZ_A" {
  subnet_id = aws_subnet.Private_Subnet_AZ_A.id
  route_table_id = aws_route_table.Web_Service_Provisioning_Private_RT_AZ_A.id
}

Security Group

resource "aws_security_group" "WSP_Default_SG" {
  name = "WSP_Default_SG"
  description = "Default Security Group"
  vpc_id = aws_vpc.Web_Service_Provisioning.id
  ingress {
    from_port = 80
    to_port = 80
    protocol = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    from_port = 443
    to_port = 443
    protocol = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    from_port = 3000
    to_port = 3000
    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 = "WSP_Default_SG"
  }
}

resource "aws_security_group" "WSP_RDS_SG" {
  name = "WSP_RDS_SG"
  description = "Security Group for RDS"
  vpc_id = aws_vpc.Web_Service_Provisioning.id
  ingress {
    from_port = 3306
    to_port = 3306
    protocol = "tcp"
    security_groups = [aws_security_group.WSP_Bastion_SG.id]
  }
  ingress {
    from_port = 3306
    to_port = 3306
    protocol = "tcp"
    security_groups = [aws_security_group.WSP_Default_SG.id]
  }
  egress {
    from_port = 0
    to_port = 0
    protocol = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
  tags = {
    Name = "WSP_RDS_SG"
  }
}

IAM

resource "aws_iam_role" "WSP_Bastion_EC2_Power_User" {
  name = "WSP_Bastion_EC2_Power_User"
  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

# EC2 Instance for Bastion Host (Amazon Linux 2)
# aws iam instance profile
resource "aws_iam_instance_profile" "WSP_Bastion_EC2_Profile" {
  name = "WSP_Bastion_EC2_Profile"
  role = aws_iam_role.WSP_Bastion_EC2_Power_User.name
}

EC2

resource "aws_instance" "WSP_Bastion" {
  ami = "ami-06b9122710049dfe7"
  instance_type = "t2.micro"
  key_name = "bastion"
  vpc_security_group_ids = [aws_security_group.WSP_Bastion_SG.id]
  subnet_id = aws_subnet.Public_Subnet_AZ_A.id
  iam_instance_profile = aws_iam_instance_profile.WSP_Bastion_EC2_Profile.name
  tags = {
    Name = "WSP_Bastion"
  }
}

EIP

resource "aws_eip" "WSP_Bastion_EIP" {
  domain = "vpc"

  instance = aws_instance.WSP_Bastion.id
  tags = {
    Name = "WSP_Bastion_EIP"
  }
}

S3

resource "aws_s3_bucket" "WSP_CloudFront" {
  bucket = "wsp-cloudfront"
  acl = "private"
  tags = {
    Name = "WSP_CloudFront"
  }
}

RDS

# RDS database
# aws db subnet group
resource "aws_db_subnet_group" "wsp_rds_subnet_group" {
  name = "wsp_rds_subnet_group"
  subnet_ids = [
    aws_subnet.Private_Subnet_AZ_B.id,
    aws_subnet.Private_Subnet_AZ_C.id
  ]
  tags = {
    Name = "wsp_rds_subnet_group"
  }
}

# RDS database instance (MySQL) Priviate AZ-C (Multi AZ) (db.t2.micro) (5GB)
resource "aws_db_instance" "wsp_rds" {
  allocated_storage = 5
  engine = "mysql"
  engine_version = "5.7"
  instance_class = "db.t2.micro"
  username = "admin"
  password = "*Nabomhalangkr0512_admin"
  identifier = "wsprds"
  db_subnet_group_name = aws_db_subnet_group.wsp_rds_subnet_group.name
  vpc_security_group_ids = [aws_security_group.WSP_RDS_SG.id]
  multi_az = true
  tags = {
    Name = "wsp_rds"
  }
  skip_final_snapshot = false
  final_snapshot_identifier = "wsprdsfinalsnapshot"
}

ALB

Target Group

resource "aws_lb_target_group" "WspTG" {
  name = "WspTG"
  target_type = "ip"
  port = 3000
  protocol = "HTTP"
  vpc_id = aws_vpc.Web_Service_Provisioning.id
  health_check {
    path = "/"
    port = 3000
    protocol = "HTTP"
    matcher = "200-399"
    interval = 30
    timeout = 5
  }
  tags = {
    Name = "WspTG"
  }
}

ELB

resource "aws_lb" "WspLB" {
  name               = "WspLB"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.WSP_Default_SG.id]
  subnets            = [aws_subnet.Public_Subnet_AZ_A.id, aws_subnet.Public_Subnet_AZ_B.id]
  tags = {
    Name = "WspLB"
  }
}

ELB - Listener

resource "aws_lb_listener" "WspLBListener" {
  load_balancer_arn = aws_lb.WspLB.arn
  port              = 80
  protocol          = "HTTP"
  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.WspTG.arn
  }
}

ECR

# Create ECR Repository
resource "aws_ecr_repository" "WSP_Repository" {
  name = "wsp_repository"
  image_tag_mutability = "MUTABLE"
  image_scanning_configuration {
    scan_on_push = true
  }
  tags = {
    Name = "WSP_Repository"
  }
}

ECS

ecs cluster, capacity providers

# ECS Cluster
resource "aws_ecs_cluster" "WSP_Cluster" {
  name = "WSP_Cluster"
}

resource "aws_ecs_cluster_capacity_providers" "WSP_Cluster_Capacity_Providers" {
  cluster_name = aws_ecs_cluster.WSP_Cluster.name

  capacity_providers = ["FARGATE"]

  default_capacity_provider_strategy {
    capacity_provider = "FARGATE"
    base = 1
    weight = 100
  }
}

ecs task execution role

# ECS Task Execution Role
# Create IAM Role for ECS Execution
resource "aws_iam_role" "ecs_execution_role" {
  name = "ecs_execution_role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Action = "sts:AssumeRole",
        Principal = {
          Service = "ecs-tasks.amazonaws.com"
        },
        Effect = "Allow",
        Sid    = ""
      }
    ]
  })
}

# Attach the AmazonECSTaskExecutionRolePolicy to the execution role
resource "aws_iam_role_policy_attachment" "ecs_execution_role_attachment" {
  role       = aws_iam_role.ecs_execution_role.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}

ecs task definition

# ECS Task Definition
resource "aws_ecs_task_definition" "WSP_Task_Definition" {
  family                   = "WSP_Task_Definition"
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  execution_role_arn = aws_iam_role.ecs_execution_role.arn
  cpu = 256
  memory = 512
  container_definitions = jsonencode([
    {
      name  = "WSP_Task_Definition"
      image = "${aws_ecr_repository.WSP_Repository.repository_url}:latest"
      essesntial = true
      portMappings = [
        {
          containerPort = 3000
          hostPort      = 3000
        }
      ]
    }
  ])
}

ECS Service

# ECS Service
resource "aws_ecs_service" "WSP_Service" {
  name            = "WSP_Service"
  cluster         = aws_ecs_cluster.WSP_Cluster.id
  task_definition = aws_ecs_task_definition.WSP_Task_Definition.arn
  desired_count   = 1
  launch_type     = "FARGATE"
  network_configuration {
    subnets = [
      aws_subnet.Private_Subnet_AZ_A.id,
      aws_subnet.Private_Subnet_AZ_B.id
    ]
    security_groups = [aws_security_group.WSP_Default_SG.id]
    assign_public_ip = false
  }
  load_balancer {
    target_group_arn = aws_lb_target_group.WspTG.arn
    container_name   = "WSP_Task_Definition"
    container_port   = 3000
  }
}

CloudWatch

# CloudWatch metric alarm for RDS CPU Utilization
resource "aws_cloudwatch_metric_alarm" "WSP_RDS_CPU_Utilization" {
  alarm_name          = "example"
  comparison_operator = "GreaterThanOrEqualToThreshold"
  evaluation_periods  = "2"
  metric_name         = "CPUUtilization"
  namespace           = "AWS/EC2"
  period              = "60"
  statistic           = "Average"
  threshold           = "80"
  alarm_description   = "This metric checks ec2 cpu utilization"
  alarm_actions       = []
}

原文(韓国語): tistory — 2023-03-08 公開、当ブログへ移行。この翻訳は AI の協力で作成されました。

コメント

コメントを削除しますか?

関連記事

Terraform の基本的な使い方 · 나봄하랑