DevOps / Kubernetes / OpenShift

Kubernetes Minikube #1 – Configmaps, Storage, Ingress


Let’s mess around with Kubernetes’ Minikube and learn how to use it to launch an application with an ingress point, external configuration and volume claims. We will do this by reproducing a bunch of OpenShift MiniLabs and hack around with a bunch of kubectl commands and Kubernete’s yaml resource files in the process. Now for a picture of Adelaide.



This tutorial will cover the following:

  • Install Minikube and associated dependencies
  • Launch Minikube using VM-less technique
  • Create an application from an existing Docker image
  • Set up a Kubernetes ingress to access the application
  • Demonstrate use of Kubernetes configmaps
  • Use Kubernetes to create/claim a permanent volume



1. Install Software

The setup used here is for a Linux environment and required VirtualBox, kubectl and Minikube. The installations instructions for same and other environments are documented at .

2. Start Minikube

Once the necessary software has been installed we are ready to go. We are going to launch a VM-less minikube instance using the instructions as per below. This approach requires a Docker daemon and has the advantage that your image assets are all colocated in your local Docker image registry. An OpenShift equivalent to this is “oc cluster up” as shown here.

# Check installed software
$ kubectl version 
$ minikube version

# Stop/start minikube
$ minikube stop 
$ sudo minikube start \ 
  --vm-driver=none \ 

# Follow instructions as per Minikube stdout
$ sudo mv /root/.kube $HOME/.kube 
# this will write over any previous configuration
$ sudo chown -R $USER $HOME/.kube
$ sudo chgrp -R $USER $HOME/.kube

$ sudo mv /root/.minikube $HOME/.minikube 
# this will write over any previous configuration
$ sudo chown -R $USER $HOME/.minikube
$ sudo chgrp -R $USER $HOME/.minikube

# Check all OK then launch the dashboard
$ minikube addons enable ingress
$ minikube status
$ docker images | grep
$ minikube dashboard


1. Create Namespace

We will use a namespace to organise our application assets. Do this as follows, and then make that the default namespace. The OpenShift equivalent to this is “oc new-project” as shown here.

# Create a new namespace
$ kubectl create -f - << EOF!
apiVersion: v1
kind: Namespace
  name: mlops

# Check your new namespace then set as default
$ kubectl get namespaces
$ kubectl config set-context $(kubectl config current-context) --namespace=cotd

2. Create Application

We are going to create a pod by bootstrapping it straight off an existing Docker image (stefanopicozzi/pets. Do this as follows. The OpenShift equivalent to this is “oc new-app” as shown here.

# Pull down a Docker image
$ docker pull stefanopicozzi/pets

# Create a deployment and expose directly from the image
$ kubectl run pets --image=stefanopicozzi/pets --port=8080 -n=cotd
$ kubectl expose deployment pets --type=NodePort --port=8080 --target-port=8080 --name=pets -n=cotd 

# Check pod status
$ kubectl get deployments -n=cotd
$ kubectl get pods -n=cotd

$ curl $(minikube service pets --url -n=cotd)

3. Create Ingress

Create an ingress point into your application as follows. Once successful you will be available to access the endpoint using something like http://pets. The OpenShift equivalent to this is “oc expose service” as shown here.

# Set up an Ingress
$ kubectl create -n=cotd -f - << EOF!
apiVersion: extensions/v1beta1
kind: Ingress
  name: pets-ingress
  annotations: /
    serviceName: default-http-backend
    servicePort: 80
  - host: pets
      - path: /
          serviceName: pets
          servicePort: 8080
$ kubectl get ingress -n=cotd 
$ kubectl describe ingress pets-ingress -n=cotd 

# Set up host file entry for convenience and verify
$ sudo echo "$(minikube ip) pets" | sudo tee -a /etc/hosts
$ while true; do curl -s http://pets/item.php | grep "data/images" | awk '{print $5}'; sleep 2; done

4. Configure Configmaps

The COTD sample application has an environment variable (SELECTOR) to change themes, e.g. cats, cities, pets. To demonstrate  externalising configuration data, we can set this variable using Kubernetes configmaps. The OpenShift equivalent to this is “oc create configmap” as shown here.

One of the configuration steps requires editing the deployment yaml. You can inspect a complete and known-good deployment file at .

# Create a configmap that changes application to show cities
$ kubectl create configmap pets-config -n=cotd --from-literal=selector=cities 
$ kubectl edit deployment pets -n=cotd
     - name: SELECTOR
           key: selector
           name: pets-config
$ while true; do curl -s http://pets/item.php | grep "data/images" | awk '{print $5}'; sleep 2; done

# Now change the env variable value to cities and verify
$ kubectl delete configmap pets-config -n=cotd
$ kubectl create configmap pets-config -n=cotd --from-literal=selector=cats
$ export POD=$(sudo kubectl get pods -n=cotd | grep pets | awk '{print $1}')
$ kubectl delete pod $POD -n=cotd
$ while true; do curl -s http://pets/item.php | grep "data/images" | awk '{print $5}'; sleep 2; done

5. Working with Storage

Let’s now demonstrate how to attach storage to our pod. We will do this by mapping the images directory to a local HostPath file system. You can verify success by noting that the pet images (http://pet) in your Browser do not appear until the image content is copied across to the local HostPath. The OpenShift equivalent to this is shown here.

There are 3 steps to this procedure – 1) create a persistent volume, 2) create a claim and 3) map the storage path to your pod. Again, one of the configuration steps requires editing the deployment yaml. You can inspect a complete and known-good deployment file at .

# 1. Create a persistent volume 
$ kubectl create -n=cotd -f - << EOF!
kind: PersistentVolume
apiVersion: v1
  name: pets-pv
    type: local
  storageClassName: manual
    storage: 100Mi
    - ReadWriteOnce
    path: "/tmp/pets"
$ kubtectl get pv

# 2. Create a peristent volume claim
$ kubectl create -n=cotd  -f - << EOF!
kind: PersistentVolumeClaim
apiVersion: v1
  name: pets-pvc
  storageClassName: manual
    - ReadWriteOnce
      storage: 50Mi
$ kubectl get pvc

# 3. Map claim to pod
$ kubectl edit deployment pets -n=cotd

        - mountPath: "/opt/app-root/src/data/images"
          name: pets-images-storage
      - name: pets-images-storage
          claimName: pets-pvc

# Point a browser and point to http://pets and storage claim 
$ cd /tmp
$ git clone
$ cd pets
$ sudo cp -r ../cotd/data/images/* .



Get used to rebuilding your Minikube environment now and then. Do the following, then reboot for good measure.

# Reset minikube environment to ignore previous vm-driver 
$ minikube stop 
$ minikube delete 
$ sudo rm -rf $HOME/.kube $HOME/.minikube

Internet Not Accessible

If you cannot curl or ping an Internet resource from inside your pod, check your /etc/resolv.conf for a valid DNS entry such as . Hunt around for techniques to prevent this file being overwritten, e.g. . If you need to change /etc/resolv.conf, restart as follows:

$ sudo /etc/init.d/network-manager restart
$ minikube start ...


If you experience some weirdness with Kubernetes attempting to create a container, refer “Internet Not Accessible” tip.

Canary/Blue/Green/A/B Deployments

Not covered in this blog #1 have been the various Cloud deployment patterns. OpenShift implementation patterns for this are described here. If you need to achieve this without OpenShift, suggest you check out Istio, e.g. as at . Now read blog #2.


2 thoughts on “Kubernetes Minikube #1 – Configmaps, Storage, Ingress

  1. Pingback: Messing with Kubernetes Minikube #2 – Istio | emergile

  2. Pingback: Kubernetes Minikube #3 – Jupyter, Tensorflow with eGPU | emergile

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s