Terraform:将负载均衡器 IP 添加到 EC2 实例安全组

huangapple go评论78阅读模式
英文:

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
}

huangapple
  • 本文由 发表于 2023年8月9日 14:07:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76864986-2.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定