允许负载平衡的自动缩放实例连接到互联网 - AWS / Terraform

Allowing load-balanced autoscaled instances to connect to the internet - AWS / Terraform

我正在使用 Terraform,但在将自动缩放的 AWS EC2 实例连接到 Internet 时遇到了棘手的问题。我可以启动一个独立的 EC2,连接起来没有任何困难,但是当我访问我使用自动缩放组创建的实例的 public IP 地址时,我得到“无法访问此站点 xxx.xx.xxx.xxx 意外关闭了连接。"

我看到的主要区别是我可以使用 EC2 指定网络接口,但我不确定这将如何与我的启动模板一起使用。我的实例启动到不同可用区的不同子网,模板如下:

provider "aws" {
  region     = "us-east-1"
  access_key = "xxxxx"
  secret_key = "xxxxx"
}

data "template_file" "testfile" {
  template = <<EOF
                #!/bin/bash
                sudo apt update -y
                sudo apt install apache2 -y
                sudo systemct1 start apache2
                sudo bash -c 'echo hello, world! > var/www/html/index.html'
                EOF
}

resource "aws_vpc" "first_vpc" {
  cidr_block = "10.0.0.0/16"
  tags = {
    Name = "prod-vpc"
  }
}

resource "aws_internet_gateway" "gw" {
  vpc_id = aws_vpc.first_vpc.id

  tags = {
    Name = "prod-igw"
  }
}

resource "aws_route_table" "prod_route_table" {
  vpc_id = aws_vpc.first_vpc.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.gw.id
  }

  route {
    ipv6_cidr_block = "::/0"
    gateway_id      = aws_internet_gateway.gw.id
  }

  tags = {
    Name = "prod-rt"
  }
}

resource "aws_subnet" "subnet_1" {
  vpc_id            = aws_vpc.first_vpc.id
  cidr_block        = "10.0.1.0/24"
  availability_zone = "us-east-1a"
  map_public_ip_on_launch = true

  tags = {
    Name = "prod-subnet-1"
    Tier = "public"
  }
}

resource "aws_subnet" "subnet_2" {
  vpc_id            = aws_vpc.first_vpc.id
  cidr_block        = "10.0.2.0/24"
  availability_zone = "us-east-1b"
  map_public_ip_on_launch = true

  tags = {
    Name = "prod-subnet-2"
    Tier = "public"
  }
}

resource "aws_subnet" "subnet_3" {
  vpc_id            = aws_vpc.first_vpc.id
  cidr_block        = "10.0.3.0/24"
  availability_zone = "us-east-1c"
  map_public_ip_on_launch = true

  tags = {
    Name = "prod-subnet-3"
    Tier = "public"
  }
}

resource "aws_route_table_association" "a" {
  subnet_id      = aws_subnet.subnet_1.id
  route_table_id = aws_route_table.prod_route_table.id
}

resource "aws_route_table_association" "b" {
  subnet_id      = aws_subnet.subnet_2.id
  route_table_id = aws_route_table.prod_route_table.id
}

resource "aws_route_table_association" "c" {
  subnet_id      = aws_subnet.subnet_3.id
  route_table_id = aws_route_table.prod_route_table.id
}

resource "aws_security_group" "allow_web" {
  name        = "allow_web"
  description = "Allow web inbound traffic"
  vpc_id      = aws_vpc.first_vpc.id

  ingress {
    description = "HTTPS from VPC"
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    description = "HTTP from VPC"
    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"]
    ipv6_cidr_blocks = ["::/0"]
  }

  tags = {
    Name = "allow_tls"
  }
}

resource "aws_launch_template" "frontend" {
  name                   = "frontend"
  image_id               = "ami-0ee02acd56a52998e"
  instance_type          = "t2.micro"
  vpc_security_group_ids = [aws_security_group.allow_web.id]

  network_interfaces {
    device_index = 0
    associate_public_ip_address = true
  }

  user_data = base64encode(data.template_file.testfile.rendered)
}

resource "aws_lb" "loadbalancer" {
  name               = "loadbalancer"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.allow_web.id]
  subnets            = [aws_subnet.subnet_1.id, aws_subnet.subnet_2.id, aws_subnet.subnet_3.id]

  tags = {
    Environment = "production"
  }
}

resource "aws_autoscaling_group" "as_group_1" {
  vpc_zone_identifier = [aws_subnet.subnet_1.id, aws_subnet.subnet_2.id, aws_subnet.subnet_3.id]
  desired_capacity    = 3
  max_size            = 5
  min_size            = 2
  target_group_arns   = [aws_lb_target_group.frontendhttp.arn]

  launch_template {
    id      = aws_launch_template.frontend.id
    version = "$Latest"
  }
}

resource "aws_lb_target_group" "frontendhttp" {
  name     = "frontendhttp"
  port     = 80
  protocol = "HTTP"
  vpc_id   = aws_vpc.first_vpc.id
}

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

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


#Test standalone instance

resource "aws_network_interface" "web_server_1" {
  subnet_id       = aws_subnet.subnet_1.id
  private_ips     = ["10.0.1.50"]
  security_groups = [aws_security_group.allow_web.id]
}

resource "aws_instance" "ubuntu-1" {
  ami               = "ami-0ee02acd56a52998e"
  instance_type     = "t2.micro"
  availability_zone = "us-east-1a" #hardcoded to ensure that subnet and instance are in same availability availability zone 

  network_interface {
    device_index         = 0
    network_interface_id = aws_network_interface.web_server_1.id
  }
  user_data = <<-EOF
                #!/bin/bash
                sudo apt update -y
                sudo apt install apache2 -y
                sudo systemct1 start apache2
                sudo bash -c 'echo hello! > var/www/html/index.html'
                EOF
  tags = {
    Name = "web-server"
  }
}

我稍微修改了您的模板(用户数据、缩进和 aws_launch_template),现在 现在可以使用了。它只能通过 HTTP 工作,因为您没有设置 HTTPS,因此不需要 HTTPS 的 SG 规则。




data "template_file" "testfile" {
  template = <<EOF
#!/bin/bash
apt update -y
apt install apache2 -y
systemct1 start apache2
echo "hello, world!" > var/www/html/index.html
EOF
}

resource "aws_vpc" "first_vpc" {
  cidr_block = "10.0.0.0/16"
  tags = {
    Name = "prod-vpc"
  }
}

resource "aws_internet_gateway" "gw" {
  vpc_id = aws_vpc.first_vpc.id

  tags = {
    Name = "prod-igw"
  }
}

resource "aws_route_table" "prod_route_table" {
  vpc_id = aws_vpc.first_vpc.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.gw.id
  }

  route {
    ipv6_cidr_block = "::/0"
    gateway_id      = aws_internet_gateway.gw.id
  }

  tags = {
    Name = "prod-rt"
  }
}

resource "aws_subnet" "subnet_1" {
  vpc_id            = aws_vpc.first_vpc.id
  cidr_block        = "10.0.1.0/24"
  availability_zone = "us-east-1a"
  map_public_ip_on_launch = true

  tags = {
    Name = "prod-subnet-1"
    Tier = "public"
  }
}

resource "aws_subnet" "subnet_2" {
  vpc_id            = aws_vpc.first_vpc.id
  cidr_block        = "10.0.2.0/24"
  availability_zone = "us-east-1b"
  map_public_ip_on_launch = true

  tags = {
    Name = "prod-subnet-2"
    Tier = "public"
  }
}

resource "aws_subnet" "subnet_3" {
  vpc_id            = aws_vpc.first_vpc.id
  cidr_block        = "10.0.3.0/24"
  availability_zone = "us-east-1c"
  map_public_ip_on_launch = true

  tags = {
    Name = "prod-subnet-3"
    Tier = "public"
  }
}

resource "aws_route_table_association" "a" {
  subnet_id      = aws_subnet.subnet_1.id
  route_table_id = aws_route_table.prod_route_table.id
}

resource "aws_route_table_association" "b" {
  subnet_id      = aws_subnet.subnet_2.id
  route_table_id = aws_route_table.prod_route_table.id
}

resource "aws_route_table_association" "c" {
  subnet_id      = aws_subnet.subnet_3.id
  route_table_id = aws_route_table.prod_route_table.id
}

resource "aws_security_group" "allow_web" {
  name        = "allow_web"
  description = "Allow web inbound traffic"
  vpc_id      = aws_vpc.first_vpc.id

  ingress {
    description = "HTTP from VPC"
    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"]
    ipv6_cidr_blocks = ["::/0"]
  }

  tags = {
    Name = "allow_http"
  }
}

resource "aws_launch_template" "frontend" {
  name                   = "frontend"
  image_id               = "ami-0ee02acd56a52998e"
  instance_type          = "t2.micro"
  vpc_security_group_ids = [aws_security_group.allow_web.id]

# DONT NEED THIS
#   network_interfaces {
#     device_index = 0
#     associate_public_ip_address = true
#   }

  user_data = base64encode(data.template_file.testfile.rendered)
}

resource "aws_lb" "loadbalancer" {
  name               = "loadbalancer"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.allow_web.id]
  subnets            = [aws_subnet.subnet_1.id, aws_subnet.subnet_2.id, aws_subnet.subnet_3.id]

  tags = {
    Environment = "production"
  }
}

resource "aws_autoscaling_group" "as_group_1" {
  vpc_zone_identifier = [aws_subnet.subnet_1.id, aws_subnet.subnet_2.id, aws_subnet.subnet_3.id]
  desired_capacity    = 3
  max_size            = 5
  min_size            = 2
  target_group_arns   = [aws_lb_target_group.frontendhttp.arn]

  launch_template {
    id      = aws_launch_template.frontend.id
    version = "$Latest"
  }
}

resource "aws_lb_target_group" "frontendhttp" {
  name     = "frontendhttp"
  port     = 80
  protocol = "HTTP"
  vpc_id   = aws_vpc.first_vpc.id
}

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

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