We will be using Terraform to initialize the GCP environment. This article will take you step by step from creating a Service Account to GCS and saving Terraform State for version control.

Preparation

Installing Terraform

Please refer to the Official Terraform Documentation to install Terraform. MacOS can be installed using Homebrew.

1
brew install terraform

Installing Google Cloud SDK

Please refer to the Google Cloud SDK official documentation to install Google Cloud SDK. MacOS can be installed using Homebrew.

1
brew install --cask google-cloud-sdk

Once the installation is complete, use the following command to log in to your Google Cloud account.

1
gcloud auth application-default login

Create a Service Account on GCP

Make sure that the Google Cloud SDK is installed and set up, and that you are logged into your Google Cloud account. You can run the following commands to check if the gcloud tools are correctly installed.

1
2
3
4
5
6
7
$ gcloud version
Google Cloud SDK 432.0.0
bq 2.0.93
core 2023.05.19
gcloud-crc32c 1.0.0
gke-gcloud-auth-plugin 0.5.3
gsutil 5.24

Next, use the following command to create a service account.

1
2
gcloud iam service-accounts create [SERVICE_ACCOUNT_NAME] \
  --display-name "[DISPLAY_NAME]"

Replace [SERVICE_ACCOUNT_NAME] with the name of the service account you want to create and [DISPLAY_NAME] with the appropriate display name.

After creating a service account, you can add the required roles/permissions to that account. For example, if you want to assign the service account as the project owner, run the following command.

1
2
3
gcloud projects add-iam-policy-binding [PROJECT_ID] \
    --member "serviceAccount:[SERVICE_ACCOUNT_EMAIL]" \
    --role roles/owner

Replace [PROJECT_ID] with your project ID and [SERVICE_ACCOUNT_EMAIL] with the email address of the service account you just created.

After completing the above steps, you have successfully created a service account using the gcloud command and assigned it the appropriate roles/permissions. Next, you can use the following command to create a service account key.

1
2
gcloud iam service-accounts keys create [FILE_NAME].json \
  --iam-account [SERVICE_ACCOUNT_EMAIL]

Replace [FILE_NAME] with the name of the key file you want to create and [SERVICE_ACCOUNT_EMAIL] with the email address of the service account you just created. Please keep this key file in a safe place because you will need to use it later.

Create Terraform Profile

Please refer to the Official Terraform Documentation to create a Terraform profile. You can use the following commands to initialize Terraform.

1
terraform init

Next, please set project, credentials, region, zone in the main.tf file as your GCP project information.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "4.66.0"
    }
  }

  required_version = ">= 0.14"
}

provider "google" {
  project     = "your-project-id"
  credentials = file("your-service-account-key.json")
  region      = "asia-east1"
  zone        = "asia-east1-a"
}

The credentials parameter is the key file of the service account you just created. Here you can use terraform.tfvars to set it.

1
2
3
4
project     = "your-project-id"
credentials = "your-service-account-key.json"
region      = "asia-east1"
zone        = "asia-east1-a"

In addition to setting credentials, you can also use the GOOGLE_APPLICATION_CREDENTIALS environment variable to set the path to the service account key file.

1
export GOOGLE_APPLICATION_CREDENTIALS="your-service-account-key.json"

Create GCP resources

Create the main.tf file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "4.66.0"
    }
  }

  required_version = ">= 0.14"
}

variable "project_id" {
  description = "project id"
}

variable "region" {
  description = "region"
}

variable "zone" {
  description = "zone"
}

provider "google" {
  project = var.project_id
  region  = var.region
  zone    = var.zone
}

Create VPC resources.

1
2
3
4
5
# VPC
resource "google_compute_network" "tf-vpc" {
  name                    = "${var.project_id}-tf-vpc"
  auto_create_subnetworks = "false"
}

After completing the above steps, you can use the following commands to preview the resources that Terraform will create.

1
terraform plan

If there are no problems with the preview results, you can use the following commands to create resources.

1
terraform apply

Save Terraform State to GCS

After running the above steps, you will find a terraform.tfstate file at the bottom of the directory. This file is used to record the status of resources managed by Terraform and the correlation between resources. If you want to save this file to GCS, you can use Terraform to create GCS-related resources.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# GCS
resource "random_id" "bucket_prefix" {
  byte_length = 8
}

resource "google_storage_bucket" "tf-state-bucket-demo" {
  name     = "tf-state-bucket-demo-${random_id.bucket_prefix.hex}"
  force_destroy = false
  location      = "US"
  storage_class = "STANDARD"
  versioning {
    enabled = true
  }
}

Output the GCS bucket name.

1
2
3
output "tf_state_bucket" {
  value = google_storage_bucket.tf-state-bucket.name
}

The following results can be seen.

1
2
3
4
5
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Outputs:

tf_state_bucket = tf-state-bucket-demo-5704c463dc9b78df

Open the main.tf file and add the following settings to the terraform main settings.

1
2
3
4
  backend "gcs" {
    bucket = "tf-state-bucket-demo-5704c463dc9b78df"
    prefix = "terraform/state"
  }

Do the terraform init again and you will see the following result.

1
2
3
4
5
6
7
8
9
Initializing the backend...
Acquiring state lock. This may take a few moments...
Do you want to copy existing state to the new backend?
  Pre-existing state was found while migrating the previous "local" backend to the
  newly configured "gcs" backend. No existing state was found in the newly
  configured "gcs" backend. Do you want to copy this state to the new "gcs"
  backend? Enter "yes" to copy and "no" to start with an empty state.

  Enter a value:

Enter yes and you will see the results below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Successfully configured the backend "gcs"! Terraform will automatically
use this backend unless the backend configuration changes.

Initializing provider plugins...
- Reusing previous version of hashicorp/google from the dependency lock file
- Reusing previous version of hashicorp/random from the dependency lock file
- Using previously-installed hashicorp/google v4.66.0
- Using previously-installed hashicorp/random v3.5.1

Terraform has been successfully initialized!

This will allow you to save and version control the Terraform state through GCS. Finally, the following files can be deleted.

1
2
rm terraform.tfstate
rm terraform.tfstate.backup

Delete GCP Resources

If you want to delete a resource you just created, you can use the following command.

1
terraform destroy

For full example code, please refer to terraform-gcp-demo.

Ref