How to Run Kubernetes on Localhost (Terraform, Mac)
In this article, I will show you how to run Kubernetes locally (localhost). It's useful for people who need to teach themselves new skills or build a prototype without having to pay for hosting.

How do you run Kubernetes on a Mac?
You can run Kubernetes on a Mac (as localhost) using Docker for Desktop and Terraform.
I will show you how to set that up in the steps below.
Step 1. Install Terraform
You can find Terraform install instructions for Mac, Windows, and Linux here:
I followed the instructions for using brew to install it on my Mac.
On a Mac, you can install Terraform like this:
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
Check the version
To check the version, run this command:
terraform version
If you get a warning that your version is out of date, ignore the instructions to download and do this instead:
brew upgrade terraform
Step 2. Run Docker
To run Docker on a Mac, run this command from a terminal window:
open -a Docker
Step 3. Enable Kubernetes
On a Mac, open the Docker for Desktop Settings dialog. This can usually be found using the Docker icon in the top right main menu bar.
- Find the Kubernetes tab or window
- Check Enable Kubernetes
- If applicable, click Apply & Restart
I've noticed that this can take a while. But I've also had many issues with Docker for Desktop getting corrupt. If that happens then use the button to reset your environment. But only as a last resort if it seems to be stuck after 20 minutes.
There are alternative ways to run Kubernetes on a Mac. But that's beyond the scope of this article.
Step 4. Install kubectl
The command line tool that I use all the time to interact with Kubernetes is kubectl.
To install kubectl on a Mac, run the following:
brew install kubectl
If you already had it installed, that command will upgrade it.
Check the version
To check the version of kubectl, run this command:
kubectl version
Check that Kubernetes is configured properly
To check that Kubernetes is running properly, run this command:
kubectl cluster-info
On a typical Mac setup, you should see a line like this:
Kubernetes control plane is running at https://kubernetes.docker.internal:6443
We will need to verify that the setting matches in a later step.
Step 5. Create a project folder
To create a project folder, run these commands:
mkdir ~/projects/terraform/terraform-kubernetes-101
cd ~/projects/terraform/terraform-kubernetes-101
Step 6. Create a main.tf file
Terraform works by reading *.tf files. Those files contain declarative statements defining the cloud infrastructure you want to build. By default, it looks for a file called main.tf .
- Create a file called main.tf in the root of your project:
- Open main.tf in an IDE like Visual Studio Code (VS Code)
- If VS Code prompts you about extensions to support the *.tf file, go ahead and install them
touch main.tf
Step 7. Declare a provider
For this example, we're going to be working with Kubernetes. So we can specify the use of a Kubernetes provider.
In Terraform you can think of a provider as a plugin, that provides extra third-party resource types and data sources. You can use them to define your infrastructure.
To use the recommended Kubernetes provider, add this to the top of main.tf and save it:
# Configure Kubernetes provider and connect to the Kubernetes API server
provider "kubernetes" {
host = "https://localhost:6443"
config_context_cluster = "docker-desktop"
config_path = "~/.kube/config"
}
This setup assumes the standard defaults when running Kubernetes on a Mac using Docker for Desktop.
Verify settings
Verify the settings. If they don't match your environment, update the declaration above to match.
Verify host setting
To verify that the host setting matches the Kubernetes control plane (default: https://localhost:6443), run this command:
kubectl cluster-info
Verify config_context_cluster
To verify that the config_context_cluster setting matches the current Kubernetes context (default: docker-desktop), run this command:
kubectl config current-context
Verify config_path
By default on a Mac, your Kubernetes config (config_path above) should be here ~/.kube/config. You can verify that with this command:
ls -la ~/.kube/config
You can also check some of the settings with this command:
kubectl config view
Step 8. Declare a Kubernetes pod
Kubernetes is a "container orchestrator". You can run a container (like a Docker container) in what's known in Kubernetes as a pod. Going into detail is beyond the scope, but I will link to some references at the end of this article. For now, we just want to get a container up and running in a pod.
To declare a pod, add this block at the end of main.tf and save it:
# Create a pod
resource "kubernetes_pod" "random_server" {
metadata {
name = "random-example"
labels = {
App = "random_server"
}
}
spec {
container {
image = "mitchallen/random-server:latest"
name = "random"
port {
container_port = 3100
}
}
}
}
This declaration will create a pod using one of my random docker containers. By default, that container maps to port 3100.
You can add multiple pods to a Kubernetes cluster. But to keep things simple, here we are only adding one.
Step 9. Declare a Kubernetes service
Besides a pod, you usually need to also declare a Kubernetes service. Think of a service as a way to open up your container so it can be accessed by the outside world, usually using a port.
To declare a service, add this block at the end of main.tf and save it:
# Create a service
resource "kubernetes_service" "random" {
metadata {
name = "random-example"
}
spec {
selector = {
App = "${kubernetes_pod.random_server.metadata.0.labels.App}"
}
port {
port = 80
target_port = 3100
}
type = "NodePort"
}
}
The selector refers back to the metadata of the pod that was declared earlier. It also maps its port.
Step 10. Terraform init
The first thing you should always do with a new Terraform project is run this command (once):
terraform init
The command does several things to initialize the current directory to work with Terraform. For more information on the command, see the references section.
Step 11. Format the *.tf file
To format the main.tf file, do the following:
- Save all files in your project
- Run this command:
terraform fmt
It's an optional step that can keep your code clean and consistent.
Step 12. Run the plan
Once you've saved all the files, it's time to make a Terraform plan. Think of it as a dry run. Terraform parses your *.tf file(s) to determine how to build the infrastructure that you've defined. Or it may fail with an error - like if your docker host is incorrect.
Run this command to see if a plan can be generated successfully.
terraform plan
If you get an error regarding docker: either docker isn't running, or you need to try a different docker endpoint passed to the provider.
You may see a warning like this:
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
You can get by for this demo without creating an out file. But eventually, you should learn how to use them.
Step 13. Apply the plan
To actually make the changes, run this command:
terraform apply
When prompted, type Yes to agree to apply the plan.
Hopefully you will get a response like this while your project is being created:
kubernetes_pod.random_server: Creating...
kubernetes_pod.random_server: Creation complete after 6s [id=default/random-example]
kubernetes_service.random: Creating...
kubernetes_service.random: Creation complete after 1s [id=default/random-example]
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Step 14. Check the results
Once your project is up and running, check the pods with this command:
kubectl get pods
You should get back a response like this:
NAME READY STATUS RESTARTS AGE
random-example 1/1 Running 0 39s
The pod name (random-example) should match what was defined main.tf.
Step 15. Get the port
Now we have to figure out what port Kubernetes used for NodePort to make the service accessible to the outside world. To do that, run this command:
kubectl get svc random-example -o jsonpath='{.spec.ports[0].nodePort}'
On my Mac, I got back a port value of 30427. So to verify that my service is available I ran this command (adjust for whatever port was returned to you on your machine):
curl localhost:30427
You should see a response from my service like this:
{"status":"OK","app":"random-server","version":"1.0.2","uptime":"00:05:16","route":"/"}
Step 17. Check the services
Another way to get the NodePort is to look at the services. You can do that with this command:
kubectl get services
You should get back a response like this:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10....... <none> 443/TCP 79m
random-example NodePort 10......... <none> 80:30427/TCP 6s
See how the NodePort (30427 in my case) for the service (random-example) matches above?
Step 18. Generate a graph
Terraform has a graph command that can be used to create a visual representation of the plan. It does this by generating DOT code.
Run this command to see an example of the generated DOT code:
terraform graph -type=plan
Install dot
To turn the output of the graphic command into a picture, you need to install the special dot cli tool. For a Mac, you would do it like this:
brew install graphviz
For other operating systems, use this link to find install instructions:
Generate a plan picture
Once the dot utility is installed, you can pipe the instructions through it to turn the plan into a picture.
Run this command to:
- Turn the plan into dot code
- Pipe it through the dot utility and
- Open and view the result
terraform graph -type=plan | dot -Tpng > plan.png
open plan.png
Step 19. Cleanup
When you are done experimenting, Terraform makes it very easy to clean up.
You can remove the Kubernetes pods and services by running this command:
terraform destroy
- Type yes when asked to confirm
Verify cleanup
Run this command to verify that your pods were removed:
kubectl get pods
Step 20. Add .gitignore
The makers of Terraform have posted an example .gitignore file, which you can copy from here:
To use it:
- Create a new file called .gitignore in the root of your project
- Copy the contents from the file in the link to your .gitignore file and save it
Example project
You can find the example project here:
Conclusion
In this article, you learned how to:
- Install Terraform on a Mac
- Use Terraform to define a Kubernetes Infrastructure as Code (IaC)
- Install kubectl to interact with Kubernetes from the command-line
- Initiate, plan, and apply a Terraform project
- Define Kubernetes pods, services and ports
- Create a visual representation of a Terraform plan
- Clean up using a simple command
References
- developer.hashicorp.com/terraform - [1]
- developer.hashicorp.com/terraform/downloads - [2]
- github.com/hashicorp/terraform-provider-kubernetes - [3]
- kubernetes.io/docs/tasks/tools/install-kubectl-macos/ - [4]
- kubernetes.io/docs/reference/kubectl/cheatsheet/ - [5]
- www.redhat.com/sysadmin/kubeconfig - [6]
- www.redhat.com/en/topics/containers/what-is-kubernetes-pod - [7]
- hub.docker.com/r/mitchallen/random-server - [8]
- kubernetes.io/docs/concepts/services-networking/service/ - [9]
- kubernetes.io/docs/tutorials/kubernetes-basics/expose/expose-intro/ - [10]