Skip to content

How to manage second EBS volume from AMI

0

I'm using a vendor-provided AMI on the Marketplace, and it includes configs for a 50 GiB EBS root volume and a 500 GiB EBS data volume.

The way that the vendor manages their software updates is by deploying a new EC2 instance using a new AMI, detaching the data volumes from both the old and new instances, then attaching the old data volume to the new instance, to carry forward the application data. Then deleting the old instance and new (empty) 500 GiB EBS data volume.

Is there a way to manage the attaching and detaching of the data volume via Terraform?

I've tried and succeeded importing the old data volume, and volume attachment, but when I taint the instance and redeploy it via the AMI, I haven't found a way yet in Terraform to detach the new data volume before trying to reattach the old data volume to the new instance, so I get an error that the device name is already taken.

Thank you!

1 Answer
0

1. Import the Existing Data Volume and Attachment:

First, import the existing data volume and its attachment to Terraform. This is crucial to ensure Terraform manages it properly.

terraform import aws_volume_attachment.old_data_volume_attachment vol-xxxxxxxx
terraform import aws_ebs_volume.old_data_volume vol-xxxxxxxx

2. Define the Old and New Data Volumes in Terraform:

Define both the old and new data volumes in your Terraform configuration. Ensure that you create a dependency between the new instance and the detachment of the new data volume.

resource "aws_ebs_volume" "old_data_volume" {
  volume_id = "vol-xxxxxxxx"  # The existing data volume ID
}

resource "aws_volume_attachment" "attach_old_data_volume" {
  device_name = "/dev/sdf"
  volume_id   = aws_ebs_volume.old_data_volume.id
  instance_id = aws_instance.new_instance.id

  depends_on = [aws_volume_attachment.detach_new_data_volume]
}

resource "aws_volume_attachment" "detach_new_data_volume" {
  device_name = "/dev/sdf"
  volume_id   = aws_instance.new_instance.root_block_device[0].volume_id
  instance_id = aws_instance.new_instance.id

  force_detach = true
  lifecycle {
    create_before_destroy = true
  }
}

3. Lifecycle Rules for Detachment:

Use the lifecycle block to control the order of operations. Specifically, the create_before_destroy setting ensures that the detachment of the new data volume occurs before the old data volume is attached.

resource "aws_volume_attachment" "detach_new_data_volume" {
  device_name = "/dev/sdf"
  volume_id   = aws_instance.new_instance.root_block_device[0].volume_id
  instance_id = aws_instance.new_instance.id

  force_detach = true

  lifecycle {
    create_before_destroy = true
  }
}

4. Manage Instance Recreation:

Use the terraform taint command to force the recreation of the instance. Terraform will first detach the new (empty) data volume, then attach the old data volume to the new instance.

terraform taint aws_instance.new_instance
terraform apply

5. Handling Device Name Conflicts:

The depends_on block ensures that the attachment of the old data volume only occurs after the new data volume has been detached, avoiding device name conflicts.

6. Cleanup Unused Volumes:

After the new instance is up and running with the old data volume, you may want to delete the unused new data volume. This can be handled manually or by adding a null_resource or similar mechanism in Terraform.

Example Terraform Configuration

Here's a simplified version of the Terraform configuration:

resource "aws_instance" "new_instance" {
  ami           = "ami-xxxxxxxx"
  instance_type = "t3.medium"

  root_block_device {
    volume_size = 50
  }

  # Other instance configurations
}

resource "aws_ebs_volume" "old_data_volume" {
  volume_id = "vol-xxxxxxxx"  # Replace with your old data volume ID
}

resource "aws_volume_attachment" "attach_old_data_volume" {
  device_name = "/dev/sdf"
  volume_id   = aws_ebs_volume.old_data_volume.id
  instance_id = aws_instance.new_instance.id

  depends_on = [aws_volume_attachment.detach_new_data_volume]
}

resource "aws_volume_attachment" "detach_new_data_volume" {
  device_name = "/dev/sdf"
  volume_id   = aws_instance.new_instance.root_block_device[0].volume_id
  instance_id = aws_instance.new_instance.id

  force_detach = true

  lifecycle {
    create_before_destroy = true
  }
}

Useful Documents https://docs.aws.amazon.com/prescriptive-guidance/latest/backup-recovery/new-ebs-volume-backups.html

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/creating-an-ami-ebs.html

EXPERT

answered 2 years ago

EXPERT

reviewed 2 years ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.