I am trying to launch an elastic beanstalk apllication inisde a VPC but I am getting the following error:
aborted operation. Current state: 'CREATE_FAILED' Reason: The following resource(s) failed to create: [AWSEBInstanceLaunchWaitCondition].
The EC2 instances failed to communicate with AWS Elastic Beanstalk, either because of configuration problems with the VPC or a failed EC2 instance. Check your VPC configuration and try launching the environment again
I've tried to debug my terraform config below but can't identify the issue
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"
}
}
Please try to add this into your
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"
}
}