How to Fix a Kubernetes Service targetPort Mismatch

Pods are Running, endpoints are populated, but every request to the Service gets connection refused. The cause is almost always a targetPort that doesn't match the port the container actually listens on. Here's how to diagnose and fix it.

Kubernetes Engineerkuberneteskubectlservices

Why connection refused happens even when pods are Running

Kubernetes validates that a Service has endpoints - pods selected by the label selector - but it does NOT check that targetPort matches a port the container actually listens on. Traffic is forwarded to whatever targetPort says, and if nothing is listening there, you get connection refused.

A pod can show Running and 1/1 Ready while all traffic to its Service silently fails.

Diagnose: compare targetPort to containerPort

First confirm that endpoints exist (selected pods are present):

kubectl get endpoints web

If endpoints are populated, the selector is fine. Now read the Service and Deployment side by side:

# What port is the Service routing to?
kubectl get service web -o yaml | grep targetPort

# What port is the container actually listening on?
kubectl describe deployment web | grep containerPort

A mismatch like targetPort: 8080 with containerPort: 80 is the bug. The Service is sending traffic to port 8080 but the container's process only binds port 80.

Fix: align targetPort to containerPort

In your Deployment manifest, set targetPort in the Service spec to match containerPort in the container spec:

# deployment.yaml (Service portion)
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 80   # must match containerPort below

---
# deployment.yaml (Deployment portion)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  template:
    spec:
      containers:
        - name: web
          image: nginx
          ports:
            - containerPort: 80   # what the process actually binds

Apply and verify:

kubectl apply -f deployment.yaml
kubectl rollout status deployment/web
kubectl get endpoints web   # should show IP:80, not IP:8080

Better: name the port so the mismatch is impossible

Reference ports by name instead of number. Define a name on the container port and use that name as targetPort in the Service:

# Service
ports:
  - port: 80
    targetPort: http   # name reference - always tracks the container port

# Container
ports:
  - name: http
    containerPort: 80

With named ports, changing containerPort automatically fixes targetPort with no cross-field hunting. This is the recommended pattern for any non-trivial manifest.

Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.

Try it in a workspace →

What you'll practice

FAQ

Why does my Kubernetes Service get connection refused even though pods are Running?

The most common cause is a targetPort mismatch - the Service routes to a port number the container isn't listening on. Pods show Running because Kubernetes only checks that the container process started, not that the right port is bound. Compare targetPort in the Service to containerPort in the Deployment.

How do I check if my Kubernetes Service targetPort is correct?

Run kubectl get service <name> -o yaml | grep targetPort and kubectl describe deployment <name> | grep containerPort. They must match. You can also check kubectl get endpoints <name> - populated endpoints mean the selector works, but traffic can still fail if targetPort points nowhere.

What is the difference between port and targetPort in a Kubernetes Service?

port is the port the Service listens on (what callers connect to). targetPort is the port on the pod the Service forwards traffic to - it must match the containerPort the application actually binds. They are often different values, for example port 80 -> targetPort 3000 for a Node app.

What are the types of Kubernetes Services?

Four: ClusterIP (internal-only, the default), NodePort (a port on every node), LoadBalancer (an external load balancer), and ExternalName (maps to a DNS name). Most internal traffic uses ClusterIP.

Keep learning

Fix a Kubernetes CrashLoopBackOffKubernetes projectHeal a Kubernetes Service With No EndpointsKubernetes projectFix a Kubernetes ImagePullBackOffKubernetes projectKubernetes roadmapStep by step to hiredKubernetes interview questionsSTAR answersAll Kubernetes projectsProjects hub

Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.

Open the workspace →