Unplanned IaC
Navigating the software development landscape often feels like deciphering a buzzword labyrinth — DevOps, Platform Engineering, Infrastructure as Code (IaC). These terms become learning priorities, especially when they dominate the “required skills” section of every DevOps job listing. However, my initiation into IaC wasn’t a result of a deliberate pursuit. Instead, it unfolded out of the blue, courtesy of an unplanned migration to a new Google Cloud Platform (GCP) project.
A Console-Centric Approach to Infrastructure
In my initial days of building on GCP, I leaned heavily on the console for everything — from spinning up virtual machines to crafting service accounts with specific permissions and configuring firewalls. Fast forward to the migration phase, and the thought of manually provisioning every single resource hit me like a ton of bricks. The whole process felt needlessly laborious.
The Solo Struggle
Compounding the challenge was my startup-esque work environment, where I single-handedly managed the entire infrastructure. The stakes were high, as this arrangement meant that the entirety of system knowledge resided in my mind. The absence of IaC felt like a potential setup for my team’s failure.
The Transition to IaC
The call for transitioning to the new GCP project came down from the higher-ups at an unexpected mere three hours before the workday’s end. I found myself facing the challenge of provisioning every piece of infrastructure within this tight timeframe. The twist? I was determined to tackle it all with IaC this time.
In a race against the clock, my choice of IaC tool was crucial. With just three hours to learn, implement, and ensure a seamless transition, Terraform emerged as my tool of choice — a decision driven by its speedy learning curve and an abundance of well-documented resources.
Here’s a rundown of the steps I followed in navigating this transition:
Step 1: Listing out all the resources I needed to re-provision
- Compute Engines
- Cloud SQL database instances
- Artifact Registry Repositories
- Cloud Storage buckets
- Service accounts with distinct permissions for the above instances
- Definition of Firewall rules
Step 2: Downloading and installing Terraform so that I could begin writing IaC.
Step 3: Creating a Google Cloud Service Account
Terraform requires a Google Cloud service account with specific permissions to manage the resources. Based on my list of things I needed to provision, I gave this service account the following permissions:
- Create Service Accounts
- Project IAM Admin
- Artifact Registry Administrator
- Cloud SQL Admin
- Compute Admin
- Storage Admin
I enabled these APIs through the Google Cloud Console in the APIs and Services
section.
I also downloaded the the service account credentials (as a JSON key file) so that they were available and correctly configured in my environment. I used these credentials to authenticate Terraform with my GCP project.
Step 4: Creating a folder structure for my infrastructure
Here’s how I structured my Terraform project: I created a directory called infrastructure
, which contained the following Terraform files.
- provider.tf: This file defines the GCP provider configuration. In the context of Terraform, a “provider” allows Terraform to interact with a specific cloud or infrastructure platform. I used it to establish the connection between my Terraform configuration and GCP.
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "5.0.0"
}
}
}
provider "google" {
credentials = file(var.gcp_svc_key)
project = var.gcp_project
region = var.gcp_region
}
In the above snippet, the google provider is specified, and its version is locked to ensure consistent behavior. The provider “google” block contains essential details like credentials, project, and region. It acts as the bridge enabling Terraform to interact seamlessly with GCP resources.
Now is also a good time to mention that the JSON-like language in which we specify Terraform configurations is called HCL (HashiCorp Configuration Language).
main.tf: In here, I laid out resource configurations for various components — service accounts, firewall rules, Compute instances, Cloud Storage instances, Cloud SQL instances, and Artifact Registry repository instances. I relied on Terraform’s extensive documentation to configure these GCP resources.
variables.tf: In this file, I defined variables that acted as placeholders for values that might change across my Terraform configuration.
variable "gcp_svc_key" {
}
variable "gcp_project" {
}
variable "gcp_region" {
}
... (more variables here)
- terraform.tfvars : Here’s where I specified actual values for the variables defined in
variables.tf
, configuring the details for my deployments.
gcp_svc_key = "path/to/service_account_credential_for_terraform.json"
gcp_project = "my-gcp-project-name"
gcp_region = "my-gcp-project-region"
... (more variables here)
Step 5: Initializing Terraform
I navigated to the infrastructure directory and ran the following command:
terraform init
This step will create the Terraform State Files
and .terraform.lock.hcl
Terraform uses state files to track the current state of the infrastructure. These files are automatically managed by Terraform and should not be manually modified:
- .terraform/: Contains provider plugins and provider-specific data.
- terraform.tfstate: The default state file that tracks the state of the infrastructure.
- terraform.tfstate.backup: A backup of the state file from the previous run. Useful for recovery in case of errors.
The .terraform.lock.hcl
locks the versions of providers and modules to prevent unintended upgrades or changes and ensures consistency in infrastructure deployments.
Step 6: Previewing and Applying Changes
I ran
terraform plan
to preview changes. Although optional, this step acts as a safeguard, and it helped me assess whether the configuration I described aligned with my expectations.
After I was happy with the preview, I ran
terraform apply
to create resources on GCP (can be also used for modifying these resources). I confirmed the action, by typing a yes
when prompted, and within a few seconds I had my new infrastructure ready.
Step 7: Pushing changes to GitHub to track and manage infrastructure code changes. (This is very important for state tracking.)
Parting thoughts
Embracing IaC using Terraform wasn’t just a practical move but a game-changer. I was able to streamline what would to be hours of manual work into a swift execution of less than a minute, while also creating a thorough snapshot of my infrastructure and all its components. In hindsight, I wish I had made this move earlier.