Terraform: Change EC2 user_data without recreating instance

1 minute read

When you have set up your infrastructure with Terraform and then do any change to the user_data of a EC2 instance, Terraform will detect the change and generally do a force-replacement of the instance. In the planning stage this could look something like this:

  # aws_instance.web_backend must be replaced
-/+ resource "aws_instance" "web_backend" {
      [...]
      ~ user_data                            = "1c4e236bd5dec74fecc99d3a3d57679b9b12a927" -> "f8d9add08d4ead74d44af35452c6070dbfcb1576" # forces replacement
      + user_data_base64                     = (known after apply)
      [...]

So what can you do when you want to make changes to user_data but don’t want to destroy your instance and create a new one?

For this case there is a lifecycle meta-argument in which you can customize certain resource behaviours.

The argument we are looking for is ignore_changes. You can declare this to tell Terraform to ignore changes to certain attributes of a resource that occur after its creation.

The user_data of a EC2 instance is just an example here – you may use it for any other data as well. But sticking with this example, let’s see how our modified EC2 instance could look like:

resource "aws_instance" "web_backend" {
  [...]
  user_data = local.ec2_user_data

  # don't force-recreate instance if only user data changes
  lifecycle {
    ignore_changes = [user_data]
  }
}

Making changes to user_data and then running terraform plan again, you will see that Terraform won’t pick up the change and thus won’t tell you that the resource must be replaced.

Like to comment? Feel free to send me an email or reach out on Twitter.

Did this or another article help you? If you like and can afford it, you can buy me a coffee (3 EUR) ☕️ to support me in writing more posts. In case you would like to contribute more or I helped you directly via email or coding/troubleshooting session, you can opt to give a higher amount through the following links or adjust the quantity: 50 EUR, 100 EUR, 500 EUR. All links redirect to Stripe.