DEV Community

Cover image for Understanding Kubernetes Before You Lose Your Mind
Cem AKAN
Cem AKAN

Posted on

Understanding Kubernetes Before You Lose Your Mind

Hey everyone. If you are tired of reading boring technical docs and want to understand Kubernetes without losing your mind you are exactly where you need to be :)

captionless image

Grab a coffee and get comfortable. A while ago I gave a detailed presentation on Kubernetes 101 for the UN SDG AI Lab and I realized it would make a highly beneficial Medium article for anyone trying to learn this technology.

captionless image

Today we are going deep into the architecture and concepts. We will keep it conversational but stay focused on the technical details.

captionless image

Let us look at our roadmap for today. We are going to talk about the why first. You need to thoroughly understand the fundamental need and the pain points before we touch any new technology. Then we move to the what by actually defining Kubernetes. After that we will explore the how by breaking down the complex architecture into simple mental models. We will also do a live demonstration to prove it all works and map out your path forward.

captionless imagecaptionless imagecaptionless image

Before we dive into the deep end let me give you a quick background about myself. I am Cem Akan. I study Computer Engineering at Cukurova University. Right now I am heavily involved in developing an internal automation tool using Go and Node js. On the community side I am the Founder and Leader of Yazilim Cukurova. My core technical interests revolve around Back End Development, DevOps Culture and System Architecture.

captionless imagecaptionless imagecaptionless image

Here is what we are going to achieve together today. We will understand the challenges of modern application deployment, define what Kubernetes is and the specific problems it solves, identify its core components and finally witness it in action.

captionless imagecaptionless image

To truly appreciate the peace we have now we must revisit the dark ages. We are talking about the evolution of application deployment.

captionless image

We started in the traditional era. Back then people deployed applications directly on bare metal servers. It was incredibly expensive and scaling was a massive headache. If you needed more computing power you had to physically buy a new server and set it up manually.

Then the tech industry evolved into the Virtualization era. This let us run multiple virtual computers on one single physical machine. But virtual machines are incredibly heavy because each one needs a full operating system to run.

captionless image

Finally we reached a new era called containerization.

Let us take a quick look at containers and define what they actually are.

captionless imagecaptionless image

Containerization is a software deployment process. It packages an applications code together with all the files and libraries it needs to run on any infrastructure. This beautiful process creates a single lightweight executable unit that we call a container. You build it once and it just works anywhere without giving you endless configuration headaches.

captionless image

So life is perfect right. Having one or two containers running on your personal laptop is super easy.

captionless image

But in the real world you do not just have one container. The true challenge is managing containers at scale. Managing hundreds or thousands of them in a live production environment is absolute chaos.

captionless imagecaptionless imagecaptionless image

Picture this scenario. You are fast asleep in your bed. Suddenly a crucial server catches fire and crashes. All your containers on that server die instantly. You wake up to a terrifying 404 error nightmare.

captionless image

Trying to fix that manually while thousands of users are getting errors is a terrible experience. We definitely need a moment of silence for all the developers who lived through this pain before modern orchestrators existed.

captionless image

This kind of sudden disaster is exactly why we need automation. But imagine you are having a normal day. Everything is running fine but you need to push a new feature. You need to update your application from version one to version two without stopping service. If you have hundreds of containers managing that traffic and ensuring zero downtime manually is another level of difficulty altogether. This brings us directly to the next huge challenge in application deployment.

captionless image

Or think about doing a live update. You need to push a new version of your application without dropping any user connections. Trying to handle this update manually across hundreds of containers is a complete nightmare. You are just a developer and not a traffic cop.

captionless image

Imagine staring at that broken server and thinking there has to be a better way to handle these live deployments and sudden crashes.

captionless image

But look up in the sky. It is a bird. It is a plane. It is Kubernetes.

captionless image

When you have hundreds of these containers running wild you need a master conductor to organize the chaos.

captionless image

What exactly is Kubernetes anyway.

captionless image

Kubernetes acts exactly like that conductor in an orchestra. It takes all your separate containers and makes them work together in perfect harmony. It is an open source container orchestration system and it completely automates deploying scaling and managing your applications.

So how does it actually solve our 3 AM nightmare. Let us look at the three main superpowers it brings to the table.

captionless imagecaptionless image

First we have self healing. If a container crashes or a node dies Kubernetes instantly notices the exact problem. It does not wait for you to wake up. It automatically restarts or replaces that container to bring your system back to the desired healthy state.

captionless image

Then we have smart scaling. Imagine your application suddenly goes viral and traffic spikes by ten times. Kubernetes monitors your resource usage and automatically scales your application up by adding more containers. When the traffic drops it scales them back down to save you money.

captionless image

And remember that live update nightmare. Kubernetes handles auto updates smoothly. It gradually rolls out new versions of your application while taking down the old ones so your users never experience any downtime at all.

captionless imagecaptionless imagecaptionless image

Because of these massive benefits it became the undeniable industry standard. It gives you high availability so your app is always online. It provides insane scalability. It gives you infrastructure freedom meaning you can run it on AWS Google Cloud Azure or your own bare metal servers without changing your code. And obviously it leads to massively increased productivity for your developer teams.

captionless imagecaptionless imagecaptionless image

Now Kubernetes architecture is famously complex and can be really hard to grasp at first glance. So let us use a mental model.

captionless image

Analogy time. We are going to look at the maritime shipping industry to understand how a Kubernetes cluster actually operates.

captionless image

Think of a massive cargo ship that carries physical shipping containers across the ocean.

captionless image

In our Kubernetes world this cargo ship represents a Worker Node. The worker node is the absolute workhorse of your cluster. It does the actual heavy lifting of running your application containers. A cluster is made up of multiple worker nodes basically a whole fleet of these cargo ships working together.

captionless image

But a fleet of ships cannot just sail blindly into the ocean. They need direction. Enter the Control Ship.

captionless image

The control ship represents the Master Node. The master node is the absolute brain of the entire operation. It manages everything plans schedules monitors and tells the cargo ships exactly what to do. The worker nodes just follow the orders given by the master node blindly.

Let us zoom in and look at the specialized crew working inside this Master Node brain.

captionless image

So we have this massive control ship making all the big decisions but it needs specialized crew members to actually handle specific tasks. First up we have the ship cranes. In the Kubernetes world we call this the Kube Scheduler.

captionless image

Think about how a real port works. When a brand new shipping container arrives someone has to decide exactly where it goes. You cannot just drop it anywhere and hope for the best. The Kube Scheduler is a core component of the control plane that does exactly this job.

captionless image

Its main function is to assign newly created pods to specific worker nodes. It does not just throw them randomly. It makes this placement decision based on strict resource requirements policies and other constraints you define. It checks which cargo ship has enough CPU and memory space and assigns the cargo there smoothly. If a ship is full the scheduler is smart enough to find another one.

Now imagine having thousands of containers spread across hundreds of ships. You absolutely need a highly reliable way to track them all. You need to know which containers are on which ships and exactly when they were loaded.

captionless image

This is where our highly available database comes in. We call it the ETCD cluster.

captionless image

ETCD is essentially a consistent and highly available key value store. It acts as the primary data store for all cluster data. You can think of it as the ultimate source of truth because it stores and replicates the entire Kubernetes cluster state. If this database goes down your control ship basically loses its memory completely. That is why keeping it healthy and backed up is one of the most critical things in cluster administration.

Moving on we have the offices in the dock. Picture an operation team handling ship control and a cargo team verifying if containers are damaged or need to be rebuilt. In our cluster this is known as the Controller Manager.

captionless image

The Controller Manager handles various controllers that keep the system running automatically.

captionless image

These controllers are basically continuous control loops that constantly watch the state of your cluster. When they notice something is wrong they make or request changes immediately. Every single controller tries to move the current cluster state closer to the desired state you originally defined. For example if a node goes down the node controller notices this failure and takes action to handle the onboarding of new nodes or rescheduling the lost workload.

But how do all these different services and teams actually communicate with each other. They need a central IT and communication office. Enter the Kube API Server.

captionless image

The API Server is the primary management component responsible for orchestrating all operations within a cluster. It exposes the Kubernetes API which is used by external users to perform management operations and by internal controllers to monitor the state of the cluster.

captionless image

It is literally the front end for the control plane and the central point of communication for all components. Whenever you type a kubectl command in your terminal you are talking directly to this API server.

captionless image

It does not just blindly accept commands though. It goes through a strict pipeline. First it uses authentication to check who you are. Then it uses authorization to see if you actually have the right permissions. Finally it uses admission control to validate the request before saving the new state to ETCD.

captionless image

Alright we covered the control ship. Now let us talk about the worker components down in the actual cargo ships. Every good ship needs a captain to manage all sorts of activity on board.

captionless image

The captain lets the master ship know they are ready to join the fleet and sends regular reports back about the overall status of the ship and its containers. We call this captain the Kubelet.

captionless image

The Kubelet is an agent that runs on every single worker node in a cluster. Its main job is to watch for pod specifications and ensure the containers described in those specs are running correctly and are perfectly healthy on its node. It is the core component making sure your cargo does not sink into the ocean.

captionless image

But we still have a networking issue to solve. How will a web server running on one worker node reach out to a database server running on another worker node. Basically how do two separate cargo ships communicate with each other over the network. They use the Kube Proxy service.

captionless image

Kube Proxy is a network proxy running on each node that manages all the necessary network rules.

captionless image

These rules enable network communication to your pods from both inside and outside the cluster. It basically handles all the complex routing making the whole Kubernetes service concept actually work without you having to configure routing tables manually on every single machine.

captionless imagecaptionless image

You might be wondering what exactly a pod is and why it is so important. A pod is the smallest deployable unit you can possibly create and manage in Kubernetes. It is the atomic unit of scheduling.

captionless imagecaptionless image

When you tell the master node to run something you do not ask it to run a container. You ask it to run a pod. A pod represents a single running process in your cluster and it can hold one or more containers inside it.

captionless image

Now a lot of developers ask a very valid question here. They look at this and say why do we even need this extra layer. Why can we not just deploy a basic raw Docker container directly onto the worker node. Why did the engineers invent this whole pod concept.

To understand this you need to think of a pod as a special house. We can call it a pod house.

captionless image

If you just deploy a raw Docker container it is completely isolated. But in modern architecture your main application often needs sidekick processes to function properly. You might have your main program container but you also need a proxy container to handle network traffic or a log container to collect error messages or a helper container to sync files.

captionless image

If these were just separate standard containers scattered on a massive server they would have a hard time finding each other and sharing resources securely. But when you put them together inside the same pod house magical things happen. First of all they get a shared network.

captionless image

Because they are in the same pod they literally share the exact same network namespace and IP address. This means they are speaking the exact same language. They can communicate with each other simply by using localhost.

captionless image

They just use different ports to talk to one another. It is incredibly fast and efficient. Second they get shared space.

captionless image

They can mount the exact same storage volumes. So your main application can write a log file to a folder and your helper container can instantly read that exact same file and send it to your monitoring dashboard. The pod creates this perfect cooperative environment for containers that need to be tightly coupled.

But a pod is not immortal. It has a very specific lifecycle from the moment you create it until it dies.

captionless image

When you first tell the API server to create a pod it enters a pending state while the scheduler looks for a good worker node. Once it is assigned and the containers start it moves to a running state. Eventually it will either finish its job and reach a succeeded state or something will break and it will hit a failed state.

To create a pod you do not click buttons in a user interface. You write a configuration file called a manifest.

captionless image

This manifest is usually a simple YAML file. You tell it the api version the kind of resource which is Pod in this case and give it metadata like a name. Then in the spec section you define exactly which containers you want inside this pod and what container ports they should expose. You hand this file to the API server and Kubernetes builds the exact house you asked for.

So running one pod is great. But what happens when your application goes viral.

captionless image

What if you suddenly need one hundred identical pods running at the same time. What if one of those pods randomly crashes at 3 AM. Or what if you need to update the application image inside all one hundred pods without causing any downtime. You absolutely cannot sit there and manage them one by one. That would defeat the entire purpose of automation.

This is where we introduce the ReplicaSet.

captionless image

The sole purpose of a ReplicaSet is to maintain a stable set of replica pods running at any given time. It acts like a strict manager.

captionless image

If you define a ReplicaSet and scream give me exactly 3 pods it will constantly monitor the cluster to guarantee the availability of those 3 identical pods. If one pod accidentally dies the ReplicaSet instantly notices the count dropped to 2 and it immediately spins up a brand new pod to replace the dead one.

But we can evolve even further. Managing ReplicaSets directly is a bit outdated because we have an even bigger boss now. We call it a Deployment.

captionless image

A deployment is a higher level concept that manages both pods and replicasets for you. It allows you to describe the ultimate desired state for your application. The true power of a deployment is that it automates updates scaling and rollbacks in a completely controlled way. It ensures your application is always running exactly as you intended even when you are pushing massive version changes.

captionless image

captionless image

When you are ready to release a brand new version of your application a deployment performs what we call a rolling update.

captionless image

Let us say you are moving from version 1 to version 2 and eventually to version 3. If you just killed all your old pods at once your users would experience a massive outage. Instead a deployment creates a new pod with version 2 waits for it to become completely healthy and then gracefully shuts down one of the old version 1 pods. It repeats this process one by one until your entire application is updated. If something goes terribly wrong with the new code you can just tell the deployment to roll back and it will automatically revert to the previous stable state. It is pure magic for developers.

But there is one final piece to this massive architectural puzzle. We already established that pods are completely mortal. They die they get replaced and when they do their IP addresses change constantly.

captionless image

So think about this problem. If your backend database pod crashes and gets replaced with a brand new pod it will inevitably have a brand new IP address. How does your frontend web server consistently find that backend database if the address keeps changing every single day.

captionless image

This is exactly why you use a Service. A service provides a stable permanent IP address and a reliable DNS name for a specific group of pods. It basically acts as an internal load balancer. Instead of your frontend trying to memorize the individual IP addresses of your backend pods it just sends traffic directly to the backend service. The service then routes that traffic to the correct healthy pods automatically. This allows all your different application components to communicate reliably even if the underlying pod IPs are changing a hundred times a day.

captionless image

All of this theory is amazing but nothing beats seeing it run on your own machine. In my original presentation I did a live demo to prove that this architecture is not just a fairy tale.

captionless image

If you want to practice all of this yourself I highly recommend installing minikube. It is a fantastic lightweight tool that lets you run a complete single node Kubernetes cluster right on your local laptop. You can create deployments break them fix them and learn the entire system without spending a single dollar on expensive cloud servers.

captionless image

We covered an insane amount of ground today. We went from the absolute dark ages of bare metal servers to the futuristic automated world of Kubernetes container orchestration. It might seem overwhelming at first but once you understand the cargo ship analogy everything just clicks into place.

captionless image

I want to give a massive thank you to everyone who stuck around for this deep dive. Also a big shoutout to the UN SDG AI Lab for hosting the original presentation that inspired this guide.

captionless image

If you want to talk about tech complain about buggy code or just connect with me you can find me on social media. You can also shoot me an email or visit my personal website to see what else I am working on.

captionless image

Thank you so much for reading and I will catch you all in the next article. Bye for now.

captionless imagecaptionless image

Top comments (0)