Learn MetalLB - Ingress & Nginx Integration
Episode 12 of 23

Learn MetalLB - Ingress & Nginx Integration

The most common combination on bare-metal clusters: MetalLB exposes the Ingress Controller, and Ingress splits traffic across many Services. This episode covers setting up Nginx Ingress as a LoadBalancer, the comparison with NodePort, and the end-to-end flow from an application to Ingress and out through MetalLB.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

Exposing every application with its own LoadBalancer Service is possible, but it wastes IPs and is hard to manage. That's where Ingress comes in: a single entry point that splits traffic across many Services based on hostname or path. The combination of MetalLB and an Ingress Controller is the most common pattern on bare-metal clusters — MetalLB provides the external IP, and Ingress splits the traffic.

Episode 12 guides you through building this pattern with the Nginx Ingress Controller: installing the controller, exposing it via a LoadBalancer Service, comparing it with the NodePort approach, and assembling the end-to-end flow from an application to Ingress and out through MetalLB.

Why Ingress + MetalLB

One IP for Many Applications

Without Ingress, one application needs one LoadBalancer IP. With Ingress, a single LoadBalancer IP can serve dozens of applications — the router is the Ingress Controller, which evaluates requests based on hostname and path.

Comparing IP usage
kubectl get svc -A

In kubectl get svc -A, you'll see many internal ClusterIP Services and only one LoadBalancer Service for Ingress. That's a significant IP saving, especially for pools with limited capacity.

A Three-Layer Architecture

The traffic flow becomes:

  1. External traffic arrives at the MetalLB IP owned by the Ingress LoadBalancer Service.
  2. The Ingress Controller receives the request and matches the hostname or path against Ingress rules.
  3. Ingress forwards the request to the backend Service, then to the application pods.

Install the Nginx Ingress Controller

Installation via Helm

The fastest way to install the Nginx Ingress Controller is via Helm:

Install the Nginx Ingress Controller
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress-nginx ingress-nginx/ingress-nginx --namespace ingress-nginx --create-namespace

helm install ingress-nginx ingress-nginx/ingress-nginx --namespace ingress-nginx creates the controller in the ingress-nginx namespace. Wait until the controller pod reports Running:

Verify the controller and its Service
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx

Expose the Ingress Controller via MetalLB

A LoadBalancer Service for the Controller

By default, the Nginx Ingress chart creates a Service of type LoadBalancer. MetalLB will allocate an external IP for this Service from the configured pool:

Viewing the Ingress LoadBalancer IP
kubectl get svc ingress-nginx-controller -n ingress-nginx
kubectl get svc ingress-nginx-controller -n ingress-nginx -o jsonpath='{.status.loadBalancer.ingress[0].ip}'

If EXTERNAL-IP is filled in — for example 192.168.1.201 — MetalLB has successfully exposed the Ingress Controller. kubectl get svc ingress-nginx-controller -n ingress-nginx is the command to check that status.

Making Sure It's Announced

The Ingress IP must also be announced. In Layer 2 mode, check from another machine that the IP answers ARP. In BGP mode, check the routes on the router. Both checks use the same steps as episodes 5 and 6.

LoadBalancer vs NodePort for Ingress

A Practical Comparison

Both approaches can expose Ingress, but there are important differences:

  • LoadBalancer: a dedicated IP per Service, source IPs are easier to preserve with externalTrafficPolicy: Local, and there's no need to remember a random port.
  • NodePort: needs no extra IP, but the port used is random on every node, and access uses a node IP plus a port — for example http://192.168.1.10:31234.

For production, LoadBalancer is by far the cleaner choice. NodePort remains useful as a quick fallback or when IP blocks are limited.

End-to-End Flow: Application to Ingress

Deploying Applications and Ingress Rules

Now let's put it all together. Deploy two applications and create hostname-based Ingress rules:

Ingress rule for two applications
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo-apps
spec:
  ingressClassName: nginx
  rules:
    - host: app1.example.internal
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: app1
                port:
                  number: 80
    - host: app2.example.internal
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: app2
                port:
                  number: 80

Testing Access Through Ingress

From a machine outside the cluster, point the hostname at the Ingress LoadBalancer IP:

Testing Ingress through the MetalLB IP
curl --resolve app1.example.internal:80:192.168.1.201 http://app1.example.internal
curl -H "Host: app1.example.internal" http://192.168.1.201

curl -H "Host: app1.example.internal" http://192.168.1.201 forces Nginx to treat the request as if it were for that hostname. If the app1 application answers, the end-to-end flow works: application to Ingress, out through MetalLB.

Conclusion

Episode 12 completes the Ingress + MetalLB pattern: one external IP serves many applications, the Ingress Controller is exposed via a LoadBalancer Service, and the end-to-end flow from application to outside the cluster is proven to work.

Key takeaways:

  • One LoadBalancer IP for Ingress replaces many per-application IPs.
  • helm install ingress-nginx ingress-nginx/ingress-nginx is the fastest install path.
  • kubectl get svc ingress-nginx-controller -n ingress-nginx checks the IP allocated by MetalLB.
  • LoadBalancer is cleaner than NodePort for production.
  • Ingress rules split traffic based on hostname or path.
  • Test with curl -H "Host: ..." to verify Ingress routing.

In the next episode, episode 13, we'll discuss peering & network design — multi-peer BGP configuration, using routerID, planning the advertised subnets, placing IP pools, and coordinating with firewalls so peering and advertisement work securely.

Learn MetalLB - Ingress & Nginx Integration | Learn MetalLB