我们需要将企业防火墙中的一些弹性 IP 列入白名单,作为 SSH 的允许目标 IP。有没有办法使用 Terraform 配置堡垒实例并为其分配特定的弹性 IP?同样,当堡垒被摧毁时,它是否将该 EIP 返回到预置池?显然,我们不希望从我们的 AWS 账户中释放 EIP。
5 回答
现有答案已过时。由于此更改,现在可以关联现有的弹性 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 预先存在或分发给客户或用户且因此无法更改的情况下很有用。
目前,当您可以选择将弹性 IP 附加到实例或弹性网络接口时, Terraform 仅支持在创建 EIP时将弹性 IP 附加到 EC2 实例。NAT 网关当前允许您在创建 NAT 网关时将 EIP 与其关联,但这是一个稍微特殊的情况。
实例模块本身只允许对实例是否获得正常的公共 IP 地址进行布尔选择。关于允许实例与预先存在的 EIP 相关联的GitHub 问题,但在撰写本文时没有任何拉取请求来支持它。
如果只是想在公司防火墙上打开一个端口一次而不必为定期拆除的堡垒盒而触摸它,并且您愿意允许 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
,您将无法使用 Terraform 销毁该文件夹中的任何内容(包括堡垒实例本身)lifecycle
块,因为它只会在计划期间导致错误。删除块只会让您在每次销毁实例时重新销毁 EIP。
我花了一些时间解决这个问题,发现其他答案很有帮助,但不完整。
对于那些尝试使用 Terraform 重新分配 AWS 弹性 IP 的人,我们可以terraform_remote_state
使用aws_eip_association
. 让我解释。
我们应该使用两个单独的根模块,它们本身位于父文件夹中:
parent_folder
├--elasticip
| └main.tf
└--server
└main.tf
您可以使用以下代码创建弹性 IP,并将状态存储在elasticip/main.tf
本地后端,以便您可以从服务器模块访问其输出。输出变量名称不能是 '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 destroy
,terraform apply
并且新服务器将获得相同的弹性 IP。
我们不希望 EIP 从我们的 AWS 账户中解除分配。
是的,你可以阻止它。设置prevent_destroy
为真
resource "aws_eip" "bastion_eip" {
count = "${var.num_bastion}"
lifecycle {
prevent_destroy = true
}
}
关于分配的 EIP,请参考@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