DEV Community

Cover image for Deploying a Web service with GCP compute & Terraform
Shubham Tiwary
Shubham Tiwary

Posted on

Deploying a Web service with GCP compute & Terraform

Let's start off with something simple:
GCP Compute is an on-cloud VM to run everything like your own machine.

We'll deploy a simple http web server container and make it accessible from anywhere.


Pre-Requisites:


Provision a GCP Compute Virtual Machine

We'll use terraform to quickly set this up. Terraform configs are written with "*.tf"
It contains information such as what resources (services) to run and what provider (service provider) to use.



.

First, make a "config.tf" file (or whatever you want, doesn't matter), and write these:

Define GCP to be the provider:

terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "6.8.0"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Terraform acts as a middleman, where its: us <-> terraform <-> aws/gcp/etc

So we ask it to use the terraform provider SDK for GCP services to be setup, this is the terraform block



.

Then pass some configuration for the GCP project:

provider "google" {
  project = "<your-gcp-project-id>" 
  region  = "asia-south2"   #delhi
  zone    = "asia-south2-b"
}
Enter fullscreen mode Exit fullscreen mode

I'm using my project ID and closer region, use whatever is closer to you. You can check regions and zones for GCP here


Then make another "main.tf" file in same dir (any name works just like before although).

Now, this is the main thing, the resource block, every service is defined in this order:

resource "google_compute_instance" "vm-instance" {
  name         = "vm-instance-tf"
  machine_type = "f1-micro"
  zone         = "asia-south2-b"

  boot_disk {
    initialize_params {
      image = "ubuntu-os-cloud/ubuntu-2204-lts"
    }
  } 

  tags = ["allow-web-ssh"]
}
Enter fullscreen mode Exit fullscreen mode

This defines a resource block for making a f1-micro (the smallest VM) with ubuntu-22 OS

How to actually format these reources blocks in terraform can be referenced from here

The format for a resource block is:

resource "<type>" "<name-for-terraform>" {
   name = "<name-for-gcp>"
}
Enter fullscreen mode Exit fullscreen mode

Just don't get confused between the names here (will come handy later)



.

Now, VMs are like our local machines, the only difference being the Network configuration we have to setup to make it accessible. So let's do that:

resource "google_compute_network" "vpc_network" {
  name = "terraform-network"
}

resource "google_compute_firewall" "vm-firewall" {
  name    = "vm-firewall"
  network = google_compute_network.vpc_network.name

  allow {
    protocol = "tcp"
    ports    = ["22", "80", "443", "8080"]
  }

  #access from anywhere (dev mode)
  source_ranges = ["0.0.0.0/0"]
  target_tags   = ["allow-web-ssh"]
}
Enter fullscreen mode Exit fullscreen mode

Define a network firewall resource (just like compute), similarly, any roles, properties to be added are also made into individual resources.

And add this to update the VM resource block for access in these ports:

resource "google_compute_instance" "vm-instance" {
  name         = "vm-instance-tf"
  machine_type = "f1-micro"
  zone         = "asia-south2-b"

  boot_disk {
    initialize_params {
      image = "ubuntu-os-cloud/ubuntu-2204-lts"
    }
  }

  network_interface {
    network       = google_compute_network.vpc_network.name
    access_config {}
  }

  tags = ["allow-web-ssh"]
}
Enter fullscreen mode Exit fullscreen mode

In Terraform, to provision, we have the init -> plan -> apply process.

  • Init: setup dependencies, providers, etc (run first time)
  • Plan: make changes (after any change in config)
  • Apply: apply those changes planned.

Now, regardless of what filenames you have, as long as they end in "*.tf", it'll be counted in this.

So perform these commands:

terraform init
Enter fullscreen mode Exit fullscreen mode
terraform plan  #check and confirm the changes
Enter fullscreen mode Exit fullscreen mode
terraform apply  #see whether it passes
Enter fullscreen mode Exit fullscreen mode

Setup Web Server on this GCP VM

After setup is successful, ssh into the machine with gcloud (will work after doing gcloud auth, if failing, do that first):

gcloud compute ssh vm-instance-tf --zone=<your-zone>
Enter fullscreen mode Exit fullscreen mode

Then, quickly setup Docker (go checkout my series on docker for more detail) or by following the guide in this link

And run this custom container for testing a web app:

docker run -d --name test-go-web-app -p 8080:8080 sardinesszsz/go-hello:v2
Enter fullscreen mode Exit fullscreen mode

Now the web app should run, test it with a HTTP GET request:

curl -X GET http://localhost:8080/  #returns Hello-World!
Enter fullscreen mode Exit fullscreen mode

Each VM has a ephemeral IP which is public for access, since we made port 8080 accessible, we can use this IP for HTTP calls on port 8080 to call this web server.

Get the public IP of this VM with gcloud again:

gcloud compute instances describe vm-instance-tf --zone=<your-zone> --format='get(networkInterfaces[0].accessConfigs[0].natIP)'
Enter fullscreen mode Exit fullscreen mode

Suppose you got 10.10.10.10 as the IP, then make a call on this IP:

curl -X GET http://10.10.10.10:8080/
Enter fullscreen mode Exit fullscreen mode

That should successfully retrieve the response, if not follow this through, and try seeing what the issue could be or doubts in the comments are welcome!


So with Terraform, you didn't even have to go to GCP cloud console! Everything is done here in terminal with very less friction once one gets used to it.

This was a lot to take it (if you're new to Terraform or GCP), but slowly, I'll try to cover more so it can sink in well.

P.S: for destroying the service, make sure to go into the dir with the terraform files and run:

terraform destroy
Enter fullscreen mode Exit fullscreen mode

Top comments (0)