Kubernetes: Getting Started

28/12/2020

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

ONET IDC thành lập vào năm 2012, là công ty chuyên nghiệp tại Việt Nam trong lĩnh vực cung cấp dịch vụ Hosting, VPS, máy chủ vật lý, dịch vụ Firewall Anti DDoS, SSL… Với 10 năm xây dựng và phát triển, ứng dụng nhiều công nghệ hiện đại, ONET IDC đã giúp hàng ngàn khách hàng tin tưởng lựa chọn, mang lại sự ổn định tuyệt đối cho website của khách hàng để thúc đẩy việc kinh doanh đạt được hiệu quả và thành công.
Bài viết liên quan

Getting Started with Kubernetes Helm Charts

Getting Started With Helm Charts Helm makes Kubernetes more user-friendly. It is a package manager. Helm Charts makes it...
28/12/2020

Deploying Apps on Kubernetes Clusters

In a previous article we deployed a Kubernetes Cluster with one master and one worker node. Kubernetes clusters are mainly...
28/12/2020

Book Review: Getting Started with Kubernetes – Second Edition

Kubernetes is both a powerful tool and a work in progress. Naturally, there is a lot of interest in the technology. At...
28/12/2020