Kubernetes, from the ground up
How a cluster is put together, how a Pod actually gets scheduled and kept alive, and the commands you reach for once it’s running — with a diagram for every moving part.
What Kubernetes is, and the problem it solves
Kubernetes (K8s) is an open-source container orchestration platform. It automates deployment, scaling, networking, and self-healing for containerized applications — originally built at Google, now maintained by the CNCF.
Why it exists
Docker alone is great at packaging a single container — but running dozens or hundreds of them in production exposes problems it was never designed to solve.
| Docker alone | Kubernetes |
|---|---|
| Manages a single container | Manages fleets of containers across many machines |
| Manual scaling process | Automatic scaling based on load |
| No self-healing | Restarts / reschedules failed containers automatically |
| No built-in load balancing | Distributes traffic across replicas natively |
| No rolling updates | Zero-downtime rollouts and instant rollbacks |
The stack, top to bottom
Core features at a glance
Self-healing
Failed containers are restarted, unhealthy Pods are replaced automatically.
Auto scaling
Scale Pods up or down manually or via the Horizontal Pod Autoscaler.
Rolling updates
Ship new versions with zero downtime, and roll back instantly if something breaks.
Service discovery
Stable networking and load balancing even as Pods are destroyed and recreated.
Storage orchestration
Mount local, network, or cloud storage automatically.
Config & secret management
Separate configuration and credentials from your container images.
Cluster architecture: control plane vs. worker nodes
Kubernetes follows a master–worker (client–server) model. Every cluster splits into two halves: the Control Plane, which makes decisions, and Worker Nodes, which do the work.
Control plane components
| Component | Role |
|---|---|
| API Server | The front door of Kubernetes — exposes the REST API that kubectl and every other component talks to. |
| etcd | A consistent, highly-available key-value store holding all cluster data. |
| Scheduler | Watches for newly created Pods with no Node assigned, and picks the best Node for them. |
| Controller Manager | Runs the background controllers (Node, ReplicaSet, etc.) that continuously push the cluster toward its desired state. |
Worker node components
| Component | Role |
|---|---|
| kubelet | Ensures the containers described for a Pod are actually running on this node. |
| kube-proxy | Maintains network rules so traffic reaches the right Pods. |
| Container Runtime | Pulls images and runs containers (e.g. containerd, Docker). |
Pods: the smallest deployable unit
A Pod wraps one or more containers that share the same network and storage. Containers inside a Pod are always scheduled together, on the same node — they’re never split up.
Why a Pod instead of a bare container?
| Container (Docker alone) | Pod (Kubernetes) |
|---|---|
| Single container | One or more containers |
| Managed manually | Managed by Kubernetes |
| No self-healing | Self-healing — restarts on failure |
| Scaling is manual | Auto-scaling is possible |
| No shared resources | Shares network & storage across its containers |
Pod lifecycle
Pod types
Single-container Pod
The common case — one container per Pod, doing one job.
Multi-container Pod
Tightly-coupled helper containers (e.g. sidecars, log shippers) that must live and scale alongside the main container.
ReplicaSets & Deployments
You almost never create Pods directly. Instead, a Deployment manages a ReplicaSet, which manages the Pods — giving you scaling, rolling updates, and rollbacks for free.
ReplicaSet vs. Deployment
| Feature | ReplicaSet | Deployment |
|---|---|---|
| Purpose | Ensures N Pod replicas are running | Manages ReplicaSets, adds declarative updates |
| Rolling updates | Not supported | Supported |
| Rollbacks | Not supported | Supported, to any previous revision |
| Scaling | Supported | Supported |
| Self-healing | Yes | Yes |
| Typical use | Rare, simple cases | Production standard |
Rolling update, step by step
Rollback flow
# roll back to the previous working version kubectl rollout undo deployment my-app # see revision history first if you need to pick a specific one kubectl rollout history deployment my-app
Deployment strategies
Recreate
All old Pods are killed first, then new ones are created. Simple, but causes downtime.
RollingUpdate (default)
Pods are updated one by one — zero downtime, the workhorse strategy.
Blue/Green
Run two full environments (blue = current, green = new) and switch traffic over instantly once green is verified. More infrastructure, but instant, safe cutover and rollback.
Commands you’ll actually use
| Command | Description |
|---|---|
kubectl create deployment name --image=img |
Create a new Deployment |
kubectl get deployments |
List all Deployments |
kubectl scale deployment name --replicas=5 |
Scale to N replicas |
kubectl rollout status deployment/name |
Check rollout progress |
kubectl rollout undo deployment/name |
Roll back to the previous version |
kubectl set image deployment/name c=img:tag |
Update a container’s image |
Services: stable networking for ephemeral Pods
Pods are ephemeral — they get created, destroyed, and rescheduled, and their IPs change every time. A Service gives them a stable IP and DNS name, and load-balances traffic across whichever Pods currently exist.
The four Service types
| Type | Use | Accessible from | Description |
|---|---|---|---|
| ClusterIP | Internal communication | Inside the cluster | Default type. Cluster-internal IP only. |
| NodePort | Expose on each Node’s IP | Outside, via Node IP : Port | Opens a static port on every Node. |
| LoadBalancer | Expose to external traffic | Outside, via cloud LB | Provisions a cloud provider load balancer. |
| ExternalName | Map to an external domain | Inside the cluster | Maps the Service to a DNS name outside the cluster. |
my-service, ClusterIP 10.96.0.15, port 80, target port 8080. A client inside the cluster hits my-service:80, and the Service load-balances that to port 8080 on one of the matching Pods.Ingress: smart routing at Layer 7
A LoadBalancer or NodePort Service exposes one application. Ingress sits in front of many Services behind a single entry point, routing by hostname or path — at the HTTP layer, not just TCP/UDP.
Service vs. Ingress
| Feature | Service | Ingress |
|---|---|---|
| Layer | Layer 4 (TCP/UDP) | Layer 7 (HTTP/HTTPS) |
| Routing | Basic, port-based | Advanced — host and path-based |
| SSL/TLS | Not handled | Can terminate SSL |
| Usage | Exposes one Service | Exposes many Services via rules |
| Requires | Nothing extra | An Ingress Controller |
# list every Ingress across all namespaces kubectl get ingress -A # create an Ingress from a YAML manifest kubectl apply -f ingress.yaml # inspect the rules on a specific Ingress kubectl describe ingress my-ingress
ConfigMaps & Secrets
Both decouple configuration from your container image, so the same image can run in dev, test, and prod without rebuilding it. The difference is sensitivity.
ConfigMap
Stores non-sensitive key–value config — app settings, URLs, feature flags — as plain text.
Secret
Stores sensitive data — passwords, tokens, keys, certificates — Base64-encoded (not encrypted by default).
| Feature | ConfigMap | Secret |
|---|---|---|
| Data type | Non-sensitive | Sensitive |
| Encoding | Plain text | Base64-encoded |
| Purpose | Configuration | Passwords, keys |
| Security | Less secure | More secure (but not encrypted at rest by default) |
| Consumed as | Env vars or mounted files | Env vars or mounted files |
Volumes, Persistent Storage & StorageClasses
Containers are ephemeral — delete one, and everything inside it is gone. Volumes give Pods storage that survives container restarts and deletions.
Volume types
| Type | What it does |
|---|---|
| emptyDir | Temporary storage; deleted when the Pod is removed |
| hostPath | Mounts a file or directory from the host node (use with caution) |
| nfs | Mounts an NFS share |
| configMap | Mounts a ConfigMap as files |
| secret | Mounts a Secret as files |
| persistentVolumeClaim | Uses persistent storage (PV) — the production choice |
How PV, PVC, and StorageClass fit together
fast-ssd for high performance, standard for general purpose, slow-hdd for backups — and enables dynamic provisioning so a PV doesn’t have to be created manually.# storage inspection
kubectl get pv
kubectl get pvc
kubectl describe pvc my-pvc
kubectl get storageclass
kubectl describe storageclass fast-ssd
Namespaces
A Namespace divides cluster resources between multiple users, teams, or environments. Resources in one namespace are invisible to another by default.
- The default namespace is literally called
default. - Namespaces help with isolation and resource management (e.g. quotas per team).
- Resources in different namespaces are isolated from each other.
# list namespaces, and everything scoped to one
kubectl get ns
kubectl get pods -n my-namespace
Resource management & health checks
Two mechanisms keep a cluster stable under real load: resource requests/limits control how much a container can use, and probes control whether it’s considered healthy.
Requests vs. Limits
| What it means | |
|---|---|
| Requests | Minimum resources guaranteed; used by the scheduler to place the Pod. If unset, scheduling can be poor. |
| Limits | Maximum resources a container may use. Prevents one noisy container from starving the node. Exceeding it can throttle or kill the container. |
The three probes
Liveness Probe
“Is the container running?” — fails it, and Kubernetes restarts the container.
Readiness Probe
“Is it ready to serve traffic?” — fails it, and the Pod is pulled out of Service rotation without being killed.
Startup Probe
“Has the application finished starting up?” — protects slow-starting apps from being killed too early by the liveness probe.
Common labels
| Label | Meaning |
|---|---|
| app | Name of the application |
| env | Environment — dev, test, prod |
| tier | Tier — frontend, backend |
| version | Version of the application |
| team | Owning team |
kubectl command reference
Grouped by what you’re actually trying to do, so you can scan straight to the section you need.
Inspecting the cluster
kubectl get pods # list all Pods kubectl get svc # list all Services kubectl get nodes # list all Nodes kubectl get ns # list all Namespaces kubectl describe pod <pod-name> # full details of a Pod kubectl logs <pod-name> # logs of a Pod kubectl exec -it <pod-name> -- /bin/bash # shell into a Pod
Deployments & ReplicaSets
kubectl create deployment <name> --image=<image> kubectl get deployments kubectl get rs kubectl describe deployment <name> kubectl scale deployment <name> --replicas=<n> kubectl rollout status deployment <name> kubectl rollout undo deployment <name> kubectl rollout history deployment <name>
Services & Ingress
kubectl get svc kubectl get ingress -A kubectl describe ingress <name> kubectl apply -f ingress.yaml kubectl delete ingress <name>
Storage
kubectl get pv kubectl get pvc kubectl describe pvc <name> kubectl delete pvc <name> kubectl get storageclass kubectl describe storageclass <name>
