🎉 DevOps Interview Prep Bundle is live — 1000+ Q&A across 20 topicsGet it →
All Articles

What are Kubernetes Endpoints and EndpointSlices? Explained Simply

Kubernetes Endpoints and EndpointSlices explained from scratch — how Services use them to route traffic to pods, why empty Endpoints means no traffic reaches your app, and how to debug selector mismatches.

DevOpsBoys4 min read
Share:Tweet

You created a Kubernetes Service. Your pods are running. But traffic is not reaching your app. The most common reason: the Endpoints object is empty.

This post explains what Kubernetes Endpoints are, how they work, and how to fix the most common problems.

What is an Endpoint in Kubernetes?

When you create a Service, Kubernetes automatically creates an Endpoints object with the same name. The Endpoints object holds the list of IP addresses and ports of the pods that the Service should forward traffic to.

Think of it like a dynamic phone book: the Service is the name, the Endpoints is the current list of pod IPs.

bash
# List all endpoints in the default namespace
kubectl get endpoints
 
# Example output:
# NAME         ENDPOINTS                         AGE
# kubernetes   10.0.0.1:443                      30d
# my-app       10.244.1.5:8080,10.244.2.3:8080   2m
# empty-svc    <none>                            5m

my-app has two pod IPs — traffic will be load-balanced between them. empty-svc shows <none> — no pods are registered, so all traffic is dropped.

How Services Use Endpoints to Route Traffic

When a request hits a Service (via ClusterIP or NodePort), kube-proxy on each node reads the Endpoints object and sets up iptables or IPVS rules to forward traffic to one of the pod IPs.

This happens automatically:

  1. A pod matching the Service's selector starts up and passes its readiness probe
  2. The Endpoints controller adds that pod's IP to the Endpoints object
  3. kube-proxy updates routing rules on all nodes
  4. Traffic to the Service now reaches that pod

When a pod is deleted or fails its readiness probe, its IP is removed from Endpoints, and traffic stops going to it — no downtime for healthy pods.

Why Empty Endpoints = No Traffic

This is the most common issue beginners hit:

yaml
# Service definition
apiVersion: v1
kind: Service
metadata:
  name: my-app
spec:
  selector:
    app: my-application   # <-- looks for pods with this label
  ports:
    - port: 80
      targetPort: 8080
yaml
# Pod definition — notice the label mismatch
apiVersion: v1
kind: Pod
metadata:
  name: my-app-pod
  labels:
    app: my-app           # <-- this does NOT match "my-application"
spec:
  containers:
    - name: app
      image: nginx
      ports:
        - containerPort: 8080

The Service selector is app: my-application but the pod has app: my-app. The Endpoints object will be empty. Fix the label to match exactly:

yaml
# Fixed pod labels
labels:
  app: my-application

Checking and Debugging Endpoints

bash
# See endpoint details
kubectl describe endpoints my-app
 
# Output when healthy:
# Name:         my-app
# Namespace:    default
# Subsets:
#   Addresses: 10.244.1.5,10.244.2.3
#   Ports:
#     Name  Port  Protocol
#     ----  ----  --------
#     <unset> 8080  TCP
 
# If empty:
# Subsets: <none>
 
# Check pod labels (to compare with service selector)
kubectl get pods --show-labels
 
# Check service selector
kubectl get service my-app -o yaml | grep -A5 selector

If the pod is running but not in Endpoints, the pod's labels do not match the Service selector, or the pod is failing its readiness probe.

What are EndpointSlices?

EndpointSlices are the newer replacement for Endpoints, introduced because the original Endpoints object had a scaling problem.

The problem with Endpoints: A single Endpoints object holds ALL pod IPs for a Service. If a Service has 1000 pods and 1 pod restarts, Kubernetes has to update the entire Endpoints object and send it to every node in the cluster. At large scale (hundreds of nodes, thousands of pods), this creates massive network traffic.

EndpointSlices: Instead of one big object, Kubernetes splits the pod IPs into multiple EndpointSlice objects, each holding a maximum of 100 endpoints. When one pod changes, only one small slice is updated and propagated.

bash
# List EndpointSlices
kubectl get endpointslices
 
# Example output:
# NAME             ADDRESSTYPE   PORTS   ENDPOINTS         AGE
# my-app-abc12     IPv4          8080    10.244.1.5        5m
# my-app-xyz99     IPv4          8080    10.244.2.3        5m

EndpointSlices are enabled by default in Kubernetes 1.21+. You do not need to configure anything — kube-proxy uses them automatically.

Common Issues and Fixes

Issue 1: Endpoints empty, pods running

bash
# Check selector vs labels
kubectl get svc my-app -o jsonpath='{.spec.selector}'
kubectl get pods -l app=my-application  # use the selector value here

If this returns no pods, the labels do not match. Fix the pod labels or the Service selector.

Issue 2: Pod IP in Endpoints but not receiving traffic

bash
# Check if the pod's readiness probe is passing
kubectl describe pod <pod-name> | grep -A10 "Readiness"
# If it shows "Unhealthy" the pod will be removed from Endpoints

Issue 3: Service with ExternalName has no Endpoints This is expected. ExternalName type Services route to an external DNS name, not pod IPs. They do not create Endpoints objects.

Issue 4: Headless Service — Endpoints exist but no ClusterIP Headless Services (clusterIP: None) still populate Endpoints, but DNS returns the pod IPs directly instead of a virtual IP. This is intentional for stateful apps like databases.

Endpoints are one of the most fundamental objects in Kubernetes networking. Every time you create a Service, check the Endpoints — it tells you immediately whether the Service and pods are correctly wired together.

🔧

Today I Fixed

Short real fixes from production — posted daily

Browse fixes
Newsletter

Stay ahead of the curve

Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.

Related Articles

Comments