In this blog I’ll be offering a comprehensive guide to the [.code]terraform apply[.code] command, detailing its role in the Terraform CLI workflow for managing and provisioning infrastructure. I will be comparing it to the [.code]terraform plan[.code] command, and discussing best practices before running [.code]terraform apply[.code].
What is terraform apply?
The [.code]terraform apply[.code] command is a fundamental part of the Terraform workflow, which propagates the changes specified in your Infrastructure-as-Code (IaC) configuration to the real-world infrastructure.
The [.code]terraform apply[.code] command executes planned actions, creating, updating, or deleting infrastructure resources to match the new state outlined in your IaC.
Before making any real changes to the infrastructure, [.code]terraform apply[.code] provides an execution plan for reviewing the changes, ensuring transparency and control.
Terraform provisions infrastructure via the following steps:
- [.code]terraform init[.code] - Initializes terraform working directory by installing necessary plugins (providers), setting up the backend, and initializing modules.
- [.code]terraform plan[.code] - Creates an execution plan, compares the desired state (defined in the configuration with the actual state of the infrastructure), and outputs the changes to be made.
- [.code]terraform apply[.code] - Terraform applies the changes required to reach the new state of the infrastructure. This is where the actual creation, modification, or deletion of infrastructure happens, making it the most critical step in the Terraform workflow.
If you are new to these, my advice visit here to learn more about Terraform CLI commands. If not, read on to dive deeper into [.code]terraform apply[.code].
What does terraform apply do?
Let us set up an EC2 instance and discuss how the [.code]terraform apply[.code] command works and the aftermath after running the [.code]terraform apply[.code] command.
We have defined the EC2 instance in our Terraform configuration main.tf file:
Before running terraform apply
- The [.code]terraform init[.code] downloads all the providers along with initializing the directory.
- The [.code]terraform plan[.code] compares the desired state (defined in main.tf) with the actual state of AWS and determines that an EC2 instance needs to be created.
- After [.code]terraform apply[.code] command executes, we are prompted to confirm whether to apply the changes.
- Upon confirmation with a [.code]yes[.code], Terraform takes the configuration and communicates (makes an API call) with AWS to set up the EC2 instance according to the specifications in main.tf.
Aftermath of terraform apply
- The EC2 instance is provisioned in your AWS account. You can see the instance running in the AWS Management Console.
- Terraform creates a state file called terraform.tfstate. This state file contains all the metadata and the current state of the EC2 instance.
- From this point onwards, any further changes you make in your main.tf file and [.code]apply[.code] via Terraform will be compared against the state file. For example, if you change the instance type from [.code]t2.micro[.code] to [.code]t2.medium[.code] in your main.tf, running [.code]terraform plan[.code] again will recognize this change, and [.code]terraform apply[.code] will modify the existing instance or recreate it as per the defined configuration.
Examples: How to use terraform apply options
Let’s dive deep into what additional [.code]terraform apply[.code] options can be utilized with the apply command.
Terraform apply -auto-approve
Running the [.code]terraform apply -auto-approve[.code] will immediately start applying any changes as per the configuration, without waiting for user input.
When you're confident in your Terraform configuration and you want to apply the changes without manual intervention, you can use [.code]-auto-approve[.code]. This is especially useful in automated environments like CI/CD pipelines.
Terraform apply -target
The [.code]terraform apply-target=resource_type.resource_name[.code] focuses Terraform's actions on specific resources. If you want to apply changes to a specific resource or to resources within a specific module without affecting the rest of the managed resources, you can use [.code]-target[.code].
For example, running [.code]terraform apply -target=aws_instance.env0-instance[.code] will apply changes only to the resource named [.code]env0-instance[.code] of the type [.code]aws_instance[.code].
Terraform apply -refresh-only
This option instructs Terraform to refresh the state file to match the real-world resources without applying any configuration changes.
When you suspect that the actual infrastructure might be out of sync with your state file, running [.code]terraform apply -refresh-only[.code] will update the state file with any changes it detects (like manually deleted or externally altered resources).
Terraform apply -parallelism=’n’
The [.code]-parallelism=n option[.code] limits Terraform to making only concurrent operations. This can be helpful if you're running into API rate limits of a cloud provider or if your infrastructure has other performance constraints that make executing too many operations at once undesirable.
For example, [.code]terraform apply -parallelism=1[.code] tells Terraform to make the changes with no more than 1 [.code]terraform apply[.code] operation running at the same time. Change this to [.code]-parallelism=5[.code] will increase the number to 5, and so on.
Terraform apply -lock=’false and -lock-timeout=DURATION
By default, Terraform enables state locking. However, if you need to override this function for some reason, you would use [.code]terraform apply -lock=false[.code]. It can act as a safety mechanism designed to prevent concurrent operations made by other engineers in a team.
The [.code]terraform apply -lock-timeout[.code] command is used to specify a duration for which Terraform will wait for a state lock before it gives up and returns an error. The duration syntax is a number followed by a time unit, such as [.code]5s[.code] for five seconds.
Terraform apply -input=’false’
The [.code]-input=false[.code] option specifically instructs Terraform not to prompt for input. This is useful in automated scripts or environments (like CI/CD pipelines) where no human intervention is needed to input variables interactively.
When [.code]-input=false[.code] is set, Terraform will not ask for input and will instead use the default values for any variables that have not been otherwise specified. If any required inputs are not provided and do not have default values, Terraform will produce an error and exit.
Terraform plan vs. apply
Let us take a look at some key differences between Terraform [.code]plan[.code] and [.code]apply[.code].
Best Practices
DevOps and Infrastructure engineers should keep certain measures in mind before executing the terraform apply command.
Store Terraform files in Version Control
Store all your Terraform files ([.code].tf[.code] and [.code].tfvars[.code]) in a version control system like Git.
This practice is fundamental for tracking changes, team collaboration, and maintaining history.
These are the key benefits of storing your Terraform files in VCS:
- Change tracking: Every change made to your Terraform files is tracked. You can see who made what changes, and when.
- Team collaboration: Team members can collaborate on IaCs, reviewing each other's changes and managing merges to avoid conflicts.
- Maintain history: You can revert to previous versions if a new change causes issues.
Remote Backend
You can use your S3 bucket or Google Cloud storage, or leverage the env0 remote backend capabilities to store your Terraform state file (terraform.tfstate).
Doing so will provide you with several benefits, including:
- Remote shared state: The state is shared and accessible to all authorized team members in an organization.
- Security: Remote backends are secured and encrypted to protect sensitive information in state files.
- State locking: Many remote backends support state locking, preventing conflicting operations from being applied simultaneously.
Secure Secret Data
Avoid hard coding sensitive data like passwords or AWS access keys in your Terraform files. Instead, use environment variables or a secrets management system like HashiCorp Vault.
Benefits of secret management include:
- Security: Sensitive data is not exposed in your codebase. It's stored securely and only accessed when needed. For example, before running [.code]terraform apply[.code], you can export your AWS access key and secret as environment variables, or configure Terraform to fetch secrets from HashiCorp Vault.
- Flexibility: You can easily update secrets without changing your Terraform configuration. For instance, if you have an environment variable [.code]TF_VAR_db_password[.code], you can update it by running export [.code]TF_VAR_db_password="newpassword"[.code], or you can update the secret at a specific path of a secret in Hashicorp Vault (using Vault CLI).
Use Terraform Workspaces
Terraform Workspaces are essential for managing multiple distinct states within the same set of Terraform files.
This is particularly useful when managing different environments (like development, staging, and production). Benefits of workspaces include:
- Environment isolation: Workspaces allow you to keep state and Terraform configuration file data separate for each environment.
- Resource efficiency: Workspaces allow for the efficient use of resources by leveraging the same working copy of a Terraform configuration file and the same plugin and module caches across different infrastructure sets.
What happens if terraform apply fails?
When terraform apply fails, you might find yourself facing a few challenges:
Partial apply of resources
One common issue is that Terraform doesn't record the changes made up to the point of failure in the state file, potentially leaving your infrastructure in an inconsistent state. If you rerun apply after a partial failure, you might encounter errors due to resources that Terraform is unaware of because they weren't recorded in the state.
The general advice in such situations is to manually identify and remove the resources that were partially created before re-running [.code]terraform apply[.code], or to use [.code]terraform import[.code] to reconcile the state with the actual infrastructure.
ResourceAlreadyExistsException
You might encounter specific errors such as [.code]ResourceAlreadyExistsException[.code]. This error typically means that Terraform attempted to create a resource that already exists in your infrastructure, which it wasn't expecting.
This could happen for several reasons, such as manual changes made to the infrastructure outside of Terraform, or issues with the Terraform state file not being up-to-date with the actual infrastructure.
Sometimes, the simplest approach is to manually delete the conflicting resource, especially if it's something that was created automatically by a cloud provider (like log groups in AWS) and not explicitly managed by Terraform.
Otherwise, you can use [.code]terraform import[.code] to bring resources created outside Terraform into Terraform's management.
Resource creation timeouts
When managing AWS resources using Terraform, timeouts happen. This is seen most with resources like CloudFront distributions, Aurora clusters, and sometimes DNS records and certificates. These resources are going to take significant time to get created, leading to timeouts.
In many instances, just waiting a few minutes and then re-running the [.code]terraform apply[.code] command is enough to resolve the problem.
Terraform apply tutorial: Streamline plan and apply with env0
With env0, you can also manage your Infrastructure-as-Code (IaC) deployments directly from your VCS (Github, Gitlab, Bitbucket) provider.
By commenting with env0 on pull requests, it is possible to interact with your env0 environments without the need to log in to the env0 platform.
This fosters collaboration by enabling developers to execute [.code]terraform plan[.code] and [.code]terraform apply[.code] commands directly from the comments section of a pull or merge request.
To demonstrate this, I’ve already created a template to provision an S3 bucket using Terraform.
To configure the PR comments feature, I’ve set an alias for your environment. This can be done in Environments > Settings > Run PR Comments Commands using an Alias.
Next, I’ve changed our Terraform code and created a new pull request:
Now, as shown below, after creating the pull request, env0 ran a [.code]terraform plan[.code] command against our changes.
One more thing to mention here is the Remote Apply feature, which env0 added to the roster of Remote Backend capabilities.
The feature allows you to run [.code]apply[.code] commands with your local Terraform files, while also executing the process remotely within env0, utilizing the shared state, shared variables set for the env0 environment, etc.
This is useful for quickly iterating and testing your changes locally before committing.
Commonly Asked Questions/FAQs
Q: How do I run terraform apply without a state refresh?
Use [.code]terraform plan -refresh=false or terraform apply -refresh=false[.code]. The [.code]-refresh=false[.code] option is used in normal planning mode to skip the default behavior of refreshing the Terraform state before checking for configuration changes.
Q: Can we run terraform apply without plan?
When you run the [.code]apply[.code] command without the plan, Terraform will still create an execution plan of your infrastructure and prompt you to apply the changes to your infrastructure.
Q: What is the opposite of terraform apply?
The opposite of [.code]terraform apply[.code] is [.code]terraform destroy[.code]. The terraform apply command creates or modifies the state of the infrastructure. Likewise, the terraform destroy command deletes the infrastructure and updates the state file by removing the details of the destroyed infrastructure.
Q: What happens if you run terraform apply multiple times?
The infrastructure remains unaltered if the Terraform configuration files haven't undergone any changes relative to the existing Terraform state. Given Terraform's declarative nature, it's entirely secure to execute the apply command repeatedly without concern, provided no changes are made to the infrastructure definition in the configuration files.
Q: Can we stop terraform apply?
If the Terraform CLI is interrupted during the apply process, for instance through a manual interruption like pressing CTRL+C (or Command+C on MacOS) or a SIGINT signal, it will prompt all active provider requests to cancel and aim to halt all operations promptly.
Wrap-up
This quick guide covers the [.code]terraform apply[.code] command's role, usage options, best practices, failure handling, and common questions.
env0 streamlines [.code]terraform apply[.code] by automating state file management, preventing version control issues, and enhancing collaboration.
It supports comments, log history, and comment-driven workflows for streamlined deployments directly from Git repositories. This reduces manual intervention, ensuring efficiency, security, and collaboration in [.code]terraform apply[.code].
To learn more about how you can confidently automate your Terraform at scale with env0 and see it in action, schedule a call with a technical expert here.
In this blog I’ll be offering a comprehensive guide to the [.code]terraform apply[.code] command, detailing its role in the Terraform CLI workflow for managing and provisioning infrastructure. I will be comparing it to the [.code]terraform plan[.code] command, and discussing best practices before running [.code]terraform apply[.code].
What is terraform apply?
The [.code]terraform apply[.code] command is a fundamental part of the Terraform workflow, which propagates the changes specified in your Infrastructure-as-Code (IaC) configuration to the real-world infrastructure.
The [.code]terraform apply[.code] command executes planned actions, creating, updating, or deleting infrastructure resources to match the new state outlined in your IaC.
Before making any real changes to the infrastructure, [.code]terraform apply[.code] provides an execution plan for reviewing the changes, ensuring transparency and control.
Terraform provisions infrastructure via the following steps:
- [.code]terraform init[.code] - Initializes terraform working directory by installing necessary plugins (providers), setting up the backend, and initializing modules.
- [.code]terraform plan[.code] - Creates an execution plan, compares the desired state (defined in the configuration with the actual state of the infrastructure), and outputs the changes to be made.
- [.code]terraform apply[.code] - Terraform applies the changes required to reach the new state of the infrastructure. This is where the actual creation, modification, or deletion of infrastructure happens, making it the most critical step in the Terraform workflow.
If you are new to these, my advice visit here to learn more about Terraform CLI commands. If not, read on to dive deeper into [.code]terraform apply[.code].
What does terraform apply do?
Let us set up an EC2 instance and discuss how the [.code]terraform apply[.code] command works and the aftermath after running the [.code]terraform apply[.code] command.
We have defined the EC2 instance in our Terraform configuration main.tf file:
Before running terraform apply
- The [.code]terraform init[.code] downloads all the providers along with initializing the directory.
- The [.code]terraform plan[.code] compares the desired state (defined in main.tf) with the actual state of AWS and determines that an EC2 instance needs to be created.
- After [.code]terraform apply[.code] command executes, we are prompted to confirm whether to apply the changes.
- Upon confirmation with a [.code]yes[.code], Terraform takes the configuration and communicates (makes an API call) with AWS to set up the EC2 instance according to the specifications in main.tf.
Aftermath of terraform apply
- The EC2 instance is provisioned in your AWS account. You can see the instance running in the AWS Management Console.
- Terraform creates a state file called terraform.tfstate. This state file contains all the metadata and the current state of the EC2 instance.
- From this point onwards, any further changes you make in your main.tf file and [.code]apply[.code] via Terraform will be compared against the state file. For example, if you change the instance type from [.code]t2.micro[.code] to [.code]t2.medium[.code] in your main.tf, running [.code]terraform plan[.code] again will recognize this change, and [.code]terraform apply[.code] will modify the existing instance or recreate it as per the defined configuration.
Examples: How to use terraform apply options
Let’s dive deep into what additional [.code]terraform apply[.code] options can be utilized with the apply command.
Terraform apply -auto-approve
Running the [.code]terraform apply -auto-approve[.code] will immediately start applying any changes as per the configuration, without waiting for user input.
When you're confident in your Terraform configuration and you want to apply the changes without manual intervention, you can use [.code]-auto-approve[.code]. This is especially useful in automated environments like CI/CD pipelines.
Terraform apply -target
The [.code]terraform apply-target=resource_type.resource_name[.code] focuses Terraform's actions on specific resources. If you want to apply changes to a specific resource or to resources within a specific module without affecting the rest of the managed resources, you can use [.code]-target[.code].
For example, running [.code]terraform apply -target=aws_instance.env0-instance[.code] will apply changes only to the resource named [.code]env0-instance[.code] of the type [.code]aws_instance[.code].
Terraform apply -refresh-only
This option instructs Terraform to refresh the state file to match the real-world resources without applying any configuration changes.
When you suspect that the actual infrastructure might be out of sync with your state file, running [.code]terraform apply -refresh-only[.code] will update the state file with any changes it detects (like manually deleted or externally altered resources).
Terraform apply -parallelism=’n’
The [.code]-parallelism=n option[.code] limits Terraform to making only concurrent operations. This can be helpful if you're running into API rate limits of a cloud provider or if your infrastructure has other performance constraints that make executing too many operations at once undesirable.
For example, [.code]terraform apply -parallelism=1[.code] tells Terraform to make the changes with no more than 1 [.code]terraform apply[.code] operation running at the same time. Change this to [.code]-parallelism=5[.code] will increase the number to 5, and so on.
Terraform apply -lock=’false and -lock-timeout=DURATION
By default, Terraform enables state locking. However, if you need to override this function for some reason, you would use [.code]terraform apply -lock=false[.code]. It can act as a safety mechanism designed to prevent concurrent operations made by other engineers in a team.
The [.code]terraform apply -lock-timeout[.code] command is used to specify a duration for which Terraform will wait for a state lock before it gives up and returns an error. The duration syntax is a number followed by a time unit, such as [.code]5s[.code] for five seconds.
Terraform apply -input=’false’
The [.code]-input=false[.code] option specifically instructs Terraform not to prompt for input. This is useful in automated scripts or environments (like CI/CD pipelines) where no human intervention is needed to input variables interactively.
When [.code]-input=false[.code] is set, Terraform will not ask for input and will instead use the default values for any variables that have not been otherwise specified. If any required inputs are not provided and do not have default values, Terraform will produce an error and exit.
Terraform plan vs. apply
Let us take a look at some key differences between Terraform [.code]plan[.code] and [.code]apply[.code].
Best Practices
DevOps and Infrastructure engineers should keep certain measures in mind before executing the terraform apply command.
Store Terraform files in Version Control
Store all your Terraform files ([.code].tf[.code] and [.code].tfvars[.code]) in a version control system like Git.
This practice is fundamental for tracking changes, team collaboration, and maintaining history.
These are the key benefits of storing your Terraform files in VCS:
- Change tracking: Every change made to your Terraform files is tracked. You can see who made what changes, and when.
- Team collaboration: Team members can collaborate on IaCs, reviewing each other's changes and managing merges to avoid conflicts.
- Maintain history: You can revert to previous versions if a new change causes issues.
Remote Backend
You can use your S3 bucket or Google Cloud storage, or leverage the env0 remote backend capabilities to store your Terraform state file (terraform.tfstate).
Doing so will provide you with several benefits, including:
- Remote shared state: The state is shared and accessible to all authorized team members in an organization.
- Security: Remote backends are secured and encrypted to protect sensitive information in state files.
- State locking: Many remote backends support state locking, preventing conflicting operations from being applied simultaneously.
Secure Secret Data
Avoid hard coding sensitive data like passwords or AWS access keys in your Terraform files. Instead, use environment variables or a secrets management system like HashiCorp Vault.
Benefits of secret management include:
- Security: Sensitive data is not exposed in your codebase. It's stored securely and only accessed when needed. For example, before running [.code]terraform apply[.code], you can export your AWS access key and secret as environment variables, or configure Terraform to fetch secrets from HashiCorp Vault.
- Flexibility: You can easily update secrets without changing your Terraform configuration. For instance, if you have an environment variable [.code]TF_VAR_db_password[.code], you can update it by running export [.code]TF_VAR_db_password="newpassword"[.code], or you can update the secret at a specific path of a secret in Hashicorp Vault (using Vault CLI).
Use Terraform Workspaces
Terraform Workspaces are essential for managing multiple distinct states within the same set of Terraform files.
This is particularly useful when managing different environments (like development, staging, and production). Benefits of workspaces include:
- Environment isolation: Workspaces allow you to keep state and Terraform configuration file data separate for each environment.
- Resource efficiency: Workspaces allow for the efficient use of resources by leveraging the same working copy of a Terraform configuration file and the same plugin and module caches across different infrastructure sets.
What happens if terraform apply fails?
When terraform apply fails, you might find yourself facing a few challenges:
Partial apply of resources
One common issue is that Terraform doesn't record the changes made up to the point of failure in the state file, potentially leaving your infrastructure in an inconsistent state. If you rerun apply after a partial failure, you might encounter errors due to resources that Terraform is unaware of because they weren't recorded in the state.
The general advice in such situations is to manually identify and remove the resources that were partially created before re-running [.code]terraform apply[.code], or to use [.code]terraform import[.code] to reconcile the state with the actual infrastructure.
ResourceAlreadyExistsException
You might encounter specific errors such as [.code]ResourceAlreadyExistsException[.code]. This error typically means that Terraform attempted to create a resource that already exists in your infrastructure, which it wasn't expecting.
This could happen for several reasons, such as manual changes made to the infrastructure outside of Terraform, or issues with the Terraform state file not being up-to-date with the actual infrastructure.
Sometimes, the simplest approach is to manually delete the conflicting resource, especially if it's something that was created automatically by a cloud provider (like log groups in AWS) and not explicitly managed by Terraform.
Otherwise, you can use [.code]terraform import[.code] to bring resources created outside Terraform into Terraform's management.
Resource creation timeouts
When managing AWS resources using Terraform, timeouts happen. This is seen most with resources like CloudFront distributions, Aurora clusters, and sometimes DNS records and certificates. These resources are going to take significant time to get created, leading to timeouts.
In many instances, just waiting a few minutes and then re-running the [.code]terraform apply[.code] command is enough to resolve the problem.
Terraform apply tutorial: Streamline plan and apply with env0
With env0, you can also manage your Infrastructure-as-Code (IaC) deployments directly from your VCS (Github, Gitlab, Bitbucket) provider.
By commenting with env0 on pull requests, it is possible to interact with your env0 environments without the need to log in to the env0 platform.
This fosters collaboration by enabling developers to execute [.code]terraform plan[.code] and [.code]terraform apply[.code] commands directly from the comments section of a pull or merge request.
To demonstrate this, I’ve already created a template to provision an S3 bucket using Terraform.
To configure the PR comments feature, I’ve set an alias for your environment. This can be done in Environments > Settings > Run PR Comments Commands using an Alias.
Next, I’ve changed our Terraform code and created a new pull request:
Now, as shown below, after creating the pull request, env0 ran a [.code]terraform plan[.code] command against our changes.
One more thing to mention here is the Remote Apply feature, which env0 added to the roster of Remote Backend capabilities.
The feature allows you to run [.code]apply[.code] commands with your local Terraform files, while also executing the process remotely within env0, utilizing the shared state, shared variables set for the env0 environment, etc.
This is useful for quickly iterating and testing your changes locally before committing.
Commonly Asked Questions/FAQs
Q: How do I run terraform apply without a state refresh?
Use [.code]terraform plan -refresh=false or terraform apply -refresh=false[.code]. The [.code]-refresh=false[.code] option is used in normal planning mode to skip the default behavior of refreshing the Terraform state before checking for configuration changes.
Q: Can we run terraform apply without plan?
When you run the [.code]apply[.code] command without the plan, Terraform will still create an execution plan of your infrastructure and prompt you to apply the changes to your infrastructure.
Q: What is the opposite of terraform apply?
The opposite of [.code]terraform apply[.code] is [.code]terraform destroy[.code]. The terraform apply command creates or modifies the state of the infrastructure. Likewise, the terraform destroy command deletes the infrastructure and updates the state file by removing the details of the destroyed infrastructure.
Q: What happens if you run terraform apply multiple times?
The infrastructure remains unaltered if the Terraform configuration files haven't undergone any changes relative to the existing Terraform state. Given Terraform's declarative nature, it's entirely secure to execute the apply command repeatedly without concern, provided no changes are made to the infrastructure definition in the configuration files.
Q: Can we stop terraform apply?
If the Terraform CLI is interrupted during the apply process, for instance through a manual interruption like pressing CTRL+C (or Command+C on MacOS) or a SIGINT signal, it will prompt all active provider requests to cancel and aim to halt all operations promptly.
Wrap-up
This quick guide covers the [.code]terraform apply[.code] command's role, usage options, best practices, failure handling, and common questions.
env0 streamlines [.code]terraform apply[.code] by automating state file management, preventing version control issues, and enhancing collaboration.
It supports comments, log history, and comment-driven workflows for streamlined deployments directly from Git repositories. This reduces manual intervention, ensuring efficiency, security, and collaboration in [.code]terraform apply[.code].
To learn more about how you can confidently automate your Terraform at scale with env0 and see it in action, schedule a call with a technical expert here.