Workload Management: Matching Workloads to Controls
Not every workload should scale, stop, or be interrupted the same way. Classify first, then choose the control.
Workload management is the practice of grouping the things you run by how they behave (stateful or stateless, always-on or periodic, interruptible or not) and then giving each group the placement, scaling, scheduling, and cost controls that suit it. The mistakes it prevents are mismatches: a batch job kept running around the clock, a database scaled like a web tier, a singleton service stopped by an office-hours schedule.
Four questions that classify a workload
- Does it hold state? If a replica can be replaced without losing anything, it is stateless and can scale horizontally and be restarted freely. If each replica owns data, replacing it needs care.
- When does it need to run? Continuously, during working hours, on a timetable, or once until done.
- What happens if it is interrupted? Can it retry from a checkpoint, or does interruption mean user-facing failure?
- What does it depend on, and what depends on it? Order matters when starting or stopping a group.
Map classes to Kubernetes workload resources
Kubernetes gives each class its own controller:
- Deployment for stateless applications where any pod is interchangeable and can be replaced.
- StatefulSet for related pods that track state, typically each matched to its own PersistentVolume.
- DaemonSet for node-local facilities such as networking plugins or log agents; a pod is scheduled onto every matching node, including new ones.
- Job for a task that runs to completion once, and CronJob for running the same Job on a schedule.
The choice has cost consequences. A task written as a long-running Deployment that sleeps between runs holds its resource requests all day; as a CronJob it only reserves capacity while it runs. The Horizontal Pod Autoscaler can scale Deployments and StatefulSets, but not DaemonSets, whose size follows node count.
Protect availability during voluntary disruption
Draining nodes, upgrades, and autoscaler scale-down are voluntary disruptions. A PodDisruptionBudget (PDB) limits how many pods of a replicated application can be down at the same time from those actions. It does not protect against involuntary disruptions such as hardware failure, and the Kubernetes docs note that deleting a Deployment or pods directly bypasses PDBs. For involuntary failures the guidance is to request the resources the pod needs and to run more than one replica.
Pick the cost lever per class
| Workload class | Typical lever |
|---|---|
| Stateless, variable load | Autoscaling on a proportional metric; see autoscaling fundamentals |
| Stateless, office-hours only (dev, test, demo) | Stop or scale to zero outside working hours |
| Batch and periodic | Jobs and CronJobs, sized to the run, not the day |
| Stateful, always-on | Right-size carefully; commit to the stable baseline |
| Known one-off peaks | Scheduled pre-scaling; see the event readiness playbook |
Doing this in ZopNight
ZopNight lets you express these classes directly. Resource groups bundle related resources so a whole environment follows one schedule, with exclusive membership so each resource has one scheduling source. Within a group, execution is ordered in tiers (storage, then databases, then compute, then apps on start, reversed on stop) with a per-resource delay; this is simple tiered ordering with time spacing, not a dependency graph. Kubernetes namespaces can be stopped on a schedule by scaling Deployments and StatefulSets to zero and suspending CronJobs, with system namespaces skipped. Overrides keep a specific resource or group on or off for a bounded window with a reason attached. Its Kubernetes workload rules also flag single-replica workloads and suspended or failed jobs.