英文:
Terraform: adding loadbalancer ip to ec2 instance security group
问题
我遇到了一个问题,我可以通过它们的IP地址单独访问我的两个公共子网中的两个EC2实例,但是无法通过负载均衡器访问,负载均衡器返回504错误。EC2实例和负载均衡器都使用相同的安全组,该安全组允许一个IP地址进行入站访问。
问题出在安全组上。如果在AWS控制台中将负载均衡器的IP地址添加到安全组的允许入站IP列表中,那么我就可以从负载均衡器正常访问我的实例。所以我的问题是:使用Terraform,如果我还不知道负载均衡器的IP地址,并且它是我Terraform脚本中最后创建的东西,我该如何允许负载均衡器访问这些实例?
更新:我创建资源的顺序。请注意EC2和ALB模块之间的循环依赖关系...EC2模块创建并公开安全组,ALB模块也使用该安全组。由于我的安全组具有硬编码的入站IP地址并且在ALB之前创建,我无法动态地将ALB添加到安全组的入站规则中:
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 =
}
英文:
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 =
}
答案1
得分: 3
我会使用ALB安全组的引用而不是使用IP地址范围,因为它可能会发生变化。所以代码中的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"
security_groups = [ aws_security_group.alb.id ] # 或者根据实际情况设置多个SG
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
请注意,最好使用单独的security_group_rule资源来定义入站和出站规则。
英文:
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:
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"
security_groups = [ aws_security_group.alb.id ] # or however many SGs there are
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
Note that it also might be better to use a separate security group rule resource for defining ingress and egress rules.
答案2
得分: 0
这里的解决方案是为负载均衡器创建一个安全组,该安全组限制了我所需的IP和端口。然后为我的实例创建一个单独的安全组,该安全组只接受来自ALB的端口80的连接,使用aws_security_group_rule。通过这种方式,安全组之间建立了关系,而不是实际资源ID或IP,解决了资源动态IP的鸡生蛋问题。
@marko-e:我认为你之前提到了其中一些内容,只是没有完全理解。感谢你与我一起迭代这个解决方案。
resource "aws_security_group" "ec2_security_group" {
name = "${var.name}_security_group"
vpc_id = var.vpc_id
ingress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_security_group_rule" "allow_lb_only" {
type = "ingress"
from_port = 80
to_port = 80
protocol = "tcp"
source_security_group_id = "${var.lb_security_group_id}" # 处理负载均衡器的安全组
security_group_id = "${aws_security_group.ec2_security_group.id}" # EC2实例的安全组
}
英文:
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
resource "aws_security_group" "ec2_security_group" {
name = "${var.name}_security_group"
vpc_id = var.vpc_id
ingress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_security_group_rule" "allow_lb_only" {
type = "ingress"
from_port = 80
to_port = 80
protocol = "tcp"
source_security_group_id = "${var.lb_security_group_id}" #security group that handles the load balancer
security_group_id = "${aws_security_group.ec2_security_group.id}" #ec2 instance security group
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论