How to create a Kubernetes cluster locally - simple tutorial
How to create a Kubernetes cluster locally and deploy simple front-end apps that communicate with Kubernetes.
Introduction
Today we are going to create a Kubernetes cluster and deploy a simple React JS app which generates a random number by calling an Express JS app. We are going to orchestrate the whole process by using Kubernetes. We will first dockerize our front end/back end apps. Then using Kubernetes we will deploy the pods (React front end app/Express back end app) and access them via Kubernetes services.
What is a Kubernetes cluster?
Like any cluster you provide a set of nodes to Kubernetes. You tell kubernetes how to deploy containers in the cluster. How much memory or processing units each container gets and how they interact with each other.
Kubernetes cluster diagram
The below diagram depicts what we are going to achieve today, where we will create a Kubernetes cluster and services/deployments for our front and back ends.
Prerequisites
- Docker for Desktop (latest version)
- Kubernetes or Docker Kubernetes
- Node & NPM (Only if you want to run the applications stand alone)
- YAML
NOTE: This tutorial requires basic/working knowledge on Docker, Node, & NPM.
Let’s dive in without any further ado.
Getting started with Kubernetes
Installing Kubernetes
If you have Docker Desktop, go to preferences, go to the Kubernetes tab, and click Enable Kubernetes. It may take a while to spin up Kubernetes on to your machine, so go make a coffee while it does its magic.
To verify if Kubernetes is running, type the below two commands:
kubectl version
Outputs:
Client Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.0", GitCommit:"e8462b5b5dc2584fdcd18e6bcfe9f1e4d970a529", GitTreeState:"clean", BuildDate:"2019-06-19T16:40:16Z", GoVersion:"go1.12.5", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.8", GitCommit:"211047e9a1922595eaa3a1127ed365e9299a6c23", GitTreeState:"clean", BuildDate:"2019-10-15T12:02:12Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"linux/amd64"}
kubectl cluster-info
Outputs:
Kubernetes master is running at https://kubernetes.docker.internal:6443
KubeDNS is running at https://kubernetes.docker.internal:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
Bundling application as docker images
The full code for this can be found on GitHub.
Please download the project. The project has two sub folders in it.
- Client -> React based app
- Server -> Express based app
Client
- cd client
- npm install
- npm run build
- docker build -t frontend:1.0 .
- kubectl apply -f frontend.deploy.yml
- kubectl apply -f frontend.service.yml
Backend
- cd server
- npm install
- docker build -t backend:1.0 .
- kubectl apply -f backend.deploy.yml
- kubectl apply -f backend.service.yml
Go to the browser, type localhost and hit enter, you should see the application loaded.
Bringing it down further
Kubernetes Pods
Pods are the smallest deployable units of computing that can be created and managed in Kubernetes.
kubectl run nginx-frontend --image=frontend:1.0
The above creates a pod which hosts the front end container. You can’t access it yet since a host port isn’t exposed for the container. We will uncover those later.
A pod can host multiple containers as well. Instead of creating via command line let’s create via a YAML file.
# To create a pod with multiple containers
kubectl apply -f app.pod.yml
# To see container status
kubectl get pod/mymulticontainerapp
Outputs:
NAME READY STATUS RESTARTS AGE
mymulticontainerapp 2/2 Running 0 9m
# To see more details about the container
kubectl describe pod/mymulticontainerapp
To access the container from the host machine you have to do a port forwarding, i.e attaching host port to container port. You can do that via the below command:
kubectl port-forward pod/mymulticontainerapp 9999:80 3000:3000
Outputs:
Forwarding from 127.0.0.1:9999 -> 80
Forwarding from [::1]:9999 -> 80
Forwarding from 127.0.0.1:3000 -> 3000
Forwarding from [::1]:3000 -> 3000
The above command exposes the host port 9999 to container port 80 and host port 3000 to container port 3000 which is what our front end/back end containers are listening on. Any request to host 9999 will be forwarded to container on port 80. Any request to the host 3000 will be forwarded to container on port 3000.
Go to the browser and open 127.0.0.1:9999 or localhost:9999, it should load the front end app.
To delete a pod you can do with below command:
k delete pod/mymulticontainerapp
To inspect a pod you can use the below command:
Front End:
kubectl exec mymulticontainerapp -c myfrontendapp -it /bin/sh
ls /usr/share/nginx/html
exit
Back End:
kubectl exec mymulticontainerapp -c mybackendapp -it /bin/sh
ls
exit
The above commands open a shell inside a container to interact.
Before we jump on to the next topic - deployments - it’s crucial that you understand metadata in a YAML file. Metadata is data about the containers. You can add labels and key-values to the metadata. You can also use the labels or key-values as selectors to identify a pod which will be used by deployments/services later.
Let’s get all the pods labeled as mymulticontainerapp:
kubectl get pods --selector=name=mymulticontainerapp
Deployments
You describe a desired state in a deployment, and the Deployment Controller changes the actual state to the desired state at a controlled rate. You can define deployments to create new ReplicaSets, or to remove existing deployments and adopt all their resources with new deployments.
It should look pretty similar to the previous YAML you saw. The salient point to note here is kind - it’s a deployment rather than pod.
Selector: It is used to identify existing pods by labels, such as their metadata. If there is a pod already running with such a label, it will be part of this deployment.
Replicas: It specifies how many pods within this container you wish to create. If you say two, it will have two pods running the back end.
Let’s say replicas is set to two and there are four pods already running with the label app: node-backend. It will terminate two of those pods to meet the requirement of two replicas. It will also scale up the pods by two if replicas is set to six.
Spec: It specifies the details about the container such as image name, container port, CPU/memory limits for the container inside the pod, etc.
Template: It specifies the tags to be used for the newly created pods via the spec.
***
To create a deployment run the below command:
kubectl apply -f backend.deploy.yml
Output:
deployment.apps/node-backend created
To see all the deployments:
k get deployments
Output:
NAME READY UP-TO-DATE AVAILABLE AGE
node-backend 2/2 2 2 46s
To access the containers created during deployment you can use port-forward.
kubectl port-forward deployment/node-backend 3000:3000
You can access by going to localhost:3000/random
Kubernetes services
An abstract way to expose an application running on a set of pods is as a network service.
Things to notice here - the kind is Service and the type is LoadBalancer. This creates a LoadBalancer on host port 3000 and proxies the request to container on 3000.
What is LoadBalancer balancing here? If you look closely we specified a selector. The selector searches for pods with label app: node-background and any request sent to the host on 3000 will be load balances among those pods. Here we have two replicas and the request will be load balanced to these two pods.
To create a service run the below command:
kubectl apply -f backend.service.yml.
To see all the services run the below command:
k get service
This tells you the service name and what type of service it is. Here if you see there is a service called backend and of type LoadBalancer, which we just created using the service yml.
You can do the same steps for frontend as well:
kubectl apply -f backend.deploy.yml
kubectl apply -f backend.service.yml
Wasn't that easy?
We have looked at how to create a Kubernetets cluster and deploy a simple front end app that communicates with a backend app in Kubernetes. Hope this helps your understanding of the basics of Kubernetes. Kubernetes is a vast ocean and we just touched a tiny drop of it. But I hope this helps pave the path for your future Kubernetes learning!
Useful Links: