
Terraform is a common choice for Infrastructure as Code (IaC), and it manages Kubernetes through a set of providers. A provider is a plugin that takes your declarative configuration and turns it into calls against the Kubernetes API or a cloud's API.
This post covers how those providers work, which ones you actually need for Kubernetes, and what changes once you run them across more than a handful of clusters and teams.
A Terraform Provider is a plugin that lets Terraform talk to a specific API. Think of it as a translator. You write what you want in HashiCorp Configuration Language (HCL), and the provider turns that into the exact API calls the target platform needs, whether that's AWS, Azure, Google Cloud, or, in our case, Kubernetes.
If you know Kubernetes, providers are like client libraries with a declarative model. You define the desired state of your Kubernetes resources (Deployments, Services, Namespaces, etc.), and the provider figures out how to get there.
The typical workflow involves:
terraform init: Downloads and initializes the necessary providers.terraform plan: Shows you what changes the provider will make to reach your desired state.terraform apply: Executes the plan and makes the changes.This plugin-based architecture keeps Terraform core lean and lets it support a lot of services.
A few providers do the bulk of the work when you manage Kubernetes environments with Terraform.
The hashicorp/kubernetes provider is your main tool for managing resources directly inside a Kubernetes cluster. It can manage almost any Kubernetes API object:
kubernetes_manifest resource, which supports Server-Side Apply (SSA).Authentication is flexible, supporting kubeconfig files, service account tokens, client certificates, and exec plugins for cloud-specific authentication (e.g., for EKS, AKS, GKE).
Code Sample: Managing a Kubernetes Namespace and Deployment
provider "kubernetes" {
# Configuration for connecting to your K8s cluster
# e.g., using kubeconfig
config_path = "~/.kube/config"
config_context = "my-dev-cluster"
}
resource "kubernetes_namespace" "example_ns" {
metadata {
name = "app-namespace"
}
}
resource "kubernetes_deployment" "example_app" {
metadata {
name = "nginx-deployment"
namespace = kubernetes_namespace.example_ns.metadata[0].name
labels = {
app = "nginx"
}
}
spec {
replicas = 2
selector {
match_labels = {
app = "nginx"
}
}
template {
metadata {
labels = {
app = "nginx"
}
}
spec {
container {
image = "nginx:1.21.6"
name = "nginx"
port {
container_port = 80
}
}
}
}
}
}This example defines a namespace and a simple Nginx deployment within that namespace.
Helm is the de facto package manager for Kubernetes. The hashicorp/helm provider pulls Helm into your Terraform workflow so you can manage Helm chart releases declaratively.
That's handy when you're deploying third-party apps or your own internal apps packaged as charts.
Code Sample: Deploying a Helm Chart
provider "helm" {
kubernetes {
config_path = "~/.kube/config"
config_context = "my-dev-cluster"
}
}
resource "helm_release" "prometheus" {
name = "prometheus"
repository = "https://prometheus-community.github.io/helm-charts"
chart = "prometheus"
namespace = "monitoring"
version = "15.0.0" // Specify chart version for consistency
create_namespace = true // Ensure the namespace exists
values = [
<<YAML
server:
persistentVolume:
enabled: false # For simplicity in this example
alertmanager:
persistentVolume:
enabled: false # For simplicity in this example
YAML
]
# Optional: Wait for resources to be ready
atomic = true
timeout = 300
}This example deploys the Prometheus Helm chart into a 'monitoring' namespace.
Before you can manage resources inside Kubernetes, you often need to provision the cluster itself. This is where cloud-specific providers come in:
hashicorp/aws: For Amazon EKS.hashicorp/azurerm: For Azure AKS.hashicorp/google: For Google GKE.These providers manage the control plane, node groups, networking, and the rest of the underlying cloud infrastructure your Kubernetes workloads run on.
Using Terraform for Kubernetes gives you a few real benefits:
One tool and one language cover your entire infrastructure, from cloud resources like VPCs and databases to the Kubernetes cluster and the applications within it. Terraform's state file tracks your managed resources, which makes planning accurate and deployments consistent, and it helps you detect and remediate configuration drift. With modules, you can build reusable components for common Kubernetes patterns or entire cluster setups, which enforces best practices and speeds up deployments.
Terraform is powerful, but Kubernetes-native tools like kubectl, Kustomize, and GitOps tools (ArgoCD, FluxCD) have their own strengths. A common pattern that works well is "Terraform for Platform, GitOps for Apps":
This hybrid approach uses Terraform's strengths for infrastructure provisioning and the agility of GitOps for application delivery. If you want to think through exactly where that line should fall, we cover it in Terraform vs GitOps for Kubernetes. But as environments grow, coordinating these layers, managing Terraform state across teams, and enforcing consistent policies gets complicated.
As more organizations run Terraform for Kubernetes, especially in larger or more complex environments, managing it well becomes the hard part. The usual challenges show up in areas like:
This is where platforms like Scalr help. Scalr is built to handle these operational challenges by giving you a structured environment for Terraform runs. It provides features such as:
By adding a management layer, platforms like Scalr help teams get the most out of Terraform for Kubernetes without drowning in the overhead of managing Terraform itself at scale. That lets platform teams give developers a self-service IaC experience while keeping governance and control.
| Provider Name | Type | Primary Use Case in Kubernetes Context | Key Notes |
|---|---|---|---|
hashicorp/kubernetes |
Official | Manage Kubernetes API objects directly (Deployments, Services, CRDs) | Dedicated resources for common Kinds; kubernetes_manifest for arbitrary objects (uses Server-Side Apply). |
hashicorp/helm |
Official | Deploy and manage applications packaged as Helm charts. | Manages helm_release resources; integrates Helm lifecycle into Terraform. |
hashicorp/aws |
Official | Provision and manage Amazon EKS clusters & related AWS infrastructure. | Manages EKS control plane, node groups, VPCs, IAM roles. |
hashicorp/azurerm |
Official | Provision and manage Azure Kubernetes Service (AKS) & Azure resources. | Manages AKS control plane, node pools, virtual networks. |
hashicorp/google |
Official | Provision and manage Google Kubernetes Engine (GKE) & GCP resources. | Manages GKE clusters, node pools, VPC-native networking. |
gavinbunney/kubectl |
Community | Apply raw Kubernetes YAML manifests. | Alternative for YAML-centric workflows; evaluate maintenance status. |
Terraform providers are hard to do without if you want to apply Infrastructure as Code principles to your Kubernetes environments. They give you a declarative way to manage everything from the underlying cluster infrastructure to the apps running on it.
Once you know what the key providers do, like the official Kubernetes and Helm providers, and you pair them with cloud-specific providers, you can build one automated workflow. As your usage grows and scales, think about how platforms like Scalr can support your Terraform operations with governance, collaboration features, and the workflow automation you need to manage Kubernetes at scale.
