Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use ebs_block_device?

I want to create an EC2 instance with Terraform. This instance should have some EBS.

In the documentation I read that Terraform provides two ways to create an EBS:

  • ebs_block_device
  • aws_ebs_volume with aws_volume_attachment

I want to know, when should I use ebs_block_device?

Documentation

Unfortunately the documentation isn't that clear (at least for me) about:

  • When to use ebs_block_device?
  • How is the exact actual behavior?

See Resource: aws_instance:

ebs_block_device - (Optional) One or more configuration blocks with additional EBS block devices to attach to the instance. Block device configurations only apply on resource creation. See Block Devices below for details on attributes and drift detection. When accessing this as an attribute reference, it is a set of objects.

and

Currently, changes to the ebs_block_device configuration of existing resources cannot be automatically detected by Terraform. To manage changes and attachments of an EBS block to an instance, use the aws_ebs_volume and aws_volume_attachment resources instead. If you use ebs_block_device on an aws_instance, Terraform will assume management over the full set of non-root EBS block devices for the instance, treating additional block devices as drift. For this reason, ebs_block_device cannot be mixed with external aws_ebs_volume and aws_volume_attachment resources for a given instance.

Research

I read:

  • No change when modifying aws_instance.ebs_block_device.volume_size, which says that Terraform doesn't show any changes with plan/apply and doesn't change anything in AWS, although changes were made..
  • AWS "ebs_block_device.0.volume_id": this field cannot be set, which says that Terraform shows an error while running plan.
  • Ebs_block_device forcing replacement every terraform apply, which says that Terraform replaces all EBS.
  • aws_instance dynamic ebs_block_device forces replacement, which says that Terraform replaces all EBS, although no changes were made.
  • adding ebs_block_device to existing aws_instance forces unneccessary replacement, which says that Terraform replaces the whole EC2 instance with all EBS.
  • aws_instance dynamic ebs_block_device forces replacement, which says that Terraform replaces the whole EC2 instance with all EBS, although no changes were made.

I know that the issues are about different versions of Terraform and Terraform AWS provider and some issues are already fixed, but what is the actual intended behavoir?

In almost all issues the workaround/recommendation is to use aws_ebs_volume with aws_volume_attachment instead of ebs_block_device.

Question

When should I use ebs_block_device? What is the use case for this feature?

like image 949
dur Avatar asked Jul 21 '26 22:07

dur


1 Answers

I strongly suggest using only resource aws_ebs_volume. When creating an instance, the root block will be created automatically. For extra EBS storage, you will want Terraform to manage them independently. Why?

Basically you have 2 choices to create an instance with 1 extra disk:

resource "aws_instance" "instance" {
  ami                  = "ami-xxxx"
  instance_type        = "t4g.micro"
  #... other arguments ...

  ebs_block_device {
    volume_size = 10
    volume_type = "gp3"
    #... other arguments ...
  }
}

OR

resource "aws_instance" "instance" {
  ami                  = "ami-xxxx"
  instance_type        = "t4g.micro"
  #... other arguments ...
}

resource "aws_ebs_volume" "volume" {
  size = 10
  type = "gp3"
}

resource "aws_volume_attachment" "attachment" {
  volume_id   = aws_ebs_volume.volume.id
  instance_id = aws_instance.instance.id
  device_name = "/dev/sdb"
}

The first method is more compact, creates fewer Terraform resource and makes terraform import easier. But if you need to recreate your instance what will happen? Terraform will remove the instance, and redeploy it from scratch with new volumes. If you use the argument delete_on_termination to false, the volumes will still exist but they won't be attached to your instance.

In the contrary, when using a dedicated resource, the instance recreation will recreate the attachements (because the instance id changes) and then, reattach your existing volumes to your instance, which is what we need 90% of the time.

Also, if at some point you need to manipulate your volume in the Terraform state (terraform state commands), it will be much easier to do it on the individual resource aws_ebs_volume.

Finally, at some point in your Terraform journey, you will want to industrialize your code by adding loops, variables and so on. A common use case is to make the number of volumes variables: you provide a list of volumes and Terraform create 1, 2 or 10 volumes according to this list. And for this you have also have 2 options :

variable "my_volume" { map(any) }
my_volume = {
  "/dev/sdb": {
    "size": 10
    "type": "gp3"
  }
}

resource "aws_instance" "instance" {
  ami                  = "ami-xxxx"
  instance_type        = "t4g.micro"
  #... other arguments ...

  dynamic "ebs_block_device" {
    for_each = var.my_volumes
    content {
      volume_size = ebs_block_device.value["size"]
      volume_type = ebs_block_device.value["type"]
      #... other arguments ...
    }
  }
}

OR

resource "aws_instance" "instance" {
  ami                  = "ami-xxxx"
  instance_type        = "t4g.micro"
  #... other arguments ...
}

resource "aws_ebs_volume" "volume" {
  for_each = var.
  size = 10
  type = "gp3"
}

resource "aws_volume_attachment" "attachment" {
  volume_id   = aws_ebs_volume.volume.id
  instance_id = aws_instance.instance.id
  device_name = "/dev/sdb"
}
like image 191
SamRoch08 Avatar answered Jul 26 '26 06:07

SamRoch08



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!