Skip to content
Alexander Holbreich
Go back

Terraforming the Google Cloud

This article will help you start using Hashicorp’s Terraform to create infrastructure resources in the Google Cloud.

Prerequisites

You need to have an account in the Google Cloud Platform (GCP). For lucky new users Google offers starter bonus. As well you need terraform installed somewhere too.

Granting access

First of all, we need to allow terraform access to GCP. This can be achieved by Service Accounts with corresponding access keys. Within the GCP console tool gcloud it can be done like:

gcloud iam service-accounts create terraform
gcloud iam service-accounts keys create gce-terraform-key.json --iam-account=terraform@<ỳour-project-id>.iam.gserviceaccount.com

The first line will create a new service account named terraform. The reason for the new separate service accounts is that you can grant and revoke rights to them independently to the default service account. The second line creates a new access key and the export it as file gce-terraform-key.json. With this key, terraform can be authenticated to the GCP.

However, the newly created user needs writing permission to be able to create any resources. Several possibilities exiting to do achieve this, here we use biding of new service role terraform@<ỳour-project-id>.iam.gserviceaccount.com to predefined editor role

gcloud projects add-iam-policy-binding <ỳour-project-id> --member terraform@<ỳour-project-id>.iam.gserviceaccount.com --role roles/editor

This should be sufficient to start, for more background to what happens here take a look at Google Cloud Documentation.

Configure terraform to access Google Cloud

Now we can start with terraforming. First, let’s teach terraform how to access GCP. Terraform provider’s name for GCP is “google”. So if we put this

variable "gce_project" {}
variable "gce_region" { default= "europe-west1"}

provider "google" {
  project     = "${var.gce_project}"
  region      = "${var.gce_region}"
}

in to main.tf we are nearly there. But I’ve only provided project and region through terraform variables, we still missing credentials property. Since I care about credentials here and do not want to commit them accidentally I better provide them via environment variable GOOGLE_CREDENTIALS. This variable1 needs to contain everything from the gce-terraform-key.json file we created above. One way to do handle it on Linux:

export GOOGLE_CREDENTIALS=$(cat ~/.gce/gce-terraform-key.json)

Now we are ready to test everything. Let’s declare a small Cloud SQL instance in main.tf

resource "google_sql_database_instance" "test-db" {
  name = "test-instance"
  region      = "${var.gce_region}"

  settings {
    tier = "db-f1-micro"
  }
}

and then execute

terraform plan
terraform apply

You will be asked for the value of gce_project variable - provide it and continue. Also, you should see an error stating some access restrictions to API. Normally not all Google APIs are activated by default. But normally this kind of error points you to a particular URL where you can activate API access once. Even after the activation, it may take several minutes, but then it works.

If you like destroy your resources with:

terraform destroy

At this point, you might think about further improvements. One of them is the remote state.

Configuring remote state

Remote states are a great feature when it comes to working in a team. To enable Remote state with GCP you only need to define backend and initialize new configuration.

Unfortunately, backend configuration does not support variable interpolation. Even if it not that sensitive information like access.key I probably do not want to show it to everyone. Therefore my solution for this now is to put backend configuration into a separate file e.g. local_config.tf and notice it in the .gitignore.

terraform {
  backend "gcs" {
    bucket  = "org.holbreich"
    path    = "terraform/default"
    project = "my_cool_project_id"
  }
}

This file will be omitted on commits, but considered by terraforming as long it’s in the same directory with the rest of the resource definitions. Now don’t forget to apply a new configuration:

terraform init

You will be asked if you want to migrate your local state to a new remote location…

However, not everything is shiny with Google Cloud integration at the moment. The relative fresh Environment States feature is not supported with GCE backend yet. From now you will receive errors if you try to work with environment states.

$ terraform env list
named states not supported

Also, state locking is not supported with GCS, which can get important too.

Summary

Even if not everything is supported to the degree of AWS terraform has good support of most important resources for GCE and additional features like “remote state”. Yes, environments should be supported by a remote state soon as well to make a better picture. Anyway, I would say it worth starting working with terraform to provision GCE. Existing infrastructure can be integrated with terraform import. I’ve tested it with several resources and it worked well even if the import feature is systematically not documented on resources (in contrast to AWS).

If you like you can check git repo with the code mentioned here (it may evolve in the future). And as always appreciate your comments.

Footnotes

  1. In fact, not only GOOGLE_CREDENTIALS is checked and also region and project can be defined via variables. Consult terraform documentation for more


Archived comments (6)

These comments were migrated from Disqus and are no longer accepting replies.

  • beatcracker

    Thanks for the writeup, very handy. Although Glcoud tool complains about:

    INVALID_ARGUMENT: Account [email protected] is of type "serviceAccount".
    Please set the type prefix to be "serviceAccount:".

    So the correct command for me was

    gcloud projects add-iam-policy-binding bar --member serviceAccount:[email protected] --role roles/editor

    .

  • AlexH

    Glad you liked it. Yes, thank for command correction, a mistake has slipped in. :)

  • Halil Kaya

    Thanks for the article. Have you used Terraform in production with Google Cloud? If so, have you faced its disadvantages comparing to AWS?

  • AlexH

    Actually i have more experiences with AWS and terraform than with google and i can tell you more about problems there... I would not expect more problem with google here yet, but i've used it only for small set of resources (in production as well).

    Do you have any specific concerns?

  • Halil Kaya

    Usually, Terraform is used with AWS by community and there are lots of examples and use cases for AWS again. Ansible's GCE module is not very effective, as you know. We're planning to move our whole infrastructure to Terraform and using Google Cloud. I'm curious about if we would face any disadvantage when doing this. I've researched it on some articles, but couldn't find any concerns up to now. I just wanted to ask if any of the disadvantages (if exists) that you have seen or not.

  • AlexH

    Ok. Unfortunately can't help you with a lot of praxis experince on GCE here. However as genrl thoughts. Your question is more about the quality of terraform's GCE provider and quality of GCE api that is the final limitation.

    I general, i think there are no big stones on your way, nothing that could stop you. Yes terraform started with AWS and was long time not recomendet for GCE, but meanwhile it's not the case. Maybe you should go through the docu in see whether the majority of GCE resources that you plan to use is present now? It was in my case.

    As well yesterday's release 0.10.0 marks the separation of development of terraform core and providers. It is to expect that the community behind the providers (including GCE) will grow and can also release bug-fixes or features faster and independent of the code. So even you run into something, very very special, there is a chance to fix it by contributing.

    And last but not least the quality of Googles APIs is usually very good, what i cannot state for AWS at some corners.