VPC 内的 Elastic Beanstalk 使用 terraform 失败

问题描述 投票:0回答:1

我正在尝试在 VPC 中启动弹性 beanstalk 应用程序,但出现以下错误:

操作中止。当前状态:“CREATE_FAILED”原因:无法创建以下资源:[AWSEBInstanceLaunchWaitCondition]。

EC2 实例无法与 AWS Elastic Beanstalk 通信,原因可能是 VPC 配置问题或 EC2 实例出现故障。检查您的 VPC 配置并尝试再次启动环境

我尝试调试下面的 terraform 配置,但无法识别问题

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.16"
    }
  }

  required_version = ">= 1.2.0"
}

# Configure AWS provider
provider "aws" {
  region = "us-west-2"
}

# Create VPC
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"

  tags = {
    Name = "testapp"
  }
}

# Create private subnet for database
resource "aws_subnet" "private" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.1.0/24"
  availability_zone = "us-west-2b"

  tags = {
    Name = "Private Subnet"
  }
}

resource "aws_subnet" "private_2" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.3.0/24"
  availability_zone = "us-west-2a"

  tags = {
    Name = "Private Subnet 2"
  }
}

# Create Internet Gateway and attach it to VPC
resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "Main IGW"
  }
}

# Create Elastic IP for NAT Gateway
resource "aws_eip" "nat" {
  vpc = true
}

# Create NAT Gateway in public subnet
resource "aws_nat_gateway" "main" {
  allocation_id = aws_eip.nat.id
  subnet_id     = aws_subnet.public.id

  tags = {
    Name = "Main NAT"
  }
}

# Create public subnet for Elastic Beanstalk
resource "aws_subnet" "public" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.2.0/24"
  availability_zone = "us-west-2a"

  tags = {
    Name = "Public Subnet"
  }
}

resource "aws_subnet" "public_2" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.4.0/24"
  availability_zone = "us-west-2b"

  tags = {
    Name = "Public Subnet 2"
  }
}

# Create route table and add public route
resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id

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

  tags = {
    Name = "Public Route Table"
  }
}

# Associate public route table with public subnet
resource "aws_route_table_association" "public" {
  subnet_id      = aws_subnet.public.id
  route_table_id = aws_route_table.public.id
}

resource "aws_route_table_association" "public_2" {
  subnet_id      = aws_subnet.public_2.id
  route_table_id = aws_route_table.public.id

}

# Create route table for private subnet and add route through NAT gateway
resource "aws_route_table" "private" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block     = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.main.id
  }

  tags = {
    Name = "Private Route Table"
  }
}

# Associate private route table with private subnet
resource "aws_route_table_association" "private" {
  subnet_id      = aws_subnet.private.id
  route_table_id = aws_route_table.private.id
}

resource "aws_route_table_association" "private_2" {
  subnet_id      = aws_subnet.private_2.id
  route_table_id = aws_route_table.private.id
}

# Create security group for Elastic Beanstalk 
resource "aws_security_group" "beanstalk" {
  name   = "beanstalk_sg"
  vpc_id = aws_vpc.main.id

  # Allow HTTP access from anywhere
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  # Allow HTTPS access from anywhere
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  # Allow access from other security groups
  ingress {
    from_port       = 0
    to_port         = 0
    protocol        = "-1"
    security_groups = [aws_security_group.bastion.id]
  }

  #Allow outbound internet access
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

# Create security group for bastion host
resource "aws_security_group" "bastion" {
  name   = "bastion_sg"
  vpc_id = aws_vpc.main.id

  # Allow SSH access from anywhere
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  # Allow outbound internet access
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

# Create RDS PostgreSQL database
resource "aws_db_instance" "postgres" {
  allocated_storage      = 20
  storage_type           = "gp2"
  engine                 = "postgres"
  engine_version         = "15.3"
  instance_class         = "db.t3.micro"
  db_name                = "testapp"
  username               = "testappadmin"
  password               = var.db_password
  db_subnet_group_name   = aws_db_subnet_group.private.name
  vpc_security_group_ids = [aws_security_group.rds.id]

  skip_final_snapshot = true
}

# Create DB subnet group
resource "aws_db_subnet_group" "private" {
  name       = "private"
  subnet_ids = [aws_subnet.private.id, aws_subnet.private_2.id]
}

# Create security group for RDS
resource "aws_security_group" "rds" {
  name   = "rds_sg"
  vpc_id = aws_vpc.main.id

  # Allow access from EB security group
  ingress {
    from_port       = 5432
    to_port         = 5432
    protocol        = "tcp"
    security_groups = [aws_security_group.beanstalk.id]
  }
}



# Create S3 bucket for static files
resource "aws_s3_bucket" "static" {

  bucket = "testapp-static-files"

  tags = {
    Name = "testapp Static Files"
  }
}

resource "aws_s3_bucket_ownership_controls" "name" {

  bucket = aws_s3_bucket.static.id

  rule {
    object_ownership = "BucketOwnerPreferred"
  }

}

resource "aws_s3_bucket_public_access_block" "static" {
  bucket = aws_s3_bucket.static.id

  block_public_policy = false

}

resource "aws_s3_bucket_policy" "static" {
  bucket = aws_s3_bucket.static.bucket

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid       = "PublicReadGetObject"
        Effect    = "Allow"
        Principal = "*"
        Action    = ["s3:GetObject"]
        Resource = [
          "arn:aws:s3:::testapp-static-files/*",
          "arn:aws:s3:::testapp-static-files"
        ]
      }
    ]
  })

}



#Create S3 user
resource "aws_iam_user" "s3_user" {
  name = "s3-uploader"
}

resource "aws_iam_user_policy" "s3_policy" {
  name = "s3-access"
  user = aws_iam_user.s3_user.name

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = [
          "s3:*",
        ]
        Effect = "Allow"
        Resource = [
          "${aws_s3_bucket.static.arn}/*",
          "${aws_s3_bucket.static.arn}"

        ]
      },
    ]
  })
}



resource "aws_iam_access_key" "s3_user" {
  user = aws_iam_user.s3_user.name
}



# Chroma EC2 instance
resource "aws_instance" "chroma" {
  ami           = "ami-002829755fa238bfa" # Amazon Linux 2
  instance_type = "t3.micro"

  subnet_id              = aws_subnet.private.id
  vpc_security_group_ids = [aws_security_group.chroma.id]

  tags = {
    Name = "Chroma"
  }
}

# Security group for Chroma
resource "aws_security_group" "chroma" {
  name   = "chroma_sg"
  vpc_id = aws_vpc.main.id

  ingress {
    from_port   = 8000
    to_port     = 8000
    protocol    = "tcp"
    cidr_blocks = [aws_subnet.private.cidr_block]
  }
}



# Create Elastic Beanstalk application
resource "aws_elastic_beanstalk_application" "app" {
  name        = "testapp"
  description = "testapp Django application"
}



# Create production environment
resource "aws_elastic_beanstalk_environment" "prod" {
  name                = "testapp-prod"
  application         = aws_elastic_beanstalk_application.app.name
  solution_stack_name = "64bit Amazon Linux 2023 v4.0.3 running Python 3.9"

  setting {
    namespace = "aws:ec2:vpc"
    name      = "VPCId"
    value     = aws_vpc.main.id
  }

  setting {
    namespace = "aws:ec2:vpc"
    name      = "Subnets"
    value     = "${aws_subnet.public.id},${aws_subnet.public_2.id}"
  }

  setting {
    namespace = "aws:ec2:vpc"
    name      = "ELBSubnets"
    value     = "${aws_subnet.public.id},${aws_subnet.public_2.id}"
  }


  setting {
    namespace = "aws:autoscaling:launchconfiguration"
    name      = "SecurityGroups"
    value     = aws_security_group.beanstalk.id
  }

  setting {
    namespace = "aws:autoscaling:launchconfiguration"
    name      = "IamInstanceProfile"
    value     = "aws-elasticbeanstalk-ec2-role"

  }

  setting {
    namespace = "aws:autoscaling:launchconfiguration"
    name      = "InstanceType"
    value     = "t2.medium"
  }

  setting {
    namespace = "aws:elasticbeanstalk:application"
    name      = "Application Healthcheck URL"
    value     = "/health"
  }


  setting {
    namespace = "aws:elasticbeanstalk:environment"
    name      = "LoadBalancerType"
    value     = "application"
  }


  setting {
    namespace = "aws:elasticbeanstalk:environment:process:default"
    name      = "MatcherHTTPCode"
    value     = "200"
  }


  setting {
    namespace = "aws:elasticbeanstalk:application:environment"
    name      = "DATABASE_URL"
    value     = "postgres://${aws_db_instance.postgres.username}:${var.db_password}@${aws_db_instance.postgres.endpoint}/${aws_db_instance.postgres.db_name}"
  }

  setting {
    namespace = "aws:elasticbeanstalk:application:environment"
    name      = "DJANGO_SECRET_KEY"
    value     = var.django_secret_key
  }

  setting {
    namespace = "aws:elasticbeanstalk:application:environment"
    name      = "STATIC_BUCKET"
    value     = aws_s3_bucket.static.bucket
  }


  setting {
    namespace = "aws:elasticbeanstalk:application:environment"
    name      = "CHROMA_DB_URL"
    value     = "http://${aws_instance.chroma.private_ip}:8000"
  }


  setting {
    namespace = "aws:elasticbeanstalk:application:environment"
    name      = "AWS_ACCESS_KEY_ID"
    value     = aws_iam_access_key.s3_user.id
  }

  setting {
    namespace = "aws:elasticbeanstalk:application:environment"
    name      = "AWS_SECRET_ACCESS_KEY"
    value     = aws_iam_access_key.s3_user.secret
  }

  setting {
    namespace = "aws:elasticbeanstalk:application:environment"
    name      = "AWS_STORAGE_BUCKET_NAME"
    value     = aws_s3_bucket.static.id
  }

  tags = {
    Environment = "Production"
  }
}



amazon-web-services terraform amazon-elastic-beanstalk amazon-vpc
1个回答
0
投票

请尝试将其添加到您的

resource "aws_elastic_beanstalk_environment" "prod" {
  name                = "testapp-prod"
  application         = aws_elastic_beanstalk_application.app.name
  solution_stack_name = "64bit Amazon Linux 2023 v4.0.3 running Python 3.9"

  setting {
    namespace = "aws:ec2:vpc"
    name      = "AssociatePublicIpAddress"
    value     =  "True"
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.