英文:
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添加到安全组的入站规则中。
英文:
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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论