The course is part of this learning path
Terraform is a tool for building, changing, and versioning infrastructure safely and efficiently. Terraform can help with multi-cloud by having one workflow for all clouds. The infrastructure Terraform manages can be hosted on public clouds like Amazon Web Services, Microsoft Azure, and Google Cloud Platform, or on-prem in private clouds such as VMWare vSphere, OpenStack, or CloudStack. Terraform treats infrastructure as code (IaC) so you never have to worry about you infrastructure drifting away from its desired configuration. If you like what you are hearing about Terraform then this course is for you!
In this course, we’ll learn Terraform from the ground up. While building a strong foundation for you to solve real-world challenges with Terraform, you'll learn about its core concepts including HashiCorp Configuration Language, providers, resources, and state. The course concludes with a demo to illustrate how Terraform can be used to manage a practical infrastructure for deploying development and production versions of a two-tier application in Google's Cloud using Cloud SQL, Google Kubernetes Engine (GKE), and Kubernetes. The Terraform configuration files used in the course are all available in the course's GitHub repository.
This course is for anyone that is interested in managing infrastructure in public, private, or hybrid clouds. Some roles that fit into that category are:
- DevOps Engineers
- IT Professionals
- Cloud Engineers
After completing this course, you will be able to:
- Describe what Terraform is
- Write Terraform configuration files
- Understand how Terraform integrates infrastructure sources
- Manage multiple infrastructure environments with Terraform
This is an intermediate level course that assumes:
- You have priors experience with a scripting or programming language.
|Lesson||What you'll learn|
|Introduction||What will be covered in this course|
|What is Terraform?||Take a high-level look at what Terraform is and when to use it|
|Terraform Configuration||Understand the ins and outs of HashiCorp Configuration Language (HCL)|
|Providers||Discover how Terraform integrates various infrastructure sources|
|Resources||See how to configure parameters that are common to all resources|
|State||Learn how Terraform state connects your configuration with the real world|
|Two-Tier App Demo||See how to deploy a two-tier app in multiple environments with Terraform|
|Summary||Review the course and see what's next|
If you have thoughts or suggestions for this course, please contact Cloud Academy at firstname.lastname@example.org.
This course includes a lot of configuration examples in Terraform. This lesson will guide you through writing and working with Terraform configurations. In later lessons we will focus more on the specific topics and applying our configuration knowledge to configure practical infrastructure.
This lesson will explain:
· The HashiCorp Configuration Language that is abbreviated HCL and is the language used to write configurations in Terraform.
· The lesson will also cover the interpolation syntax in HCL which is used to make your configurations dynamic.
· The lesson will finish with a few related topics including how to assign configuration variables, and how to organize your configuration files.
HashiCorp Configuration Language
n. a structured configuration language that is both human and machine friendly for use with command-line tools, but specifically targeted towards DevOps tools, servers, etc. -- https://github.com/hashicorp/hcl
What You Can Configure
Before getting into the details of the syntax of HCL, let’s first discuss the sorts of things that you can configure in Terraform and give an HCL example of each to get a feel for what HCL looks like. We’ll focus more on the details of HCL syntax after.
The most essential pieces to managing infrastructure with Terraform are called resources. Resources are the infrastructure components managed by Terraform. Examples of resources are virtual machines, a database, or a version control system. You can declare resources in your configuration and configure their properties all in HCL. The example declares a Google Compute Engine disk resource. Terraform refers to the disk as default. The properties of the disk are configured between the enclosing braces.
Resources are made available through providers. The providers are the infrastructure integrations mentioned in the intro lesson of this course. The configuration for providers usually involves some form of credentials to grant you access to the provider’s API. The provider essentially wraps the API provided by the underlying infrastructure host. The example illustrates how to configure the Google Cloud Platform provider. I’ll have more to say about both resources and providers in following lessons dedicated to these subjects.
Besides resources, and providers, you can configure:
· Variables which are configured as inputs to your configuration. The example declares a string variable and includes a description and a default value, so the configuration won’t throw an error if the user doesn’t specify a value.
· Outputs are infrastructure values you want to easily access. For example, the DNS name of a load balancer, the ssh command used to connect to an instance created by the configuration, et cetera. When you apply changes in your configuration Terraform displays the outputs that you configure. You can also access outputs at any time using the Terraform output command. The output command is useful for integrating Terraform with scripting environments. In the example, the IP address of the Google Kubernetes Engine Kubernetes master node is declared as an output.
· Data sources to fetch information that is defined outside of the current Terraform configuration. For example, if you have divided your infrastructure into separate projects, you can retrieve information from other Terraform projects using data sources. The information can be retrieved using data sources made available via providers. There is no requirement that the data being retrieved is managed by Terraform. In the example, the data source references a Google Compute Engine address. The address may be attached to an instance that runs an application needed by your configuration. The address doesn’t need to be managed by Terraform, nor does your infrastructure need to be in GCP.
Those examples cover most of what you would declare in Terraform configurations and have given you a peak at what HCL looks like. Now we’ll focus in on the syntax of HCL.
HashiCorp Configuration Language was designed to be human readable and editable. Hopefully you got a sense of that when we looked at the examples before. Depending on your background, you may be able to pick up HCL with minimal effort.
We’ll now analyze a complete Terraform example to highlight the various aspects of HCL syntax. The configuration creates an instance in Google Cloud Platform. The examples in this course will use GCP although the configuration process is the same with other providers. The Cloud Academy Labs on Terraform demonstrate working with the AWS and Azure providers.
HCL supports two forms of commenting, multi-line and single line. Multi-line comments are enclosed in slash asterisk characters and single line comments begin after a number sign.
A value is assigned to a key using an equal sign. The amount of whitespace doesn’t before and after the equal sign doesn’t matter. Although it isn’t required, the equal signs are aligned to improve readability. The Terraform fmt command can automatically format a configuration file to follow the recommended spacing rules.
The values you assign can be any of the supported types. The primitive types include strings, which are always enclosed in double quotation marks, numbers, and Booleans which have a binary values of either true or false.
Or the values can be complex types: either lists, which are enclosed in brackets and separate items of primitive types with a comma, or maps, which are enclosed in braces and assign a collection of keys and values. Both lists and maps are allowed to be empty.
In most cases, values can be interpolated inside of strings. The syntax for interpolating values is a dollar sign preceding a pair of braces. We’ll discussion interpolation syntax in more detail later.
Configuration blocks start with a keyword to indicate the type of configuration, be it provider, variable, resource, output, et cetera, followed by one or more strings, and then a map enclosed in braces.
Usually there is one string after the keyword and it indicates a name, for example the name of a provider or the name of a variable.
For resources there are two strings, the first is the type of resource and the second is the name Terraform uses to identify the resource.
The name used by Terraform doesn’t have to match the name used by the provider. The names Terraform uses must be unique, or an error will be thrown. That completes our journey through HCL syntax.
We saw an example of interpolation syntax for interpolating a value within a string in HCL. Interpolations are very useful and an essential tool in your Terraform toolkit. You can interpolate from a variety of sources. Each has their own unique syntax, as we’ll see in the following examples.
We’ve seen how to interpolate a string variable by using var dot and the name of the string variable. The same pattern works for retrieving entire maps or lists.
When you want to interpolate the value of a specific key from a map, you appended the key name within brackets.
When you want to interpolate the value of a specific item in a list, you appended the index within brackets. Indexing starts from zero so to retrieve the first element in a list you’d enter 0 between brackets.
You can also interpolate values of resource attributes. Attributes are all of the properties Terraform knows about for a resource. They include arguments that you set in resource blocks as well as values that are set as a side effect of creating a resource. For example, although you don’t configure an ID for an instance, when it is created the provider assigns an ID and you can reference the ID using attribute interpolation. The syntax for attribute interpolation is the resource type, followed by the name of the resource, and ending with the attribute to interpolate. For example, Google compute instance dot web server dot instance ID.
As a final example, to interpolate from a data source, you use the same pattern as a resource but with data dot at the beginning.
You can use conditions inside of interpolation syntax to making branching decisions. An example of when this could be useful is when you share the same configuration between environments, but you may want to use smaller instances for the test environment than in production. Another common scenario is disabling some resource blocks unless a certain variable is true.
The syntax for conditions is the condition, followed by a question mark and the expression if the condition is true, and lastly a colon and the expression to evaluate if the condition is false.
The condition must be Boolean. That is to say it must evaluate to true or false.
You can use equality operators in the condition. Two equal signs compare if expressions on either side of the operator are equal, and an exclamation point equal sign checks if they are not equal to each other.
Numerical values can be compared using less than, greater than, less than or equal to, or greater than or equal to.
Logical operators can be used to combine Boolean expressions. Two ampersands represent logical to evaluate true only if both expressions are true. Two pipes represent logical or to evaluate true if either of the expressions are true. The exclamation point negates a Boolean value converting true to false and false to true.
The true and false expressions can include any valid interpolation syntax.
But both expressions must evaluate to the same type. For example, both expressions can be strings, but one can’t be a string and the other is a number.
As an example, the following sets the machine type of a Google Compute Engine instance based on the value of a variable that stores a string representing the current environment. If the environment is production, then a high memory machine type is used, otherwise a standard machine type is used.
Interpolation Math and Functions
Interpolation syntax supports basic math operations on numbers, both floating point and integer.
The supported operators are addition, subtraction, multiplication, division, and the modulo operator which only applies to integers.
Besides the basic match operators, there are dozens of built-in functions to enrich the capabilities of interpolations.
The syntax for functions is the function name followed by a list of comma-separated arguments all enclosed in parentheses.
To see what kind of functions are available, let’s go through a small sample of the built-in functions. The abs function returns the absolute value of a number. There are several more built-in functions that are mathematical in nature.
The index function can return the index of an element in a list. There are a variety of other functions for operating with lists and maps.
The file function reads the contents of a file into a string.
The last function that we’ll discuss is replace which takes a string and replaces all occurrences of a search string with a replace string.
As you can see, there are a wide variety of built-in functions. A link to the documentation page that describes all of the available functions is at the end of the transcript for this lesson.
Up until now we’ve seen how to declare variables, and how to refer to them inside interpolation syntax. We also saw one method for assigning variables.
The default key for a variable specifies what value to use if no other value is assigned.
The default value is used by Terraform to infer the type of the variable. When no default is given and no type is specified, the default type of string is used. The default value can’t use interpolations. When no default is provided, you must specify a value. You have several options for specifying the value of a variable. If you specify a value when a default is provided, the specified value is used overriding the default.
The first option is to have Terraform interactively prompt you to enter values for missing variables.
This may work for small exercises but is painful to re-enter the values every time you issue a plan or apply. It is also not applicable for automation.
Another option is using the -var command line option for both plan and apply commands.
You specify the variable name followed by an equal sign and the value you want to use for the variable. You can use any many -var options as required, but the commands can get very long if you have more than a few variables.
Another option that is more amenable to version control is to use variable files.
Variable files use HCL syntax for defining the variable values. The image in the lower-right corner shows the contents of a variable file that defines an env string variable, a list named list, and a map named map. Variable files can be included using the var-file option or they can be automatically included if they are in your current working directory and are either named terraform.tfvars or have a file extension of .auto.tfvars. You can use multiple variable files. Variables defined using the -var-file option override variables defined using automatic variable files.
There is one last way to set variables, and that is using environment variables.
When setting Terraform variables using environment variables the name of the environment variable must begin with TF_VAR_ and be followed by the name of the Terraform variable. The example shows how to define a Terraform variable named env using an environment variable.
When a variable is defined multiple times, the value of the variable is usually set to the highest precedent definition. One thing to note is that map variables are set to the highest precedent definition. Instead the values of the map variable definitions are merged. All other variables are overridden by the highest precedent value.
The order of precedence from lowest to highest is as follows:
· default values have the lowest precedence
· then environment variables
· followed by automatic variable files
· and -var and -var-files share the highest precedence level
When variables are defined within the same precedence level, the last value is used. For example, if you define a variable in a var-file and a -var option, the one that you specify last on the command-line will take precedence.
Configuration File Discovery
When you run Terraform, it will inspect the current directory for files ending with .tf to discover configuration files written in HCL.
If you are using JSON, the file extension should be .tf.json. Terraform can read in a mixture of HCL and JSON configuration files. Most of this course will use a single file for declaring infrastructure configurations, but it is common to use multiple .tf files to organize your configurations.
For example, variables, outputs, and main resource configuration are commonly split into three files.
The configuration files are loaded in alphabetical order. The loaded files are essentially appended. This means that if you have two resources with the same name Terraform will throw an error instead of using the last declared resource with the name. Beyond splitting your configuration across multiple files, there is another feature available to you for organizing your configurations.
Terraform Configurations can be organized and shared through reusable configuration packages called modules.
Modules can be shared using many sources such as file systems, GitHub, Amazon S3, or Terraform Module Registries. Terraform Module Registries have the benefit of supporting versions specified in HCL. Other sources do not have built-in support for module versions.
HashiCorp hosts a public Terraform Registry at https://registry.terraform.io/. Anyone can publish modules to the public registry. Terraform Enterprise includes a private module registry if your organization needs more control over who can access the modules. That is all that I’ll say about modules in this Course. There is a Cloud Academy Lab that demonstrates using modules from the public Terraform Registry as well as creating your own module to provision a virtual machine in Microsoft Azure.
This lesson built up a strong foundation for working with Terraform in the following lessons.
You now understand how Terraform configurations are written using the HashiCorp Configuration Language. HCL aims to be easy for humans to read and write.
You learned how to make generalize your configurations by using the interpolation syntax to retrieve values from variables, resource attributes, and data sources. You also learned how to use conditions to make branching decisions within your configuration, and built-in functions to enrich the capabilities of interpolation syntax.
The various ways to assign configuration variable values were then described. You also learned the precedence order of the different ways.
Lastly, you learned how to organize configurations by using multiple files and by creating reusable and shareable modules.
The remaining lessons will focus in on particular topics and include demos working with Terraform at the command line. The next lesson covers providers and how they give Terraform its powerful capabilities. When you are ready to get started working with Terraform providers, continue on to the next lesson.
List of all the built-in functions https://www.terraform.io/docs/configuration/interpolation.html#supported-built-in-functions
About the Author
Logan has been involved in software development and research since 2007 and has been in the cloud since 2012. He is an AWS Certified DevOps Engineer - Professional, AWS Certified Solutions Architect - Professional, Microsoft Certified Azure Solutions Architect Expert, MCSE: Cloud Platform and Infrastructure, Google Cloud Certified Associate Cloud Engineer, Certified Kubernetes Administrator (CKA), Certified Kubernetes Application Developer (CKAD), Linux Foundation Certified System Administrator (LFCS), and Certified OpenStack Administrator (COA). He earned his Ph.D. studying design automation and enjoys all things tech.