Forcefully replace a terraform resource / terraform taint

3 min read | by Jordi Prats

With terraform taint we are telling terraform that a particular object has become degraded so it will propose to replace it in the next plan. This command is going to be deprecated on terraform v1.0 since now we have the -replace flag on the apply command

$ terraform taint kubernetes_namespace.pet2cattle_namespace
Acquiring state lock. This may take a few moments...
Resource instance kubernetes_namespace.pet2cattle_namespace has been marked as tainted.
Releasing state lock. This may take a few moments...

Once the resource have been tainted, on the next plan we will be able to see how it's going to get replaced:

$ terraform plan
Acquiring state lock. This may take a few moments...
aws_s3_bucket.s3_bucket: Refreshing state... [id=pet2cattle-dev]
kubernetes_namespace.pet2cattle_namespace: Refreshing state... [id=pet2cattle]
aws_s3_bucket_policy.bucket_policy: Refreshing state... [id=pet2cattle-dev]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # kubernetes_namespace.pet2cattle_namespace is tainted, so must be replaced
-/+ resource "kubernetes_namespace" "pet2cattle_namespace" {
      ~ id = "pet2cattle" -> (known after apply)

      ~ metadata {
          - annotations      = {} -> null
          ~ generation       = 0 -> (known after apply)
          - labels           = {} -> null
            name             = "pet2cattle"
          ~ resource_version = "24294779" -> (known after apply)
          ~ self_link        = "/api/v1/namespaces/pet2cattle" -> (known after apply)
          ~ uid              = "d7d4e4fd-40ec-45fb-b2d5-3b83b2e0e793" -> (known after apply)
        }
    }

Plan: 1 to add, 0 to change, 1 to destroy.
(...)

This can be useful when the resource have still exists but have been degraded in some way. For example, if a database or a instance have been corrupted (or hacked) and we want to replace it with a fresh one

Since the taint command is going to be removed, we can get used to the -replace option on the plan and apply commands:

$ terraform apply -replace=kubernetes_namespace.pet2cattle_namespace
Acquiring state lock. This may take a few moments...
aws_s3_bucket.s3_bucket: Refreshing state... [id=pet2cattle-dev]
kubernetes_namespace.pet2cattle_namespace: Refreshing state... [id=pet2cattle]
aws_s3_bucket_policy.bucket_policy: Refreshing state... [id=pet2cattle-dev]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # kubernetes_namespace.pet2cattle_namespace will be replaced, as requested
-/+ resource "kubernetes_namespace" "pet2cattle_namespace" {
      ~ id = "pet2cattle" -> (known after apply)

      ~ metadata {
          - annotations      = {} -> null
          ~ generation       = 0 -> (known after apply)
          - labels           = {} -> null
            name             = "pet2cattle"
          ~ resource_version = "24372472" -> (known after apply)
          ~ self_link        = "/api/v1/namespaces/pet2cattle" -> (known after apply)
          ~ uid              = "c4c19675-6f5b-400d-a3ba-662497326dd8" -> (known after apply)
        }
    }

Plan: 1 to add, 0 to change, 1 to destroy.

(...)

Either way, we achieve the same result: The existing resource is going to be destroyed and a fresh one will be created to replace it


Posted on 12/05/2021

Categories