ClusterIP, NodePort, and LoadBalancer as three progressively more externally-reachable Service types, and Ingress as the HTTP-aware routing layer that sits above all of them.
Published September 23, 2026
Pods are ephemeral — a Deployment can replace a pod at any time (a crash, a rolling update, a rescheduling), and each new pod gets a NEW IP address. Nothing that depends on reaching "the payment service" should have to track individual, constantly-changing pod IPs directly — a Service provides a stable, unchanging virtual IP and DNS name that automatically load-balances across whichever pods currently match its label selector, regardless of how many times those pods are replaced underneath it.
ClusterIP → internal-only, reachable from WITHIN the cluster only (the default)
NodePort → additionally exposes a static port on EVERY node's own IP
LoadBalancer → additionally provisions an external cloud load balancer (an actual
public IP from AWS/GCP/etc.) pointing at the service
<any-node-ip>:<nodeport> — mainly useful for local/dev clusters without a cloud load balancer available; rarely the right choice for production external exposure.
{ { , { } } }
{ { , { } } }
Provisioning a separate LoadBalancer Service (and a separate public IP/cost) for EVERY service in a cluster doesn't scale well — Ingress solves this by defining HTTP/HTTPS routing RULES (host-based, path-based — exactly like API Contract Design's routing discussion) that sit in front of MULTIPLE services behind a single entry point, typically a single shared LoadBalancer. This is conceptually the same role an API Gateway plays in a broader microservices architecture (Domain Decomposition, API Contract Design), applied specifically as a Kubernetes-native object.
An Ingress object on its own is just a set of ROUTING RULES — it does nothing by itself without an Ingress controller actually running in the cluster to read and implement those rules (nginx-ingress and cloud-provider-specific controllers like AWS's ALB Ingress Controller are common choices). This is a genuinely important distinction: creating an Ingress resource in a cluster with NO ingress controller installed simply does nothing — the controller is the piece that actually watches for Ingress objects and configures real routing (an nginx config reload, or provisioning an actual ALB) to match.
Q: Why would you ever still need a LoadBalancer Service if Ingress already handles HTTP routing to multiple services? A: Ingress specifically handles HTTP/HTTPS traffic; a service that speaks a non-HTTP protocol directly (a raw TCP database connection, a gRPC service without HTTP/1.1 semantics, though gRPC over HTTP/2 CAN work through some ingress controllers) may still need its own dedicated LoadBalancer Service, since Ingress's routing rules are fundamentally built around HTTP concepts (host, path).
Q: How does a Service actually find which pods to route to?
A: Via LABEL SELECTORS — a Service is configured with a label selector (e.g. app: order-service), and Kubernetes continuously matches that selector against all pods' labels, automatically updating the Service's routing targets as matching pods come and go; this label-based, declarative matching (rather than an explicit list of pod IPs) is what lets it stay correct automatically through rolling updates and rescheduling.
Q: Does Ingress provide load balancing, or just routing? A: Both — once Ingress routes a request to the right SERVICE based on host/path, that Service itself still load-balances across its matching pods exactly as it would for any other traffic reaching it; Ingress adds an HTTP-aware routing layer ON TOP of, not instead of, the underlying Service's own load-balancing behavior.
Q: Is TLS termination typically handled by the Ingress, the Service, or the application itself? A: Commonly the Ingress (or its controller) — Ingress resources typically support specifying a TLS certificate/secret, letting the ingress controller terminate HTTPS at the cluster's edge and forward plain HTTP internally; this centralizes certificate management in one place rather than requiring every individual service to handle its own TLS termination.