Kubernetes is an open-source platform for managing containerized applications across a cluster of physical or virtual machines. The original inspiration for Kubernetes was Google’s Borg system. Borg is a cluster management system that handles hundreds of thousands of jobs and applications across massive Google data centers. Kubernetes was intended to be a friendlier version of the cluster management system that everyone could use.
The popularity of containers in the software development process is making Kubernetes popular too. In the old software development process, applications were deployed on physical host machines. Developers working on different components of the application needed to maintain a cohesive environment. Operation and IT personnel needed to carefully manage executables, configurations, and libraries. Different components of the application could run into conflict during the integration process. Also, the process was susceptible to human errors and miscommunications.
Virtual machines (VM) helped bring some level of reliability to the process. But it was still hard to manage applications. Also, VMs are expensive to maintain. Containers changed the landscape. With containers, it was possible for developers working on different components of the same software to maintain separate environments. Containers are light-weight, inexpensive and fast. These benefits gave rise to the idea of developing software using microservices where each container serves a specific task for the application.
With the rise of container use, Kubernetes has become an effective tool to schedule and run applications across clusters. As a platform, it can free developers from the burden of dealing with any kind of machines. Instead of designing for host-centric infrastructures with physical or virtual machine considerations, developers can start designing for container-centric infrastructure. Kubernetes provides the necessary layer of abstraction.
Part 1: Concepts
Master Components
Master components are the controlling services for the cluster. These components handle global decisions and events. Any node in the cluster can run them. However, assigning particular nodes to these components is considered good practice.
kube-apiserver
The kube-apiserver serves the Kubernetes API. Kubernetes API implements a RESTful interface. It works as the bridge between various Kubernetes components like pods, services, replication controllers and others. It is responsible for consistency of communication between the etcd store and the deployed containers.
etcd
The etcd is responsible for storing all Kubernetes cluster data. The etcd project was developed by the CoreOS team. It is a lightweight, distributed key-value store that uses HTTP/JSON API. Nodes in the cluster can use configuration data from the etcd to discover services and recover from failed states. Due to the importance of the data, etcd should be backed up properly.
kube-controller-manager
The kube-controller-manager runs various controllers to provide different services. For example, node controllers recover failed nodes and replication controllers maintain the correct number of pods. Each controller runs as a separate thread and depends on the etcd information to perform their tasks.
cloud-controller-manager
The cloud-controller-manager provides cloud-specific controllers. It can be disabled in the kube-controller-manager. The cloud-controller-manager has been separated out from the core to allow the Kubernetes core to evolve independently of cloud provider specific code. In the past, the dependencies were causing problems.
kube-scheduler
The kube-scheduler is responsible for workload distribution. It keeps track of resource requirements and assigns nodes for newly created pods. It also takes care of the quality of service requirements.
addons
Addons are pods and services used to implement cluster features. Users can use the add-on manager to create and maintain addons. Some important and useful addons are DNS, Web UI(Dashboard), Container Resource Monitoring and Cluster-level logging.
Node Components
A worker machine in Kubernetes is called a node. Node components are present in every node and they handle different aspects of the workload.
kubelet
The kubelet service on each node is the primary agent. It keeps track of the pods assigned to its node through apiserver or local configuration file. It communicates with the master components to find out work requests and report the status of its node.
kube-proxy
The kube-proxy is a small proxy service on each node to deal with individual host subnetting. It can perform rudimentary load balancing for TCP and UDP.
docker
Kubernetes primarily depend on docker to run containers. It is able to build applications from docker images.
rkt
Kubernetes also supports rkt containers. The support is currently experimental.
supervisord
The supervisord can be used to monitor and control kubelets and docker containers.
fluentd
The fluentd is a deamon for providing custer-level logging.
Workloads
Kubernetes workloads can be defined as follows:
Pods
A pod is a fundamental unit in the Kubernetes workload. Containers are not individually assigned to hosts. Groups of containers, generally belonging to an application, are represented as a pod and the pod is then deployed to the host as a single unit. Of course, a pod can contain only one container. This is generally more common in Kubernetes. However, containers are grouped together based on resource and application needs. The grouping is intended to optimize resource sharing.
Controllers
Controllers like replica sets, replication controller, deployments, stateful sets, garbage collection and cron jobs help manage Kubernetes workloads. Replication controllers manage the number of pods. It starts and terminates pods to maintain the correct number of pods running. Deployment controller helps change pods and deployment objects to reach the desired deployment state.
Other Important Ideas
Services
Kubernetes pods are created and destroyed regularly. So it’s difficult to keep track of them through IP addresses. The dynamic nature of the pods makes it difficult for them to communicate with each other. A service works as an abstraction. It provides the policy to reach a logical set of pods. In Kubernetes, a service is a REST object. Services simplify the container design.
Labels
Labels are a powerful way to keep track and manage groups of working components. Labels are key-value pairs that work as arbitrary tags to help gain finer control over different functions of the system.
Part 2: Hands-on Project
Running a Minikube Project
Minikube is a binary that sets up a single Kubernetes cluster on a local machine. In this project, a Node.js application will be turned into a docker container image and the image will be run on Minikube.
Installing Minikube, kubectl, Hypervisor, NodeJS and Docker
You can install Minikube and Kubernetes command line tool kubectl on Mac OS X, Linux and Windows with various hypervisors. The instructions for different operating systems are available here. Also, you will need NodeJS installed on your machine to run the example HelloWorld application. You can install docker here.
Starting a Cluster
Use the following command to start a cluster:
$ minikube start Starting local Kubernetes v1.7.5 cluster... Starting VM... Downloading Minikube ISO 106.36 MB / 106.36 MB [============================================] 100.00% 0s Getting VM IP address... Moving files into cluster... Setting up certs... Connecting to cluster... Setting up kubeconfig... Starting cluster components... Kubectl is now configured to use the cluster.
Use the command below to see if the cluster is running properly:
$ kubectl cluster-info Kubernetes master is running at https://192.168.99.100:8443
Create Application Image
Let’s create a server.js file with the following content:
var http = require('http'); var handleRequest = function(request, response) { console.log('Received request for URL: ' + request.url); response.writeHead(200); response.end('Hello World!'); }; var www = http.createServer(handleRequest); www.listen(8080);
You can run the following command:
$ node server.js
And check if the server is running on http://localhost:8080. You should see “Hello World!” text on the web page.
Convert to Docker Container
In the same directory as server.js create a file Dockerfile with following text:
FROM node:6.9.2 EXPOSE 8080 COPY server.js . CMD node server.js
The Dockerfile will create an image that will start from the node:6.9.2 image on the Docker Hub.
We want to run the docker images locally. So the following command will tell docker to use Minikube deamon to for docker image storage:
$ eval $(minikube docker-env)
You can use eval $(minikube docker-env -u) to change it back to the default.
Now let’s build the docker image:
$ docker build -t my-node:v1 . Sending build context to Docker daemon 3.072kB Step 1 : FROM node:6.9.2 6.9.2: Pulling from library/node 75a822cd7888: Pull complete 57de64c72267: Pull complete 4306be1e8943: Pull complete 871436ab7225: Pull complete 0110c26a367a: Pull complete 1f04fe713f1b: Pull complete ac7c0b5fb553: Pull complete Digest: sha256:2e95be60faf429d6c97d928c762cb36f1940f4456ce4bd33fbdc34de94a5e043 Status: Downloaded newer image for node:6.9.2 ---> faaadb4aaf9b Step 2 : EXPOSE 8080 ---> Running in da7d251b3fd5 ---> 881f9fb69b2c Removing intermediate container da7d251b3fd5 Step 3 : COPY server.js . ---> 0acf61d9e75e Removing intermediate container 3a4025539cf6 Step 4 : CMD node server.js ---> Running in 8aa9a4cbd723 ---> 41445e5c48fe Removing intermediate container 8aa9a4cbd723 Successfully built 41445e5c48fe
Deploy to the Cluster
To deploy my-node:v1, run the following command:
$ kubectl run my-node --image=my-node:v1 --port=8080 deployment "my-node" created
It will create a pod on the cluster. We can check the pod statuses with the following commands:
$ kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE my-node 1 1 1 1 34s
$ kubectl get pods NAME READY STATUS RESTARTS AGE my-node-276881918-qth5s 1/1 Running 0 1m
$ kubectl get events LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON SOURCE MESSAGE 32m 32m 1 minikube Node Normal Starting kube-proxy, minikube Starting kube-proxy. 32m 32m 1 minikube Node Normal Starting kubelet, minikube Starting kubelet. 32m 32m 2 minikube Node Normal NodeHasSufficientDisk kubelet, minikube Node minikube status is now: NodeHasSufficientDisk 32m 32m 2 minikube Node Normal NodeHasSufficientMemory kubelet, minikube Node minikube status is now: NodeHasSufficientMemory 32m 32m 2 minikube Node Normal NodeHasNoDiskPressure kubelet, minikube Node minikube status is now: NodeHasNoDiskPressure 32m 32m 1 minikube Node Normal NodeAllocatableEnforced kubelet, minikube Updated Node Allocatable limit across pods 32m 32m 1 minikube Node Normal RegisteredNode controllermanager Node minikube event: Registered Node minikube in NodeController 32m 32m 1 minikube Node Normal NodeReady kubelet, minikube Node minikube status is now: NodeReady 6m 6m 1 minikube Node Normal RegisteredNode controllermanager Node minikube event: Registered Node minikube in NodeController 5m 5m 1 minikube Node Normal Starting kubelet, minikube Starting kubelet. 5m 5m 1 minikube Node Normal NodeAllocatableEnforced kubelet, minikube Updated Node Allocatable limit across pods 5m 5m 1 minikube Node Normal NodeHasSufficientDisk kubelet, minikube Node minikube status is now: NodeHasSufficientDisk 5m 5m 1 minikube Node Normal NodeHasSufficientMemory kubelet, minikube Node minikube status is now: NodeHasSufficientMemory 5m 5m 1 minikube Node Normal NodeHasNoDiskPressure kubelet, minikube Node minikube status is now: NodeHasNoDiskPressure 5m 5m 1 minikube Node Normal NodeNotReady kubelet, minikube Node minikube status is now: NodeNotReady 5m 5m 1 minikube Node Normal Starting kube-proxy, minikube Starting kube-proxy. 5m 5m 1 minikube Node Normal NodeReady kubelet, minikube Node minikube status is now: NodeReady 2m 2m 1 my-node-276881918-qth5s Pod Normal Scheduled default-scheduler Successfully assigned my-node-276881918-qth5s to minikube 2m 2m 1 my-node-276881918-qth5s Pod Normal SuccessfulMountVolume kubelet, minikube MountVolume.SetUp succeeded for volume "default-token-r5pl1" 2m 2m 1 my-node-276881918-qth5s Pod spec.containers{my-node} Normal Pulled kubelet, minikube Container image "my-node:v1" already present on machine 2m 2m 1 my-node-276881918-qth5s Pod spec.containers{my-node} Normal Created kubelet, minikube Created container 2m 2m 1 my-node-276881918-qth5s Pod spec.containers{my-node} Normal Started kubelet, minikube Started container 2m 2m 1 my-node-276881918 ReplicaSet Normal SuccessfulCreate replicaset-controller Created pod: my-node-276881918-qth5s 2m 2m 1 my-node Deployment Normal ScalingReplicaSet deployment-controller Scaled up replica set my-node-276881918
Create a Service
A pod is inaccessible. You have to create a service to make the pod accessible to the world. The following command should create the necessary service:
$ kubectl expose deployment my-node --type=LoadBalancer service "my-node" exposed
You can check the service status like this:
$ kubectl get services NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes 10.0.0.1 <none> 443/TCP 34m my-node 10.0.0.213 <pending> 8080:31460/TCP 31s
If you use the following command, it will open up the service on a web browser:
$ minikube service my-node Opening kubernetes service default/my-node in default browser...
You can check what going in your pod with the “logs” command — kubectl logs [nameOfThePod].
$ kubectl logs my-node-276881918-qth5s Received request for URL: / Received request for URL: /favicon.ico
The above logs are showing the requests made to the server.js application running on the cluster.
Cleaning up
You can delete the service and the pod with the following commands:
$ kubectl delete service my-node service "my-node" deleted $ kubectl delete deployment my-node[/code] deployment "my-node" deleted
You can stop the minikube:
$ minikube stop Stopping local Kubernetes cluster... Machine stopped.
Conclusion
Kubernetes is a vast system with large-scale capabilities. Kubernetes documentation is the best place to learn about this powerful technology.
Further Study:
Kubernetes Documentation: https://kubernetes.io/docs