pkaramol
pkaramol

Reputation: 19322

Assign pre-existing static (elastic) IP to EC2 instance

Assuming I have an existing Elastic IP on my AWS account.

For reasons beyond the scope of this question, this EIP is not (and cannot) be managed via Terraform.

I know want to assign this EIP (say 11.22.33.44) to an EC2 instance I create via TF

The traditional approach would to of course create both the EIP and the EC2 instance via TF

resource "aws_eip" "my_instance_eip" {
  instance = "my_instance.id"
  vpc      = true
}

resource "aws_eip_association" "my_eip_association" {
  instance_id   = "my_instance.id"
  allocation_id = "aws_eip.my_instance_eip.id"
}

Is there a way however to let EC2 know via TF that it should be assigned as EIP, 11.22.33.44 that is outside of TF lifecycle?

Upvotes: 10

Views: 2332

Answers (2)

BertC
BertC

Reputation: 2656

Following up on the previous answer, Terraform has no "public_ip" attribute anymore in aws_eip.

Therefore I've come up with a solution wich works in Terraform v1.7.4 and hashicorp/aws v5.39.0 (March-2024)

Problem description

When creating an AWS EC2 Server in Terraform, you want to be able to Destroy and Apply (recreate) that Server.

But there might be some domainnames pointing to that EC2 server in your DNS. Therefore, you want to stick to the same IP address.

You use AWS-Elastic-IP to get a fixed IP address. But since you want to be able to Terraform-Destroy your infrastructure, the Elastic IP is created outside Terraform.

That IP Address (having the AWS Tag "Name" = "MY_IP") should be associated to the EC2 server you create with Terraform.

(I'm writing this down because this business case seemed totally logical to me, but I did not find it anywhere in examples or tutorials)

Create the EIP in AWS by hand

Give it the name (Tagname = "Name") "MY_IP"

Pick it up in Terraform scripts

In your Terraform script you pick it up with the "data.aws_eip" data-resource

data "aws_eip" "my_ip" {
  filter {
    name   = "tag:Name"
    values = ["MY_IP"]
  }
}

The above code is updated code compared to the previous answer and works in the mentioned versions.

The aws_eip_association

Use the picked up IP in the aws_eip_association resource

resource "aws_eip_association" "eip_assoc" {
  instance_id   = aws_instance.this.id
  allocation_id = data.aws_eip.my_ip.id
}

Strange behaviour in Terraform Outputs

After creating the Instance, you might want to output the Public IP.

output "Instance_public_ip" {
  value = aws_instance.this.public_ip
}

You would expect that to be the same as your EIP, but this is not the case.

Getting the Public IP from the aws_instance will return the initial IP it was given before the aws_eip_association.

Get the correct Public IP from the aws_eip_association to get your Elastic IP

output "Instance_public_ip" {
  value = aws_eip_association.eip_assoc.public_ip
}

Upvotes: 1

Marcin
Marcin

Reputation: 238081

You can use aws_eip data source to get info of your existing EIP and then use that in your aws_eip_association:

data "aws_eip" "my_instance_eip" {
  public_ip = "11.22.33.44"
}

resource "aws_eip_association" "my_eip_association" {
  instance_id   = aws_instance.my_instance.id
  allocation_id = data.aws_eip.my_instance_eip.id
}

Upvotes: 6

Related Questions