HashiCorp Learn
Infrastructure
  • TerraformTerraformLearn terraformDocs
  • PackerPackerLearn packerDocs
  • VagrantVagrantLearn vagrantDocs
Security
  • VaultVaultLearn vaultDocs
  • BoundaryBoundaryLearn boundaryDocs
Networking
  • ConsulConsulLearn consulDocs
Applications
  • NomadNomadLearn nomadDocs
  • WaypointWaypointLearn waypointDocs
  • HashiCorp Cloud Platform (HCP) LogoHashiCorp Cloud Platform (HCP)HashiCorp Cloud Platform (HCP)Docs
Type '/' to Search
Loading account...
  • Bookmarks
  • Manage Account
  • Overview
  • Prerequisites
  • Setting up GCP
  • Configuration
  • Initialization
  • Creating Resources
DocsForum
Back to terraform
GCPView Collection
    Introduction to Infrastructure as Code with TerraformInstall TerraformBuild InfrastructureChange InfrastructureDestroy InfrastructureCreate Resource DependenciesProvision InfrastructureDefine Input VariablesQuery Data with Output Variables

Build Infrastructure

  • 9 min
  • Products Usedterraform

With Terraform installed, let's dive right into it and start creating some infrastructure.

We'll build infrastructure on GCP for this getting started tutorial, but Terraform can manage many other things using providers. Some examples of this are in the use cases section.

Warning! While everything provisioned in this tutorial should fall within GCP's free tier, if you provision resources outside of the free tier, you may be charged. We cannot be responsible for any charges you may incur.

As you follow this tutorial, you'll use Terraform to provision, update, and destroy a simple set of infrastructure using the sample configuration provided.

The sample configuration provisions a resource group, networking resources and rules, storage, and a basic Linux virtual machine. You'll also learn about remote backends, outputs, and provisioners. These are the building blocks for more complex configurations.

»Prerequisites

  • A Google Cloud Platform account. If you don't have a GCP account, create one now. This tutorial can be completed using only the services included in the GCP free tier. However, if you provision infrastructure beyond the free tier, you may be charged.

  • A system with Terraform installed. This tutorial includes instructions for installing Terraform on the platform of your choice.

»Google Cloud Shell

This tutorial is also available as an interactive tutorial within Google Cloud Shell. If you prefer, you can follow that version instead, the material covered is the same.

Follow this tutorial in Google Cloud Shell

»Setting up GCP

In addition to a GCP account, you'll need two things to use Terraform to provision your infrastructure:

  • A GCP Project: GCP organizes resources into projects. Create one now in the GCP console. You'll need the Project ID later. You can see a list of your projects in the cloud resource manager.

  • Google Compute Engine: You'll need to enable Google Compute Engine for your project. Do so now in the console. Make sure the project you're using to follow this tutorial is selected and click the "Enable" button.

  • A GCP service account key: Terraform will access your GCP account by using a service account key. Create one now in the console. When creating the key, use the following settings:

    • Select the project you created in the previous step.
    • Under "Service account", select "New service account".
    • Give it any name you like.
    • For the Role, choose "Project -> Editor".
    • Leave the "Key Type" as JSON.
    • Click "Create" to create the key and save the key file to your system.

You can read more about service account keys in Google's documentation.

WARNING: The service account key file provides access to your GCP project. It should be treated like any other secret credentials. Specifically, it should never be checked into source control.

»Configuration

The set of files used to describe infrastructure in Terraform is known as a Terraform configuration. We're going to write our first configuration now to launch a single GCP instance.

The format of the configuration files is documented here. Configuration files can also be JSON, but we recommend only using JSON when the configuration is generated by a machine.

The entire configuration is shown below. We'll go over each part soon.

When run, Terraform loads all configuration files from the current directory. So it's a good idea to organize your configurations into separate directories based on your needs (e.g. departments, production vs development, etc).

Create a directory for the examples in this tutorial, and inside of it save the example configuration below to a file named main.tf. Terraform recognizes files ending in .tf or .tf.json as configuration files and will load them when it runs.

terraform {
  required_providers {
    google = {
      source = "hashicorp/google"
      version = "3.5.0"
    }
  }
}

provider "google" {

  credentials = file("<NAME>.json")

  project = "<PROJECT_ID>"
  region  = "us-central1"
  zone    = "us-central1-c"
}

resource "google_compute_network" "vpc_network" {
  name = "terraform-network"
}

Tip: To use this snippet with Terraform 0.12, remove the terraform {} block.

Note: Be sure to replace <NAME> with the name of the service account key file, and <PROJECT_ID> with your project's ID.

You'll also need to copy the service account key file that you downloaded earlier into this directory and reference it in the "credentials" line.

There are other ways to supply your account credentials, see the provider reference for more details.

This is a complete configuration that Terraform is ready to apply. In the following sections we'll review each block of the configuration in more detail.

»Terraform Block

The terraform {} block is required so Terraform knows which provider to download from the Terraform Registry. In the configuration above, the google provider's source is defined as hashicorp/google which is shorthand for registry.terraform.io/hashicorp/google.

You can also assign a version to each provider defined in the required_providers block. The version argument is optional, but recommended. It is used to constrain the provider to a specific version or a range of versions in order to prevent downloading a new provider that may possibly contain breaking changes. If the version isn't specified, Terraform will automatically download the most recent provider during initialization.

To learn more, reference the provider source documentation.

»Providers

The provider block is used to configure the named provider, in our case google. A provider is responsible for creating and managing resources. Multiple provider blocks can exist if a Terraform configuration manages resources from different providers.

»Resource

The resource block defines a resource that exists within the infrastructure. A resource might be a physical component such as a server, or it can be a logical resource such as a Heroku application. In this example, we're creating a network for the resources we'll created later in this tutorial.

The resource block has two strings before opening the block: the resource type and the resource name. In our example, the resource type is "google_compute_network" and the name is "vpc_network." The prefix of the type maps to the provider. In our case "google_compute_network" automatically tells Terraform that it is managed by the "google" provider. The resource type and name together form the resource ID, in this case "google_compute_network.vpc_network". The resource can be referenced by this ID in other parts of your configuration.

Within the resource block itself is configuration for that resource. This is dependent on each resource provider and is fully documented within our providers reference.

The GCP provider documents supported resources, including google_compute_network.

There are a number of optional arguments, but for our network, we just specify the name, which will be how the network is identified in GCP.

»Initialization

The first command to run for a new configuration — or after checking out an existing configuration from version control — is terraform init, which initializes various local settings and data that will be used by subsequent commands.

Initialize your new Terraform configuration by running the terraform init command in the same directory as your main.tf file.

$ terraform init

Initializing the backend...

Initializing provider plugins...
- Reusing previous version of hashicorp/google from the dependency lock file
- Installing hashicorp/google v3.5.0...
- Installed hashicorp/google v3.5.0 (signed by HashiCorp)

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

Terraform will download the plugins you use in your configuration and set up the backend where it will store information about your infrastructure.

The Google Cloud Platform provider plugin has been downloaded and installed in a subdirectory of the current working directory.

»Creating Resources

Note: The commands shown in this tutorial apply to Terraform 0.12 and above. Earlier versions require using the terraform plan command to see the execution plan before applying it. Use terraform version to confirm your running version.

Apply you configuration now by running the command terraform apply.

$ terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # google_compute_network.vpc_network will be created
  + resource "google_compute_network" "vpc_network" {
      + auto_create_subnetworks         = true
      + delete_default_routes_on_create = false
      + gateway_ipv4                    = (known after apply)
      + id                              = (known after apply)
      + ipv4_range                      = (known after apply)
      + name                            = "terraform-network"
      + project                         = (known after apply)
      + routing_mode                    = (known after apply)
      + self_link                       = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value:

Terraform will indicate what infrastructure changes it plans to make, and wait for your approval before it makes those changes.

This output shows the execution plan, describing which actions Terraform will take in order to create infrastructure to match the configuration. The output format is similar to the diff format generated by tools such as Git. The output has a + next to resource "google_compute_network" "vpc_network", meaning that Terraform will create this resource. Beneath that, it shows the attributes that will be set. When the value displayed is (known after apply), it means that the value won't be known until the resource is created.

If the plan was created successfully, Terraform will now pause and wait for approval before proceeding. If anything in the plan seems incorrect or dangerous, it is safe to abort here with no changes made to your infrastructure.

In this case the plan looks acceptable, so type yes at the confirmation prompt to proceed.

Executing the plan will take a few minutes since Terraform waits for the network to be created successfully.

  Enter a value: yes

google_compute_network.vpc_network: Creating...
google_compute_network.vpc_network: Still creating... [10s elapsed]
google_compute_network.vpc_network: Still creating... [20s elapsed]
google_compute_network.vpc_network: Still creating... [30s elapsed]
google_compute_network.vpc_network: Creation complete after 38s [id=projects/testing-project/global/networks/terraform-network]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

After this, Terraform is all done! You can go to the GCP console to see the network you have provisioned. Make sure you're looking at the same region and project that you configured in the provider configuration.

If you look in your current working directory, you'll see that Terraform also wrote some data into the terraform.tfstate file. This state file is extremely important; it keeps track of Terraform's understanding of the resources it created. We recommended that you use source control for the configuration files, but the state file should not be stored in source control. You can also setup Terraform Cloud to store and share the state with your teams.

You can inspect the current state by running terraform show.

$ terraform show
# google_compute_network.vpc_network:
resource "google_compute_network" "vpc_network" {
    auto_create_subnetworks         = true
    delete_default_routes_on_create = false
    id                              = "projects/testing-project/global/networks/terraform-network"
    name                            = "terraform-network"
    project                         = "testing-project"
    routing_mode                    = "REGIONAL"
    self_link                       = "https://www.googleapis.com/compute/v1/projects/testing-project/global/networks/terraform-network"
}

Terraform will print all the information it knows about the infrastructure it created.

You can see that by creating our resource, we've also gathered a lot of information about it. These values can be referenced to configure other resources or outputs, which will be covered later in this tutorial.


PreviousInstall TerraformNextChange Infrastructure
HashiCorp
  • System Status
  • Terms of Use
  • Security
  • Privacy
stdin: is not a tty