Creating a Kubernetes Cluster via Terraform

Infrastructure should be reproducible just like the other components in the software world. Most of the configurations and settings have been done manually through guidelines and documentation traditional infrastructure and platform engineering. Any decision to change something on the platform needs to be documented in order to keep track of the current status. However, it is a common pitfall to forget updating the documentation among engineers. I love documentation but keeping history is much easier using one of the version control systems such as git! It makes things a lot more transparent if you define your infrastructure as code. The knowledge is not only in somebody's head but also in a place where your whole team can rerun everything when things are down. Then I met Terraform.

In this blog post we will be creating a Kubernetes Cluster on Google Cloud Platform using Terraform.

Terraform is a tool to “Use Infrastructure as Code to provision and manage any cloud, infrastructure, or service”. It is a life saving tool that allows you to manage most of your services. I love it. I hope you will like it too!

Okay, let's get our hands dirty. First things first, start with opening your favorite IDE. My favorite is PyCharm. But I am going to use Visual Studio Code for this tutorial. I am creating a new folder called “terraform-kubernetes” and will open the project in VSC. I will be installing a Terraform plugin in my VSC that has linting and formatting features which is very helpful.

Next Step: Install Terraform

If you use Mac, install it via brew;

brew install terraform

I have a Ubuntu machine. So, I installed following the steps below;

  1. Install unzip
    sudo apt-get install unzip
  2. Choose the version that you want to install. You can find the change log in its GitHub repo.
  3. At this point in time I downloaded the latest version from Terraform Downloads.
  4. Unzip it:
    unzip terraform_0.12.24_linux_amd64.zip
  5. Install it:
    sudo install terraform /usr/local/bin/
  6. Let’s see if it is working
    terraform

Woohoo! You just installed Terraform. We are ready to go!

The next step is creating a Google Cloud project. We will need the ID of that project.

For this tutorial we are going to use Kubernetes on GCP. Go ahead and enable Kubernetes API for your project!

You can enable it from the following link, make sure you update the project_id to yours:

https://console.cloud.google.com/apis/api/container.googleapis.com/overview?project=project_id

For example this is the URL for my project:

https://console.cloud.google.com/apis/api/container.googleapis.com/overview?project=terraform-selin

Now we are ready to start writing our first Terraform configuration. Let’s go back to Visual Studio Code and create a file called main.tf.

We need to tell Terraform which provider we are going to use. A provider understands the API interactions for the given provider. In this case we are going to use Google Cloud Platform. So, the provider name will be google. This main.tf file will be the place we are going to connect our Terraform project with Google Cloud project.

The file should look something like this below;

provider "google" {
    project = <project>
    region = <region>
    zone = <zone>
}

We can pass the values of the variables directly in this file. But I don’t like that so much. Variables help labeling values with a descriptive name. It is much easier to read the code when the variables are used. Let’s create a file called variables.tf under the root directory of the project.

variables.tf

variable "project" {
   description  = "My Google project id"
   default = "terraform-selin"
}

variable "region" {
   description  = "Europe West region NL"
   default = "europe-west4"
}

variable "zone" {
   description  = "Europe West region NL"
   default = "europe-west4-a"
}

Update the default value in the “project_id” variable with your own project id. For my case it is GKE

Here:

Get the project id

I am going to go ahead and update the values on my main.tf file with reading from variables.tf file.

main.tf


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

We want to install Kubernetes, so I will be creating a different directory for that to keep the repository clean and readable. Let’s create a folder called kubernetes (Google Kubernetes Engine)

mkdir kubernetes

So, under this directory I’ll be describing what kind of Kubernetes cluster I want to create.
So, we will be using google_container_cluster resource to do that. Let’s create a file called main-k8s.tf and variables.tf under the kubernetes folder.

Your folder structure should look like this:

Folder structure

In the variables I’ll define the machine type and the region for the cluster. I am using “n1-standard-1” which is the smallest machine at this point in time.

gke/variables.tf

variable "region" {
   description  = "Europe West region NL"
   default = "europe-west4"
}

variable "machine-type" {
   description  = "The default type of machine"
   default = "n1-standard-1"
}

Now, we will write down the configuration for the google_container_cluster resource. Give a unique name to your kubernetes cluster. Location is the region information. google_container_node _pool manages a node pool in GKE cluster.

gke/main.tf

resource "google_container_cluster" "my_gke_cluster" {
   name = "selin-k8s-terraform"
   location = var.region
   initial_node_count = 1
}

resource "google_container_node_pool" "preemptible_nodes" {
 name       = "selin-node-pool"
 location   = var.region
 cluster    = google_container_cluster.my_gke_cluster.name
 node_count = 1

 node_config {
   preemptible  = true
   machine_type = var.machine-type

   metadata = {
     disable-legacy-endpoints = "true"
   }

   oauth_scopes = [
     "https://www.googleapis.com/auth/logging.write",
     "https://www.googleapis.com/auth/monitoring",
   ]
 }
}

We need to login to Google Cloud Project in order to communicate with it. I am going to use my own credentials. Execute the command below;

gcloud auth application-default login

We need to initialize a Terraform working directory. Execute the command:

terraform init

It is time to execute my favorite command in Terraform. Terraform plan! This command is used to prepare the execution of the plan. We can see the entire changes that will take place. We can also give specific names to a plan with -out parameter.

terraform plan -out kubernetes-plan

What message did you see? Did it say “No changes. Infrastructure is up-to-date.”? Yes, because first Terraform reads the main.tf file. There are only project configurations stated in the main.tf file. We need to add our Kubernetes module here.

So, I am adding the piece of code below to my main.tf file

module "kubernetes_cluster" {
   source = "./kubernetes"
}

We execute the init command again to install all modules required by this configuration

terraform init

Make sure all the configuration are valid using the command below;

terraform validate

Let’s execute our plan again

terraform plan -out kubernetes-plan

We need to see a message “This plan was saved to: kubernetes-plan”. If you see an error message instead of this one, please go back to your configuration and check if something is wrong.
It is time to apply all the changes that are planned.

terraform apply

Type yes and hit Enter to approve the change.

You did it! It is going to take a couple of minutes to get all the services up and running.

Let’s look at the visual graph of Terraform resources using graph command

terraform graph

If you want to destroy the resources that are created use the command below;

terraform destroy

Here you can find the code on GitHub.

I hope you enjoyed this post. If you have any questions or remarks, leave a comment! Stay tuned!