Once you get to know Docker, it is time to learn some truly mystic tool for Continuous integration / Continuous deployment (CI/CD). Kubernetes, which does all management and automation for application (containers) scaling and deployment.
To work with Kubernetes you need to understand the basic concept behind pods, deployments, services, nodes, and cluster and how they relate to each other. There is no better place than Kubernetes official Docs to learn these definitions.
Tools used
To start working with this tool you could run some VPS on Google or Amazon Cloud for free … but if your code fail with an infinite loop you could get instantly bankrupted. For that reason, for local testing purpose, we will use free minikube software installed on our local machine.
Let’s play safe and deploy to cloud only applications proved no to generate us a massive bill.
1) Install minikube on your machine and run it with Hyper-V.
Minikube comes with kubectl preinstalled but it only allows us to talk to this single cluster. If we want to talk to other clusters on Google or Amazon servers, we should install kubectl separately. Therefore do not alias kubectl command with minikube kubectl as instructed in minikube documentation!
On Windows with Hyper-V enabled in Windows Features run:
minikube start --driver=hyperv
If you Mac or Linux user, you could use VirtualBox to run minikube –driver=virtualbox. Other Virtual tools are supported. Container or virtual machine manager, such as: Docker, Hyperkit, Hyper-V, KVM, Parallels, Podman, VirtualBox, or VMware Fusion/Workstation. Note that Docker option is not recommended due to some important limitations of this method.
To access minikube control panel, you can run:
minikube dashboard
CTRL + C
to exit dashboard from terminal. In production setup this would required setting up password and authentication, but Minicube allows us to omit those important security factors.
2) Install stand alone kubectl
To install this tool, navigate to Kubernetes docs page – getting started. If you fallow the instruction, you will see different ways of installing this tool. I will use chocolaty package manager for Windows.
choco install kubernetes-cli
Now check if tool is up-to-date. Run kubectl version --client
.
Configuration file (You might want to skip this section)
For the purpose of this tutorial you don’t need to, but if you want to create and play with the config file you can do it by navigating to your home directory: cd ~
(on Linux) and cd %USERPROFILE%
(on Windows). Here, create the .kube directory: mkdir .kube
, enter it cd .kube
and run:
New-Item config -type file
Red more here: https://kubernetes.io/docs/tasks/tools/install-kubectl-windows/
3) Install code editor.
Recommended: Visual Studio Code with Kubernetes extension, which allows us to generate yaml configuration files very quickly.
4) Continue setup
Once we had spin minikube start with selected driver we can now check IP of created server. Then we can SSH to that machine using this IP.
minikube ip
Now login to server with using fallowing command:
minikube ssh
Once inside minikube run docker ps
to see default docker containers run on this VPS server. Now let’s exit from minikube ssh and lets use kubectl tool we installed before.
Get access to Kubernetes API locally through https protocol. Using kubectl run:
kubectl cluster-info
Minikube spins a single Node which is both master and slave node. In real word application we would have several node separated from master node. If you using Linux or bitbash you could create an alias for which iwll make your command quicker alias k="kubectl"
.
kubectl get nodes // one Node
kubectl get pods // list pods inside default namespace only (list empty by default)
kubectl get namespaces // list of namespaces
To list pods for different namespace use –namespace flag when runnign kubectl get pod command. For example:
kubectl get pods --namespace=kube-system // list pods inside kube-system namespace
Creating custom pods
We can create custom pods from docker image
kubectl run nginx --image=nginx
kubectl get pods
kubectl describe pod nginx
So now we have created a nginex pod from nginex image on docker hub and we display information about this nginex pod container. We can see that it was assigned to default namespace. We can aslo see it IP address and status, image information, container ID and log this particular pod. We are not ready to connect to this service using its IP address. To be able to access this pod, we will first have to create a service configuration file in Kubernetes.
Now let’s again log in to SSH of minikube server (Node).
minikube ssh
then run docker ps | grep nginx
On the image a above, we have selected a container ID. To connect to this container, we can run the fallowing command:
docker exec -it df653efb911a sh
Once we in the container, we can check hostname and host IP address like on the example below:
Getting content of the nginx pod with curl. While in minikube ssh run curl 172.17.0.3
as result in your terminal should print default nginx HTML output. In this case, that’s mean that until now, everything works as expected.
Once exited from pod and minikube ssh. Run
kubectl get pods -o wide
Now you will get similar information about created pod. You will also notice that you can not access this pod running curl 172.17.0.3 from the host machine (laptop CLI outside of minikube VPS cluster).
Deleting created pod
Now once we know how basic concept behind Kubernetes we can delete created nginx pod and do something different.
kubectl delete pod nginx
Creating multiple PODs using deployments
Allowing you to increase scaling of your app by increasing and decrease quantity of the pods on demand, allowing for pods configurations. Deployment will be responsible for creating pods. Note that all pods created this way will be exacly the same, but we could distribute those nodes against different nodes in Kubernetes cluster.
Creating multiple nginx pods using deployment.
In this tutorial, we will create multiple pods of nginx image using deployments. We will name this pod the same as the name of the image. Then we will configure the service for that pod to be able to access it from the host machine.
kubectl create deployment nginx-dep --image=nginx
Note that this pod is now managed by this deployment. You can get more information about deployment by running kubectl describe deployment nginx-dep
. You can also describe single pod using its ID like so: kubectl describe pods nginx-dep-845cc48b5d-tcgnp
.
Scaling deployments
We can easily scale our nginx server pod managed by deployment by this command:
kubectl scale deployment nginx-dep --replicas=4
You can scale down or up pods using same command with lover or higher –replicas values. To list all available pods type kubectl get pods -o wide
Note like each pod in deployment has its own unique IP address assigned. Remember that at the moment you can not access those pods from outside of the minikube cluster/node. If you SSH to minikube you will be able to curl those pots IP addresses.
Kubernates – Creating services
Creating services for deployment allow us to connect to pots from outside of the cluster. You can create internal cluster IP address for specific deployments. Kubernetes will take care of load balancing between the pods. Single internal IP for entire deployment.
We can also create an external IP addresses to open deployment to outside word. Which basicaly is exposing specyfic IP address of the Cluster Node or use load balancer. Inside of the kubernetes cluster we can run multiple nodes where pods replicas are distributed. Which is single IP address for entire cluster for specific deployment. In production, load balancing is usually managed by cloud providers AWS or Google Cloud – Cloud controller manager running on the master Node.
Creating united deployment IP by creating service
Services can be created through expose command. First let’s check our deployment ID by running kubectl get deploy
now let’s expose internal port of the deployment to Cluster Node.
kubectl expose deployment nginx-dep --port=8080 --target-port=80
Where 80 is internal port of nginx and 8080 is external port accessible by our host machine.
Now we can list exposed service using kubectl get services
command or kubectl get svc
which will output the fallowing:
As we can see, nginx-dep deployment is now accessible on port 8080/TCP on Cluster IP 10.111.112.48. Which is single IP address generated by Kubernetes which can be used to access to any of the pods of that deployment. ClusterIP are accessible only with in cluster and not from outside word. To create an IP address accessible from outside word, we would have to create this IP on Node level or load balancer.
Wrapping up curl 10.111.112.48:8080
will not be accessible from outside word (our host machine) but will be accessible from Node / Cluster level. That is after login in to minikube ssh
. After running curl 10.111.112.48:8080
from server Node, you will get random pod response. Kubernetes take care of proxy and load balancing between pods when receiving a request to this specific IP.
Now lets describe our nginx-dep service with kubectl describe service nginx-dep
minikube ssh
and accessing exposed deployment port with load balancing functionality
curl 10.111.112.48:8080
Clean up
So far we have learned how to create pots, deployments, scale those deployments, expose deployment IP to Cluster IP with port mapping. Accessing this port from Cluster Node (after SSH to minikube which internally load balance the request and return random pot response.
Let’s make some clean-up before continuing this tutorial.
kubectl delete deployment nginx-dep
kubectl delete service nginx-dep
// list again
kubectl get deploy // short from deployments
kubectl get svc // short from services
Continue tutorial on Set Kubernetes with Docker Hub spinning Node.js, MongoDB and Express.js App