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.
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.
mkdir -p ~/Project/k8s/bin cd ~/Project/k8s/bin
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.7.0/kind-$(uname)-amd64 chmod +x ./kind
curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 chmod +x ./minikube
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
If everything worked well, you can check version using following commands.
kind version minikube version kubectl version
Use kind or minikube to create a local Kubernetes cluster.
kind create cluster --name kind
The output is similar to this
Creating cluster "kind" ... ✓ Ensuring node image (kindest/node:v1.17.0) 🖼 ✓ Preparing nodes 📦 ✓ Writing configuration 📜 ✓ Starting control-plane 🕹️ ✓ Installing CNI 🔌 ✓ Installing StorageClass 💾
Get information about the cluster
kubectl cluster-info --context kind-kind
The output should be similar to following
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
Output should be similar to following
😄 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"
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.
kubectl create deployment hello-world --image=k8s.gcr.io/echoserver:1.10
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
kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE hello-world 1/1 1 1 43s
kubectl get pods
NAME READY STATUS RESTARTS AGE hello-world-6fc4596b9-wqvm6 1/1 Running 0 49s
kubectl exec -it hello-world-6fc4596b9-wqvm6 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
kubectl logs hello-world-6fc4596b9-wqvm6
Generating self-signed cert Generating a 2048 bit RSA private key ....................+++ ...........................+++ writing new private key to '/certs/privateKey.key' ----- Starting nginx
Expose the Deployment to Kubernetes Service.
kubectl expose deployment hello-world-deployment --type=ClusterIP --port=8080
Get the Service
kubectl get svc hello-world-deployment
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.
Starting to serve on 127.0.0.1:8001
At this point, you can access the service in your browser on the following link
It will show the output similar to this
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-
You can use following command to clean the environment.
For kind cluster
kind delete cluster --name kind
Deleting cluster "kind" ...
For minikube cluster
✋ Stopping "minikube" in docker ... 🛑 Node "m01" stopped.