Terraform templates to deploy an API on GKE (Google Kubernetes Engine)
In 2 previous articles we have seen how it is possible to deploy an API based on the HAPI framework and create a Kubernetes cluster to for a single Flask application.
We’ll go a step further using Terraform to orchestrate the complete deployment:
- build the VPC and the GKE cluster inside
- build and push the container
- deploying it to the created cluster and expose it as a service
The application is a Node.js server based on the HAPI framework that will answer just with “OK” to root path. From there it is possible to enrich and evolve the application as anyone wants.
The complete code is available at https://github.com/manupeco/CloudCO2/tree/kubernetes-optimization/gke-optimizer
The application
The code is very simple. Everything is inside the server.js file that will create a server accepting connections from internet to the port 3000 and it will respond with “OK” to the root resource “/”.
In the repository, the server.js is inside the ‘api’ folder
The Dockerfile
The application is a classic Node.js application whose Dockerfile can look like this to expose the server on port 3000:
FROM node:16# Create app directory
WORKDIR /usr/src/app# Install app dependencies# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)COPY package*.json ./RUN npm install# If you are building your code for production
# RUN npm ci --only=production# Bundle app source
COPY . .EXPOSE 3000
CMD [ "node", "server.js" ]
Terraform templates for deployment
Run terraform init in the terraform folder to download the libraries to manage the kubernetes provider used in one of the Terraform templates in the project.
The template variables
All the Terraform templates will use the variables defined in variables.tf
Template for the VPC
The following is the Terraform template for the VPC and the subnet that will host our cluster (vpc.tf):
Create the cluster
The template to create the GKE cluster is gke-cluster.tf . It will create an autoscaling cluster with a node pool that can scale between 1 and 5 nodes.
It uses the network and subnet previously specified in the vpc.tf using their names. The default node is created and immediately removed during the creation of the cluster because a managed pool will be created later.
resource "google_container_cluster" "primary" {
name = "${var.project_id}-gke"
location = var.region # We can't create a cluster with no node pool defined, but we want to only use
# separately managed node pools. So we create the smallest possible default
# node pool and immediately delete it.
remove_default_node_pool = true
initial_node_count = 1
network = google_compute_network.vpc.name
subnetwork = google_compute_subnetwork.subnet.name
}
The template defines also the OAuth scopes that allow the cluster to write the logs, use the monitoring services and also read the storage to access the container registry where the application image is stored:
oauth_scopes = [
"https://www.googleapis.com/auth/logging.write",
"https://www.googleapis.com/auth/monitoring",
"https://www.googleapis.com/auth/devstorage.read_only"
]
This is the content of the template:
Application deployment
The template responsible to deploy the application is api.tf
The first resource builds and push the image (api-skaffold:v1) to the Google Container Registry
This will create (if not existing) the storage bucket to host container images. The access to this bucket is granted thanks to these 3 other sections of the template
Finally, the resources kubernetes_deployment and the kubernetes_service will create the application deployment and the services.
The service will expose the application on the port 3000 mapping it to the port 3000 of the running container.
The final template content is the following:
Deploy on GKE
Go to folder ‘gke-optimizer/terraform’ and run
terraform apply
The deployment will take several minutes and it will produce the following messages in the console:

The IP address assigned to the deployed services can be retrieved going to the section Services and Ingress of the Kubernetes Engine service on GCP (35.223.80.25 in the example below)

Visiting http://<Endpoint_address> the page below will show

Remove resources
Run the following commands to remove the resources previously deployed
terraform destroy