Skip to main content
orphan · kubernetes

Services whose EndpointSlice lists zero ready or not-ready endpoints

resource types
1
rule IDs covered
3
severity
medium

What does ZopNight detect here?

ZopNight flags a Kubernetes Service on EKS, GKE or AKS whose EndpointSlice has 0 ready and 0 not-ready endpoints once the slice is at least 5 minutes old. Traffic sent to that Service has no pod to reach, which usually means its selector no longer matches any pod labels. Headless and ExternalName Services are skipped.

Signal and threshold

How ZopNight evaluates Services whose EndpointSlice lists zero ready or not-ready endpoints.
Field Value
Rule IDsRC-1742 · RC-1842 · RC-1942
Categoryorphan
Severitymedium
MetricEndpointSlice endpoint count
Threshold0 ready and 0 not-ready endpoints, slice at least 5 minutes old
Evaluation window5m
SourceZopNight
Permissions usedlist endpointslices.discovery.k8s.io · list services

A Service with no backends drops every request

A Service finds its pods through a label selector, and the control plane records the matching pod addresses in EndpointSlices. Each slice carries a kubernetes.io/service-name label linking it to its Service, as the EndpointSlices documentation describes. When the slice has no endpoints at all, not even pods that are running but failing readiness, the Service is routing traffic to nothing.

This most often follows a relabel. A Deployment’s pod template gains app.kubernetes.io/name while the Service still selects on app, or a workload is deleted and its Service is left behind. Clients see connection failures, and if the Service is of type LoadBalancer, the cloud load balancer created for it keeps existing for as long as the Service does.

Listing Services with empty slices

Terminal window
kubectl get endpointslices -A -o json | jq -r '
.items[]
| select((.endpoints // []) | length == 0)
| "\(.metadata.namespace)/\(.metadata.labels["kubernetes.io/service-name"] // .metadata.name)"'

For each result, compare the selector with real pod labels:

Terminal window
kubectl get service <name> -n <namespace> -o jsonpath='{.spec.selector}'
kubectl get pods -n <namespace> --show-labels

Conditions for the finding

ZopNight evaluates the EndpointSlice and counts its ready and not-ready endpoints. It fires only when both counts are zero. A slice with pods that exist but fail their readiness probes is not an empty Service and is not flagged here. Because a fresh deploy, a crash-loop recovery or a scale-up from zero briefly produces an empty slice, the slice must also be at least 5 minutes old by its creation timestamp. If neither endpoint count was reported, or the creation time is unknown, ZopNight stays silent.

Services that are empty on purpose

Two Service shapes are excluded because an empty slice is normal for them. ExternalName Services resolve to a DNS name and never select pods. Headless Services, those with clusterIP: None, are also skipped. The rule does not know whether a workload was scaled to zero deliberately; see Stopped deployment for that side.

Filed as an orphan without a price

The finding does not carry a savings amount. When the Service is a LoadBalancer, the cloud load balancer behind it is the part that costs money, and removing the Service is what releases it.

Reconnecting or removing the Service

  1. Run kubectl describe service <name> and read the Selector line.
  2. Compare it with the labels in the pod template of the workload that should serve it, and fix whichever side is wrong.
  3. Confirm the slice fills in with kubectl get endpointslices -l kubernetes.io/service-name=<name>.
  4. If no workload should serve it any more, delete the Service with kubectl delete service <name>. For a LoadBalancer Service, a finalizer holds the deletion until the cloud load balancer is cleaned up, as described in Create an External Load Balancer.

See it fire on your bill.

Connect an account read-only. The first findings land in minutes.

472 rule families across 353 resource types on 22 platforms. Every threshold, metric, and IAM action is documented on these pages before you grant anything.

472 rule families documented
353 resource types covered
read-only default access level
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·