是否可以使用 Terraform 为堡垒分配特定的 AWS 弹性 IP



我们需要将企业防火墙中的一些弹性 IP 列入白名单,作为 SSH 允许的目标 IP。有没有办法使用 Terraform 配置堡垒实例并为其分配特定的弹性 IP?同样,当堡垒被摧毁时,它是否将该 EIP 返回到预配的池?显然,我们不希望从我们的 AWS 账户中取消分配 EIP。

现有的答案已经过时了。由于此更改,现在可以关联现有弹性 IP:https://github.com/hashicorp/terraform/pull/5236

文档:https://www.terraform.io/docs/providers/aws/r/eip_association.html

摘录:

aws_eip_association

提供 AWS EIP 关联作为顶级 资源,用于关联和取消弹性 IP 与 AWS 实例的关联 和网络接口。

注意:aws_eip_association在 EIP 为 预先存在或分发给客户或用户,因此不能 被改变。

目前,Terraform 仅支持在创建 EIP 时将弹性 IP 附加到 EC2 实例,您可以选择将其附加到实例或弹性网络接口。NAT 网关目前允许您在创建 NAT 网关时将 EIP 与其关联,但这是一个稍微特殊的情况。

实例

模块本身仅允许布尔选择实例是否获得正常的公有 IP 地址。GitHub 存在一个问题,即允许实例与预先存在的 EIP 关联,但在撰写本文时没有拉取请求来支持它。

如果只是想在公司防火墙上打开一个端口一次,而不必为定期拆除的堡垒盒触摸它,并且您可以允许 Terraform 为您创建和管理 EIP,那么您可以执行以下操作:

resource "aws_instance" "bastion" {
  ami           = "ami-abcdef12"
  instance_type = "t2.micro"
  tags {
    Name = "bastion"
  }
}
output "bastion_id" {
  value = "${aws_instance.bastion.id}"
}

在一个单独的文件夹中,您可以定义 EIP,还可以从堡垒主机的远程状态文件中查找输出的实例 ID,并在应用 EIP 时使用它:

resource "terraform_remote_state" "remote_state" {
  backend = "s3"
  config {
    bucket = "mybucketname"
    key    = "name_of_key_file"
  }
}
resource "aws_eip" "bastion_eip" {
  vpc      = true
  instance = "${terraform_remote_state.remote_state.output.bastion_id}"
  lifecycle {
    prevent_destroy = true
  }
}

在上面的示例中,我使用了@BMW的方法,因此您应该在任何试图破坏 EIP 的计划中出现错误,只是作为故障保险。

这至少应该允许您使用 Terraform 构建和销毁短期实例,但每次都对实例应用相同的 EIP,这样您就不必更改防火墙上的任何内容。

仅使用 Terraform 的一种稍微简单的方法是将 EIP 定义放在与堡垒实例相同的.tf文件/文件夹中,但如果您保留lifecycle配置块,您将无法使用 Terraform 销毁该文件夹中的任何内容(包括堡垒实例本身),因为它只会导致计划期间出错。删除块只会让您在每次销毁实例时重新销毁 EIP。

我花了一些时间解决这个问题,发现其他答案很有帮助,但不完整。

对于那些尝试使用 Terraform 重新分配 AWS 弹性 IP 的人,我们可以结合使用terraform_remote_stateaws_eip_association来实现。让我解释一下。

我们应该使用两个单独的根模块,它们本身位于父文件夹中:

parent_folder
├--elasticip
|   └main.tf
└--server
    └main.tf

elasticip/main.tf中,您可以使用以下代码来创建弹性 IP,并将状态存储在本地后端中,以便您可以从服务器模块访问其输出。输出变量名称不能为"id",因为这将与远程状态变量 id 冲突,并且不起作用。只需使用其他名称,例如 eip_id .

terraform {                                                                                                             
  backend "local" {                                                                                                     
    path = "../terraform-eip.tfstate"                                                                                   
  }                                                                                                                     
}                                                                                                                       
                                                                                                                    
resource "aws_eip" "main" {
  vpc = true
  lifecycle {
    prevent_destroy = true
  }
}
output "eip_id" {
  value = "${aws_eip.main.id}"
}

然后,在server/main.tf中,以下代码将创建一个服务器并将弹性 IP 与其关联。

data "terraform_remote_state" "eip" {
  backend = "local"
  config = {
    path = "../terraform-eip.tfstate"
  }
}
resource "aws_eip_association" "eip_assoc" {
  instance_id   = "${aws_instance.web.id}"
  allocation_id = "${data.terraform_remote_state.eip.eip_id}"
  #For >= 0.12
  #allocation_id = "${data.terraform_remote_state.eip.outputs.eip_id}"
}
resource "aws_instance" "web" {
  ami = "insert-your-AMI-ref"
}

完成所有这些设置后,您可以进入elasticip文件夹,运行terraform init,然后terraform apply以获取弹性 IP。然后进入server文件夹,并运行相同的两个命令以获取服务器及其关联的弹性 IP。在服务器文件夹中,您可以运行terraform destroyterraform apply,新服务器将获得相同的弹性 IP。

我们不希望从我们的 AWS 账户中取消分配 EIP。

是的,您可以阻止它。 将prevent_destroy设置为 true

resource "aws_eip" "bastion_eip" {
    count           = "${var.num_bastion}"
    lifecycle {
      prevent_destroy = true
    }
}

关于分配的弹性公网IP,请参考@ydaetskcoR的回复

如果使用自动缩放组,则可以在用户数据中执行此操作。 https://forums.aws.amazon.com/thread.jspa?threadID=52601

#!/bin/bash
 
# configure AWS
aws configure set aws_access_key_id {MY_ACCESS_KEY}
aws configure set aws_secret_access_key {MY_SECRET_KEY}
aws configure set region {MY_REGION}
 
# associate Elastic IP
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
ALLOCATION_ID={MY_EIP_ALLOC_ID}
aws ec2 associate-address --instance-id $INSTANCE_ID --allocation-id $ALLOCATION_ID --allow-reassociation

最新更新