The Terraform taint and untaint commands are important to be aware of if you are a regular user of Terraform. The Terraform Taint command allows you to manually flag a resource as tainted, which means it will be destroyed and recreated on the next terraform apply. Terraform untaint allows you to remove that tainted condition from the resource.
So, why is that useful? What are the use cases for terraform taint?
Terraform Taint Use Cases
Let’s say you had a resource to which some manual changes have occurred, which have led to a problem with the resource. You might want to have Terraform recreate the resource entirely, in which case you could taint it, forcing it to be re-deployed on the next terraform apply. Basically we are informing Terraform that there is a problem with the resource, and that we want it to be replaced.
Another terraform taint use case would be during the development of a Terraform plan. For example, if we have a large plan which creates a number of different resources, we may be happy with 80% of the plan, but are still working out the best configuration for one or two resources. Using Terraform taint, we can destroy and re-create only these in-development parts of the Terraform plan, without having to destroy and redeploy the whole thing, which can help save a lot of time!
Finally, another example where you might want to taint a resource is where Terraform has considered a resource to have deployed correctly, but there have been subsequent issues. A common example of where this might occur is when deploying a virtual machine workload using terraform, you then call upon some additional external scripts. Whilst the virtual machine may provision without issue as far as Terraform is concerned, an issue with post deployment configuration scripts may lead you to need to re-create the resource. If the virtual machine is part of a wider Terraform plan, then using terraform taint is an ideal option to only replace the virtual machine rather than re-create all the resources defined in the plan.
Terraform Taint and Untaint Example
Let’s say we have deployed a bunch of resources using Terraform, in this example, a Azure Resource Group, vNet (and subnet), and a virtual machine. After running the plan successfully, there are now a bunch of resources in the terraform state file. We can list these resources with the ‘terraform state list’ command:
$ terraform state list
azurerm_network_interface.nic
azurerm_network_security_group.nsg
azurerm_public_ip.pip
azurerm_resource_group.demo-rg
azurerm_subnet.demo-subnet
azurerm_virtual_machine_extension.ext
azurerm_virtual_network.demo-vnet
azurerm_windows_virtual_machine.vm
Amongst these resources we have a number which relate to the virtual machine deployment. These are:
azurerm_public_ip.pip
azurerm_network_interface.nic
azurerm_virtual_machine_extension.ext
azurerm_windows_virtual_machine.myvm
These are fairly typical of an Azure virtual machine workload. We have resources for a public IP address, network interface, the virtual machine, and a custom script extension which runs some post-deployment PowerShell code.
Now lets say there was a problem with running some post deployment configuration of the virtual machine and we wanted to use terraform to re-deploy the virtual machine workload. We can taint the resource using the following command:
$ terraform taint azurerm_windows_virtual_machine.myvm
Resource instance azurerm_windows_virtual_machine.myvm has been marked as tainted.
Note that terraform hasn’t done anything at this point other than mark the resource as tainted. It hasn’t made any changes to infrastructure. Now, if we run the terraform plan command:
# azurerm_windows_virtual_machine.vm is tainted, so must be replaced
-/+ resource "azurerm_windows_virtual_machine" "myvm" {
~ computer_name = "demo-mytestvm" -> (known after apply)
- encryption_at_host_enabled = false -> null
...
Plan: 2 to add, 0 to change, 2 to destroy.
The output from the terraform plan command is telling us that the azurerm_windows_virtual_machine.myvm is tainted and must be replaced. Note that 2 resources will be destroyed and re-created – this is due the the custom script extension resource which is dependent on the virtual machine resource. This is an important point – if you taint a resource that other resources in the plan are dependent upon, it will likely result in terraform wanting to replace those resources as well – use with caution, and always confirm what terraform is going to do before going ahead with an apply!
At this point, if the terraform apply command was ran then those tainted resources would be destroyed and re-created. This maybe exactly what we want to happen. However, if after reviewing the output of the terraform plan command we determine the impact of tainting the resources will not result in a desired outcome, then we can manually untaint the resource using the terraform untaint command:
$ terraform untaint azurerm_windows_virtual_machine.myvm
Resource instance azurerm_windows_virtual_machine.myvm has been successfully untainted.
Now, when running the terraform plan command we can see that terraform does not want to make any changes:
No changes. Infrastructure is up-to-date.
This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed.
Summary
Terraform taint and untaint can be used to manually force terraform to re-deploy certain resources. We have taken a look at some of the use cases where you may want to make use of the terraform taint and untaint commands, and then went through a practical example of how the commands can be used.