Blog
Thoughts on engineering, design, and building great products.
Topology spread, pod overhead, and scheduling readiness
Anti-affinity is rigid: one pod per node, anything extra hangs. Topology spread is softer — it spreads pods evenly by maxSkew while still allowing several pods per node. This article digs into three finer scheduling mechanisms: topologySpreadConstraints (flexible spreading), pod overhead (extra resource accounting for the sandbox runtime), and schedulingGates (hold a pod back from scheduling). All three tested for real on the cluster.
Affinity, taints, and tolerations
The scheduler picks a node on its own, but often you need to intervene: this pod must be on an SSD node, two replicas shouldn't share a machine, that node is for one team. This article digs into three tools for steering the scheduler — nodeAffinity (pull a pod toward labeled nodes), podAntiAffinity (push pods apart), taint/toleration (a node pushes pods away unless tolerated). Tested for real: a pod stuck on affinity, a third with nowhere to go, one evicted by NoExecute.
The scheduler and the scheduling framework
Every pod we create has someone quietly picking a node for it — that's kube-scheduler, the thing we stood up in Article 8 but never looked at closely. This article opens Part VII by digging into exactly how it picks: filter out nodes that don't fit, score the remaining nodes, then bind. We test for real a pod stuck because no node has room, a pod that gets a node, and watch scoring pile pods onto the less-loaded node — not a naive round-robin.
LimitRange and ResourceQuota
When many teams share one cluster, nothing stops team A from creating 10,000 pods or asking for 64Gi RAM for a single container — unless you set rules. LimitRange sets defaults and min/max for each pod in a namespace; ResourceQuota caps the total resources and object count the whole namespace can use. This article closes Part VI with both: testing for real the default-injection, the over-max 403, and the fourth pod blocked by quota.
Node Allocatable: the resources a pod actually gets
Article 22 looked at requests/limits from the pod side. This one flips to the node side: a 2-vCPU machine doesn't let pods use all 2 vCPUs. Kubernetes carves off a slice for system daemons, one for Kubernetes daemons, and a buffer against running out of RAM — what's left is Allocatable, the part the scheduler divides up. We dig into the formula, read Capacity vs Allocatable on a real node, then add a reservation by hand and watch Allocatable drop by exactly that many Ki.
ConfigMap and Secret
Don't bake configuration into the image — pull it into a ConfigMap for ordinary data, a Secret for sensitive data, then inject it via environment variables or files. This article opens Part VI with both: four ways to consume them, one key difference (files auto-update on edit, env doesn't), and the harsh truth that a Secret is only base64, not encrypted — unless you turn it on, which our cluster did in Article 5. Tested for real, dug into etcd.
Object management, recommended labels, and storage version
For the same Deployment, we have three ways to create and edit it — type a command directly, create -f a file, or apply a whole directory — and mixing them invites bugs. This article closes Part V with those three object-management techniques (plus why apply differs from create -f), the recommended app.kubernetes.io/* label set so tools speak the same language, and storage version — digging into etcd to see which API version an object is actually stored in.