Updated: Aug 9, 2020

Hello Readers, This blog is the Part-2 of our Terraform course series. In case you missed previous blogs please check out part one of it before going further.


Configurations: A Terraform configuration is the text file that contains the infrastructure resource definitions. You can write Terraform configurations in either Terraform format (using the .tf extension) or in JSON format (using the .tf.json extension). In this article, we are going to use the terraform format.

Providers: Terraform leverages multiple providers to talk to back-end platforms and services, like AWS, Azure, DigitalOcean, Docker, or OpenStack. We are going to focus on Terraform with AWS.

Provisioners: Terraform not only helps us in infrastructure creation and management but also in provisioning them during resource creation or deletion. It uses a feature named provisioner for the same. Provisioners are used for executing scripts or shell commands on a local or remote machine as part of resource creation/deletion. They are similar to EC2 instance user data" scripts that only run once on the creation, and if it fails terraform marks, it tainted. A tainted resource is one that is planned for destruction on the next terraform apply. Terraform doesn't run these scripts multiple times. If we want more flexibility, then we must use a configuration management tool like Ansible to provision the instance correctly.

There are many provisioners available. They help in:

  1. local script execution on the machine from where we are running terraform

  2. remote script execution on resource

  3. file or directory copy on the remote resource

  4. configure and run configuration management tools on the remote resource.

local-exec provisioner helps run a script on the instance where we are running our terraform code, not on the resource we are creating.

remote-exec provisioner helps invoke a script on the remote resource once it is created. We can provide a list of command strings that are executed in the order they are provided. We can also give the scripts a local path that is copied remotely and then executed on the remote resource. File provisioner is used to copy files or directories to a remote resource. We can't provide any arguments to script in remote-exec provisioner. We can achieve this by copying script from file provisioner and then execute a script using a list of commands. Provisioner, which executes commands on a resource (like running a script or copying file) needs to connect to the resource which can be done through SSH. We can define the connection method per resource or per provisioner if we want them to connect using different SSH parameters.

Resources: Resources are the basic building blocks of a Terraform configuration. When you define a configuration, you are defining one or more (typically more) resources. Resources are provider-specific, so a resource for the AWS provider is different than a resource for Open Stack. This, in my opinion, is the one major flaw in Terraform. If you wanted to convert a configuration from using AWS to using Open Stack (or vice versa), you'd necessarily have to re-create the configuration because all the resources are provider-specific.

Variables: To help make configurations more portable and more flexible, Terraform supports the use of variables. By changing the value of the variables, you could potentially re-use a single configuration multiple times (but not across providers, since resources are provider-specific).

Modules: A module is a container for multiple resources that are used together. Every Terraform configuration has at least one module, known as its root module, which consists of the resources defined in the .tf files in the main working directory. A module can call other modules, which lets you include the child module's resources into the configuration in a concise way. Modules can also be called multiple times, either within the same configuration or in separate configurations, allowing resource configurations to be packaged and re-used.

Data sources: Data sources allow data to be fetched or computed for use elsewhere in Terraform configuration. The use of data sources enables a Terraform to make use of information defined outside of Terraform, or defined by another separate Terraform configuration.


Login with root on the Linux box. Make sure that the AWS credentials re-configured.

cd /root/terraform-lab/ 
mkdir first_ec2 
cd first_ec2 

Create a file and write below code into it

vi firstec2.tf      

Then execute the below command.

terraform init 

This will initialize the terraform and download the modules required to create an EC2 instance. Modules are specific to a provider.

After this, execute the below command.

terraform plan

Now run terraform plan, this command will show what all things will be created, will make a plan and display on the screen, if its as expected, we can read the plan and do a terraform apply

After we are sure, that terraform plan output is the same as we desired. We can do a terraform apply to create EC2 instances.

Now go to the console and check, one ec2 instance will be up and running. 😊


To destroy resources created with Terraform, use the command

terraform destroy

NOTE: To destroy a specific resource -

terraform destroy -target aws_instance.myec2 


When we build infrastructure with terraform configuration, a state file gets created in the local workspace directory named "terraform.tfstate". This state file contains information about the provisioned infrastructure which Terraform manage. Whenever we change the configuration file, it automatically determines which part of your configuration is already created and which needs to be changed with the help of the state file. State helps provides idempotent to terraform as it already knows if one resource is present and prevents it from being created again when the same configuration executes.

  • State file is essential for working with Terraform, which has the below benefits:

  • Real-world mapping of resources.

  • Track metadata of resources such as IP address of EC2 instance, its dependency with respect to other resources, etc.

  • Cache resource attributes.

  • Enables collaboration among teams.

The above terraform.tfstate file is almost empty because, as of now, there is nothing we have created with Terraform. Let's do terraform apply again, and we will see that the tfstate file will get filled.

tfstate file keeps track of resources that are built through Terraform. It can detect any manual changes as well, but anything that is not managed or created by Terraform will not be detected when we run a terraform plan. Lets us see what does it mean.

Now we will power off the machine that we have created with Terraform and change its type to t2.nano and run terraform plan again.

We here see that when we manually changed the type of ec2 instance from t2micro to t2.nano, terraform detected this and will bring back the ec2 instance to t2micro.

NOTE: Anything that is created manually from the start and not with terraform will not be detected by a terraform plan.

This brings us to the concept of the desired state v/s current state.

  • Infrastructure status (managed by Terraform + manual changes, if any) is the current state.

  • The state of the infra as per the terraform tfstate file is referred to as the desired state.

  • Terraform always tries to match the current state with the desired state.


To refresh the current state -

terraform refresh 

To view the contents of tfstate file -

terraform show 


Providers in Terraform are released frequently, and new versions keep on coming up. Though the new provider version may contain advanced features, but sometimes it may also break our code. To prevent this thing, we can explicitly mention the provider version. There are several ways to do so, as shown below.

We can make a different tf file to specify only the provider configuration like below.

That's it for this article, guys.

Terraform code for your reference is available at GitHub. CLICK HERE

Happy learning. Cheers :-)


1,237 views2 comments

Recent Posts

See All