Germany is still in Corona lockdown, which means we can not go outside, meet friends and do other activities. Therefore, I spend more time acquiring a new skill. I have been using Docker Compose and Swarm to run multi-containers application for development and testing for last 2 years. I always thought of adding Kubernetes (K8s) in my skill sets but somehow I have been busy with Hyperledger Fabric, IPFS, ESP, Arduino etc. A silver lining in COVID-19 pandemic for me is to have time to learn Kubernetes. The IoTCrawler project also gave me impetus to move in this direction. I am going to share my knowledge and leanings from time to time with a series of blogs on Kubernetes. In this blog, I will explain how can you run a single node Kubernetes cluster locally and deploy a simple container on the cluster.

What is Kubernetes ?

Docker containers are everywhere and they run your applications in total isolation (quarantine mode) as we are now in Corana time. A container is very simple to work with but it gets really messy when their number rise up. Kubernetes is an open source container orchestration system which can be used to deploy, scale, monitor and manage production grade container applications efficiently. Kubernetes eliminates manual processes involved in container management. In the beginning, container deployment on Kubernetes might be difficult and complex for Docker Swarm users but in the long run it is worth as it provides better and sophisticated resources. Here, you can find concepts and resources of Kubernetes in detail. We have many things to do, so lets start by setting up the environment.

Prerequisites

I use Ubuntu 16.04 and installation instructions for tools are specific to it. We require two essential tools, one to setup a Kubernetes cluster and second to manage containers on the cluster. There are multiple tools available to setup Kubernetes learning environment locally. I find both Kind and Minikube are the best suited for the task. I am going to use kubectl to deploy and interact with the local Kubernetes resources. First lets start by installing all the tools. Create a project directory for Kubernetes.

[code language=”bash”] mkdir -p ~/Project/k8s/bin
cd ~/Project/k8s/bin[/code]

Kind

[bash]curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.7.0/kind-$(uname)-amd64
chmod +x ./kind[/bash]

Minikube

[bash]curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
chmod +x ./minikube[/bash]

Kubectl

[bash]curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl
chmod +x ./kubectl[/bash]

If everything worked well, you can check version using following commands.

[bash]kind version
minikube version
kubectl version[/bash]

Create Cluster

Use kind or minikube to create a local Kubernetes cluster.

Kind

[code firstline=”1″ language=”bash”] kind create cluster –name kind[/code]

The output is similar to this

[code light=”true” language=”bash”] Creating cluster "kind" …
✓ Ensuring node image (kindest/node:v1.17.0) ?
✓ Preparing nodes ?
✓ Writing configuration ?
✓ Starting control-plane ?️
✓ Installing CNI ?
✓ Installing StorageClass ?[/code]

Get information about the cluster

[code firstline=”2″ language=”bash”]kubectl cluster-info –context kind-kind[/code]

The output should be similar to following

[code light=”true” language=”bash”] Kubernetes master is running at https://127.0.0.1:32768
KubeDNS is running at https://127.0.0.1:32768/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy[/code]

Minikube

[bash]minikube start[/bash]

Output should be similar to following

[code light=”true” language=”bash”] ? minikube v1.9.2 on Ubuntu 16.04
✨ Using the docker driver based on existing profile
? Starting control plane node m01 in cluster minikube
? Pulling base image …
? docker "minikube" container is missing, will recreate.
? Creating Kubernetes in docker container with (CPUs=2) (8 available), Memory=3900MB (15937MB available) …
? Preparing Kubernetes v1.18.0 on Docker 19.03.2 …
▪ kubeadm.pod-network-cidr=10.244.0.0/16
E0427 11:52:56.095757 13734 kubeadm.go:331] Overriding stale ClientConfig host https://172.17.0.2:8443 with https://172.17.0.3:8443
? Enabling addons: default-storageclass, storage-provisioner
? Done! kubectl is now configured to use "minikube"[/code]

Deployment

We have a kubernetes cluster running locally. Now, it is time to deploy a container on the cluster. I will use kubectl utility for this task. For an instance, one could use following command to deploy echoserver image on the cluster. The echoserver is an existing image which is a simple HTTP server.

[code firstline=”1″] kubectl create deployment hello-world –image=k8s.gcr.io/echoserver:1.10[/code] [code light=”true”]deployment.apps/hello-world created[/code]

kubectl is a very powerful tool which has many commands to manage and monitor containers on a cluster. I am going to demonstrate get, exec and logs sub-commands

[code firstline=”2″] kubectl get deployment[/code] [code light=”true” language=”bash”] NAME READY UP-TO-DATE AVAILABLE AGE
hello-world 1/1 1 1 43s[/code] [code firstline=”3″ padlinenumbers=”false”] kubectl get pods[/code] [code light=”true” language=”bash”] NAME READY STATUS RESTARTS AGE
hello-world-6fc4596b9-wqvm6 1/1 Running 0 49s[/code] [code firstline=”4″] kubectl exec -it hello-world-6fc4596b9-wqvm6 bash[/code] [code light=”true” language=”bash”] root@hello-world-6fc4596b9-wqvm6:/# echo "Learning Kubernetes is silver lining for me in Covid-19"
Learning Kubernetes is silver lining for me in Covid-19
exit[/code] [code firstline=”5″] kubectl logs hello-world-6fc4596b9-wqvm6[/code] [code light=”true” language=”bash” padlinenumbers=”1″] Generating self-signed cert
Generating a 2048 bit RSA private key
………………..+++
………………………+++
writing new private key to ‘/certs/privateKey.key’
—–
Starting nginx[/code]

Expose the Deployment to Kubernetes Service.[code firstline=”6″] kubectl expose deployment hello-world-deployment –type=ClusterIP –port=8080[/code] Get the Service[code firstline=”7″] kubectl get svc hello-world-deployment[/code]

Now, the Service is running inside the cluster. You can’t access by its IP address. Kubernetes provides a proxy to expose its resources outside the cluster. Run the following command to run proxy.[code firstline=”8″] kubectl proxy[/code] [code light=”true”] Starting to serve on 127.0.0.1:8001[/code] At this point, you can access the service in your browser on the following link[code light=”true”] http://localhost:8001/api/v1/namespaces/default/services/hello-world-deployment:8080/proxy/[/code] It will show the output similar to this[code light=”true” language=”html”] CLIENT VALUES:
client_address=10.244.0.1
command=GET
real path=/
query=nil
request_version=1.1
request_uri=http://localhost:8080/

SERVER VALUES:
server_version=nginx: 1.10.0 – lua: 10001

HEADERS RECEIVED:
accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
accept-encoding=gzip, deflate, br
accept-language=en-US,en;q=0.9,de;q=0.8
cookie=SID=itedaqsc8g9rmo75lom9fbr5901nvo3e
host=localhost:8001
sec-fetch-dest=document
sec-fetch-mode=navigate
sec-fetch-site=cross-site
sec-fetch-user=?1
upgrade-insecure-requests=1
user-agent=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/80.0.3987.163 Chrome/80.0.3987.163 Safari/537.36
x-forwarded-for=127.0.0.1, 172.17.0.1
x-forwarded-uri=/api/v1/namespaces/default/services/hello-world-deployment:8080/proxy/
BODY:
-no body in request-[/code]

Clean Up

You can use following command to clean the environment.

For kind cluster

[bash]kind delete cluster –name kind[/bash] [code light=”true”] Deleting cluster "kind" …[/code]

For minikube cluster

[bash]minikube stop[/bash] [code light=”true”] ✋ Stopping "minikube" in docker …
? Node "m01" stopped.[/code]