Thumbnail

Kubernetes: NodePort vs LoadBalancer vs Ingress

Kubernetes gives you several tools to make your services reachable, but picking the right one isn't always obvious. In this guide, I'll walk through ClusterIP, NodePort, Load Balancer, and Ingress, explain how each one works, and help you decide when to use which.

Prerequisites

  • A running Kubernetes cluster (any cloud provider or local setup like minikube)
  • Basic familiarity with kubectl and Kubernetes Services
  • Understanding of YAML manifests

Goals

  • Understand the four main ways to expose services in Kubernetes
  • Know the trade-offs, limitations, and costs of each approach
  • Be able to pick the right option for your use case

ClusterIP: Internal Communication Only

ClusterIP is the most basic service type in Kubernetes. It enables communication only between services within the same cluster, making it completely inaccessible from outside by default.

apiVersion: v1
kind: Service
metadata:
  name: kubernetes-dashboard
spec:
  type: ClusterIP
  selector:
    app: kubernetes-dashboard
  ports:
    - port: 80
      targetPort: 8080

The most common use case beyond debugging is exposing the Kubernetes Dashboard internally. To access a ClusterIP service from your local machine, you can use:

kubectl proxy

Then navigate to localhost in your browser. You can also use kubectl port-forward for more targeted access.

When to use ClusterIP:

  • Debugging your application by connecting directly from your development host
  • Exposing internal services and dashboards to team members when VPN isn't available

When NOT to use it: Do not rely on ClusterIP for exposing production services to external clients. It simply isn't designed for that.

NodePort: Quick and Dirty External Access

NodePort is the most primitive way to expose a service to the outside world. It works by opening a specific port on each Kubernetes node (VM), and any traffic sent to that port gets forwarded to the target service.

To make this work, your Kubernetes nodes need public IP addresses and a firewall rule allowing incoming traffic, which already introduces a potential security risk.

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: NodePort
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 8080
      nodePort: 31060

A request can be sent to any Kubernetes node, and even if your application pod lives on a different node, Kubernetes will still forward the request correctly.

Limitations to be aware of:

  • You can only expose one service per port
  • Port numbers are restricted to the range 30000–32767
  • If a node's IP address changes, you'll need to update your DNS records or notify clients
  • Placing nodes in a public subnet is a security concern

When to use NodePort: Short-lived scenarios like demos for potential clients work fine. You may also notice NodePort services appearing in your cluster automatically. Load Balancer services often create them internally as part of their routing mechanism.

Not recommended for production.

Load Balancer: The Standard Approach

The Load Balancer service type is the go-to method for exposing a service to the internet in most cloud environments. When you declare a service of type LoadBalancer, the cloud controller manager automatically provisions a corresponding load balancer in your cloud provider (AWS, GCP, Azure, etc.).

apiVersion: v1
kind: Service
metadata:
  name: my-service
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-internal: "true"
spec:
  type: LoadBalancer
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 8080

You can use annotations to control load balancer behavior. For example, the AWS annotation above creates a private internal load balancer accessible only within your VPC.

Advantages:

  • Supports virtually any protocol: HTTP, TCP, UDP, WebSockets, gRPC, and more
  • No filtering or routing complexity, just straightforward exposure

The big downside: Each service you want to expose requires its own load balancer. In cloud environments, load balancers cost money, and this can add up quickly as your number of services grows.

When to use Load Balancer: When you need to expose a single service directly and cost or complexity is not yet a concern.

Ingress: The Most Powerful Option

Ingress is not a service type. It's a separate Kubernetes resource that acts as a smart router or entry point in front of multiple services. It sits at the edge of your cluster and can route traffic to different backend services based on hostnames or URL paths.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 80
    - host: example.com
      http:
        paths:
          - path: /blog
            pathType: Prefix
            backend:
              service:
                name: blog-service
                port:
                  number: 80

There are many Ingress controllers to choose from, including nginx, Kong, Istio, and more. You can also extend them with plugins. For example, cert-manager can automatically provision and renew TLS certificates for your services.

Why Ingress wins for most production setups:

  • A single load balancer handles traffic for all your services, significantly reducing costs
  • Path-based and subdomain-based routing out of the box
  • TLS termination and certificate management
  • Authentication, rate limiting, and more depending on the controller

When to use Ingress: When you have multiple services to expose and want a robust, cost-effective, feature-rich solution. It's the most complex option, but for most production workloads it's the right call.

Conclusion

Each of these options serves a different purpose, and in practice you'll likely use more than one in the same cluster. ClusterIP handles your internal communication, a Load Balancer might expose a single critical service, and Ingress ties everything together at the edge.

Here's a quick comparison to help you decide:

Method External Access Use Case Production Ready
ClusterIP ❌ (internal only) Internal services, dashboards ✅ (for internal use)
NodePort ✅ (via node IP) Short demos, testing ⚠️ Not recommended
Load Balancer Single service exposure ✅ (watch costs)
Ingress Multiple services, advanced routing ✅ Recommended

Comments