Im facing a problem where i can access my two ec2 instances from the public subnet just fine individually by their IPs, but not from behind the loadbalancer, where i get a 504. Both the ec2 instances and the loadbalancer use the same security group – which allow a single ip on for ingress
resource "aws_security_group" "security_group" {
name = "${var.name}_security_group"
vpc_id = var.vpc_id
ingress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = var.sg_allowable_ips #for now this is a list of a single IP
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_instance" "instance" {
for_each = var.instance_specs
instance_type = each.value.instance_type
ami = each.value.ami
key_name = aws_key_pair.auth_key.id
vpc_security_group_ids = [aws_security_group.security_group.id]
subnet_id = var.subnets[each.value.subnet_key].id
}
The issue is that security group. If in AWS console i add the loadbalancer ip to the security group’s allowable ingress ips, im then able to get to my instances from the loadbalancer just fine.
So my question is: using terraform, how can i allow the loadbalancer to access these instances if i dont yet know it’s ip and it is the last thing created in my terraform script?
UPDATE:: the order of how im creating the resources. notice the circular dependency between ec2 and alb modules…the ec2 module create and exposes the security group, which alb also uses. given that my security group has a hardcoded ingress ip and is created before the alb, i have no opportunity to dynamically add the alb to the security group ingress:
module "vpc" {
source = "./modules/vpc"
name_prefix = var.name_prefix
tags = var.tags
vpc_cidr = var.vpc_cidr
public_subnets = var.public_subnets
private_subnets = var.private_subnets
}
module "ec2" {
source = "./modules/ec2"
name_prefix = var.name_prefix
tags = var.tags
dev_host_os = var.dev_host_os
vpc_id = module.vpc.vpc_id
auth_key_file = var.auth_key_file
subnets = module.vpc.public_subnets
instance_specs = local.instance_specs
sg_allowable_ips = var.sg_allowable_ips
}
module "alb" {
source = "./modules/alb"
name_prefix = var.name_prefix
tags = var.tags
security_group_ids = module.ec2.security_group_ids
subnet_ids = values(module.vpc.public_subnets)[*].id
vpc_id = module.vpc.vpc_id
instances = module.ec2.instances
#alb_certificate_arn =
}
2
Answers
the solution here was to create a security group for the load balancer which restricts the ip and port however i desire. Then create a separate security group for my instances which accept only port 80 from the alb using an aws_security_group_rule. in this way the relationship is setup among security groups, not actual resource ids or ips - resolving the chicken and egg issues with resource's dynamic ips.
@marko-e: i think some of this you were alluding to, it just wasnt clicking together. i thank you for iterating over this solution w/ me
What I would do is use the reference to the ALB security group instead of using the IP address range, since it can change. So that would mean changing the
ingress
part of the code to look something like:Note that it also might be better to use a separate security group rule resource for defining ingress and egress rules.