You will need both, as they solve separate problems:
MetalLB receives requests from the outside of the cluster, and balances them across the load balancer(s) in the cluster
Nginx receives requests from outside the cluster and balances them across the nodes.
See https://kubernetes.github.io/ingress-nginx/deploy/baremetal/#a-pure-software-solution-metallb for details.
Without MetalLB, nginx ingress service in bare metal stays in pending
state because it has no IP assigned to it. MetalLB does the job of assigning nginx an external IP.
Without Nginx, you will have to perform TLS termination on every client, something that is generally not advisable.
Another way of looking at it:
- nginx ingress handles the type
Ingress
- metallb handles the type
LoadBalancer
The confusion likely stems from the fact while the operations above are fundamentally different, they are often done by a "load balancer".
Note that the same applies in the cloud: you need to deploy an ingress to handle TLS termination and others, and the provider automatically creates a load balancer on their infrastructure.