LoadBalancer

LoadBalancer is a Service type that automatically provisions an external load balancer in cloud environments. It’s the simplest way to expose Services externally in cloud Kubernetes platforms like AWS, GCP, Azure, and others. Think of LoadBalancer as a concierge service—you request external access, and the cloud provider automatically sets up everything needed to route internet traffic to your Service.

What is LoadBalancer?

A LoadBalancer Service extends NodePort and ClusterIP by automatically creating an external load balancer provided by your cloud platform. The cloud provider assigns a stable external IP address and handles all the complexity of routing traffic from the internet to your Service.

graph TB A[Internet] --> B[Cloud Load Balancer<br/>External IP: 203.0.113.1] B --> C[Node 1] B --> D[Node 2] B --> E[Node 3] C --> F[LoadBalancer Service] D --> F E --> F F --> G[Backend Pod 1] F --> H[Backend Pod 2] F --> I[Backend Pod 3] style A fill:#e1f5ff style B fill:#fff4e1 style F fill:#e8f5e9 style G fill:#fff4e1 style H fill:#fff4e1 style I fill:#fff4e1

How LoadBalancer Works

When you create a LoadBalancer Service, Kubernetes:

  1. Creates a NodePort Service (LoadBalancer includes NodePort)
  2. Creates a ClusterIP Service (LoadBalancer includes ClusterIP)
  3. Sends request to cloud provider via the cloud controller manager
  4. Cloud provider provisions load balancer (e.g., AWS ELB, GCP Load Balancer, Azure LB)
  5. Assigns external IP address and configures routing
  6. Updates Service status with the external IP
graph LR A[LoadBalancer Service Created] --> B[Cloud Controller Manager] B --> C[Cloud Provider API Call] C --> D[Load Balancer Provisioned] D --> E[External IP Assigned] E --> F[Status Updated in Service] F --> G[Traffic Routes to Service] style A fill:#e1f5ff style D fill:#fff4e1 style E fill:#e8f5e9 style G fill:#e8f5e9

LoadBalancer Service Example

Here’s a basic LoadBalancer Service:

apiVersion: v1
kind: Service
metadata:
  name: web-loadbalancer
spec:
  type: LoadBalancer
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP

After creation, Kubernetes will provision a cloud load balancer and assign an external IP. You can check the status:

kubectl get service web-loadbalancer

Output:

NAME                TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)
web-loadbalancer    LoadBalancer   10.96.0.1      203.0.113.1      80:30080/TCP

The EXTERNAL-IP shows the public IP address assigned by the cloud provider.

Cloud Provider Integration

LoadBalancer Services work differently depending on your cloud provider:

AWS (EKS)

Creates an Elastic Load Balancer (Classic, Network, or Application LB):

apiVersion: v1
kind: Service
metadata:
  name: web-lb
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"  # Network Load Balancer
spec:
  type: LoadBalancer
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080

AWS-specific annotations:

  • service.beta.kubernetes.io/aws-load-balancer-type: “nlb”, “elb”, or “alb”
  • service.beta.kubernetes.io/aws-load-balancer-ssl-cert: ARN of SSL certificate
  • service.beta.kubernetes.io/aws-load-balancer-backend-protocol: “http” or “https”

Google Cloud (GKE)

Creates a Google Cloud Load Balancer:

apiVersion: v1
kind: Service
metadata:
  name: web-lb
  annotations:
    cloud.google.com/load-balancer-type: "Internal"  # For internal LB
spec:
  type: LoadBalancer
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080

Azure (AKS)

Creates an Azure Load Balancer:

apiVersion: v1
kind: Service
metadata:
  name: web-lb
  annotations:
    service.beta.kubernetes.io/azure-load-balancer-internal: "true"  # Internal LB
spec:
  type: LoadBalancer
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080
graph TB A[LoadBalancer Service] --> B{Cloud Provider} B -->|AWS| C[AWS ELB/NLB/ALB] B -->|GCP| D[GCP Load Balancer] B -->|Azure| E[Azure Load Balancer] B -->|Other| F[Provider-Specific LB] style A fill:#e1f5ff style C fill:#fff4e1 style D fill:#fff4e1 style E fill:#fff4e1 style F fill:#fff4e1

Service Hierarchy

LoadBalancer includes all functionality of NodePort and ClusterIP:

graph TB A[LoadBalancer Service] --> B[External IP Access] A --> C[NodePort Access] A --> D[ClusterIP Access] B --> E[Internet → Load Balancer → Service] C --> F[Node IP:NodePort → Service] D --> G[Cluster IP → Service] style A fill:#e8f5e9 style B fill:#fff4e1 style C fill:#fff4e1 style D fill:#fff4e1

Complete Example

Here’s a complete example with a Deployment and LoadBalancer Service:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web
        image: nginx:1.21
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: web-loadbalancer
spec:
  type: LoadBalancer
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP

After creation, access the application via the external IP:

curl http://203.0.113.1

Multiple Ports

LoadBalancer Services can expose multiple ports:

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

The cloud provider will configure the load balancer to handle both ports.

External IP Assignment

The external IP is assigned by the cloud provider and appears in the Service status:

kubectl get service web-loadbalancer -o yaml
status:
  loadBalancer:
    ingress:
    - ip: 203.0.113.1  # External IP assigned by cloud provider

Note: The external IP may take a few minutes to be assigned, especially on first creation.

LoadBalancer Status

You can monitor LoadBalancer provisioning:

# Check Service status
kubectl get service web-loadbalancer

# Watch for external IP assignment
kubectl get service web-loadbalancer -w

# Describe Service for detailed status
kubectl describe service web-loadbalancer

Common status messages:

  • <pending> - Load balancer is being provisioned
  • IP address - Load balancer is ready
  • Error messages - Provisioning failed (check cloud provider logs)

When to Use LoadBalancer

Use LoadBalancer when:

Cloud environments - Running on AWS, GCP, Azure, or other supported clouds
Simple external access - Need straightforward internet access to Services
Stable external IP - Require a stable, public IP address
TCP/UDP services - Exposing non-HTTP services (databases, custom protocols)
Production workloads - Production services that need reliable external access
Quick setup - Want automatic load balancer provisioning

Don’t use LoadBalancer when:

  • Running on bare metal or unsupported platforms
  • You need HTTP/HTTPS routing features (use Ingress instead)
  • Cost is a concern (each LoadBalancer has cloud costs)
  • You need path-based or host-based routing (use Ingress)
  • You want SSL termination with automatic certificates (use Ingress)

LoadBalancer vs Ingress

graph TB subgraph loadbalancer[LoadBalancer] A[One IP per Service] B[TCP/UDP Support] C[Cloud Provider Managed] D[Simple Setup] E[Higher Cost] end subgraph ingress[Ingress] F[One IP for Many Services] G[HTTP/HTTPS Only] H[Path/Host Routing] I[SSL Termination] J[Lower Cost] end style loadbalancer fill:#fff4e1 style ingress fill:#e8f5e9

Use LoadBalancer for:

  • Non-HTTP services (databases, custom TCP/UDP)
  • Simple HTTP services that don’t need routing
  • Services that need dedicated external IPs

Use Ingress for:

  • HTTP/HTTPS web applications
  • Multiple services sharing one IP
  • Path-based or host-based routing
  • SSL/TLS termination with automatic certificates

Cost Considerations

LoadBalancer Services create cloud resources that incur costs:

  • AWS: ELB charges per hour + data transfer
  • GCP: Load balancer charges per hour + forwarding rules
  • Azure: Load balancer charges + data processing

Cost optimization:

  • Use Ingress for HTTP/HTTPS (one load balancer for many services)
  • Use ClusterIP for internal-only services
  • Consider internal LoadBalancers for private access
  • Monitor and delete unused LoadBalancers

Internal Load Balancers

Some cloud providers support internal (private) load balancers:

AWS (Internal NLB)

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

GCP (Internal LB)

apiVersion: v1
kind: Service
metadata:
  name: internal-lb
  annotations:
    cloud.google.com/load-balancer-type: "Internal"
spec:
  type: LoadBalancer
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080

Internal load balancers provide:

  • Private IP addresses (not accessible from internet)
  • Lower cost than external load balancers
  • Better security for internal services
  • VPC-only access

Best Practices

  1. Use for production - LoadBalancer is ideal for production external access
  2. Monitor costs - Track LoadBalancer usage and costs
  3. Use Ingress for HTTP - Prefer Ingress for HTTP/HTTPS web traffic
  4. Specify annotations - Use cloud-specific annotations for configuration
  5. Clean up unused Services - Delete LoadBalancer Services when not needed
  6. Use internal LBs - Use internal load balancers for private access
  7. Document external IPs - Keep track of assigned external IPs
  8. Set up monitoring - Monitor load balancer health and performance
  9. Consider DNS - Point DNS records to LoadBalancer external IPs
  10. Review security - Ensure proper security groups/firewall rules

Troubleshooting

External IP Stuck in Pending

  1. Check cloud controller manager: kubectl get pods -n kube-system | grep cloud-controller
  2. Verify cloud provider integration: Ensure cloud controller manager is running
  3. Check Service events: kubectl describe service <service-name>
  4. Verify IAM permissions: Cloud controller needs permissions to create load balancers
  5. Check cloud provider quotas: Ensure you haven’t exceeded load balancer limits
  6. Review cloud provider logs: Check cloud controller manager logs

Cannot Access External IP

  1. Verify IP assigned: kubectl get service <service-name>
  2. Check security groups: Ensure firewall rules allow traffic
  3. Test from inside cluster: Verify Service works via ClusterIP
  4. Check load balancer status: Review cloud provider console
  5. Verify Endpoints: kubectl get endpoints <service-name>
  6. Test DNS resolution: Ensure DNS points to correct IP

Load Balancer Not Provisioning

  1. Cloud provider support: Verify your cloud provider supports LoadBalancer
  2. Controller logs: kubectl logs -n kube-system <cloud-controller-pod>
  3. API permissions: Check cloud provider API permissions
  4. Resource quotas: Verify cloud provider resource limits
  5. Network configuration: Check VPC/subnet configuration

High Costs

  1. Audit LoadBalancers: List all LoadBalancer Services
  2. Use Ingress: Consolidate HTTP services behind Ingress
  3. Delete unused Services: Remove Services that are no longer needed
  4. Use internal LBs: Use internal load balancers when possible
  5. Monitor usage: Set up cost alerts for load balancer usage

See Also