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
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
- IAM Module (
modules/iam/
): Manages IAM roles and permissions. - VPC Module (
modules/vpc/
): Creates a VPC network and subnets. - GCS Module (
modules/gcs/
): Sets up Google Cloud Storage buckets. - VM Module (
modules/vm/
): Provisions virtual machines.
Environments
Each environment (dev, preprod, prod) has its own Terraform configuration files:
- 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
- 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.