Introduction to Terraform using GCP

Daniel Randell
5 min readFeb 4, 2021

This is a quick introduction to using Terraform to deploy cloud resources on Google Cloud Platform.

I will assume you have an understanding of IAC (Infrastructure as Code) and have already installed Terraform. If not, I’ve detailed two links below provided by HashiCorp for further reading;

The Basics — Provider & File Structure

Before we deep dive in, let’s first talk about the file structure and the brains behind the operation; the google provider.

The google provider is what allows Terraform to interact with GCP, in its most basic form it’s a series of files written in the programming language GO which makes calls to the GCP APIs, this then creates/updates/deletes resources that a user defines in code.

There are two versions as of writing this post for the provider, the GA (general availability) and beta. It’s important to remember that some resources will only initially be available in the beta version of the provider and can potentially change before being transitioned into GA. And that’s all you need to know, for the most part, unless the specific resource you are using is not available in GA (for example, Cloud Filestore is currently only available in beta) then I would stick to using GA as much as possible.

Let’s take a look at the file structure of a typical basic Terraform repository;

Terraform File Structure

Here we have a root folder call main which then contains the following files:

  • backend.tf — Everything we do in Terraform will ultimately end up in something called a state file. The state file contains the source of truth for what has happened or what is about to happen. This file can be stored locally and by default, it is but in reality if that file gets corrupted or manipulated in any way outside of Terraform it can cause some real problems. SO instead we define a remote backend; in our case, it’s simply going to put this file into a Cloud Storage Bucket (with versioning enabled!) and update that state file as we run Terraform. Now, this can be defined in main.tf however I like to keep things isolated and clean so a separate file is my recommended approach and you will see more examples of this below.
  • main.tf — The most common file, where we define the use of modules and/or resources. It’s common convention to either use main.tf or folder -name.tf as the main file in your structure, for example; if you had a module called ‘vpc’ you might have a main.tf in that folder or vpc.tf. Ultimately it’s a personal preference, I stick with main.tf to keep things consistent.
  • outputs.tf — All the resources and modules you create can produce some kind of output upon its creation, whether that is a unique ID, a name, or something like an IP address. Outputs defined here will be shown as part of the deployment process and this can be just for human readability that an operation has succeeded or to be used further for other tasks.
  • providers.tf — Each provider you use can have required or optional configuration assigned. The GCP providers have lots of optional config (more information) which then act as default values for resources that require these values; the common entries used would be project, region, and zone. MANY users will define the provider information in their main.tf file (which is fine), however as mentioned before I like to keep things as clean/isolated as possible so recommend a separate file.
  • variables.tf — Again one of the most common files you will see. This file contains the definition for the Terraform variables you will reference in your main.tf file, for example, this could be a string variable called ‘project-id’ or a list of strings of files you want to add into a bucket.
  • versions.tf — A straightforward one, versions.tf is another common convention for specifying version constraints against providers AND Terraform. Remember that for GCP the provider is updated roughly every two weeks and Terraform is updated very frequently as-well, so be sure to check out future versions of the provider & Terraform for any breaking changes that may occur.

And that covers the providers and structure, we will now move onto Terraform commands and then finally creating some resources on GCP 😁!

Terraform Commands

Terraform has three core commands, init, plan & apply. There are some others I’ll briefly mention that are useful such as fmt & output but these are non-essential.

Init aka initialize is the first step of the process, this simply downloads any providers you require and does the necessary setup for your workspace (the folder path in which you ran the command).

Plan is where all the gears start moving, a plan defines the structure of resources to be created and the order in which to create them (which is extremely useful when you have resources that depend on other resources being available!). Note: You must initialize your workspace before running the plan stage.

Apply takes the output of the plan stage and makes it happen.

So a simple sequence of events using the Terraform CLI will go as follows;

// cd to the root of your Terraform
terraform init
terraform plan
terraform apply -auto-approve

And a more standard sequence would be something like;

// cd to the root of your Terraform
terraform fmt -check -recursive
terraform init
terraform plan
terraform apply -auto-approve
terraform output -json -no-color

I forgot to mention, all of the commands above contain -flags that provide additional control over how things are processed and how/which values are used. For the additional commands in the above sequence;

Fmt will run a format check against in the above case all sub-directories and current directory files to make sure we are adhering to the style standards set by HashiCorp.

Output will provide the output that Terraform produces at the end of an apply in JSON format. This is useful for post-processing with other automation features that you may like to kick off after a Terraform job has run.

And that covers the basics, for more in-depth information on CLI commands and flags check out the docs link.

A quick example

I’ve included a small example repository on Github, it includes the above file structure and creates a simple Google Cloud Storage Bucket using the Google Storage Module. It also includes a Github Workflow using the above Terraform commands to run the job.
That can be found in my example repository.

--

--