I'm wondering if anyone has tackled making an EC2 root volume persistent, so that one may taint the instance resource and re-apply and the instance will use that volume instead of the ami's?
My understanding from the documentation is that aws_ebs_volume and aws_ebs_volume_attachment work only with non-root volumes.
Best Answer
Terraform's
aws_instance
resource requires an AMI, and the root device is always a new volume produced from that AMI's underlying EBS snapshot. This is (as far as I know) a limitation of the underlying EC2 API.As you've seen, it's possible to attach an existing EBS volume to a running instance using
aws_ebs_volume_attachment
but there's no way to use an existing EBS volume as the root filesystem of a new instance.The official documentation on root volumes states that the closest we can come to what you want here is:
This sort of multi-step process is difficult to orchestrate using Terraform alone, since Terraform isn't able to keep track of it's position in such a process. However, a config like the following would allow you to achieve it with a bit of manual workflow when you need to replace the instance:
This config assumes that you've already manually terminated the old EC2 instance and noted its root volume EBS volume id. You then pass that volume id in via the
source_volume_id
variable and it will do the remaining steps.Each time
source_volume_id
changes Terraform should repeat this process, creating a new snapshot, AMI and instance. If you run Terraform again with the samesource_volume_id
as most recently used, it should leave everything unchanged.A weird gotcha with this semi-manual process is that it has a chicken-and-egg problem where on the first run you probably won't already have a volume to base your AMI on. In that case you'd have to initially comment out everything except the
aws_instance
resource, hard-code an AMI id to bootstrap with, and let Terraform create that initial instance. On subsequent runs you can then follow the process as described above.As noted above, Terraform is not currently well-suited for this sort of problem. Given that there's some manual steps anyway, it may work out simpler to just script this entire process using a more imperative approach e.g. using one of the AWS SDKs with your favorite programming language, though using Terraform for part of the process does at least free you from the task of keeping track of previously-used snapshot and AMI ids to ensure that they get cleaned up.