Solving the DevOps Infrastructure Dilemma: Enabling developer velocity with control 💡

Register for the webinar here →

Terraform

How to Use Ignore_Changes in Terraform Lifecycle

terraform ignore changes

In this article, we will run through the usage of the ignore_changes argument in Terraform, explaining what it is, and when you might want to use it with various practical examples.

We will cover:

  1. How to prevent changes in Terraform resources?
  2. When to ignore lifecycle changes in Terraform?
  3. Using Terraform ignore_changes – examples

How to prevent changes in Terraform resources?

In Terraform, you can use the ignore_changes block within a resource definition to prevent specific attributes of that resource from being considered when determining whether to update or recreate the resource. This can effectively prevent certain changes from being applied to your infrastructure.

The ignore_changes block is an argument that sits within the lifecycle meta-argument. The lifecycle block is available for all resource blocks regardless of type. Other arguments that the lifecycle meta-argument supports are create_before_destroy, prevent_destroy and replace_triggered_by.

When to ignore lifecycle changes in Terraform?

Ignoring lifecycle changes in Terraform using the ignore_changes attribute is useful in various scenarios, particularly when you want to prevent certain attributes from triggering updates or recreations of resources.

Common use cases for ignore_changes include:

  1. If a resource attribute is non-persistent or constantly changing (e.g., timestamps, IDs, dynamic values).
  2. Attributes that are immutable or rarely changed during the resource’s lifecycle can be safely ignored to avoid unintentional updates. For example, attributes like arn (Amazon Resource Name) in AWS resources typically remain constant once created. However, this is usually unnecessary and could confuse later if the arn did need to be changed.
  3. Attributes that contain metadata or auxiliary information (e.g., idcreated_atupdated_at) that do not affect the resource’s functionality can be ignored to maintain consistency without triggering updates.
  4. Terraform can automatically compute certain attributes based on other resource properties or external factors. Ignoring changes to these computed attributes ensures that Terraform does not attempt to update them, as they are managed automatically.
  5. If a resource attribute contains sensitive data (e.g., passwords, access keys), ignoring changes can help prevent accidental exposure or leakage of sensitive information in Terraform state files.
  6. In some cases, resources may be managed externally or have attributes controlled by external processes. Ignoring changes to these attributes allows Terraform to coexist with external management systems without interfering with their functionality.
  7. Tags attached to resources often contain metadata or organizational labels that do not affect resource behavior. Ignoring changes to tag attributes can help maintain consistent tagging practices without triggering unnecessary updates.

Using Terraform ignore_changes — examples

When using ignore_changes bear the following in mind:

  • The values specified in the ignore_changes block must exactly match the attribute names as defined in the resource schema.
  • ignore_changes operates at the attribute level, meaning you specify individual attributes of the resource that should be ignored during updates.
  • ignore_changes is specific to each resource block and only applies to the resource where it’s defined. You need to specify ignore_changes for each resource where you want to prevent certain attribute changes.
  • Only attributes defined by the resource type can be ignored. ignore_changes cannot be applied to itself or to any other meta-arguments.

Ignoring changes

In this example, we define an Azure virtual machine and use the lifecycle block with the ignore_changes argument to ignore changes to the network_interface_ids, storage_os_disk and computer_name attribute in the os_profile block. Terraform won’t trigger updates or recreation of the VM when only these attributes change.

resource "azurerm_virtual_machine" "example" {
  name                  = "example-vm"
  location              = "UK South"
  resource_group_name   = azurerm_resource_group.example.name
  network_interface_ids = [azurerm_network_interface.example.id]
  vm_size               = "Standard_DS1_v2"

  storage_os_disk {
    name              = "example-os-disk"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Premium_LRS"
  }

  os_profile {
    computer_name  = "examplevm"
    admin_username = "adminuser"

    admin_password = "Password1234!"  # Note: It's recommended to use secrets management for passwords
  }

  lifecycle {
    ignore_changes = [
      network_interface_ids,
      storage_os_disk,
      os_profile[0].computer_name,
    ]
  }
}

Ignoring tag changes

One of the most common use cases for using ignore_changes is to ignore any changes to the tags, as these can be added automatically by policy, by different sources or be updated using a different method other than Terraform. To do this, we can simply include the tags attribute within the ignore_changes argument.

The example below shows an Azure VNET with some tags that will be ignored by Terraform if they change.

resource "azurerm_virtual_network" "example" {
  name                = "example-vnet"
  address_space       = ["10.0.0.0/16"]
  location            = "UK South"
  resource_group_name = azurerm_resource_group.example.name

  tags = {
    Environment = "Production"
    Department  = "IT"
    Project     = "XYZ"
  }

  lifecycle {
    ignore_changes = [
      # Ignore changes to the 'tags' attribute
      tags,
    ]
  }
}

Ignoring all changes

Instead of a list, the special keyword all may be used to instruct Terraform to ignore all attributes, which means that Terraform can create and destroy the remote object but will never propose updates to it.

The below example shows an Azure storage account that has the ignore_changes attribute specified as all.

resource "azurerm_storage_account" "example" {
  name                     = "examplestorageaccount"
  resource_group_name      = azurerm_resource_group.example.name
  location                 = "East US"
  account_tier             = "Standard"
  account_replication_type = "LRS"

  # Other configuration options for the storage account...

  lifecycle {
    ignore_changes = all
  }
}

Key points

The ignore_changes argument of the lifecycle meta-argument is most useful when a resource is created with references to data that may change in the future, but should not affect said resource after its creation. This can commonly include things like timestamps, IDs, tags, and other dynamic values.

We encourage you also to explore how Spacelift makes it easy to work with Terraform. If you need any help managing your Terraform infrastructure, building more complex workflows based on Terraform, and managing AWS credentials per run, instead of using a static pair on your local machine, Spacelift is a fantastic tool for this. If you want to learn more, create a free account today or book a demo with one of our engineers.

Note: New versions of Terraform will be placed under the BUSL license, but everything created before version 1.5.x stays open-source. OpenTofu is an open-source version of Terraform that will expand on Terraform’s existing concepts and offerings. It is a viable alternative to HashiCorp’s Terraform, being forked from Terraform version 1.5.6.

Manage Terraform Better with Spacelift

Build more complex workflows based on Terraform using policy as code, programmatic configuration, context sharing, drift detection, resource visualization and many more.

Start free trial

Struggling to balance developer velocity with control?

Attend the June 25 webinar:

Solving the DevOps Infrastructure Dilemma

Register for the webinar