If you’ve ever tried to Google “What is Kubernetes?” you’ve probably seen a wall of buzzwords: orchestration, scalability, microservices, YAML manifests. Somewhere in there, someone will tell you it’s like “a shipping port for containers,” and you’ll want to slam your laptop shut.

Let’s skip the abstract metaphors and get to the point. Kubernetes (K8s if you want to sound cool and save keystrokes) is just a smart way to run a bunch of apps across multiple machines without losing your mind.

Why Not Just Run the Apps Directly?

You could SSH into each server, install your app, and run it. That’s how we did it back in the day. The problem?

  • Something crashes → you get 3 AM pager duty
  • You need more capacity → welcome to copy-paste hell
  • You want to upgrade → hope you like downtime

Kubernetes automates the boring stuff: restarts, scaling, rolling upgrades. It’s like having a tireless junior sysadmin who never sleeps, never complains, and always labels their cables.

Pods = Processes

In Kubernetes, the smallest thing you run is a Pod. A Pod can have one or more containers inside it. Think of it like a process on your computer — but instead of nginx running on your laptop, it’s running somewhere in your cluster.

# Traditional server

![Traditional server](/images/posts/kubernetes-without-jargon-pods-processes-services.png)

$ ps aux | grep nginx
nginx    1234  nginx: master process

# Kubernetes equivalent  
$ kubectl get pods
NAME           READY   STATUS    RESTARTS
nginx-abc123   1/1     Running   0

If the Pod dies, Kubernetes will quietly start a new one. No one calls you. No one panics. It just… works.

Here’s what a Pod definition looks like in practice:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
  - name: nginx
    image: nginx:1.25
    ports:
    - containerPort: 80

That’s it. You told Kubernetes: “Run this Nginx container and expose port 80.” Apply it with kubectl apply -f pod.yaml and it’s running somewhere in your cluster. Which node? You don’t need to care — Kubernetes handles placement based on available resources.

In production, you almost never create individual Pods. Instead, you use a Deployment — a higher-level controller that manages a group of identical Pods. A Deployment says “I always want 3 copies of this Pod running.” If one crashes, the Deployment creates a replacement. If you need more capacity, you scale the Deployment to 5. The Deployment is the real workhorse of Kubernetes.

Services = Stable Names

Containers and Pods are disposable — they come and go. The problem is, other apps need to talk to them. Enter the Service.

A Service is like a permanent name tag: “The app formerly known as Pod #54j2xa will always be reachable as payments-service.”

Behind the scenes, Kubernetes updates where that name points. You don’t have to chase changing IPs.

Here’s a Service definition that exposes our Nginx Pods:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx          # matches Pods with this label
  ports:
  - port: 80            # port the Service listens on
    targetPort: 80      # port the Pod is actually using
  type: ClusterIP       # only accessible inside the cluster

Now, any other Pod in the cluster can reach Nginx at http://nginx-service:80. It doesn’t matter which specific Nginx Pod handles the request — the Service distributes traffic automatically (basic load balancing, built in). If you scale from 1 Nginx Pod to 10, nothing else in your cluster needs to change. That’s the power of Services.

# Pod IPs change constantly
Pod nginx-abc123: 10.244.1.15 (dies)
Pod nginx-def456: 10.244.2.33 (replaces it)

# Service IP stays the same
Service nginx-service: 10.96.1.100 (permanent)

Why It’s a Big Deal

Kubernetes means you can:

Roll out new versions without downtime
Handle traffic spikes automatically
Recover from crashes without manual intervention
Scale horizontally instead of buying bigger servers

At scale, that’s the difference between “We’re down, boss” and “Oh, that? It fixed itself while I was making coffee.”

Do You Need Kubernetes?

If you’re running a single hobby project on one server: Probably not. That’s like using a 40-foot yacht to cross a swimming pool.

If you have multiple apps, multiple environments (dev, staging, prod), or need zero downtime: Kubernetes starts to make sense.

When Kubernetes Makes Sense

  • Multiple applications that need to talk to each other
  • More than 2-3 servers to manage
  • Can’t afford downtime during deployments
  • Traffic varies throughout the day/week
  • Multiple developers pushing code regularly

When It’s Overkill

  • Single application, simple architecture
  • One server handles all your traffic fine
  • Downtime is acceptable for deployments
  • Small team, infrequent deployments

The Honest Cost Comparison

People underestimate the operational cost of Kubernetes. Here’s what you’re signing up for:

  • Cluster management: Someone needs to manage the control plane, handle upgrades, and debug cluster-level issues
  • Monitoring complexity: You now need to monitor the cluster itself, not just your applications
  • Security surface area: Every Pod, Service, and network policy is a potential attack vector
  • Learning curve: Expect 3-6 months before your team is productive with K8s

For comparison, a well-written Ansible playbook + a few Docker Compose files can manage 10 servers with a fraction of the complexity. I’ve seen teams spend 6 months migrating to Kubernetes, only to realize they could have solved their actual problem (automated deployments) with a $50/month CI/CD pipeline.

Kubernetes vs Docker Compose: When to Use What

This is the question I get most often from people learning containers, so let me give you a clear, practical comparison:

Docker Compose is for defining multi-container applications on a single host. You write a docker-compose.yml file listing your containers, their connections, and their volumes. Run docker compose up and everything starts. That’s it.

Kubernetes is for running containerized applications across multiple hosts with automatic failover, scaling, and rolling updates. You write YAML manifests (plural — usually several per application), apply them with kubectl, and the cluster handles the rest.

Here’s how they compare on the things that actually matter:

ConcernDocker ComposeKubernetes
Setup time5 minutesHours to days
Multi-hostNo (single machine)Yes (its whole purpose)
Auto-restart on crashrestart: alwaysBuilt-in, default behavior
Scalingdocker compose up --scale=5kubectl scale deployment app --replicas=5
Rolling updatesNo (stop all, start all)Yes (zero downtime)
Load balancingBasic (single host)Built-in Services
Learning curveAfternoonWeeks to months
When to useSingle server, simple appsMultiple servers, production workloads

My honest recommendation: if you can solve your problem with Docker Compose, use Docker Compose. Don’t let anyone pressure you into Kubernetes prematurely. I run Docker Compose for my home lab and personal projects — it’s perfectly fine for a blog, a small API, or a handful of microservices on one VPS.

The right time to switch from Docker Compose to Kubernetes is when you hit a wall that Compose can’t climb over. For most people, that wall looks like one of these: your app needs to run on more than one server, you need automatic failover when a server dies, or you’re deploying the same app across dev/staging/production environments and need consistency.

Getting Started: The Practical Path

1. Learn Docker first: Kubernetes runs containers, so understand containers 2. Try managed Kubernetes: Vultr Kubernetes Engine, Google GKE, AWS EKS handle the hard parts 3. Start small: Deploy one simple app, get comfortable with kubectl 4. Gradually migrate: Move one service at a time, not everything at once

Learning Resources That Don’t Suck

Hands-on courses:

Books worth reading:

Free practice:

Next Steps

In my next post, I’ll show you Kubernetes hands-on with a “hello world” cluster on Vultr — no jargon, just working commands. You’ll deploy an app, break it on purpose, and watch Kubernetes fix it.

Why Vultr for learning? Simple pricing ($10/month for managed K8s), fast provisioning, and no surprise bills. Perfect for experimenting without enterprise complexity.

Want updates? Subscribe here for practical DevOps tips without the enterprise consultant speak.


A Real-World Example: What Kubernetes Actually Does

Let me walk you through what happens in a real Kubernetes deployment so you can see the pieces work together.

Imagine you have a web application with 3 components: a frontend, an API server, and a database. Here’s what Kubernetes handles for you:

  1. You define 3 Deployments (one per component) with desired replica counts
  2. You define 3 Services so each component can find the others by name
  3. You define a ConfigMap for environment variables (database URL, API keys) so you don’t hardcode them
  4. You apply all of this with kubectl apply -f ./k8s/

Now the magic:

  • Your API server crashes at 3 AM? Kubernetes restarts it. No alert, no page.
  • Traffic spikes because of a blog post going viral? You run kubectl scale deployment frontend --replicas=10 and Kubernetes spins up 7 more copies in seconds.
  • You need to deploy a new version? kubectl set image deployment/api api=myrepo/api:v2 triggers a rolling update — old pods are replaced one at a time, so there’s zero downtime.
  • A node (physical server) dies? Kubernetes reschedules all pods from that node onto healthy ones automatically.

Each of these scenarios used to require manual intervention, custom scripts, or maintenance windows. Kubernetes handles them all with the same declarative configuration.

Your First Deployment: Walkthrough

Let me show you exactly what deploying to Kubernetes looks like, step by step. This is what I wish someone had shown me when I was starting out — not theory, not diagrams, just the actual commands.

Step 1: Get a cluster. For learning, install Minikube (curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && sudo install minikube-linux-amd64 /usr/local/bin/minikube && minikube start). For production, use a managed service like Vultr, GKE, or EKS. The kubectl commands are the same either way.

Step 2: Create a Deployment. Save this as nginx-deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80

Apply it: kubectl apply -f nginx-deployment.yaml

Check it: kubectl get pods — you should see 2 nginx Pods in Running state.

Step 3: Expose it with a Service. Save this as nginx-service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30080

Apply it: kubectl apply -f nginx-service.yaml

Now you can access Nginx at http://<your-node-ip>:30080. With Minikube, just run minikube service nginx-service and it opens in your browser.

Step 4: Watch it self-heal. Delete a Pod and watch Kubernetes replace it:

kubectl delete pod <pod-name>
# Wait 5 seconds
kubectl get pods
# A new pod with a different name is already Running

That’s the core loop. Everything else in Kubernetes — ConfigMaps, Secrets, Ingress, PersistentVolumes — builds on these two concepts: Deployments (what to run) and Services (how to reach it). Don’t try to learn everything at once. Get comfortable with Deployments and Services first, then add ConfigMaps when you need environment variables, Ingress when you need proper domain routing, and PersistentVolumes when you need data that survives pod restarts.

Real Talk: When to Actually Use This

Before you dive into Kubernetes, ask yourself:

  • Are you solving a real scaling problem or just following trends?
  • Do you have time to learn the operational overhead?
  • Is your team ready for the complexity trade-off?

Kubernetes is powerful, but it’s not magic. It trades one set of problems (manual server management) for another (cluster configuration complexity).

For most small teams, a few well-configured servers with good deployment scripts will serve you better than a poorly-understood Kubernetes cluster.

Bottom line: Use Kubernetes when manual server management becomes more painful than learning Kubernetes. Not before.


Disclosure: Some links to courses, books, and cloud providers are affiliates - they help keep this blog running at no extra cost to you. I only recommend resources I’ve personally used and found valuable for learning and real-world projects.

Related reads: