Kubernetes: The Operating System for Your Distributed Applications
kubernetes docker distributed system

Kubernetes: The Operating System for Your Distributed Applications

D. Rout

D. Rout

March 30, 2026 10 min read

On this page

If you've been in software development long enough, you've probably heard the word Kubernetes thrown around in architecture discussions, job postings, and conference talks — often with a reverence usually reserved for distributed systems wizardry. And for good reason. Kubernetes (commonly abbreviated as K8s) has fundamentally changed how we think about deploying, scaling, and managing applications in production.

But behind the jargon and the YAML files, Kubernetes solves a very concrete set of problems. In this post, we'll peel back the layers — starting with why Kubernetes exists, what it actually is, and how to deploy your first application with it.

Before we dive in — if you're not yet comfortable with containers, I'd strongly recommend checking out my guide on Docker: A Practical Guide for Developers. Kubernetes orchestrates containers, so Docker fluency is an essential prerequisite.


The Problem: What Happens After Docker?

Docker solved containerization beautifully. You package your app and its dependencies into an image, run it anywhere as a container, and it behaves consistently across environments. That's a massive win.

But Docker answers one question: how do I run a container?

It doesn't answer what happens when:

  • Your app receives 10x normal traffic and needs more instances
  • One of your containers crashes at 3am
  • You need to update your app without downtime
  • You're running 50 microservices across multiple machines and need them to talk to each other
  • You want to roll back a bad deployment without manual intervention

These are operational concerns — and at scale, managing them manually is a full-time job that doesn't scale linearly. You'd be writing custom scripts, building your own health-check logic, manually load-balancing, and playing whack-a-mole with failed processes.

This is the gap Kubernetes fills.


What Is Kubernetes?

Kubernetes is an open-source container orchestration platform originally developed by Google, open-sourced in 2014, and now maintained by the Cloud Native Computing Foundation (CNCF).

At its core, Kubernetes is a control plane that manages a cluster of machines (called nodes) and decides where and how containers run on them. You describe the desired state of your system — "I want 3 replicas of this service running" — and Kubernetes continuously works to make reality match that description. This is called declarative configuration.

Think of it like an operating system for your distributed infrastructure. Just as an OS abstracts CPU and memory from your applications, Kubernetes abstracts the underlying machines from your containerized workloads.

Key Concepts You Need to Know

Cluster A Kubernetes cluster is a set of machines — one control plane (the brain) and one or more worker nodes (the muscle). Your applications run on the worker nodes.

Pod The smallest deployable unit in Kubernetes. A Pod wraps one or more containers that share networking and storage. In practice, most Pods contain a single container.

Deployment A Deployment is a higher-level abstraction that manages Pods. You tell it: "I want 3 replicas of this container image." It creates the Pods, monitors them, restarts failed ones, and handles rolling updates.

Service Pods are ephemeral — they can be killed and rescheduled at any time, and their IPs change. A Service gives your Pods a stable network identity. It acts as a load balancer, routing traffic to healthy Pods.

Namespace A way to partition cluster resources. Useful for separating environments (dev, staging, prod) or teams within a single cluster.

ConfigMap & Secret ConfigMaps hold non-sensitive configuration data (env vars, config files). Secrets hold sensitive data like API keys and passwords, stored in a slightly more protected way (base64-encoded, with RBAC controls).

Ingress An Ingress resource manages external HTTP/HTTPS access to services within the cluster — your API gateway, essentially. It routes api.yourapp.com/users to the user service and api.yourapp.com/orders to the order service.


How Kubernetes Works

Here's the mental model: you never tell Kubernetes how to do things — you tell it what you want, and it figures out the rest.

The Control Plane

The control plane is a set of components that manage the cluster:

  • API Server — The front door to Kubernetes. All kubectl commands go through it.
  • etcd — A distributed key-value store that holds the entire cluster state.
  • Scheduler — Watches for new Pods and assigns them to appropriate nodes based on resources and constraints.
  • Controller Manager — Runs controllers that watch the cluster state and move it toward the desired state (e.g., the Deployment controller ensures the right number of replicas are running).

Worker Nodes

Each worker node runs:

  • kubelet — An agent that communicates with the control plane and ensures the containers described in a Pod spec are running.
  • kube-proxy — Handles network routing within the cluster.
  • Container Runtime — Usually containerd or Docker, the actual engine that runs containers.

Reconciliation Loop

The magic of Kubernetes is its reconciliation loop. Controllers continuously compare the current state of the cluster with the desired state you declared, and take corrective action:

  • A Pod dies → the Deployment controller notices → it schedules a new one
  • A node runs out of memory → the scheduler avoids placing new Pods there
  • You update a Deployment → Kubernetes performs a rolling update, replacing old Pods one at a time

How to Deploy Your First Application

Let's make this concrete. We'll deploy a simple Nginx web server to a local Kubernetes cluster using Minikube.

Step 1: Install the Tools

You'll need:

  • Minikube — runs a single-node K8s cluster locally
  • kubectl — the Kubernetes CLI
# macOS with Homebrew
brew install minikube kubectl

Step 2: Start Your Cluster

minikube start

This spins up a local VM running a single-node Kubernetes cluster. Give it a minute. When it's ready:

kubectl cluster-info

You should see the control plane address. You're in.

Step 3: Create a Deployment

Create a file called nginx-deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  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 what happened:

kubectl get pods

You should see 3 Pods running with names like nginx-deployment-abc12-xyz. Kubernetes created 3 replicas as instructed.

Step 4: Expose It with a Service

The Pods are running but not accessible from outside the cluster. Let's create a Service:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: NodePort
kubectl apply -f nginx-service.yaml

With Minikube, you can access the service directly:

minikube service nginx-service

Your browser opens and you see the Nginx welcome page — served by one of your 3 Pods, load-balanced automatically.

Step 5: Simulate a Failure

Delete one of the Pods:

# Get the pod name from kubectl get pods
kubectl delete pod nginx-deployment-

Now immediately run:

kubectl get pods

You'll notice Kubernetes immediately starts a new Pod to replace the deleted one. The Deployment controller saw the count drop to 2 and reconciled it back to 3. This is self-healing in action.

Step 6: Roll Out an Update

Let's update the Nginx version with zero downtime:

kubectl set image deployment/nginx-deployment nginx=nginx:1.26

Watch the rolling update:

kubectl rollout status deployment/nginx-deployment

Kubernetes terminates old Pods and creates new ones incrementally. Your service stays available throughout. If something goes wrong:

kubectl rollout undo deployment/nginx-deployment

One command. You're back to the previous state.


ConfigMaps and Secrets in Practice

Real applications need configuration. Here's how you'd inject environment variables:

ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  APP_ENV: "production"
  LOG_LEVEL: "info"

Reference it in your Deployment:

spec:
  containers:
    - name: my-app
      image: my-app:latest
      envFrom:
        - configMapRef:
            name: app-config

For sensitive values, use a Secret:

kubectl create secret generic db-credentials \
  --from-literal=username=admin \
  --from-literal=password=s3cr3t

Then reference it the same way with secretRef. Your container gets the values as environment variables — without them being hardcoded in your image or Deployment manifest.


Resource Requests and Limits

One of Kubernetes' most important features is resource management. Without constraints, a runaway process can starve other services on the same node.

spec:
  containers:
    - name: my-app
      image: my-app:latest
      resources:
        requests:
          memory: "128Mi"
          cpu: "250m"
        limits:
          memory: "256Mi"
          cpu: "500m"
  • requests: The minimum resources guaranteed to the container. Used by the scheduler to place Pods on nodes.
  • limits: The maximum the container can consume. Exceed memory limits and the container gets killed (OOMKilled). Exceed CPU limits and it gets throttled.

This gives you predictable performance and prevents noisy neighbour problems in shared clusters.


Horizontal Pod Autoscaling

Once your app is stable, you want it to scale dynamically with traffic. Kubernetes has a built-in Horizontal Pod Autoscaler (HPA):

kubectl autoscale deployment nginx-deployment \
  --cpu-percent=50 \
  --min=2 \
  --max=10

This tells Kubernetes: keep average CPU usage at 50%. If it goes above, add Pods (up to 10). If it drops, scale down (to a minimum of 2). Combine this with resource requests/limits and you have auto-scaling that actually knows what it's doing.


Kubernetes in Production: What Changes

Local Minikube is great for learning but production Kubernetes looks different:

  • Managed clusters — Most teams use Amazon EKS, Google GKE, or Azure AKS. They manage the control plane for you.
  • Helm — The package manager for Kubernetes. Instead of managing raw YAML files for complex applications, you use Helm charts — templated, versioned, reusable configurations.
  • GitOps — Tools like Argo CD and Flux let your Git repo be the single source of truth for cluster state. Merge a PR → your cluster updates automatically.
  • Observability — Kubernetes integrates well with Prometheus for metrics and Grafana for dashboards. You'll also want centralised logging (ELK stack or Loki).
  • RBAC — Role-Based Access Control governs who can do what in your cluster. Critical for multi-team environments.

Summary

Kubernetes exists because running containers in production at scale is a hard distributed systems problem. It gives you:

  • Self-healing — failed containers are replaced automatically
  • Scaling — horizontal scaling on demand, manually or automatically
  • Zero-downtime deployments — rolling updates and instant rollbacks
  • Service discovery — stable networking between ephemeral Pods
  • Declarative infrastructure — describe what you want, not how to do it

The learning curve is real. YAML verbosity, networking abstractions, and the sheer number of concepts can feel overwhelming at first. But the mental model — declare desired state, let the control loop reconcile — is consistent throughout. Once it clicks, the rest follows.

Start with Minikube. Break things intentionally. Then move to a managed cluster when you're ready for production.


Further Learning

Share

Comments (0)

Join the conversation

Sign in to leave a comment on this post.

No comments yet. to be the first!