EKS node groups at zero nodes with orphaned volumes still billing
What does ZopNight detect here?
An EKS node group scaled to 0 nodes, or stuck in DEGRADED status, bills nothing itself; the waste sits in what it strands. ZopNight sums the cluster's Released and Available PersistentVolumes' backing EBS volumes, plus load balancers with zero healthy targets, and reports that whole amount as recoverable.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-043 |
| Category | idle |
| Severity | medium |
| Metric | none — pure configuration read |
| Source | eks_abandoned_workloads.go |
Where it applies
Zero desired nodes or a DEGRADED status
Two signals mark an EKS node group as abandoned. Either its discovered desired node count is exactly 0 (read from metadata the discoverer records, so a group with no recorded count is never assumed empty), or the group sits in the DEGRADED state AWS uses for an unrecoverable error. Either signal starts the evaluation; a healthy group with running nodes never does.
Why the node group row bills $0
An EKS managed node group is a free control object: the per-cluster hourly charge covers the control plane, not the group. Its worker EC2 instances are billed individually, and a group at zero nodes has none. So the rule refuses to price the group row itself: a made-up dollar figure against a $0 resource is precisely the kind of finding the platform bans. What abandonment actually costs is the debris left around it.
Released volumes and dead load balancers
When workloads leave a cluster, two kinds of paid resources routinely stay behind. A PersistentVolume in the Released phase (its claim was deleted but the reclaim policy kept the volume) or the Available phase (provisioned, never bound) still has an EBS volume billed on provisioned size every month; Bound volumes are in active use and excluded. Service-created load balancers whose target health reports 0 healthy targets are the second kind. The rule joins each orphaned PersistentVolume to its EBS volume through the CSI volume handle, joins each cluster service to its load balancer through the DNS name, and sums the monthly price of everything it matches.
One node group owns the cluster’s orphan bill
A cluster can hold several abandoned node groups, and one EBS volume can be referenced from two abandoned clusters. In both cases a single owner (the abandoned group, then the cluster, with the smallest UID) carries the whole figure. Companion rules for orphaned EBS volumes and idle load balancers cede these same resources, so the money is counted once, never per rule.
Spotting an abandoned group from the CLI
aws eks describe-nodegroup --cluster-name my-cluster --nodegroup-name workers \ --query 'nodegroup.{status:status,desired:scalingConfig.desiredSize}'Follow up inside the cluster with kubectl get pv and look for Released or Available entries.
When RC-043 reports nothing
The evaluation abstains without an org-wide resource and pricing context, since the join is cross-resource by nature. It also stays silent when the group has no recorded parent cluster, when another group owns the cluster’s figure, and when the orphaned-attachment total comes to zero. A load balancer whose health probe never ran contributes nothing. Fail closed, never guess.