Skip to content

Service vs Ingress (Kubernetes Networking)

Mental model

Service = internal phone extension (L4, TCP/UDP). Ingress = the reception desk routing calls by name (L7, HTTP).

What it looks like

"How do I expose my app?" has three different answers depending on context, and it is not obvious which one to use.

What it really is

Service: a stable network identity for a set of pods. Gets a virtual cluster IP that load-balances across matching pod IPs. Operates at L4 (TCP/UDP). Selects pods via label selectors. kube-proxy maintains iptables or IPVS rules to implement it.

Service types: - ClusterIP: internal only (default). - NodePort: opens a port on every node. - LoadBalancer: provisions a cloud load balancer.

Ingress: HTTP/HTTPS routing rules. Maps hostnames and URL paths to backend Services. Operates at L7 (HTTP). Requires an Ingress Controller (nginx, traefik, etc.) to function. Without a controller, Ingress resources are inert specs.

Why it seems confusing

Service and Ingress both "expose" things, but at different layers. A LoadBalancer Service and an Ingress can both give you an external IP, but they solve different problems.

What actually matters

  • Service = L4 load balancing to pods.
  • Ingress = L7 HTTP routing to services.
  • You need a Service even if you use Ingress. Ingress routes to Services, not directly to pods.
  • Ingress Controller must be installed separately. It is not built into Kubernetes.

Common mistakes

  • Creating an Ingress without installing an Ingress Controller. Nothing happens.
  • Using LoadBalancer Services for every app instead of one Ingress routing to many services (costs more cloud LBs).
  • Forgetting that NodePort exposes on ALL nodes, not just the one running your pod.

Small examples

# ClusterIP Service for internal communication
apiVersion: v1
kind: Service
metadata:
  name: backend
spec:
  selector:
    app: backend
  ports:
    - port: 80
      targetPort: 8080

# Ingress routing two domains to two services
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: routes
spec:
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api-svc
                port:
                  number: 80
    - host: web.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web-svc
                port:
                  number: 80

One-line summary

A Service gives pods a stable L4 endpoint; an Ingress adds L7 HTTP routing rules on top, directing traffic to Services.