Running Kubernetes Locally via Minikube

In this post I'll show you have to run Kubernetes locally via Minikube, a basic understanding of Kubernetes is required. Lets get started!


Minikube is a tool that makes it easy to run Kubernetes locally. Minikube runs a single-node Kubernetes cluster inside a VM on your laptop for users looking to try out Kubernetes or develop with it day-to-day.

More documentation can be found on Github


k8s-scrum is the demo project that we will be using in this tutorial. The project contains 2 microservices: k8s-product-owner and k8s-developer.

k8s-product-owner has a REST endpoint mapped on '/meeting'. When the endpoint is called the product owner has a meeting with a couple of important people and they decide to request new development during an active sprint...

public DeveloperResponse addToActiveSprint() {"Requesting out of scope development");
    return restTemplate.getForObject("http://k8s-developer-service/develop", DeveloperResponse.class);

As you can see we are sending the request to 'k8s-developer-service', this is a regular Kubernetes service.

The k8s-developer microservice will receive develop request and will return an appropriate response back to the k8s-product-owner microservice:

public DeveloperResponse develop() {"Received new develop request during an active sprint");
    return new DeveloperResponse("Put it on the backlog!");

The code can be found on Github

Making it work

We first need to create the Kubernetes cluster (I use VirtualBox):

minikube start  

Once the cluster is started we need to be able to push docker images to the docker environment within Minikube:

eval $(minikube docker-env)  

Now run docker ps and docker images and you'll see something like this:

CONTAINER ID        IMAGE                                                        COMMAND                  CREATED             STATUS              PORTS               NAMES  
bf8d8677d0dd   "/dashboard --port=90"   5 minutes ago       Up 5 minutes                            k8s_kubernetes-dashboard.90e9da9f_kubernetes-dashboard-zw9pf_kube-system_8ed2ed5b-8d78-11e6-94cb-36f5793698cf_e9253648  
18ccd6bce12d                     "/pause"                 5 minutes ago       Up 5 minutes                            k8s_POD.2225036b_kubernetes-dashboard-zw9pf_kube-system_8ed2ed5b-8d78-11e6-94cb-36f5793698cf_fe538489  
76e143fa4be3         "/opt/"    5 minutes ago       Up 5 minutes                            k8s_kube-addon-manager.a1c58ca2_kube-addon-manager-minikube_kube-system_3e8322eb546e1d90d2fb7cac24d6d6a2_86db91dd  
371a813f1d05                     "/pause"                 6 minutes ago       Up 6 minutes                            k8s_POD.d8dbe16c_kube-addon-manager-minikube_kube-system_3e8322eb546e1d90d2fb7cac24d6d6a2_eea99a51
REPOSITORY                                            TAG                 IMAGE ID            CREATED             SIZE   v1.4.0              436faaeba2e2        2 weeks ago         86.27 MB     v2                  a876fb07f9c2        4 months ago        231.1 MB                  3.0                 99e59f495ffa        5 months ago        746.9 kB

Those are the containers/images configured by Minikube. Now lets push our own images into Minikube. Navigate into the microservices and run the following command in both of them:

mvn clean package docker:build  

When you run docker images you will see that we now have our images in the docker environment within Minikube:

REPOSITORY                                            TAG                 IMAGE ID            CREATED              SIZE  
jdruwe/k8s-developer                                  latest              f446544d04f0        21 seconds ago       195.5 MB  
jdruwe/k8s-product-owner                              latest              58ce7d2ff470        About a minute ago   195.5 MB  
frolvlad/alpine-oraclejdk8                            slim                f8103909759b        2 weeks ago          167.1 MB   v1.4.0              436faaeba2e2        2 weeks ago          86.27 MB     v2                  a876fb07f9c2        4 months ago         231.1 MB                  3.0                 99e59f495ffa        5 months ago         746.9 kB

We can now create a new Kubernetes deployment:

kubectl run k8s-product-owner --image=jdruwe/k8s-product-owner --port=8080 --image-pull-policy=Never  

Do the same for the other microservice:

kubectl run k8s-developer --image=jdruwe/k8s-developer --port=8080 --image-pull-policy=Never  

Remember to turn off the imagePullPolicy:Always, as otherwise kubernetes won't use images you built locally (it will use my public image on docker hub).

Open up the dashboard using 'minikube dashboard', you should see something like this:

Both deployments have 1 pod running by default, you can see the also using kubectl get pods.

We have the pods up and running so the next step would be to configure a LoadBalancer service to allow web traffic to the k8s-product-owner pod(s). This is external to Kubernetes. Unfortunately this is not supported at the moment in Minikube

Features that require a Cloud Provider will not work in Minikube. These include: LoadBalancers...

They do provide a workaround

Any services of type NodePort can be accessed over that IP address, on the NodePort. Lets create a service just doing that:

kubectl expose deployment k8s-product-owner --type=NodePort  

We can figure out its external IP address and port using the following command:

minikube service k8s-product-owner --url  

Navigating to the url and its meeting endpoint will fail at this moment because we did not configure a Kubernetes service for the developer pod(s) yet. Remember: ...k8s-developer-service... in the REST call? Create the service now:

kubectl expose deployment k8s-developer --port=80 --target-port=8080 --name=k8s-developer-service  

Lets try that REST call again:

The product-owner pod now calls and returns the response from the developer-pod!


You could try out scaling the k8s-developer deployment just for fun :)

kubectl scale --replicas=2 deployment/k8s-developer  

You should now have 2 pods running:

You can also view the registered endpoints (developer pods):

kubectl describe svc k8s-developer-service  

Calls to the service will now be distributed among its 2 running pods. If you have a comment or question just drop me a line below.