ECS clusters with no services, no tasks, and no registered instances
What does ZopNight detect here?
An ECS cluster object is free, so ZopNight reports an empty one at $0, but only after 4 counters all read zero: active services, running tasks, pending tasks, and registered container instances. That last axis is what stops the "default" cluster with idle EC2s attached from being called empty.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-1504 |
| Category | advisory |
| Severity | low |
| Metric | none — pure configuration read |
| Source | ecs_cluster_empty.go |
Where it applies
Four zeros, because three lie
Services, running tasks, pending tasks: a cluster can have all three at zero and still not
be empty in the way that matters. The classic case is the default cluster with EC2
container instances registered and idling. Their cost is real, but it belongs to the EC2
instances, not the cluster object, and deleting the cluster would strand rather than save.
So the rule reads a fourth counter, registered container instances, and requires all four
axes present and zero before firing. Any missing counter abstains; emptiness is asserted
only on complete evidence.
Why the finding is worth exactly nothing
The cluster object is free in every billing sense: the aggregator classifies it as having no cost of its own, with all real spend carried by child resources. An earlier version gated on a positive cluster cost that could never exist, which made the rule a permanent zombie that never fired at all. The fix was honesty in the other direction: fire on the real all-zeros signal, attach an explicit $0, and let the value be the cleanup action. An empty cluster’s cost is cognitive: one more object in every list, one more “wait, is this used?” in every audit.
Count the four axes yourself
aws ecs describe-clusters --clusters my-cluster \ --query 'clusters[].[clusterName,activeServicesCount,runningTasksCount,pendingTasksCount,registeredContainerInstancesCount]' \ --output tableFour zeros across the row reproduces the finding.
Before deleting
Empty now is not never-used: check whether CI/CD pipelines or task-run scripts reference the
cluster by name, because aws ecs run-task against a deleted cluster fails at the next deploy, not
today. Capacity providers attached to the cluster deserve a look too, since an auto-scaling
group left behind by one can hold real cost. Deletion itself is a single call with nothing
to drain, which is the pleasant consequence of only ever firing on genuinely empty clusters.
The recurring source
Empty clusters accumulate from tutorials, abandoned experiments, and IaC stacks whose destroy step failed halfway. If the same names keep reappearing, the fix is upstream in whichever pipeline creates clusters per-branch or per-experiment without a matching teardown.