Workloads with no CPU or memory limits set
What does ZopNight detect here?
A container without limits can consume whatever the node has. ZopNight reads the pod spec across 3 workload kinds and names each offending container. Note the asymmetry: a missing memory limit risks taking the node down, while a missing CPU limit is often the better choice.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-1703 · RC-1803 · RC-1903 · RC-1704 · RC-1804 · RC-1904 · RC-1705 · RC-1805 · RC-1905 |
| Category | reliability |
| Severity | medium |
| Metric | none — pure configuration read |
| Source | internal/rules/k8s/workload_no_limits.go |
Where it applies
CPU and memory limits are not the same decision
They are usually discussed together and they behave completely differently under pressure. This is the single most useful thing to understand about this finding.
Memory is incompressible. A container exceeding available memory cannot be slowed down. It gets OOM-killed. Without a limit, one leaking process can consume the node’s memory and take neighbouring pods with it.
CPU is compressible. A container exceeding its CPU limit is throttled, not killed. It simply runs slower.
Why a missing CPU limit is often correct
CPU limits cause throttling even when the node has idle capacity. A service limited to 500m gets throttled at 500m regardless of whether the node is 90% idle. Latency spikes for no benefit to anybody.
Many production Kubernetes practitioners deliberately set CPU requests and omit CPU limits, letting workloads burst into spare capacity while requests guarantee the floor.
So treat the CPU half of this finding as a prompt to decide, not a defect to fix. The memory half is closer to a genuine defect.
What limits do give you
Quality of Service. A pod with requests equal to limits on both resources is Guaranteed, the
last class evicted under node pressure. Requests without limits is Burstable. Neither is
BestEffort, evicted first.
If a workload must survive node pressure, Guaranteed is the only class that gets you there.
No metric here
This is a configuration read. There is no utilisation threshold and no lookback window: a container declares limits or it does not. The rule abstains when the workload metadata carries no containers.
Filtering containers with no memory limit
kubectl get deploy,statefulset,daemonset -A -o json | jq -r ' .items[] | . as $w | .spec.template.spec.containers[] | select((.resources.limits.memory // "") == "") | "\($w.kind) \($w.metadata.namespace)/\($w.metadata.name): \(.name)"'Filtering on memory alone surfaces the half that actually threatens the node.
Where to set them
A namespace LimitRange applies defaults to anything that does not declare its own, which fixes
the whole backlog at once and stops new workloads arriving without them.