The ingress service defines the external load balancer. E.g. on AWS, creating the Ingress service as type: LoadBalancer creates an ELB for you. I believe the equivalent occurs for GCP/GKE as well.
Kubernetes nginx-ingress-controller
It is the K8s service that acquires the static IP address, etc. A bit oddly, imo, the TLS configuration is on the Ingress object and not the service object. But, se la vie.
As a practical matter, when you create an Ingress, e.g. nginx, it includes a Pod deployment for the nginx daemon itself, which runs on containers inside the cluster. I.e. an Ingress always runs inside the cluster. Seems like an external load balancer is something else and not an Ingress, per se.
Took a look. Same goes for Contour:
https://raw.githubusercontent.com/projectcontour/contour/release-1.0/examples/render/contour.yaml
So it just comes down to how one pod (LB) accesses another (your app): directly or via a service. If directly, it has to communicate with the K8s service to maintain the current list of containers for the pod. This is necessary to maintain session affinity. Otherwise, it’s probably best avoided without a strong justification.
I know this is an old thread. Just clarifying this stuff for my own benefit … :–)