Picking the Right Load Balancer for Your Kubernetes Environment

Introduction

As Kubernetes adoption skyrockets, managing traffic within and to your clusters becomes a critical aspect of ensuring availability, performance, and scalability. One of the most important decisions when running Kubernetes in production is choosing the right load balancer. In this blog, we’ll explore the different types of load balancers — L4, L7, Ingress, & external and guide you in picking the one that fits your use case. We’ll also dive into popular solutions like NGINX Ingress, Traefik, and external options such as AWS ALB.

Understanding Load Balancers in Kubernetes

In Kubernetes, a load balancer distributes incoming traffic across multiple pods to ensure efficient resource utilization, better redundancy, and optimal performance. Load balancers operate on different layers of the OSI model, and selecting the right one for your use case hinges on your traffic type, scale, and specific deployment needs.

Types of Load Balancers

  1. Layer 4 (L4) Load Balancers:

    • Operate at the transport layer (TCP/UDP)

    • Route traffic based on IP addresses and ports

    • Best for applications that don’t need deep packet inspection or custom routing logic.

  2. Layer 7 (L7) Load Balancers:

    • Operate at the application layer (HTTP/HTTPS)

    • Can route traffic based on content (e.g., headers, URLs)

    • Ideal for microservices that need traffic routed to specific services based on custom rules.

  3. Ingress Controllers:

    • Kubernetes-native solution for managing external access to services within a cluster

    • Typically operates at Layer 7, often used to expose HTTP/S services

    • Popular Ingress controllers: NGINX Ingress, Traefik

  4. External Load Balancers:

    • Provided by cloud platforms (e.g., AWS ALB, Google Cloud Load Balancer)

    • Typically Layer 4 or Layer 7, ideal for integrating Kubernetes with cloud-based infrastructure.

Choosing the Right Load Balancer

When deciding which load balancer to use, consider the following factors:

  • Traffic Type: Is your application simple TCP/UDP-based, or does it require advanced routing based on HTTP requests?

  • Cloud Integration: Are you running Kubernetes on a cloud platform? If yes, does it make sense to use a native cloud load balancer like AWS ALB or GCP Load Balancer?

  • Customization Needs: Do you need granular control over routing rules? L7 load balancers and Ingress controllers like NGINX or Traefik provide more flexibility than traditional L4 solutions.

Let’s break this down further with a real-world example.

Real-World Example: Microservices-Based E-Commerce Application

Imagine you’re managing a microservices-based e-commerce platform hosted on AWS EKS (Elastic Kubernetes Service). You have the following requirements:

  • Your frontend services require traffic to be routed based on HTTP headers (Layer 7 routing).

  • Your payment processing service is highly sensitive and needs direct, low-latency traffic routing (Layer 4 TCP routing).

  • You want to expose services to the public while keeping internal services isolated.

  • You prefer using AWS ALB for its tight integration with AWS infrastructure.

Solution Breakdown

  1. Frontend Services (Layer 7): For HTTP-based frontend services, an Ingress Controller like NGINX Ingress or Traefik would be ideal. These controllers offer advanced routing features, allowing you to expose multiple services under the same domain and manage traffic efficiently with SSL termination.

    • Why NGINX Ingress or Traefik?
      Both provide flexibility for routing rules, SSL certificate management, and integration with Kubernetes. NGINX is widely adopted and provides a robust, feature-rich solution. Traefik, on the other hand, shines in dynamic environments with automatic service discovery and built-in metrics.
  2. Payment Processing Service (Layer 4): Since your payment processing service requires low-latency traffic routing, a Layer 4 Load Balancer (AWS Network Load Balancer) would suit this need. It routes TCP traffic directly to your service without inspecting the data, ensuring minimal overhead.

  3. External Load Balancing with AWS ALB: To expose your services externally, you can leverage AWS ALB (Application Load Balancer) for HTTP/S traffic. AWS ALB integrates seamlessly with Kubernetes, enabling you to route traffic to your Ingress controller while benefiting from AWS’s scalable load balancing service.

Implementation with Architecture Diagram

Let’s walk through how you can implement this setup on AWS EKS using a combination of NGINX Ingress for frontend services, AWS ALB for external access, and AWS Network Load Balancer for payment processing.

To implement the architecture described in the blog post, we will walk through a step-by-step guide using AWS Elastic Kubernetes Service (EKS) as the Kubernetes platform. We will set up the following components:

  1. NGINX Ingress Controller for managing Layer 7 traffic to Kubernetes services.

  2. AWS ALB (Application Load Balancer) for external access, integrated with NGINX Ingress.

  3. AWS NLB (Network Load Balancer) for low-latency Layer 4 routing to sensitive services like payment processing.

Prerequisites

  • AWS CLI installed and configured

  • kubectl configured to access your EKS cluster

  • Helm installed for Kubernetes package management

  • AWS Load Balancer Controller installed

  • An EKS cluster with worker nodes up and running

Step 1: Create an EKS Cluster

If you don't already have an EKS cluster, you can create one using the following steps:

  1. Install AWS CLI and eksctl (if not installed):

     brew install awscli
     brew tap weaveworks/tap
     brew install weaveworks/tap/eksctl
    
  2. Create the EKS cluster:

     eksctl create cluster \
     --name my-eks-cluster \
     --region us-west-2 \
     --nodegroup-name standard-workers \
     --node-type t3.medium \
     --nodes 3 \
     --nodes-min 1 \
     --nodes-max 4 \
     --managed
    
  3. Verify cluster access:

     aws eks --region us-west-2 update-kubeconfig --name my-eks-cluster
     kubectl get svc
    

Step 2: Install the AWS Load Balancer Controller

The AWS Load Balancer Controller will automatically provision ALBs and NLBs for Kubernetes services.

  1. Associate an IAM Policy for the controller:

     curl -o iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json
     aws iam create-policy \
       --policy-name AWSLoadBalancerControllerIAMPolicy \
       --policy-document file://iam-policy.json
    
  2. Create a service account for the controller:

     eksctl create iamserviceaccount \
       --cluster my-eks-cluster \
       --namespace kube-system \
       --name aws-load-balancer-controller \
       --attach-policy-arn arn:aws:iam::<ACCOUNT_ID>:policy/AWSLoadBalancerControllerIAMPolicy \
       --override-existing-serviceaccounts \
       --approve
    
  3. Install the AWS Load Balancer Controller using Helm:

     helm repo add eks https://aws.github.io/eks-charts
     helm repo update
    
     helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
       --set clusterName=my-eks-cluster \
       --set serviceAccount.create=false \
       --set region=us-west-2 \
       --set vpcId=<your-vpc-id> \
       --set serviceAccount.name=aws-load-balancer-controller \
       -n kube-system
    

Step 3: Install NGINX Ingress Controller

NGINX will handle the Layer 7 routing and expose services using ALB.

  1. Install the NGINX Ingress Controller using Helm:

     helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
     helm repo update
    
     helm install nginx-ingress ingress-nginx/ingress-nginx \
       --namespace ingress-nginx \
       --create-namespace
    
  2. Verify the installation:

     kubectl get pods -n ingress-nginx
    

Step 4: Deploy the Frontend Application with Ingress

Now, deploy your frontend service and expose it using NGINX Ingress and AWS ALB for Layer 7 routing.

  1. Create a simple frontend deployment and service:

     apiVersion: apps/v1
     kind: Deployment
     metadata:
       name: frontend
     spec:
       replicas: 2
       selector:
         matchLabels:
           app: frontend
       template:
         metadata:
           labels:
             app: frontend
         spec:
           containers:
           - name: frontend
             image: nginx:latest
             ports:
             - containerPort: 80
     ---
     apiVersion: v1
     kind: Service
     metadata:
       name: frontend
     spec:
       type: NodePort
       ports:
       - port: 80
         targetPort: 80
       selector:
         app: frontend
    

    Apply the deployment:

     kubectl apply -f frontend.yaml
    
  2. Create an Ingress resource with ALB integration:

     apiVersion: networking.k8s.io/v1
     kind: Ingress
     metadata:
       name: frontend-ingress
       annotations:
         alb.ingress.kubernetes.io/scheme: internet-facing
         alb.ingress.kubernetes.io/target-type: ip
     spec:
       rules:
       - host: "frontend.example.com"
         http:
           paths:
           - path: /
             pathType: Prefix
             backend:
               service:
                 name: frontend
                 port:
                   number: 80
    

    Apply the Ingress resource:

     kubectl apply -f frontend-ingress.yaml
    
  3. Verify the ALB is created by checking the AWS console or using kubectl:

     kubectl get ingress frontend-ingress
    

Step 5: Deploy the Payment Service with NLB (Layer 4)

For sensitive services like payment processing, you'll use a Network Load Balancer (NLB) for TCP traffic routing.

  1. Create a payment processing service:

     apiVersion: apps/v1
     kind: Deployment
     metadata:
       name: payment
     spec:
       replicas: 2
       selector:
         matchLabels:
           app: payment
       template:
         metadata:
           labels:
             app: payment
         spec:
           containers:
           - name: payment
             image: my-payment-app:latest
             ports:
             - containerPort: 443
     ---
     apiVersion: v1
     kind: Service
     metadata:
       name: payment-service
     spec:
       type: LoadBalancer
       ports:
       - port: 443
         targetPort: 443
         protocol: TCP
       selector:
         app: payment
    

    Apply the payment service:

     kubectl apply -f payment-service.yaml
    
  2. Verify the NLB is created:

    Check the service to see if the external IP is assigned:

     kubectl get svc payment-service
    

Step 6: Test and Verify the Setup

  1. Test the Frontend (L7):

    • Visit http://frontend.example.com to verify that your frontend is accessible via ALB.

    • You can use tools like curl to verify different URL routing behavior.

  2. Test the Payment Processing (L4):

    • Use a TCP client or browser (if applicable) to connect to the NLB’s IP address on port 443.

    • Ensure low-latency connections and verify the payment service’s functionality.

Step 7: Monitoring and Scaling

  1. Monitor the Load Balancers using AWS CloudWatch to track performance metrics, latency, and traffic.

  2. Scale Pods Automatically using Kubernetes Horizontal Pod Autoscaler (HPA) based on CPU utilization.

     kubectl autoscale deployment frontend --cpu-percent=50 --min=2 --max=5
     kubectl autoscale deployment payment --cpu-percent=50 --min=2 --max=4
    

Architecture Diagram

                    ┌──────────────────────────────┐
                    │        AWS ALB (L7)          │
                    └──────────────┬───────────────┘
                                   │
                         ┌─────────▼──────────┐
                         │ NGINX Ingress (L7) │
                         └─────────┬──────────┘
                                   │
                    ┌──────────────┴──────────────┐
                    │                             │
         ┌──────────▼───────────┐       ┌─────────▼──────────┐
         │  Frontend Service A  │       │ Frontend Service B │
         └──────────────────────┘       └────────────────────┘

                    ┌──────────────────────────────┐
                    │       AWS NLB (Layer 4)      │
                    └──────────────┬───────────────┘
                                   │
                    ┌──────────────▼──────────────┐
                    │  Payment Processing Service │
                    └─────────────────────────────┘

Conclusion

Choosing the right load balancer for your Kubernetes environment depends on your specific use case. For advanced HTTP routing, Ingress controllers like NGINX or Traefik offer powerful features. For cloud-native environments, external solutions like AWS ALB or NLB provide seamless integration with infrastructure. The right choice ensures optimal performance, better redundancy, and a smoother user experience.

What’s next?

Stay tuned for Part IX where we'll dive into Securing Kubernetes Operations with Runtime Security Best Practices. In this next article, we'll discuss essential runtime security strategies for Kubernetes environments using tools like Falco, Sysdig, and Aqua Security to detect anomalies, enforce container security policies, and mitigate risks in production.

14
Subscribe to my newsletter

Read articles from Subhanshu Mohan Gupta directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Subhanshu Mohan Gupta
Subhanshu Mohan Gupta

A passionate AI DevOps Engineer specialized in creating secure, scalable, and efficient systems that bridge development and operations. My expertise lies in automating complex processes, integrating AI-driven solutions, and ensuring seamless, secure delivery pipelines. With a deep understanding of cloud infrastructure, CI/CD, and cybersecurity, I thrive on solving challenges at the intersection of innovation and security, driving continuous improvement in both technology and team dynamics.