Terraform can manage Minikube Kubernetes resources, but it won’t provision the Minikube cluster itself.
Let’s see it in action. Imagine you have a simple main.tf like this:
provider "kubernetes" {
config_path = "~/.kube/config"
}
resource "kubernetes_deployment" "nginx" {
metadata {
name = "nginx-deployment"
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"
ports {
container_port = 80
}
}
}
}
}
}
resource "kubernetes_service" "nginx" {
metadata {
name = "nginx-service"
}
spec {
selector = {
app = "nginx"
}
port {
port = 80
target_port = 80
}
type = "LoadBalancer"
}
}
Before terraform apply, you need a running Minikube cluster. The command minikube start with default settings is usually sufficient. Minikube spins up a single-node Kubernetes cluster within a VM or container on your local machine. It then configures your ~/.kube/config file to point to this local cluster. Terraform, by default, reads this ~/.kube/config file. So, when you run terraform apply, Terraform uses the credentials in your config to talk to the Minikube API server and create the nginx-deployment and nginx-service resources.
The kubernetes_deployment resource tells Kubernetes to ensure a specific number of pods (replicas) are running with a particular container image (nginx:1.21.6). Kubernetes’ controller manager watches this deployment and creates or deletes pods to match the desired state. The kubernetes_service of type LoadBalancer is where Minikube’s magic happens locally. Minikube includes a built-in load balancer implementation (often MetalLB or a similar component) that intercepts requests to the service’s external IP and directs them to the correct pods.
The core problem Terraform solves here is declarative infrastructure management. Instead of manually running kubectl create deployment ... and kubectl create service ..., you define the desired state in HCL (HashiCorp Configuration Language). Terraform then figures out the difference between your desired state and the current state in your Minikube cluster and applies the necessary kubectl commands (under the hood) to reconcile them. This makes your infrastructure repeatable, version-controllable, and easier to manage.
The type = "LoadBalancer" for the service is particularly interesting in a Minikube context. Unlike cloud providers where a true load balancer is provisioned, Minikube simulates this. It allocates an IP address from a predefined range (often 192.168.49.2 for the Minikube VM itself, or a different range depending on your Minikube network driver) and sets up internal routing to expose your service. You can find this IP by running minikube service <service-name> --url or by inspecting the service details with kubectl get svc nginx-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}'.
When you run terraform destroy, Terraform reads your state file, understands what resources it created, and issues the corresponding delete commands to the Kubernetes API server, effectively cleaning up the deployment and service from your Minikube cluster.
The provider "kubernetes" block is crucial. It tells Terraform how to communicate with your Kubernetes cluster. The config_path argument points to your kubeconfig file, which contains the API server endpoint and authentication details. If you’re using multiple Kubernetes contexts (e.g., Minikube, a remote cluster), you might need to explicitly set the context in your kubeconfig or within the provider block itself to ensure Terraform targets the correct cluster.
What most people don’t realize is how the LoadBalancer service type behaves differently across environments. In Minikube, it’s a simulated load balancer, often managed by components that come bundled with Minikube itself. On a cloud provider like AWS or GCP, it provisions a managed cloud load balancer service. Terraform abstracts this difference, allowing you to write the same configuration and have it work (mostly) in different environments, relying on the underlying Kubernetes provider or cloud provider integration to handle the specifics.
The next concept you’ll likely explore is managing Minikube addons with Terraform.