How to Use Terraform with Kubernetes for Infrastructure as Code

Updated: January 30, 2024 By: Guest Contributor Post a comment

Introduction

Infrastructure as Code (IaC) is a key DevOps practice that involves managing and provisioning infrastructure through machine-readable definition files, rather than through physical hardware configuration or interactive configuration tools. In this tutorial, we will explore how to use Terraform, an open-source IaC tool developed by HashiCorp, in conjunction with Kubernetes, the popular container-orchestration system. By the end of this tutorial, you’ll have a solid understanding of deploying Kubernetes resources using Terraform.

Prerequisites

  • A basic understanding of Kubernetes concepts such as pods, services, and deployments
  • Terraform installed on your local machine
  • Kubectl installed and configured
  • Access to a Kubernetes cluster

Setting Up Your Terraform Configuration

First, create a new directory for your Terraform configuration files:

mkdir terraform-k8s
 cd terraform-k8s

Next, create a file named provider.tf that will specify the Kubernetes provider for Terraform:

terraform {
 required_providers {
   kubernetes = {
     source = "hashicorp/kubernetes"
   }
 }
}

provider "kubernetes" {
 config_path    = "path/to/your/kubeconfig"
}

Replace path/to/your/kubeconfig with the actual path to your Kubernetes configuration file.

Defining Your First Resource

With the provider set up, you can now define your first Kubernetes resource. Create a file named main.tf and define a simple Pod:

resource "kubernetes_pod" "nginx" {
 metadata {
   name = "nginx-example"
   labels {
     app = "nginx"
   }
 }
 spec {
   container {
     image = "nginx:1.19"
     name  = "nginx"
   }
 }
}

Initialize Terraform and apply the configuration:

terraform init
terraform apply

You should see output indicating that Terraform has created the Pod:

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Deploying More Complex Configurations

Let’s define a more complex scenario with a Deployment that has 3 replicas of the Nginx pod and a LoadBalancer Service to expose the application:

resource "kubernetes_deployment" "nginx-deployment" {
 metadata {
 name = "nginx-deployment"
 labels {
   app = "nginx"
 }
 }
 spec {
 replicas = 3
 selector {
   match_labels {
     app = "nginx"
   }
 }
 template {
   metadata {
     labels {
       app = "nginx"
     }
   }
 spec {
   container {
     image = "nginx:1.19"
     name  = "nginx"
   }
 }
 }
}

resource "kubernetes_service" "nginx" {
 metadata {
   name = "nginx-service"
 }
 spec {
   selector {
     app = "nginx"
   }
 type = "LoadBalancer"
 port {
   port        = 80
   target_port = 80
 }
}
}

Apply the updated configuration:

terraform apply

The output will show that Terraform created the Deployment and Service:

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Using Modules for Reusability

Terraform modules encapsulate and reuse resource configurations. To use a module, create a directory named modules, then define a module for an Nginx deployment and service:

// modules/nginx/main.tf

resource "kubernetes_deployment" "nginx" { /* ... */ }
resource "kubernetes_service" "nginx" { /* ... */ }

In your main.tf, call the module:

module "nginx" {
 source = "./modules/nginx"
}

Initialize and apply the changes:

terraform init
terraform apply

Terraform will use the module to create your resources, following the DRY (Don’t Repeat Yourself) principle.

Managing State with Terraform

Terraform keeps track of your infrastructure’s state, allowing for incremental changes and management of resources. It’s important to keep the Terraform state file secure and backed up. For team environments, consider using remote state backends like AWS S3 or Terraform Cloud to store and lock your state file.

Advanced Use Cases

Provisioning a Kubernetes Cluster with Terraform

Beyond managing resources in an existing cluster, Terraform can also provision the Kubernetes cluster itself. For example, you can use Terraform to create a cluster on a cloud provider like AWS, GCP, or Azure, though this usage would require additional provider configurations and resources specific to these services. We won’t dive deep into this, but you should be aware of this powerful capability.

Terraform Workspaces for Environment Management

When working with multiple environments (e.g., staging, production), Terraform workspaces allow you to manage distinct sets of infrastructure resources under the same configuration. This is much cleaner and safer than copying configuration files for each environment.

Best Practices

  • Commit your plans: Before applying changes, run terraform plan and commit the outcome to version control, so your team can review changes.
  • Continuous Integration: Set up CI pipelines to test and apply Terraform configurations.
  • Use Variables: Parameterize configurations using variables for flexibility and environment-specific values.
  • Read the Documentation: The Terraform documentation is a comprehensive resource to understand how to use different features and best practices.

Conclusion

Terraform empowers developers and operators to manage Kubernetes resources declaratively and predicts outcomes through its planning process. With its modular design and ability to manage the entire cluster life cycle, it’s an essential tool for scalable and efficient Kubernetes infrastructure management.