After deciding on implementing your cloud service using microservices architecture. The next step is Kubernetes. Think of it as the operating system of the cloud. Your application will no longer run on a single machine, so instead of a single machine operating system like Windows or Linux. You now need an operating system that runs your apps across multiple nodes in cluster.
Why do I need Kubernetes?
When you compose your application from multiple small services that needs to be deployed into multiple nodes (say hundreds). You will need to find a way to deploy your services automatically. You want to specify requirements of your service and decide which nodes to select to deploy.
When one node goes down (which will happen) you need something to monitor that and automatically provision all services that were running on this node, into other nodes.
When you need to scale one service (because of high traffic) you need something to automatically scale it into multiple other nodes, and distribute traffic coming from other services or from outside the cluster, into multiple instances of each service that is running in different locations.
You want to be able to deploy newer versions of your service using a rolling update without down time. And be able to roll back your deployment in case of any trouble.
You need to be able to discover what services/versions are deployed in your cluster and be able to communicate with them regardless of them being scaled, upgraded, moved around from node to others.
And since your applications are packaged as containers (whether it’s yours, or dependencies your application needs like nginx, redis, rabbitmq…) you need your cluster operating system to be designed mainly to run containers.
Why choose Kubernetes?
Because it’s the industry standard. Invented by Google, run by the open source community and adopted by Microsoft and Amazon. You don’t find this happening too much.
So you design your application to run inside Kubernetes, and you get to run it on-premise and on any public cloud without changing anything. That’s because it abstract a lot of cloud functionality in a standard format.
Tell me more..
Kubernetes is a bit complex, it has a few concepts to understand. Lets start by explaining some Kubernetes concepts here, then in the next post we will go through installation and trying a few demos.
First let’s agree that a Kubernetes cluster consists of of nodes (real machines or VMs). One or more of these nodes are master(s) which control the others.
Each node has an app called kubelet that communicates to the cluster master node, take commands and controls the containers running inside the node. Each node also uses docker to run the containers.
The master node, has a kubelet plus an API server which provides REST APIs to control objects in Kubernetes. Then as a user who wants to run something, you use an app called kubectl which is a client command line tool that runs on your PC and allows you to submit commands to the Kubernetes APIs. We will go into more details about kubectl in the next post.
One more thing to note before moving from here, is that each node in the cluster obviously has an IP address, MAC address and can communicate together and with external network/internet. This is the external network of cluster. On the other hand, inside the cluster there is an internal virtual network. That will assign a different space of network IPs to the containers inside. The internal cluster network, allows different containers to communicate with each other using internal IPs. And if they want to expose services to the outside world, we must use something to expose that, coming shortly.
First unit of deployment in Kubernetes is a Pod. A pod is an abstraction of a machine. It has an IP address. It can host one or more containers. It can have one or more volumes attached as the disk of this Pod. All containers inside a Pod, share the network address and the disk.
Usually a Pod will host a single application as a container, but in some scenarios it can have multiple other containers that provide added benefits like a container that collect logs from the main container, or a container that acts as a proxy for the main container.
A Pod (or most of Kubernetes objects) are tagged with labels. Labels are key value pairs that identify the Pods. Like app=website, version=v1. So that later when we want to refer to multiple Pods we can select them where app=website, this will select all Pods in this app with any version.
Pods are mortal, which means they can die, and usually no one deploys a Pod, or communicate to a Pod directly using its IP. There are 2 more things that are needed to make use of a Pod. ReplicaSets to manage deployments/scaling and Services to expose .
A ReplicaSet is a Kubernetes controller, which runs in the background and makes sure that there are specific number of Pods running from a specific application. For example we need a web application to have 2 instances running at the same time. This means we will create a ReplicaSet with a Pod template that runs our web application container, and tells the ReplicaSet that we need 2 instances. Once we defined this in Kubernetes as the desired state (you will hear this word a lot), the ReplicaSet will now create 2 Pods using this template, and it will keep monitoring if one of them goes down for any reason, it will kill it and will create a new Pod instead. Whenever you need to scale this web application to 3 instances, you will modify the ReplicaSet number of replicas property which indicates the desired state and the ReplicaSet will always try to achieve this state by provisioning new Pods or removing Pods.
Note that ReplicaSets are only concerned about deploying, monitoring and scaling Pods.
Although you can access a Pod using its IP, for example 10.0.0.4:80 you shouldn’t do that because a Pod is not permanent and its IP as well. Also what will you use to access a group of Pods? You need a service.
A service provides a permanent IP and DNS name for a group of Pods. So if your web application exposes port 80 on 2 Pods. You should create a service named “WebServer” for example with port 80, this service will have its own IP inside the cluster that will not change by changing the Pods inside, and will have a DNS name that will be accessible inside the cluster network and will forward traffic (TCP, http or any protocol) to the underlying Pods.
A service refers to the backend Pods by using labels, as per the earlier example a service with label app=website will route traffic to all Pods having this label. This will allow other services inside the cluster to access http://WebServer:80/ to reach any Pod inside that group without caring about where they are hosted, their IPs and how many are they.
Services simplify network communications for a microservices architected solution.
Last thing to care about for now is deployments. A deployment in Kubernetes consists of a ReplicaSet with its Pod template. Consider that we have a ReplicaSet “A” with V1 of our app. And we want to deploy V2. We can update the ReplicaSet to use the new version of our container, but this will cause all V1 Pods to be killed immediately at the time we are provisioning the new V2 Pods. If we don’t want to disrupt our service like that, we create a deployment.
The deployment will create a new ReplicaSet B of the V2 template with only 1 instance. And once this instance got created, it will scale down ReplicaSet A by 1 instance, and will keep doing that scaling up B and scaling down A, until B is fully populated and healthy and A reaches 0 instances. This is called rolling update deployment and helps keeping the old version of the service running while the new version is being provisioned.
We went through most of the basic concepts of Kubernetes and now we understand to deploy our application we will need a Deployment with a ReplicaSet, Pod template with a container image exposing ports and a Service that expose the Pods as a unique load balanced IP:port.