DEV Community

Cover image for Every Kubernetes Concept Has a Story
Akhilesh Mishra
Akhilesh Mishra

Posted on

Every Kubernetes Concept Has a Story

Kubernetes Concepts are not random; each one has a beautiful problem-solving story behind it.

Most people learn Kubernetes the wrong way.

They see it as a list of concepts. Pods. Deployments. Services. Ingress. ConfigMaps. Secrets. HPA. They memorize them without understanding why they exist.

Every concept in Kubernetes exists because something broke. Someone ran it in production, something failed, and a new concept was born to fix it.

Let me show you the full story in order.

You start with a Pod.

A pod runs your container. Simple. Clean. Done.

Until it crashes.

Nobody restarts it. It is just gone.

In production, that is not acceptable.

So you use a Deployment.

A Deployment watches your pods.

One dies and it creates another.

You want 3 running, it keeps 3 running.

You want to scale to 10, one command does it.

Pods were too fragile for production. Deployment fixed that.

But now you have a new problem.

Every pod gets a new IP when it restarts.

You have 3 pods running your app.

Another service needs to talk to them.

Which IP do you use? They keep changing.

You cannot hardcode them. You cannot track them at scale.

So you use a Service.

A Service gives your app one stable IP address.

It finds your pods using labels, not IPs.

Pods die and come back with new IPs. The Service does not care.

It always finds them. It also load balances.

Traffic coming in gets distributed across all healthy pods automatically.

Pods had unstable IPs. Service fixed that.

But your app still needs to be accessible from the internet.

So you use a LoadBalancer Service.

This creates a real cloud load balancer. AWS ALB. Azure LB. GCP LB.

Your app gets a public endpoint.

Works perfectly. Until you have 10 services.

Now you have 10 load balancers. Each one costs money every single month.

Your cloud bill does not care that 6 of them handle almost no traffic.

LoadBalancer Services solved external access. But one per service does not scale.

So you use Ingress.

One load balancer. All your services behind it.

Ingress routes traffic based on rules.

Request comes in for /api, goes to the API service.

Request comes in for /dashboard, goes to the frontend service.

One entry point. Smart routing. One cloud load balancer on your bill.

But Ingress is just a set of rules. Something has to execute those rules.

So you use an Ingress Controller.

Nginx. Traefik. AWS Load Balancer Controller.

These are the actual engines that read your Ingress rules and make the routing happen.

Ingress without a controller is just a config file nobody reads.

Ingress Controller made the rules actually work.

If you want to learn Kubernetes the way it works in production, I am starting a 9-week advanced Kubernetes on AWS bootcamp where we build real production projects, troubleshoot live incidents, write RCAs, and implement AIops on Kubernetes. Checkout 👇

9-week Advanced Kubernetes Bootcamp on AWS (EKS) + AIops

Now your app is running. But it needs configuration.

Database URL. API keys. Environment name. Feature flags.

So you do what feels natural. You hardcode them inside the container.

It works on your laptop.

You deploy to staging. Wrong database URL.

You deploy to production. Wrong API key.

You fix it by rebuilding the image every time config changes.

In production, rebuilding an image to change a config value is not acceptable.

So you use a ConfigMap.

A ConfigMap holds your configuration outside the container.

You inject it into your pod at runtime as environment variables or a mounted file.

Change the ConfigMap. Redeploy. Your app picks up the new values.

The image never changes. The config does.

Same image runs in dev, staging and production with different configs.

Hardcoded config made your image environment-specific. ConfigMap fixed that.

But now you have a new problem.

Your database password is sitting in a ConfigMap.

ConfigMaps are not encrypted.

Anyone with basic kubectl access can read them.

You just stored your production database credentials in plain text inside your cluster.

That is not a mistake. That is a security incident.

So you use a Secret.

A Secret holds sensitive data. Passwords. Tokens. Certificates. API keys.

Stored separately from ConfigMaps with its own access controls.

Your app reads it at runtime. Your image never sees it.

You control who in the cluster can access which Secret.

ConfigMaps were not safe for sensitive data. Secrets fixed that.

Now traffic starts growing. And manual scaling breaks you.

Some days 100 users. Some days 10,000.

You are running 3 pods. On a busy day all three are maxed out.

Users are seeing slow responses. Requests are timing out.

You jump on, run a scale command, bump it to 8 pods. Crisis over.

Traffic drops at night. 8 pods sitting idle. Wasting money.

Next spike you do it all over again.

You cannot babysit your cluster every time traffic changes.

So you use HPA. Horizontal Pod Autoscaler.

HPA watches your pods continuously.

CPU goes above 70 percent. It adds more pods automatically.

Traffic drops. It scales back down automatically.

You define the minimum and maximum. Kubernetes does the rest.

Your app handles the spike. You are not woken up at 2am to manually scale.

Manual scaling could not keep up with real traffic. HPA fixed that.

But scaling pods created a new problem.

HPA adds pods during a traffic spike.

Your nodes are full.

The new pods sit in Pending state.

They cannot be scheduled because there is no capacity.

HPA did its job. But your cluster had nowhere to put the pods.

Scaling pods without scaling nodes is half a solution.

So you use Cluster Autoscaler or Karpenter.

They watch for pods stuck in Pending state.

Not enough capacity. They add a new node automatically.

Pending pods get scheduled. Traffic is handled.

Load drops. Nodes sit underutilized. They remove them automatically.

You only pay for the compute you actually need.

On EKS, Karpenter is the better choice. It is faster and more cost efficient. It provisions the exact right node for your workload instead of waiting for a fixed node group to scale.

HPA scaled your pods. Karpenter scaled your nodes. Together they make your cluster truly elastic.

But one last problem. And it is the one that takes things down silently.

Everything is scaling. Pods are coming up. Nodes are being added.

One pod starts consuming 4GB of memory. It was never supposed to.

But nobody told Kubernetes that. So it keeps consuming.

It starves every other pod on that node.

Those pods start failing. A cascade begins.

One rogue pod. No limits. Your entire node is affected.

An unpredictable cluster is an unreliable cluster.

So you use Resource Requests and Limits.

Requests tell Kubernetes the minimum your pod needs to be scheduled on a node.

Limits tell Kubernetes the maximum it is ever allowed to consume.

The scheduler places pods intelligently across nodes using requests.

Limits make sure one noisy pod cannot take down everything around it.

Your cluster runs predictably. Every pod gets what it needs. Nothing more.

Uncontrolled resource usage made your cluster unpredictable. Requests and Limits fixed that.

To summarize the full story:

Pod ran your app but had no resilience. Deployment fixed that.

Pods had unstable IPs. Service fixed that.

One load balancer per service was too expensive. Ingress fixed that.

Ingress needed something to execute its rules. Ingress Controller fixed that.

Hardcoded config made images inflexible. ConfigMap fixed that.

ConfigMaps were not safe for sensitive data. Secrets fixed that.

Manual scaling could not keep up with traffic. HPA fixed that.

Pod scaling without node scaling left pods pending. Karpenter fixed that.

Uncontrolled resource usage made clusters unpredictable. Requests and Limits fixed that.

Each concept exists because the previous one was not enough.

That is how you stop memorizing Kubernetes and start understanding it.

Top comments (0)