🎀Speaking at KubeCon EU 2026Lessons Learned Orchestrating Multi-Tenant GPUs on OpenShift AIView Session
Networking beginner ⏱ 15 minutes K8s 1.28+

How to Expose Services with LoadBalancer and NodePort

Learn different ways to expose Kubernetes services externally using LoadBalancer, NodePort, and ExternalIPs. Compare options for various environments.

By Luca Berton β€’

πŸ’‘ Quick Answer: ClusterIP (default): internal only. NodePort: exposes on each node’s IP at static port (30000-32767). LoadBalancer: provisions cloud LB (AWS/GCP/Azure)β€”use for production. For on-prem, install MetalLB. Quick expose: kubectl expose deployment myapp --type=LoadBalancer --port=80 --target-port=8080. For HTTP routing, use Ingress instead of multiple LoadBalancers.

The Problem

You need to expose your Kubernetes application to external traffic, but you’re unsure which service type to use.

Service Types Comparison

TypeUse CaseExternal AccessPort Range
ClusterIPInternal onlyNoAny
NodePortDevelopment/TestingNode IP:Port30000-32767
LoadBalancerProduction (cloud)External IPAny
ExternalNameDNS aliasN/AN/A

ClusterIP (Default)

Internal access only:

apiVersion: v1
kind: Service
metadata:
  name: myapp
spec:
  type: ClusterIP  # Default, can be omitted
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: myapp

Access from within cluster:

curl http://myapp.default.svc.cluster.local

NodePort

Exposes service on each node’s IP at a static port:

apiVersion: v1
kind: Service
metadata:
  name: myapp-nodeport
spec:
  type: NodePort
  ports:
  - port: 80           # Service port (internal)
    targetPort: 8080   # Container port
    nodePort: 30080    # External port (optional, auto-assigned if omitted)
  selector:
    app: myapp

Access from external:

curl http://<node-ip>:30080

Get node IPs:

kubectl get nodes -o wide

NodePort Considerations

βœ… Pros:

  • Works without cloud provider
  • Simple to set up

❌ Cons:

  • Limited port range (30000-32767)
  • Need to know node IPs
  • No load balancing across nodes

LoadBalancer

Provisions an external load balancer (cloud providers):

apiVersion: v1
kind: Service
metadata:
  name: myapp-lb
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: myapp

Check external IP:

kubectl get svc myapp-lb
# NAME       TYPE           EXTERNAL-IP     PORT(S)
# myapp-lb   LoadBalancer   34.123.45.67    80:31234/TCP

Cloud-Specific Annotations

AWS:

metadata:
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: nlb
    service.beta.kubernetes.io/aws-load-balancer-internal: "true"

GCP:

metadata:
  annotations:
    cloud.google.com/load-balancer-type: Internal

Azure:

metadata:
  annotations:
    service.beta.kubernetes.io/azure-load-balancer-internal: "true"

LoadBalancer on Bare Metal

Use MetalLB for LoadBalancer support on bare metal:

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml

Configure IP pool:

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: default-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.1.240-192.168.1.250
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: default
  namespace: metallb-system

ExternalName

Creates a DNS alias:

apiVersion: v1
kind: Service
metadata:
  name: external-db
spec:
  type: ExternalName
  externalName: database.example.com

Now pods can access external-db which resolves to database.example.com.

External IPs

Expose on specific external IPs:

apiVersion: v1
kind: Service
metadata:
  name: myapp-external
spec:
  ports:
  - port: 80
    targetPort: 8080
  externalIPs:
  - 192.168.1.100
  selector:
    app: myapp

Multiple Ports

apiVersion: v1
kind: Service
metadata:
  name: myapp-multi
spec:
  type: LoadBalancer
  ports:
  - name: http
    port: 80
    targetPort: 8080
  - name: https
    port: 443
    targetPort: 8443
  - name: grpc
    port: 9090
    targetPort: 9090
  selector:
    app: myapp

Session Affinity

Route same client to same pod:

apiVersion: v1
kind: Service
metadata:
  name: myapp-sticky
spec:
  type: LoadBalancer
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 3600
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: myapp

Health Check Configuration

For LoadBalancer health checks:

apiVersion: v1
kind: Service
metadata:
  name: myapp-lb
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-path: /health
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-interval: "30"
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: myapp

Troubleshooting

LoadBalancer Stuck in Pending

kubectl describe svc myapp-lb

Common causes:

  • No cloud provider configured
  • Quota exceeded
  • Network misconfiguration

Service Not Reachable

# Check endpoints
kubectl get endpoints myapp

# Should show pod IPs
# NAME    ENDPOINTS
# myapp   10.1.0.5:8080,10.1.0.6:8080

If empty, check selector labels:

kubectl get pods --show-labels

Test from Inside Cluster

kubectl run test --rm -it --image=curlimages/curl -- curl http://myapp

Decision Flow

Need external access?
β”œβ”€ No β†’ ClusterIP
└─ Yes
   β”œβ”€ Cloud provider available?
   β”‚  β”œβ”€ Yes β†’ LoadBalancer
   β”‚  └─ No β†’ NodePort or Ingress + MetalLB
   └─ Development/Testing?
      └─ Yes β†’ NodePort

Key Takeaways

  • Use ClusterIP for internal services
  • NodePort for quick testing (limited ports)
  • LoadBalancer for production with cloud providers
  • Consider Ingress for HTTP/HTTPS routing
  • Use MetalLB for LoadBalancer on bare metal

πŸ“˜ Go Further with Kubernetes Recipes

Love this recipe? There’s so much more! This is just one of 100+ hands-on recipes in our comprehensive Kubernetes Recipes book.

Inside the book, you’ll master:

  • βœ… Production-ready deployment strategies
  • βœ… Advanced networking and security patterns
  • βœ… Observability, monitoring, and troubleshooting
  • βœ… Real-world best practices from industry experts

β€œThe practical, recipe-based approach made complex Kubernetes concepts finally click for me.”

πŸ‘‰ Get Your Copy Now β€” Start building production-grade Kubernetes skills today!

Want More Kubernetes Recipes?

This recipe is from Kubernetes Recipes, our 750-page practical guide with hundreds of production-ready patterns.