Short, illustrated explanations of how things work.
An interactive guide to cloud native software — containers and images, registries, declarative desired state, the control plane, pods and scheduling, service networking, configuration and secrets, state, autoscaling, resilience, progressive delivery and observability — and an honest section on what all of it costs. It is built around Container Harbour, a low-poly isometric simulation in the spirit of the 90s theme-park and transport builders, which runs as the page's live background.
Source: docs/ · Live site: https://everyways.github.io/hot-to-cna/
(once GitHub Pages is enabled, see below)
Third in a series, after how-to-internet (how a request reaches you at all) and how-to-sdlc (how the change got written and merged in the first place). This one picks the story up at the moment the image is built.
The harbour is an island, and two flows share one circuit running in opposite directions.
Delivery goes clockwise up the left side and along the waterfront: the application leaves the source quay, the shipyard builds it into an image, the registry warehouse stores it, and the manifest house declares which image should be running.
Traffic comes back the other way up the right side: the city, the sea gate, the customs gate, the signal station, the quays.
The control tower sits inside the ring with cables out to almost every station, because the control plane is not a stage of anything — it is a loop that never stops comparing what was declared with what exists. The lighthouse gathers the evidence, and the bonded store holds the one part of the system that cannot simply be replaced.
| Scenario | What it demonstrates |
|---|---|
| Ship a new version | Build, push, declare, reconcile, schedule, probe, serve |
| A request finds a pod | DNS, cache, TLS, service discovery, mTLS, and the database |
| The tide comes in | Autoscaling as two loops at different speeds — and different prices |
| A quay goes under | A machine dies; the loop reschedules; users see a couple of retries |
| A bad release, walked back | Canary, a control group, and why rollback is just another reconcile |
The canvas is pinned behind the article rather than boxed inside it, and it stays interactive while you read:
- The article can be hidden. A Hide the article toggle sits in the top-right corner at all times: press it and the whole text container fades away, leaving the harbour the entire viewport. Press it again — or esc — and the words come back at the scroll position you left them. The toggle never hides itself, so it cannot become a mode you get stuck in.
- It follows the article. Scrolling to a section highlights the station it is about and switches the simulation to the matching scenario. Uncheck Follow the article to drive it yourself.
- Drag the margins to pan, without interrupting reading — the text panels are the only pointer-catching things on the page.
- Click a building for what that station does and a link to the section about it.
- Keyboard: ← → rotate, + − zoom, space pause, esc bring the article back.
Static files, no build step, no dependencies, no external requests:
docs/
├── index.html the article, the controls and the station inspector
├── styles.css the two-layer page: a full-viewport map with panels floating over it
└── sim.js the isometric renderer, world model and scene director
The simulation is plain JavaScript on a 2D canvas. There is no WebGL and no 3D library: buildings are axis-aligned boxes projected isometrically and drawn back-to-front with a painter's algorithm, which is how the games it borrows from did it too.
Key pieces in sim.js:
- Projection —
rotXYrotates world tiles into one of four camera orientations,projectflattens them to screen space,depthOfgives the sort key. - World —
NODES(stations) andLINKS(the circuit and the control plane's spokes, as polylines) describe the map; routes are lists of node ids resolved byroutePoints. - Terrain — tile kinds are computed once into
KIND_GRIDand cached into an offscreen canvas that is only redrawn when the camera moves. The sea is a large part of the map, so only the tiles a wave is currently crossing are repainted per frame. - Work items —
spawnputs a container on a route with a speed, an optional delay and anonArrivecallback used to chain the next hop;burstfans several down one route. - Director —
SCENARIOSholds the scripted steps; each step writes the narration, spawns work items, and completes when they have all landed.
To add a step, add an entry to a scenario's steps array. To add a station, add a node,
a link in LINKS, and a draw function in BUILDERS.
The favicon PNGs are generated rather than hand-drawn; the SVG is the source of truth.
Any static server works:
cd docs
python3 -m http.server 8000 # then open http://localhost:8000The site lives in docs/ so it can be published either way:
- Simplest: Settings → Pages → Source: Deploy from a branch, branch
main, folder/docs. - Or via Actions: the included
.github/workflows/pages.ymldeploysdocs/on every push tomain— choose Source: GitHub Actions.
The explanations are deliberately simplified. Real clusters have more components, more custom resources and considerably more YAML; the descriptions of scheduling, networking and storage each omit a layer or two; and several of the trade-offs described as settled are still being argued about. Every section is accurate in outline; none is complete. The links at the bottom of the page go to the rigorous versions.
Where the page has an opinion — that most teams should rent their databases, that a mesh is rarely worth it below a certain size, and that plenty of projects should not adopt an orchestrator at all — it says so, and says it is an opinion.