Learn
Practical setup guides, configuration walkthroughs and troubleshooting notes, each paired with the terminal output you should expect. Organised by the technology you are working with.
Latest guide
A DaemonSet is one per node, minus the refusalsPaid
"A DaemonSet runs one Pod on every node" is the definition everyone learns and it is not what the controller does. It runs one Pod on every node that will accept one, and the number it reports as DESIRED is the result of that filtering rather than a count of your nodes. Four nodes, three Pods, and the missing one explained and then fixed.
kubectl delete pod webpod "web" deleted from default namespacekubectl get podsNAME READY STATUS RESTARTS AGEnginx 1/1 Running 0 12ssidecar-demo 2/2 Running 0 12s
Choose a technology and follow its path in order.
-
44 free
Kubernetes
Install and operate real clusters, then specialise by role.
Browse 131 guides -
Free
Containers
Build and run images, with a daemon or without one.
- DockerImages, layers, registries and Compose.
- PodmanDaemonless, rootless containers, pods and systemd units.
All guides
The whole library, searchable. Use this when you already know what you are looking for.
224 guides
-
A DaemonSet is one per node, minus the refusalsPaid
"A DaemonSet runs one Pod on every node" is the definition everyone learns and it is not what the controller does.
-
A Gateway that never gets programmed
The Gateway API is not in Kubernetes - it arrives as CRDs you install.
-
A Pod that is supposed to stop
Every other workload object exists to keep something running.
-
Delete the Pod and the same name comes backPaid
Deployment Pods are interchangeable and named at random; StatefulSet Pods have stable identities and each keeps its own disk across deletion and rescheduling.
-
Expired certificates read as Unauthorized
kubeadm certificates last one year and renewing them is one command.
-
NoSchedule keeps Pods out, NoExecute throws them offPaid
A taint is a node saying no.
-
One ConfigMap, three readers, three answersPaid
A ConfigMap is one object, but a Pod can consume it three ways at once - as an environment variable, as a mounted directory, and as a single file placed with subPath.
-
Running is not the same as readyPaid
STATUS says Running and the Service answers nothing.
-
The 404 came from your own backend
An Ingress object is a routing table that does nothing on its own - a controller has to be running to read it.
-
The rollout stopped and the site stayed upPaid
A Deployment does not replace Pods; it manages two ReplicaSets and moves replicas between them under a budget.
-
Three ways in, and one that waits forever
A NodePort answers on all four nodes, including the ones running nothing.
-
A canary that rolls itself backPaid
A Deployment gives you one rollout strategy and no opinion about whether the new version is any good.
-
A ClusterIP you cannot ping
A Service gets an IP address that answers HTTP and refuses ping, because nothing owns it.
-
A container as a systemd unit
A nine-line `.container` file becomes a real systemd service, and `systemctl --user enable` then fails on it because the unit is generated, not installed.
-
A container that updates itself
Push a new image under the same tag and `podman auto-update` pulls it and restarts the container - no orchestrator.
-
A pod is the point
`podman pod inspect` answers the question directly: `shared=[uts ipc net]`.
-
A registry on its own host
A registry container on podman03, and the first push fails with `http: server gave HTTP response to HTTPS client`.
-
A sidecar that starts and staysPaid
An init container with `restartPolicy: Always` is not an init container.
-
A signature was required
Two identical images in one registry, one signed.
-
A volume that is not a directory
`--opt type=tmpfs --opt o=size=8m` makes a volume that lives in RAM and enforces its size - a 16 MB write stops at 8.
-
An Application is a custom resource, not a buttonPaid
Point Argo CD at a Git path with twenty lines of YAML and it deploys, then keeps deploying.
-
An error budget you can queryPaid
An SLO is not a document.
-
Where Helm actually keeps its statePaid
helm create scaffolds a working chart, helm template renders it without a cluster, and --dry-run creates nothing at all - not even the namespace.
-
Why your HPA says unknown
An HPA on a Deployment with no CPU requests reports cpu: <unknown>/60% forever.
-
Back up a volume with one command
`podman volume export` writes a plain tar of a volume's contents - no helper container, no `-v $(pwd):/backup` incantation.
-
Build an image from a Containerfile
Five instructions, five STEP lines, and an image tagged `localhost/app:1` - Podman prefixes locally built images with a registry that does not exist, which is the first thing that will confuse you when you try to push it.
-
Buildah is what podman build calls
`buildah` is already installed - it arrived with Podman.
-
Push your build cache to a registry
A CI worker starts with an empty cache every run, which is why naive pipelines rebuild everything every time.
-
Create a user the cluster trustsPaid
Kubernetes has no User object.
-
The event stream logs do not give you
The event stream is the timeline logs do not give you.
-
Contexts and managing remote hosts
Drive a Docker host across the network from your own machine, using SSH rather than an exposed daemon port.
-
Disk usage and safe cleanup
Where the space actually goes - measured, not guessed.
-
Drain a node without breaking itPaid
`kubectl drain` refuses twice before it works, and each refusal names the flag it wants: DaemonSet pods, then pods with no controller.
-
Drive podman01 from podman02
`podman system connection add` succeeds without testing anything, then the first real command fails with an ssh handshake error.
-
Drop every capability, then add back
Each failure names the next capability: chown, then bind.
-
Essential Podman CLI commands
The dozen commands that cover most days, and the `--format` template that turns any of them into a single line you can script against.
-
A PVC that grows only halfwayPaid
Patch a PVC from 64Mi to 128Mi and it reports 128Mi requested against 64Mi actual, with FileSystemResizePending.
-
Four standards your cluster already speaks
CRI, CNI, CSI and OCI are not trivia - they are why you can swap Docker for containerd, Flannel for Calico, or one storage backend for another without Kubernetes noticing.
-
Generate Kubernetes YAML from a pod
`podman kube generate` turns a pod you built by hand into a real `apiVersion: v1 / kind: Pod` manifest.
-
generate systemd is deprecated
`podman generate systemd` still runs and opens with `[DEPRECATED]`.
-
Who actually owns your Pod
Two numbers tell you whether a controller has caught up with your change, and one field explains why deleting a Pod does not help.
-
29 dashboards you did not writePaid
The chart ships Grafana already pointed at Prometheus, with 29 dashboards delivered as ConfigMaps and loaded by a sidecar.
-
SBOMs, provenance and knowing what you shipped
You cannot answer "are we affected by this CVE" without knowing what is inside your images.
-
Inspect a running container
Four questions and the command for each: what has it said, what is it running, what is it costing, and what has it changed. `podman diff` is the one people never reach for and should.
-
Argo CD's install hits a 256 KB wall
The documented one-liner fails on this chart with "annotations: Too long".
-
Install Podman on Ubuntu 26.04
Podman installs from Ubuntu's own repository in a single command.
-
The port Prometheus cannot have
Install kube-prometheus-stack with Helm and watch all four node-exporters go into CrashLoopBackOff.
-
kubectl fast enough for the examPaid
Two hours, seventeen tasks. `--dry-run=client -o yaml` writes the manifest you were about to type from memory, `kubectl explain` replaces the browser tab, and jsonpath answers a question instead of printing a table to read.
-
kubectl is just an HTTP client
Turn up the verbosity and kubectl stops being magic: it is a GET to an HTTPS endpoint that returns JSON.
-
Linger is about boot, not logout
Everyone repeats that a rootless service dies at logout.
-
Logs outlive the container
`podman rm` the container and `podman logs` says no such container - but `journalctl --user CONTAINER_NAME=talker` still prints every line. journald is the store; `podman logs` is only a reader that needs the container to exist.
-
Migrating from Docker: what breaks
`docker run` mostly just works.
-
Move an image with no registry
`podman image scp localhost/multi:1 lab02::` copies an image host to host and prints `Loaded image`.
-
Multi-stage builds leave the compiler behind
The same Containerfile produces an 8.66 MB image and a 182 MB one, and the difference is which stage you stop at. `--target` builds the discarded half so you can look at what was thrown away.
-
netavark and aardvark-dns
Two Rust binaries in /usr/lib/podman that you never invoke: netavark configures the network and aardvark-dns answers name lookups.
-
Podman network drivers beyond bridge
`--network none` leaves a container with loopback and nothing else. `host` gives it your namespace outright.
-
Nineteen alerts on a cluster that is finePaid
A fresh kube-prometheus-stack fires nineteen alerts on a working cluster.
-
Ten Pods means ten pause containersPaid
Ten Pods on this node means ten pause containers doing nothing at all.
-
pasta gives the container your IP
A rootless container on the default network has `eth0` set to 192.168.0.24 - the host's own LAN address - and an empty IPAddress field.
-
podman-compose is a different tool
The same compose.yaml gives you `stack_web_1` from podman-compose and `stack-web-1` from `podman compose`.
-
Podman is not a Docker alias
`podman-docker` puts a /usr/bin/docker on your PATH and most commands just work.
-
Production troubleshooting handbook
The failures you will actually meet, each reproduced deliberately so you recognise the exact wording.
-
Publishing port 80 needs a sysctl
`-p 80:80` rootless fails with `pasta failed ...
-
RBAC in four commandsPaid
A ServiceAccount starts able to do almost nothing.
-
Read-only containers and dropping capabilities
Harden a real nginx container to a read-only filesystem and four capabilities - including the two failed attempts, because the failures are where the learning is.
-
Read the error, not the symptom
Every failure on this path named its own cause: `Invalid argument` versus `Permission denied`, pasta versus nginx on port 80, a netns error that still exits 0.
-
Real docker compose, through Podman
Enable `podman.socket`, set `DOCKER_HOST`, and the genuine Docker Compose binary brings up a two-service stack on Podman.
-
Renew certificates before they expirePaid
`kubeadm certs renew all` rewrites eleven certificates and tells you to restart four components.
-
Replicas: 3 gets you one pod
A Deployment asking for three replicas gets a warning and one pod.
-
Requests are the bill, not usage
A cluster can be completely full while every node sits at 3% CPU.
-
Restart the pod, not the container
A `.pod`, a `.volume` and a `.container` file, and starting one of them starts all three.
-
Rootless and rootful get the same caps
`CapEff: 00000000800405fb` in a rootless container, and the identical value under sudo.
-
Rootless builds stop at 65536
`RUN chown 65000:65000` builds fine and `RUN chown 70000:70000` fails with `Invalid argument`, because /etc/subuid grants you exactly 65536 subordinate UIDs.
-
Rootless Docker and why the socket is root
Membership of the docker group is equivalent to root on the host, and most people who have it do not know why.
-
Rootless is the default
You are root inside the container and uid 1000 outside it, at the same instant, for the same process.
-
Run a manifest without Kubernetes
`podman kube play` runs a Kubernetes manifest on a single host with no cluster, no kubelet and no API server. `podman kube down` then prints a netns error and exits 0 - the pod is gone, and the same pod built by hand tears down silently.
-
Run and manage your first Podman container
The five states a container moves through, and the two flags that decide whether you ever see it again.
-
Same nodeSelector, one Pod Pending
Two Pods with an identical nodeSelector pointing at the same node.
-
Scale to zero is already there. Waking up is not.Paid
Kubernetes will happily run zero replicas - that half of serverless is built in.
-
Scanning images and fixing what you find
Scan a deliberately old base image, read what comes back, then prove the fix: the same scan against a current base returns zero findings.
-
Self-heal undoes your change before you see itPaid
Scale a managed Deployment by hand and the change is gone before the next command runs.
-
Short names do not mean Docker Hub
`podman pull hello-world` fetches `quay.io/podman/hello`, not Docker's image - and the same command on the same host returns a different image once one is already in your store.
-
Swarm: what a cluster is made of
Docker's own orchestrator, already in the engine you have installed.
-
Draining nodes, maintenance and failover
Take a machine out of service without dropping a request.
-
Overlay networks and the routing mesh
Publish a port on a cluster and every node answers it - including nodes running none of your containers.
-
Rolling updates and rollback
Change the image on a live service and watch the cluster replace tasks a few at a time.
-
Services, replicas and scheduling
A service is a desired state, not a container.
-
Stacks and swarm secrets
Deploy a Compose file to the whole cluster with one command, and distribute a password to only the services that need it - proved by the service that should not have it finding nothing at all.
-
The budget that blocks your drainPaid
`ALLOWED DISRUPTIONS 0` and a drain that retries every five seconds forever: `Cannot evict pod as it would violate the pod's disruption budget`. minAvailable 3 with 3 replicas permits nothing, and the arithmetic is the whole guide.
-
The cgroup driver both sides must agree onPaid
The kubelet and the runtime each decide how to talk to cgroups.
-
The cluster this path uses
Four nodes, Kubernetes 1.36.4, containerd 2.2.6 - and a kubectl one minor behind the server, which is supported and worth understanding rather than fixing.
-
The default network has no DNS
`getent hosts beta` exits 2 on the default network and resolves on a user-defined one.
-
The files you cannot delete
A container running as its own user 1000 writes files owned by host UID 100999.
-
The landscape your cluster installed
The CNCF landscape is usually taught as a poster to memorise.
-
The namespace filled in limits you never set
A Pod created with no resources at all comes back holding a CPU request, a memory request and both limits.
-
One label turns Running into Forbidden
One label on a namespace turns a privileged Pod from Running into Forbidden.
-
The status is the category, not the cause
Six broken Pods at once.
-
There is no daemon
Start a container, then look for the process that owns it. `pgrep podman` finds nothing, `podman.service` is inactive, and the running nginx is a child of PID 1 by way of a 96-argument monitor called conmon.
-
There is no shell in that container
kubectl logs picks a container for you without saying which until you ask.
-
Three autoscalers, one installed
HPA adds Pods, VPA resizes them, Cluster Autoscaler adds nodes.
-
Three volumes, and what each one loses
An emptyDir shared by two containers, deleted with its Pod.
-
Two containers, one localhost
A sidecar reaches its web server on `http://localhost:80` with no network, no DNS and no service.
-
Volumes and bind mounts
A named volume is a directory in your rootless store that Podman manages; a bind mount is a path you chose.
-
What a NetworkPolicy cannot sayPaid
Two Pods talk in plaintext, a default-deny stops them dead, and one label-based rule lets exactly one caller back in.
-
What actually runs a container
The kubelet does not run containers.
-
What KCNA is, and what it is not
KCNA is broad and shallow on purpose: four domains, one of them nearly half the exam, and no live cluster to fix.
-
Where each of the four Cs failsPaid
Cloud, Cluster, Container, Code.
-
Where rootless keeps your images
185 MB of images in `~/.local/share/containers/storage`, on your home filesystem and counted against your quota.
-
Which prune loses your data
`container prune` and `image prune` reclaim space and lose nothing. `volume prune` removed two volumes here, one of them a Compose volume with data in it - and it is the only one of the three that is irreversible.
-
Four targets that will never come up
Prometheus reports kube-proxy, the scheduler, the controller manager and etcd as down on a healthy cluster.
-
Why podman stop takes ten seconds
`podman stop` on a container running `sleep` takes 10.119 seconds and ends in SIGKILL.
-
Why your rebuild was instant
Rebuilding an unchanged Containerfile produces the same image ID, so `app:1` and `app:2` are one image with two tags.
-
You asked for eight replicas and got fourPaid
Scale to 8 with a ResourceQuota and an HPA in place and you land on 4.
-
Your first PromQL queriesPaid
Query Prometheus from a Pod instead of a port-forward.
-
Your server sees 169.254.1.2
Two curls from the same machine reach the same container and its access log records `::1` for one and `169.254.1.2` for the other.
-
What survives a deleted claimPaid
Ask a node-local provisioner for ReadWriteMany and watch the claim hang.
-
Cache mounts and build secrets
Two BuildKit features that solve problems the layer cache cannot: a package cache that survives --no-cache, and a way to use a private token during a build without it ending up in the image.
-
Buildx and multi-platform images
One tag serving amd64, arm64 and arm/v7.
-
The filter Felix writesPaid
Pod networking stops being magic once you can see the pieces: a per-node IPAM block, one veth and one host route per Pod, a blackhole for the local block, and Felix rendering policy into the node's packet filter.
-
Choosing and installing a CNI pluginPaid
Why a fresh kubeadm cluster has no pod network, what a CNI plugin actually installs, how to choose between Calico, Cilium and Flannel, and how to read what Calico did to your nodes: one address block per node, routes to its neighbours, and encapsulation it turns out not to be using.
-
What to check first when a cluster breaks
Under pressure, the order you check things in matters more than knowing every command.
-
A multi-service app with a database
The shape almost every real project takes: an application talking to a database over the project network, with the data on a named volume that survives a teardown.
-
Environment variables, env files and secrets
Four different things all called environment, doing four different jobs.
-
Health checks and dependency ordering
Up does not mean ready, and the gap between them is where flaky startups live.
-
Profiles, override files and Watch
Three features that turn one Compose file into a workflow: optional services behind profiles, per-machine overrides that merge automatically, and live file sync that updates a running container without a rebuild.
-
Four ways configuration reaches a PodPaid
Four ways to hand configuration to a container, and the one difference that catches everyone: patch a ConfigMap and the mounted file updates while the environment variable does not.
-
Configure the Docker daemon
daemon.json changes every container on the host, and a malformed file stops Docker starting at all.
-
Container logs and rotation
Container logs are files on the host and by default they grow without limit.
-
The flags that make kubectl logs useful
A two-container Pod, and the flags that turn kubectl logs from a firehose into an answer: picking a container, all of them at once with prefixes, a time window, timestamps, and selecting by label across Pods.
-
Control plane and node components: who does whatPaid
Every diagram of Kubernetes architecture shows five boxes.
-
Control plane down: debugging without kubectl
Take the API server away and every kubectl command dies with it. crictl still answers, because it talks to the runtime rather than the cluster, and it is the only view you have left of a control plane that cannot report on itself.
-
The search path, ndots, and five queriesPaid
Resolve one Service four ways, get a headless Service to hand back every Pod IP, and measure the real cost of a short name by counting the queries CoreDNS receives: five for `fleet`, one for the fully qualified name.
-
The logs you want belong to a dead container
A container that exits 3 on startup, caught mid-cycle.
-
CSI drivers and the StorageClass nobody shipsPaid
Kubernetes has no storage code of its own.
-
A new kind with nothing to reconcile itPaid
A CRD gives you a real Kubernetes resource with validation, printer columns, RBAC and kubectl support, for the cost of one YAML file.
-
DaemonSets: one Pod per nodePaid
A DaemonSet has no replica count.
-
Two ways to change a clusterPaid
Create the same Deployment twice, once with a command and once with a file, then look at what each left behind on the object.
-
Rollouts, rollbacks and revision historyPaid
Write a Deployment, follow the ownership chain down to the Pods, roll an image forward and back, read what a revision records, and push a broken image to watch the rollout stall while the old ReplicaSet keeps serving every request.
-
Proving it really is DNS
A name that does not exist answers instantly; a resolver that cannot be reached takes the whole timeout.
-
Docker Compose fundamentals
One file replaces a page of docker run flags.
-
EndpointSlices: what a Service actually points atPaid
A Service is a selector; the EndpointSlice is the answer to it.
-
etcd backup and restore, end to endPaid
Take a snapshot, create something after it, then restore and watch that thing cease to exist.
-
etcd unhealthy: a timeout instead of a refusal
Stop etcd and the API server stays up, which changes the symptom completely: requests time out instead of being refused, and livez reports every check ok except one.
-
Where Kubernetes tells you what went wrong
Almost every Kubernetes failure explains itself in one of three places: an event, the Events section of describe, or a status condition.
-
Build a four-node Kubernetes clusterPaid
Build a control plane and three workers, then use the third worker to reach the placement features that need it: pod anti-affinity with somewhere to spread to, topology spread constraints, and a drain that leaves two healthy workers behind.
-
Weights Ingress cannot expressPaid
Ingress replaced with three objects owned by three different people, plus weighted splits and header matching without a single annotation.
-
Why your manual change disappearedPaid
Helm templates YAML and remembers what it sent, which is what makes rollback work.
-
Quorum loss arrives as ForbiddenPaid
A three-node control plane built from scratch: keepalived and haproxy in front, stacked etcd behind, and a controlPlaneEndpoint that has to exist before the first init.
-
Scaling on a percentage of a requestPaid
Put real load on a Deployment and watch it go from one replica to six.
-
Image layers and the build cache
Why instruction order decides whether your build takes one second or ninety.
-
ImagePullBackOff names its own cause
Two Pods with the same status and completely different problems: one image tag does not exist, one registry cannot be resolved.
-
Reading an Ingress status code as a diagnosis
The status code tells you which hop failed, and that is most of the diagnosis. 404 means nothing matched, 503 means matched but no backend, 502 means the backend answered badly.
-
An Ingress object does nothing on its ownPaid
An Ingress is a request that some controller has to answer.
-
Why /blue returns 404 from your own backendPaid
The obvious path-based Ingress returns 404, and the 404 comes from your application rather than the controller.
-
Init containers: work that must finish firstPaid
Init containers run to completion, one at a time, before any app container starts.
-
Jobs and CronJobs: run to completionPaid
Every other controller keeps Pods running forever.
-
Following a ClusterIP into iptablesPaid
Trace one Service from its ClusterIP through three iptables chains to the DNAT rule that rewrites the packet, then switch a cluster to IPVS and read the same routing out of ipvsadm.
-
A shell into a container that has none
A distroless container refuses every exec because it contains no shell.
-
Run kubectl from Windows against several clustersPaid
Stop SSH-ing to the control plane to run kubectl.
-
activating is not starting
Break the kubelet's config and restart it. systemctl reports activating, which reads like progress and means a restart loop.
-
The Kustomize hash that restarts your PodsPaid
One base, one overlay per environment, no templating language.
-
Labels, selectors and nodeSelectorPaid
Labels are the only way anything in Kubernetes finds anything else.
-
A LoadBalancer that stays Pending foreverPaid
A LoadBalancer Service off-cloud sits at Pending forever, because nothing is listening for it.
-
Usage is not requests, and only one schedules
The same node reads 1% CPU in kubectl top and 5% in describe node.
-
Move an image without a registry
Registries are the normal path, but not always an available one.
-
Multi-stage builds
Compilers, headers and package managers belong in the build, not in the thing you ship.
-
Namespaces, ResourceQuotas and LimitRangesPaid
A quota caps a namespace in total, a LimitRange constrains each container, and they are enforced at different moments by different code.
-
A NetworkPolicy timeout is not a refusal
A NetworkPolicy denial times out rather than refusing, which makes it look like a dead backend.
-
Default deny, then allow what you meantPaid
Prove that an empty cluster lets everything talk to everything, close it with a four-line policy, then open exactly one path.
-
The egress rule that breaks DNSPaid
Allow a whole namespace, then restrict egress and watch the Pod lose DNS while still reaching the same backend by IP.
-
Node affinity: required versus preferredPaid
nodeSelector is all or nothing.
-
Node NotReady: silence, not an error
Stop a kubelet and watch what happens: the node goes NotReady with Ready=Unknown, two taints appear on their own, containers keep serving, and the Pod still reports Running because nothing is left to say otherwise.
-
OOMKilled: exit 137 and the limit that caused it
A container asks for 200MB against a 64Mi limit and is killed mid-write.
-
How PVC binding actually decidesPaid
Create a 1Gi volume by hand, then two claims: one asks for 5Gi and waits forever, the other asks for 500Mi and gets the whole gigabyte.
-
Pod stuck Pending: reading the scheduler's tally
The scheduler explains itself precisely and almost nobody reads it.
-
Pods: the unit you actually deployPaid
Kubernetes does not run containers, it runs Pods.
-
Evicting something to make roomPaid
Fill a node with low-priority Pods, then schedule a high-priority one and watch the scheduler delete a running Pod to make room.
-
Authenticating to a private registry
Run a registry that demands credentials, watch an unauthenticated push get refused, log in properly - then look at where Docker actually put your password.
-
Readiness, liveness, and shutdown orderPaid
Three probes that look similar and do entirely different things: one gates traffic, one restarts the container, one buys time at startup.
-
PVC stuck Pending: the event names the cause
Three claims, all Pending, and only the event type tells them apart: one is waiting on purpose, one names a class that does not exist, and one asks for something the backend cannot do and does not say so.
-
Forbidden names the rule you are missing
Three Forbidden errors from one ServiceAccount, differing by verb, by resource and by namespace.
-
Proving what a ServiceAccount can doPaid
Four object kinds, one verb-and-resource model, and a command that answers permission questions without trial and error.
-
ReplicaSets, and why you rarely write onePaid
Create a ReplicaSet by hand, watch it replace a deleted Pod, then create a Deployment and follow the ownership chain it builds.
-
Resource requests, limits and QoS classesPaid
Requests are what the scheduler reserves.
-
Reset, rejoin and rebuild a node with kubeadmPaid
Take a node out of a cluster and put it back, and take a machine all the way back to bare Ubuntu.
-
Restart policies and resource limits
What actually happens when a container dies, and what stops one container taking the host down with it.
-
Watching maxSurge and maxUnavailable workPaid
Poll a Deployment through two rollouts and read the counts. maxSurge shows up as READY exceeding the replica count; Recreate shows up as AVAILABLE dropping to zero.
-
SecurityContext: running containers as not-rootPaid
Containers run as root unless you say otherwise.
-
A Service with no endpoints
Two broken Services with identical symptoms.
-
Services: ClusterIP, NodePort and LoadBalancerPaid
Three Service types that stack on top of each other, one address that nothing owns and that ping cannot reach, and a LoadBalancer that stays Pending forever on bare metal.
-
Build a single-node Kubernetes clusterPaid
Take one Ubuntu 26.04 machine from nothing to a working Kubernetes cluster with kubeadm: containerd on the systemd cgroup driver, the kernel settings kubelet needs, Calico for pod networking, the control-plane taint removed, and a workload proving DNS and Service routing both work.
-
StatefulSets: stable identity and ordered startPaid
A Deployment's Pods are interchangeable and get random names.
-
Static Pods: workloads the API server does not ownPaid
Your control plane is four static pods.
-
One volume per ordinal, kept on purposePaid
volumeClaimTemplates gives every replica its own claim, named by ordinal.
-
StorageClasses, and why Pending is correctPaid
A claim with no PersistentVolume behind it, deliberately stuck Pending until a Pod appears.
-
Tagging and publishing images
How an image name is actually parsed, why :latest is a trap, and a full push and pull against a registry running in a container on your own machine - no account, no credentials, real digests.
-
Taints and tolerations: keeping Pods off nodesPaid
A nodeSelector says where a Pod wants to go.
-
The Downward API: a Pod reading its own specPaid
Inject a Pod's own name, node and IP as environment variables, mount its labels as files, then find that a 50m CPU request arrives as the number 1 and that the files update while the variables never do.
-
Three ranges and no NATPaid
Three separate address ranges are in play and confusing them causes most Kubernetes networking problems.
-
Build a three-node Kubernetes clusterPaid
Build a control plane and two workers, then use the second worker for what it is actually for: watch six replicas spread across both, drain one node and see every pod reschedule onto the other while the Service keeps answering.
-
The Ingress redirect you did not ask forPaid
Add four lines and a Secret and the Ingress serves HTTPS.
-
The spread domain you forgot countsPaid
Nine replicas, maxSkew of 1, and only three ever schedule.
-
Build a two-node Kubernetes clusterPaid
Add a real worker to a kubeadm cluster.
-
Upgrade a cluster with kubeadm, 1.35 to 1.36Paid
A real minor-version upgrade of a two-node cluster, control plane then worker.
-
A volume snapshot is not a backupPaid
A snapshot is three objects with the same shape as PVC, PV and StorageClass.
-
What emptyDir and hostPath each losePaid
Two containers share an emptyDir, then the Pod is deleted and the data is gone.
-
What Kubernetes actually isPaid
Kubernetes is a database of desired state with programs that keep reality matching it.
-
Ask the cluster what it isPaid
Six commands that tell you what cluster you are pointed at, what it can be asked for, and what every field in a manifest means.
-
Back up and restore a volume
A named volume has no export command.
-
Build an image with a Dockerfile
Write a five-instruction Dockerfile, build it, run it, then build it again and watch the cache turn a 0.6 second build into 0.1.
-
User-defined networks and container DNS
Why containers on the default bridge cannot find each other by name, and how one command fixes it.
-
Containers, images, registries and the Docker daemon
The four things every later guide assumes you understand, each demonstrated with a command rather than a diagram: why the client and daemon are separate, how an image differs from a container, what a registry actually stores, and where a digest comes from.
-
Dockerfile instructions in practice
ARG versus ENV, ENTRYPOINT versus CMD, and why USER matters - shown with one Dockerfile that exercises all of them and the inspect output proving what each instruction actually recorded.
-
The build context and .dockerignore
What the trailing dot in docker build actually sends, why a stray 3MB file made the image 6MB bigger, and how one .dockerignore file cut the transfer from 3.00MB to 138B.
-
Essential Docker CLI commands
The dozen commands that cover most day-to-day container work, grouped by what you are trying to do rather than alphabetically.
-
Four questions a misbehaving container answers
How to answer the four questions you ask when something is wrong: what state is it in, what is it printing, what is it running, and what is it consuming.
-
Install Docker Engine on Ubuntu 26.04
Install Docker Engine from the official apt repository on Ubuntu 26.04, confirm the daemon is running, watch a real multi-layer image pull, and drop the sudo prefix.
-
Network drivers beyond bridge
Bridge is the default, not the only option.
-
Persist data with volumes and bind mounts
Anything written inside a container dies with it.
-
PID 1, signals and graceful shutdown
Why docker stop takes ten seconds and ends in exit 137, even for a process that should die instantly.
-
Publish ports and understand container networking
Why -p 8080:80 works, why two containers on the default bridge cannot find each other by name, and why creating your own network fixes it.
-
Run and manage your first container
Run a throwaway container, then a long-running web server, and drive it through its whole lifecycle - start, stop, restart, remove.
-
Upgrade, pin and uninstall Docker Engine
How to see which versions exist, upgrade safely, pin a version so an unrelated apt upgrade cannot move it, roll back, and remove Docker without destroying the volumes that hold your data.
-
What a container actually is
A container is an ordinary Linux process with a restricted view of the machine.