Skip to content
back to the episode
Episode summary2023Fellow

Kubernetes Patterns — Introduction & Foundational Patterns

The club opens Kubernetes Patterns, a book its listeners picked, and works through the introduction and the first six chapters. Alexander Polomodov, Ilya Zonov and colleagues are joined by Stas, who runs a platform team building large clusters for web services: primitives, predictable demands, declarative deployment, probes, lifecycle and pod placement.

Code of Architecture · Book Club9 min read

This summary is shorter than the full episode; examples and assessments reflect the participants’ experience and views.

The main thread of the material
01

A book for developers, and primitives

They read the second edition, released, by the hosts' reckoning, that same year and given away by Red Hat in exchange for registration. The plan is to cover the whole book in four episodes; today it is the introduction and the first six chapters. The hosts like that this is, they think, the first book the club has read that says it is aimed first of all at developers who will write for Kubernetes and live with it, though architects are not excluded either. Stas adds that the early parts also help anyone who wants to understand how Kubernetes' own components work, and warns that some patterns are dangerous to hand to users of a large multi-tenant system — the book itself says you can shoot yourself in the foot with them. From the book they take the main caveat: the platform will not solve everything: garbage put into a container becomes distributed garbage once you scale. In the pattern hierarchy picture clean code sits at the bottom: the club has already covered a book on it and Vlad Khononov's Learning Domain-Driven Design.

Then a quick pass over the primitives. Images and containers are compared to classes and objects, a pod to a composition of containers, and FROM in a Dockerfile is called, at a stretch, inheritance of implementation — though metaphors work only until you chase a perfect match. Composition at the pod level exists so you do not build one binary that does everything: next to the business-logic application lives the tooling that ships metrics. A pod manages the lifecycle of a group of containers on one host with shared resources, and services handle discovery and traffic, because pods keep dying and starting elsewhere. Stas makes a point about metadata: labels are identifiers for lookup, the ones services use to pick pods for traffic, while annotations are metadata that cluster automation reads and acts on; the SELECT parallel comes from another participant. The list of recommended labels appeared on the site only later. Namespaces give grouping, quotas and, if you design the platform for it, a security boundary; for capacity planning, Stas warns, their granularity is less convenient than one would like, and a cluster per tenant costs more.

02

Predictable demands: resources and priorities

The foundational patterns are framed as the minimum an application must meet, overlapping in places with the twelve-factor manifesto invented at Heroku. The chapter structure — problem, solution, discussion — goes down well, though one host notes the solution sometimes just describes a Kubernetes mechanism that closes the problem only partly. A separate complaint about the genre: the book insists it is not a manual and points to other books, yet it is full of examples and near-tutorials. The participants recall the Gang of Four, where problem and solution were followed by code you invented yourself and the examples were in long-dead Smalltalk — and the book is still reprinted. The YAML here reads easily, especially if you have once sat a certification exam. The first pattern is Predictable Demands: an application should declare its requirements and dependencies explicitly so the scheduler can place it and the team can do capacity planning. It takes forty minutes of the episode and is still not finished.

Dependencies include runtime ones — the filesystem and ports; a specific port on a node is rarely needed, though Stas recalls high-throughput applications and operator-run databases that force exposing a particular pod. The heart of the chapter is resources. Memory is incompressible, so the book advises setting request and limit to the same value: the only way to get memory back is to kill the pod, whereas a processor recovers by the next cycle. Stas explains why: a CPU shortage shows up as sluggishness, while exceeding memory on a node takes down Kubernetes' system components first and the operating system next, and the host can simply hang. Limits also treat applications with memory leaks, by restarting them. Requests and limits together decide the QoS class — there are three, guaranteed pods stay put, best-effort ones are evicted first. Pod priorities are about the placement queue rather than resources; tenants are rarely given them, because spiting a neighbour is far too easy. Stas used priorities to separate ordinary workloads from GPU ones: an entry-point mechanism sees which resource is requested, and the workload asking for a scarce one gets its place on the right node.

03

Deployment, probes and pod placement

Declarative deployment removes the manual steps of a release. Out of the box there is a rolling update, where new pods start while the old ones still take traffic, and recreate, where everything is shut down first so that versions and schemas cannot collide. One host finds recreate strange: collisions are normally handled by making old and new versions coexist while migrations roll in both directions. Stas counters that for an application draining a queue rather than serving requests the pattern is perfectly viable. That leads into declarativeness itself: instead of imperative commands, a desired state and a controller reconciling towards it. Blue-green needs twice the resources and has no native support. Stas calls canary the gold standard: their platform lacks it but will have it, and tooling does not bring the hard part — choosing metrics, thresholds and how long you hold and watch. A remark follows that canary overlaps with the metrics of their A/B platform.

Probes: liveness leads to a restart, readiness pulls the pod out of the service, and startup was split out for slow-starting applications — pushed through, the participants recall, by the Java crowd. You can check with an HTTP call or a command, and Spring's actuator serves probes out of the box; the point is to show real health rather than a ping returning 200. Stas adds a design consideration: an application should not degrade in step with its dependencies — let it show an empty list rather than fall apart — and probes had better not reach into external dependencies, or you will feast on timeouts. The episode reaches managed lifecycle two minutes past the clock; the pattern is about signals: SIGTERM, SIGKILL on timeout, preStop and postStart, whose ordering against the application's start is not guaranteed; hence the 2016 picture of the upward and downward channels between a container and the platform. In automated placement pinning to a node is a last resort, and the authors start from nodeSelector, node affinity and taints, while pod anti-affinity shrinks the blast radius when a node is lost.

Takeaways

What to take away

  1. 01Kubernetes is not a panacea: garbage in a container becomes distributed garbage once you scale, and the developer's own job is to fix resources and declare dependencies.
  2. 02Labels are identifiers for lookup, annotations are metadata for automation; services rely on that distinction when they select pods by label.
  3. 03Memory is incompressible, so request and limit are best set equal: the only way to reclaim it is to kill the pod, while a processor recovers by the next cycle.
  4. 04Priorities and scheduler knobs are dangerous to hand to tenants of a multi-tenant cluster: spiting a neighbour is trivial, so a platform keeps them with the administrators.

Sources