Terraform Provisioner Behaviour plays a key role in customizing automation during the infrastructure deployment lifecycle. It allows tasks to be performed either during creation or destruction of resources, and how Terraform reacts to success or failure of those tasks.
This tutorial will help you understand how to control when provisioners run and how to handle failure scenarios. Whether you’re new to Terraform or a seasoned user, mastering provisioner behaviour is essential for building resilient infrastructure.
Table of Contents
Understanding Terraform Provisioner Behaviour
Provisioners are scripts or commands that run on your infrastructure. They are especially useful for post-deployment setup or cleanup tasks. Terraform supports two main types of provisioner behaviour:
- Creation-Time Provisioners
- Destroy-Time Provisioners
Let’s explore both with examples and dive into how to handle failures.
Creation-Time Provisioners
What Happens at Resource Creation?
By default, provisioners run immediately after a resource is successfully created. This is known as creation-time behaviour. Common use cases include:
- Installing packages on a VM
- Setting configuration files
- Registering an instance with a service
Example using local-exec
:
provisioner "local-exec" {
command = "echo ${self.public_ip} >> ~/webserver_ips.txt"
}
This provisioner logs the public IP of a newly launched EC2 instance to a local file.
Why Is This Behaviour Default?
Terraform assumes that your setup tasks need to happen after resource provisioning. It ensures these commands execute as part of the deployment process, helping keep resources ready-to-use post-deployment.
Destroy-Time Provisioners
Running Tasks Before Resource Deletion
You can run provisioners before a resource is destroyed by explicitly setting the when
argument:
provisioner "local-exec" {
when = "destroy"
command = "echo Destroying ${self.public_ip} >> ~/destroy_log.txt"
}
This type is known as a destroy-time provisioner. It’s helpful for cleanup activities like:
- Notifying services before termination
- Backing up configuration or data
- Logging destruction events
Destroy-time provisioners allow more graceful and predictable teardown processes.
Handling Provisioner Failures
Default Failure Behaviour
When a provisioner command fails, Terraform stops the apply
operation and marks the affected resource as tainted. This means Terraform considers the resource unusable and will try to replace it in the next run.
For example, if a command tries to write to a non-existent directory:
command = "echo 'Hello' > /temp/hello.txt"
Terraform throws an error and stops the execution.
This is the default behaviour, equivalent to:
on_failure = "fail"
Continuing on Failure
Sometimes, a failed provisioner task shouldn’t stop your deployment. Maybe the script is optional, or its failure won’t impact infrastructure integrity.
You can override the default with:
on_failure = "continue"
This tells Terraform to proceed even if the command fails. The resource is still marked as provisioned, and no tainting occurs.
Summary of Terraform Provisioner Behaviour
Behaviour Type | Trigger | Default? | Can Override? |
---|---|---|---|
Creation-Time | On creation | ✅ Yes | ❌ No |
Destroy-Time | On destroy | ❌ No | ✅ Yes |
Fail on Error | Yes | ✅ Yes | ✅ Yes (continue ) |
Continue on Error | No | ❌ No | ✅ Yes (on_failure = "continue" ) |
Understanding when to use fail
vs continue
, and create
vs destroy
, is key to robust Terraform provisioning.
Best Practices for Terraform Provisioners
- Use provisioners only when necessary. Prefer built-in resource features like
user_data
,metadata
, orcloud-init
. - Keep scripts simple and idempotent.
- Always test locally before deploying to production.
- Be cautious with
on_failure = "continue"
— don’t ignore important errors. - Consider logging outputs to local files or monitoring systems for easier debugging.
Conclusion
Terraform Provisioner Behaviour gives you fine-grained control over how and when to run setup or teardown tasks. By using creation-time or destroy-time provisioners and managing failure responses smartly, you can avoid broken deployments and ensure a smoother infrastructure lifecycle.
Used responsibly, provisioners add a powerful layer of customization to Terraform workflows. Just remember—they should be your last resort, not your first choice.
Frequently Asked Questions (FAQ)
1. What is the default behaviour of a Terraform provisioner?
By default, provisioners run at resource creation and fail the apply step if any command errors out.
2. Can I ignore a provisioner failure?
Yes, set on_failure = "continue"
inside the provisioner block to ignore errors and proceed with the apply step.
3. What is a destroy-time provisioner?
It’s a provisioner that runs before a resource is deleted. Use when = "destroy"
to configure it.
4. Will a failed provisioner taint the resource?
Yes, unless on_failure
is set to "continue"
, Terraform will mark the resource as tainted.
5. Are provisioners recommended for production use?
Generally, no. Use provider-native methods like user_data
for AWS EC2, and resort to provisioners only when no alternative exists.