Provisioning a Kubernetes cluster on Amazon EKS— Part I

Introduction

Microservices Architecture (MA) is already a reality in the production environment of big corporations such as Linkedin, Netflix, Google and, others. In MA, all parts that compose the system are implemented separately, in a self-contained and containerized way. All of the containers that compose an application work together and communicate through some type of message service. This kind of architecture has some advantages in relation to monolithic architecture¹:

1- In MA, repairing and updating can be done separately, without impacting others parts making the release process more agile. Meanwhile, in monolithic, each new alteration or update requires that all the application be rebuilt.

2- In MA, if a given point of application fails, we can do local repair without affecting the other components. In contrast, in monolithic architectures, a single point of failure can compromise the entire application.

3- In MA, we don’t need robust machines to support the entire application. We can scale the infrastructure horizontally and on demand. In contrast, in a monolithic architecture, we scale the infrastructure vertically for more capacity.

I suggest reading the article beginners-guide-to-microservices-explaining-it-to-a-5-year-old by Sidarth Malhotra. It illustrates differences between the architectures in a very creative way.

To make all containers work together in the right way it is necessary to have some kind of container orchestrator/manager. It was from this need that Kubernetes¹ ² was born.

__________________

Kubernetes, also known as k8s, is an Opensource container orchestration system that aims to automate the deployment, scaling, and management of applications. It works various mechanisms such as replication, self-healing, key configuration management, resiliency, and more.

The origin

Containerization has been a reality in Google’s work routine for more than a decade. Practically all the services we know, Google Maps, Google Search, Gmail, Google Earth and etc, run on a container architecture. Managing the containers that make up each of these services is not, even today, a simple task. Imagine a few years ago. There was no tool of any kind for this purpose. Which is why Google, around the year 2000, started the development of the Borg project[1], a container-oriented cluster management tool. In very general terms Borg consisted of a macro framework called BorgMaster responsible for managing user requests and processes called Borglets that ran containerized applications distributed in replicas.

Figure 1: Image taken from reference [3]

Some changes occurred and Borg evolved into Omega but, both initiatives were totally focused on Google’s own needs and architecture and therefore did not serve a broader purpose. Thus the idea was born to develop something more generic, free and that could be used by anyone. It was in 2014 that Google created its newest opensource project, Kubernetes. For the sake of curiosity, Kubernetes is a word of Greek origin used to designate “helmsman pilot”.

At the time other commercial initiatives for container orchestration were available, but nothing really free. The main initiatives were tied to large vendors and associated with long and bureaucratic contracts. After its inception, strong community engagement led to Kubernetes’ very rapid rise. Just over 4 years after its emergence large enterprises were already migrating their containner infrastructure to Kubernetes. In 2016 Google donated Kubernetes to the Cloud Native Computing Foundation which is still its maintainer today.

The Kubernetes architecture

The Kubernetes cluster consists of two types of machines, the kuberntes control plane and the worker nodes. The control plane is responsible for managing the entire kubernetes cluster while the worker nodes are responsible for running the containers and performing the workload. The control plane consists of five elements (See Figure 2):

kube-apiserver : This is the front-end of Kubernetes, responsible for all the communication. It is from here that we interact with the cluster.
etcd : Key-value database that stores data about the state of the kubernetes cluster. Information about the lifecycle of a pod, resources, nodes, etc is persisted in etcd.
kube-scheduler : Manages incoming requests and allocates your application for execution on a given worker. It decides where a given workload will be executed.
kube-controller-manager : Manages all kubernetes controllers such as, replica set, adimission controler, authentication controler, deployments e authorization controler.
cloud-controler-manager : It interacts with the cloud provider and manages shared resources such as load balancers and disk volumes.

Os kubernetes worker nodes are composed by three elements:

kubelet : Component responsible for running pods (we will see later what a pod is) and also mediates message exchanges between kube-apiserver and the runtime container.

kube-proxy : Responsible for communication between Pods of different nodes and between Pods and the internet.

Container runtime : Responsible for starting and ending containers and managing their communications. Commonly Docker containers are used, however, other containerization services can be used.

Figure 2: The image illustrates the Kubernetes architecture.

Elements of Kubernetes

Pod : The most central and important concept in Kubernetes. A Pod is the smallest object in Kubernetes, representing one or more containers, storage volumes and a single IP address. Each container within the Pod will have a common IP and file system and so it is possible to share resources between containers. All the containers in a Pod are on the same worker node. A Pod cannot have containers on more than one worker node.

ReplicaSet : It is a set of Pods and, guarantees the desired state of the application. For example if it is desired that your application has 3 Pods and each of them has 3 replicas, the ReplicaSet works to this happen.

Deployment : Manages the versioning of the application. It is from the deployment that we can roll-back the applications. The rollback is done in an orchestrated way, that is, Pods are finalized to do the versioning without compromising the application’s operation. Each deployment version is registered inside the cluster.

Figure 3: The figure ilustrates the elements of Kubernetes and their dependences.

Services : They represent ports and are responsible for exposing the pods for communication. From the service we have access to the application itself. For example, if we want to expose an application to the Internet we must create a Load Balancer service and from it, access to the application through a predefined port.

Namespaces : Namespaces are virtual sub-clusters within the physical cluster. They provide a scope for objects in the cluster. With them we can separate the cluster applications into a smaller and more organized group.

Pods Lifecycle

Pods have a lifecycle (See Figure 3). When the pod has been accepted by Kubernetes but the containers have not been created yet, this pod is in the Pending state. When the pod has been allocated to a node and all containers have been created, this pod leaves the pending state to the Running state. Throughout the execution of a Pod it has either finished its processing correctly and then assumes the Succeeded state or some kind of failure in the process has taken it to the Failed state. There is yet another state that a Pod can assume, the Unknown state. This state is a bit rarer to happen and is associated with internal Kubernetes problems. In this case, Kubernetes cannot determine the current state of the container or even communicate with it.

Figure 4: The figure illustrates a Pod life cycle.

Creating and interacting with a Kubernetes cluster

All the major cloud providers have their own managed services for building a kubernetes cluster. AWS has Elastic Kubernetes Service (EKS), Azure has Azure Kubernetes Service (AKS), and Google has Google Kubernetes Engine (GKE). Although the above solutions comprise the real kubernetes landscape in production, for development, testing, or even study, local solutions have been developed. These are the ones we will talk about⁴. Examples of local solutions are k3s, rke2, Minikube, and k3d.

k3d is a tool supported by SUSE Rancher that greatly simplifies the study of kubernetes. Broadly speaking, k3d performs the installation of a k3s cluster inside a docker container and is therefore more performative than other solutions. The installation process can be done, under Linux, by the command :

wget -q -O - https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash

or

curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash

visit the documentation for more details⁵. Once k3d is installed, we create a kuberntes cluster using

k3d cluster create <cluster-name> 
Figure 5 : The output after de creation Kubernetes cluster from k3d.

That’s it! We have a kubernetes cluster ready to be used and tested. In k3d you can pass flags when creating the cluster. For example, if we want to specify the number of worker nodes to be used we can do :

k3d cluster create  --agents <Number_of_worker_Nodes>

For more information about k3d, visit⁵’⁶ .

Now that we have a Kuberntes cluster running on our machine, we can interact with it. We do this through kubectl. The kubectl is the command line interface (CLI) that communicates with the Kuberntes server API. From it we can deploy an application, evaluate how the cluster elements such as Pods and Replica Sets are doing, list Services, Namespaces and much more. Here we will explore some basic kubectl commands. The first command we will look at is

kubectl cluster-info  

Returns the status of the cluster. Para ter informação dos nodes,

kubectl get nodes

If we had used the agents=2 option when creating the cluster, we would have two worker nodes as shown in the image below.

kubectl get namespaces 

The namespaces listed are created by default at cluster creation time. When we deploy an application to our kubernetes cluster, if you don’t specify a namespace, the application will be deployed to the default namespace. As a best practice we always want to create namespaces for each application. As mentioned earlier, this makes it much easier to manage and monitor the cluster. We create namespaces through

kubectl create <Nome_do_namspace> 

notice that my-app now appears in the list. It is in this namespace that I want to deploy the my-app application. Let’s evaluate the pods of our my-app application. To do so, just :

kubectl get pods -n <Nome_do_namespace>

As in fact it should be. There is no deployed application in the my-app namespace. For illustration purposes I will deploy NGINX to this namespace.

NOTE: I will not go into the details of the .yaml manifest used for deployment. It will be described in more details in the part two of this article. In this text I will dedicate to the first steps with Kubernetes and how to interact with the cluster.

To get information like, date and time of Pod creation, the image is being used, ip, port, we can do

kubectl describe pod <NAME>

In case there are already deployed applications (we will see how to deploy an application in part 2 of this article) in our cluster we can list them through

kubectl get deployments -n <Namespace_name>

Conclusions and perspectives

In this article we take our first steps with Kubernetes. We started with the origin of the technology with Google, showed how to create a local cluster and finally, how to interact with it. It was an introductory text that will serve as a tool for part II of this text.

In part II, we will use Terraform and EKS to create a cluster on AWS. We will also explore the structure of a .yaml manifest, deploy applications to a cluster on AWS and finally expose the service to the internet. It will be a complete project, very close to what happens in production.

References

[1] Cloud Native Devops with Kubernetes: Building, Deploying, and Scaling Modern Applications in the Cloud, Arundel, J. and Domingus, J., O’Reilly Media, Incorporated, (2019)

[2] Kubernetes in Action, Luksa, M., Manning, (2018).

[3] Large-scale cluster management at Google with Borg, Proceedings of the European Conference on Computer Systems (EuroSys), ACM, Bordeaux, France (2015)

[4] We will dedicate a part II of this article to a cloud-based solution. Our purpose here is to give an overview about kubernetes.

[5] Minikube — https://minikube.sigs.k8s.io/docs/start/

[6] k3d — https://k3d.io/v5.3.0/

--

--

--

Physicist and Data Engineer. I intend to use this space to write about Data Science, Big Data, Programming and technology. Lets talk Data !!!

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Low/Medium/High Prioritisation Doesn’t Work

Working with gRPC microservices in K8S (And some other rambles)

Why kids should learn to code?

Three Issues With Using Database Generated IDs

Example of table with auto-increment id.

My journey on becoming a web-developer…

Too Many Emails? Time to fight it

Implementing CI/CD at Kloeckner-i — A History Lesson

Rest Assured Series with Lombok(Spice up your Test Automation)

Spice up your Test Automation

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Alexandre Furlan

Alexandre Furlan

Physicist and Data Engineer. I intend to use this space to write about Data Science, Big Data, Programming and technology. Lets talk Data !!!

More from Medium

Event Hubs Dead Letter Queue with Spring Cloud Stream

Kubernetes Architecture: An Overview

Kubernetes Events : Introduction and Filtering

Using Kubernetes Certificate Signing Requests and RBAC for User Authentication and Authorization