How to Expose a Kubernetes Deployment with a Service

A Deployment runs pods but gives them no stable address. A ClusterIP Service is what you create to expose a Kubernetes Deployment inside the cluster - it picks up your pods through a label selector and load-balances across them.

Kubernetes Engineerkuberneteskubectlservices

Why you need a Service

A Kubernetes Deployment manages a set of pods, but pod IPs are ephemeral - they change every time a pod restarts or reschedules. A Service sits in front of the pods and gives them a stable in-cluster DNS name and IP. Without one, nothing else in the cluster can reach your app reliably.

The three things that must line up

A ClusterIP Service connects to your pods through three pieces of wiring:

  1. selector - must match a label on the pod template in the Deployment (e.g. app: web)
  2. port - the port the Service itself listens on (what callers dial)
  3. targetPort - the port the container is actually listening on

If the selector doesn't match any pod labels, the Service has zero endpoints and traffic goes nowhere - no error, just silence.

Writing service.yaml

Given a Deployment whose pod template has labels: {app: web} and whose container listens on port 80:

apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  type: ClusterIP
  selector:
    app: web       # must match pod template labels exactly
  ports:
  - port: 80
    targetPort: 80  # the port your container listens on

Apply it and confirm the Service picked up endpoints:

kubectl apply -f service.yaml
kubectl get svc web
kubectl get endpoints web

A healthy output from kubectl get endpoints web shows at least one IP:PORT entry. If the ENDPOINTS column shows <none>, the selector is wrong - compare it to the pod labels with kubectl get pods --show-labels.

Verifying connectivity

Once endpoints are populated you can reach the Service by its DNS name from any pod in the same namespace:

kubectl run curl-test --image=curlimages/curl --rm -it --restart=Never \
  -- curl -s http://web/

Or kubectl port-forward svc/web 8080:80 to hit it from your local machine.

Common mistakes

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

How do I expose a Kubernetes Deployment inside the cluster?

Create a ClusterIP Service with a selector that matches the Deployment's pod labels and a targetPort that matches the container's listening port, then apply it with kubectl apply -f service.yaml.

Why does my Kubernetes Service have no endpoints?

The selector in the Service spec does not match the labels on the pods. Run kubectl get pods --show-labels and compare them to the selector in your Service. Labels are case-sensitive.

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

port is what other pods dial to reach the Service. targetPort is the port the container inside the pod is actually listening on. They can differ - for example, port 80 can forward to targetPort 8080.

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 →