How you can provision GCP infrastructure including IAM, VPC, GCS, and VMs using Terraform with a modular approach and multiple environment support (dev, pre-prod, prod), along with automated deployment using GitHub Actions with authentication and authorization

Directory Structure

Biswanath Giri
3 min readJun 8, 2024
terraform/
├── modules/
│ ├── iam/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ ├── vpc/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ ├── gcs/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ └── vm/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── backend.tf
│ │ └── terraform.tfvars
│ ├── preprod/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── backend.tf
│ │ └── terraform.tfvars
│ └── prod/
│ ├── main.tf
│ ├── variables.tf
│ ├── backend.tf
│ └── terraform.tfvars
├── .github/
│ └── workflows/
│ └── terraform.yml
└── README.md

Modules

  1. IAM Module (modules/iam/): Manages IAM roles and permissions.
  2. VPC Module (modules/vpc/): Creates a VPC network and subnets.
  3. GCS Module (modules/gcs/): Sets up Google Cloud Storage buckets.
  4. VM Module (modules/vm/): Provisions virtual machines.

Environments

Each environment (dev, preprod, prod) has its own Terraform configuration files:

  1. Terraform Files (environments/{env}/):
  • main.tf: Defines the infrastructure resources using modules.
  • variables.tf: Declares environment-specific variables.
  • backend.tf: Configures Terraform backend for state storage.
  • terraform.tfvars: Specifies environment-specific values for variables.

GitHub Actions

  1. Terraform Workflow (.github/workflows/terraform.yml):
  • Triggers on push to specific branches (e.g., dev, preprod, prod).
  • Authenticates with Google Cloud using service account key.
  • Deploys Terraform configurations for the corresponding environment.

Example Terraform Configuration

Let’s take the dev environment as an example:

environments/dev/main.tf

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

module "iam" {
source = "../../modules/iam"
project_id = var.project_id
dev_iam_members = var.dev_iam_members
}

module "vpc" {
source = "../../modules/vpc"
project_id = var.project_id
region = var.region
dev_subnet_cidr = var.dev_subnet_cidr
}

module "gcs" {
source = "../../modules/gcs"
project_id = var.project_id
bucket_name = var.dev_bucket_name
}

module "vm" {
source = "../../modules/vm"
project_id = var.project_id
region = var.region
zone = var.zone
instance_count = var.dev_instance_count
}

environments/dev/variables.tf

variable "project_id" {
description = "Google Cloud Project ID"
}

variable "region" {
description = "GCP region"
}

variable "zone" {
description = "GCP zone"
}

variable "dev_iam_members" {
description = "IAM members for dev environment"
}

variable "dev_subnet_cidr" {
description = "CIDR block for dev subnet"
}

variable "dev_bucket_name" {
description = "GCS bucket name for dev environment"
}

variable "dev_instance_count" {
description = "Number of VM instances for dev environment"
}

.github/workflows/terraform.yml

name: Terraform

on:
push:
branches:
- main
- dev
pull_request:
branches:
- main
- dev

jobs:
terraform:
name: Terraform
runs-on: ubuntu-latest
env:
TF_VERSION: 1.0.0
TF_WORKING_DIR: ./path/to/your/terraform/files
GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GCP_SA_KEY }}

steps:
- name: Checkout repository
uses: actions/checkout@v2

- name: Setup Terraform
uses: hashicorp/setup-terraform@v1
with:
terraform_version: ${{ env.TF_VERSION }}

- name: Terraform Init
working-directory: ${{ env.TF_WORKING_DIR }}
run: terraform init

- name: Terraform Plan
working-directory: ${{ env.TF_WORKING_DIR }}
run: terraform plan

- name: Terraform Apply
working-directory: ${{ env.TF_WORKING_DIR }}
run: terraform apply -auto-approve -var-file=environments/${{ github.ref_name }}/terraform.tfvars

Additional Notes:

  • Make sure to define the environment-specific variable files (terraform.tfvars) in each environment directory (environments/dev/terraform.tfvars, environments/preprod/terraform.tfvars, environments/prod/terraform.tfvars).
  • Ensure your Terraform directory structure matches the path specified in TF_WORKING_DIR.

GitHub Actions workflow should correctly initialize, plan, and apply Terraform configurations for different environments based on the branch being pushed or the pull request target.

--

--

Biswanath Giri
Biswanath Giri

Written by Biswanath Giri

Cloud & AI Architect | Empowering People in Cloud Computing, Google Cloud AI/ML, and Google Workspace | Enabling Businesses on Their Cloud Journey

No responses yet