Complete Guide to Terraform Templates and Tfvars
We break down everything you need to know about Terraform templates, the Terraform State File, and Tfvars in one easy-to-read article.
We’re continuing our beginner series on Terraform tutorials. Note: This content is targeted for newcomers, but can also be a helpful review of core concepts.
Whether you’re considering or already using Terraform, at InfraCode, we’re firm believers in Hashicorp’s vision, but think that it’s a heavy lift for small and medium businesses. And, as an individual learner, we understand that the sheer number of unorganized resources make the learning curve steep for newcomers. That’s why we decided to put together easy-to-digest guides to make the learning process that much easier.
In this blog, we’ve compiled overviews of valuable topics for Terraform learners such as:
- The World of Infrastructure on Cloud
- Terraform Templates
- Tfvars (Terraform Variables)
- The Importance of Tfvars and Key Points
- The Terraform State File and Key Points
If you’re looking to connect with other Terraform learners or experts, we encourage you to join our Slack community to meet others and exchange valuable ideas.
The World of Infrastructure on Cloud
When discussing setting up an IT enterprise, a major component of the conversation involves setting up the infrastructure. When we say “infrastructure” we’re talking about the enterprise’s entire collection of hardware, software, networks, data centers, and other facilities that are used to develop, test, operate, monitor, manage and support IT services. When managing the infrastructure through a descriptive model or through code, the same environment is generated every time that code is applied--thereby creating a very fitting name: “Infrastructure as Code (IaC).”
The facilities discussed above can be provided by a cloud service provider, which is referred to as an area known as “Cloud Computing.” Cloud computing can be widely classified into 3 services: Infrastructure as a Service (IaaS), Platform as a Service (PaaS), and Software as a Service (SaaS).
IaC can be deployed on the cloud by either pushing the configuration to the designated system or by pulling the required configuration on to the system from the server.
Source: Cloud Computing
Terraform is an open-source tool for building, changing, and versioning infrastructure safely and efficiently. Terraform can manage existing and popular service providers as well as custom in-house solutions. As mentioned above, there are two ways of provisioning your architecture on the cloud, and of these, Terraform follows the “push” process.
Configurations on Terraform are usually written within files and then compiled into a folder. A “Terraform template” consists of these files. Each of these folders can be considered as a “module”, and every Terraform template contains at least 1 root module, which consists of the following files:
- main.tf: This is where the execution of your Terraform template begins
- variables.tf: A file where you declare all your “input variables”
- outputs.tf: The file with the definitions for every “output value”
Each of these files is written in a block structure, which contains the type of block, its name, and then arguments with assigned values in the form of expressions.
Let’s see an example for a block:
In the above image, the text after the symbol “#” is a comment, “resource” is the type of block, and “aws_vpc” and “main” are the labels or names for the block. “cidr_block = var.main_cidr” and “enable_dns_support = true” are the expressions where cidr_block and enable_dns_support are the arguments to which values are assigned after the “=” symbol.
If you found the above paragraph confusing, let’s simplify it. We can say that a Terraform template is built like this:
A common question that we hear is “Why is the Terraform template important? What should I focus on?”
Let’s put it this way: a Terraform template is the main root on which your entire configuration is dependent. Without it, there is no configuration and no infrastructure.
An even more pressing question is what should you consider in order to design an efficient template?
Look at the image above, where you can see that arguments build-up to blocks, which are then built up as modules, and finally, the collection of these form your final Terraform template.
While this cycle may be obvious, have you considered that when you sit down to design and write the template, you’re actually going to move through the cycle in reverse order. Therefore, there are some Terraform best practices you should follow when designing:
1. Understand your infrastructure needs: This is a crucial step to consider. Irrespective of the size of your enterprise, understanding what exactly is needed as a part of your infrastructure is very important. Based on how well you can analyze and break down your needs, you can build the perfect infrastructure. There are various considerations to think about, such as the resources that are required, your budget, the availability of man-power to code and test the build, etc.
2. Concentrate on your provider and resources blocks: Once you have a clear idea of your needs, selecting the right provider should be your priority. We’ve already emphasized the need for this in our “Best Practices” blog. When it comes to the Terraform template, it’s important that you understand how to write your provider and resources block. Always have the exact arguments as per your block, and do not define anything that is not needed and might lead to confusion.
3. Define your Terraform Variables file: The tfvars file helps the manipulation of your resources and ensures the exact configurations. Declare all the necessary variables and use them efficiently.
4. Modular Structure: Your modules, if structured correctly, move you towards the success of your configuration. Concentrate on small details such as defining the child module inside the parent module and having the correct tfvars file with the corresponding module. This will ensure that you do not face any bugs with your Terraform template file.
5. Plan before you Apply: Always keep this step in mind! By using the “plan” command before “apply,” you’ll be aware of any unforeseen errors or unexpected resource creation/modification.
6. Remember: Your template is your documentation: Writing efficient templates will mean lesser documentation on your end. If your code is written in a simple and readable format, then anyone looking at the code won’t require other documentation to understand. However, we also recommend creating a README.md file, as well.
Terraform Variables (Tfvars)
You may have noticed that in the discussion about templates, we repeatedly mentioned tfvars. For a more in-depth discussion about them, check out our recent blog post which goes deeper. They’re vital in our configuration process.
Tfvars, just like the variables of any other programming language, are named memory space whose location is known and whose value may be read, written, and re-used. However, in this case, it’s not necessary to directly declare the tfvars in the program source. You can define a separate file, every module, and declare the tfvars that are required. You’ll notice that these files have the “.tfvars” or “.tfvars.json.” extension.
We have three types of tfvars, as depicted in the image below:
The input tfvars can be passed from a parent to child module. Output values are the values that can be returned from a child module to the parent module and can also be printed on the CLI. The output block is almost the same as the variable block, except that the type of block is written with the keyword “output.” Local values are those variables that are written within the “locals” block and the arguments defined inside them are restricted to the module inside which they are defined.
We previously mentioned that all files are written in a block structure. The tfvars block structure for input variables can be seen in the below example:
Importance of Tfvars and Key Points
Let’s imagine a configuration without variables. You have your provider file with the block defining the provider. There’s also the resource block in the resource file, defining the resources that need to be allocated. Is that really enough? No. Let’s say, you need storage space, part of the network space or to include the authentication or SSH keys. Each of these needs should be declared within tfvars. Variables are a major part of the configuration and are the means of manipulating your resources to give you the exact infrastructure you need. There is no way to set up your requirements without them. So, learn them well and use them wisely.
For someone just starting out with these concepts, it’s always good to keep the following points in mind:
1. Declaration and Usage: When you declare variables in the “tfvars” file, it’s just the declaration of the variable and not the place where it’s in use. Never forget this, or else you may end up not using the tfvars, and resulting in faulty configuration.
2. Practice Custom Validation: Though custom validation is a new feature and to some extent can be considered experimental, we would recommend that you start practicing them in your configurations. They enhance your code and can notify you even if there’s a small deviation.
3. Usage of the right data type is healthy: Terraform doesn’t force you to declare the data type of a variable. You can choose not to or use the data type “any.” However, we recommend declaring tfvars with their data types and leaving a description for each. This ensures that in the future, anyone who is working with the data doesn’t mess it up. Also, remember to have your SSH keys as a “map” type, and not a “string” type, so you can declare them under one variable, and reference them anywhere in your configuration using the same tfvars.
The Terraform State File and Key Points
There are many providers available and with them resources that are provided. There’s also a high possibility that more than one person in your team will handle the infrastructure architecture. Every single time a requirement comes up, and someone makes a change to the configuration file, the changes are applied. But, how does Terraform know what to change? You can thank the Terraform state file. For more information about the importance of the Terraform state file and tips on using it, we’ve written a blog post dedicated to the topic.
The main responsibility of the Terraform state file is to store the map and store the link between your resource and the remote object that’s created. Every time the resource is changed, the Terraform state file is updated. Every time the resource is destroyed, it’s also tracked. In fact, it even maps the dependency of your modules and resources, to ensure that no object is destroyed outside of its dependency.
When it comes to “Terraform State” always remember the following points:
1. Avoid manual editing and managing your Terraform state file: It’s already being managed and updated for you automatically. If the provision is already there for you, why bother manually trying to change the file and potentially undoing your own or a team member’s work? Let the Terraform state file be. Don’t mingle with it.
2. State Locking: When your state file is stored on the remote backend, a provision called “State Locking” is provided. This happens automatically on any command that may alter your state and it prevents others from updating the state at the same time and corrupting it. When you are performing a task that is updating the state, you become the owner of the lock, and others cannot acquire it. If the lock fails to be acquired, then the update can’t be performed. Although there is a provision to disable this and even to force unlock, it’s highly recommended that you don’t perform either. If performed, there may be scenarios with multiple writers of the file and a corrupted state file with severe consequences.
3. Remote file storage: Do you have multiple team members working on your infrastructure? In this case, we always suggest that you store your Terraform State file on a remote storage space such as cloud service providers. When you store remotely, anytime a team member changes the configuration, the state file is updated. Another advantage of storing files remotely is security. If your configuration involves any credentials or other form of sensitive data, it’s suggested that you store your file on the cloud, so that it’s encrypted and saved instead of saved as plain text on your local system.
While this article is only the tip of the iceberg, we hope you found some value from going through the core concepts of Terraform. Looking to learn more? Through our Slack community, we’re fostering a conversation around Terraform best practices, as well as providing expert resources and opinions at your fingertips. Join our Slack community to connect with other DevOps professionals and continue the conversation.