<p>I have set up and configured the <a href="https://kubernetes.io/docs/concepts/services-networking/service-topology/" rel="nofollow noreferrer">Service Topology</a> feature in a self-hosted Kubernetes Cluster. Everything is working as expected when I route traffic directly to a configured service using either the ClusterIP or NodePort. Topology Keys are respected, the correct node is chosen for routing to pod, etc, etc.</p>
<p>However, when using an ingress that is mapped to a service (tried with both the haproxy and traefik ingress), Topology aware routing is ignored. I'm not sure if this just not supported, a bug, or some configuration I am missing. The following are the methods I have tried.</p>
<p>1r) client curl -&gt; Topology Keyed Service -&gt; Deployment -&gt; Pod</p>
<p>Result: Works as expected.</p>
<p>2r) busybox pod curl -&gt; Topology Keyed Service -&gt; Deployment -&gt; Pod</p>
<p>Result: Works as expected.</p>
<p>3r) client curl -&gt; routed clusterIP of Traefik Service Ingress -&gt; Topology Keyed Service -&gt; Deployment -&gt; Pod</p>
<p>Result: Selected node pod is random and does not align with Topology Keys on Node.</p>
<p>4r) client curl -&gt; Host Networked Haproxy Ingress DaemonSet -&gt; Topology Keyed Service -&gt; Deployment -&gt; Pod</p>
<p>Result: Selected node pod is random and does not align with Topology Keys on Node.</p>
<p>From what I can tell, it seems that both the haproxy and traefik ingresses route traffic directly to the pods and bypass the service.</p>
<p>I've tested this by configuring the topology keys as follows (without * catch-all which should fail if not matched):</p>
<pre class="lang-yaml prettyprint-override"><code>topologyKeys:
  - &quot;kubernetes.io/hostname&quot;
  - &quot;topology.kubernetes.io/zone&quot;
  - &quot;topology.kubernetes.io/region&quot;
</code></pre>
<p>When testing with the ingresses, the service will always respond, though still randomly picking a pod in the replica set. When testing with the service, it will fail when no pods are satisfied with the topology labels on the node that the inbound request was received on (as expected).</p>
<p>I've looked through all the docs and spent many hours already googling and looking through Github issues and can't find any mention of this as an issue or as an unsupported config, etc.</p>
<p>-- EDIT --</p>
<p>Thanks to @Rico I was able to get this working on Ingresses with both the <a href="https://kubernetes.github.io/ingress-nginx/" rel="nofollow noreferrer">nginx</a> and <a href="https://haproxy-ingress.github.io/docs/" rel="nofollow noreferrer">haproxy-ingress</a>. The fix required the following annotations on the ingress.</p>
<p>nginx:</p>
<pre class="lang-yaml prettyprint-override"><code>annotations:
  nginx.ingress.kubernetes.io/service-upstream: &quot;true&quot;
</code></pre>
<p>haproxy-ingress:</p>
<pre class="lang-yaml prettyprint-override"><code>annotations:
  ingress.kubernetes.io/service-upstream: &quot;true&quot;
</code></pre>

<p>The answer here is that typically ingress controllers talk to the <a href="https://kubernetes.io/docs/concepts/services-networking/service/#services-without-selectors" rel="nofollow noreferrer">Endpoint API</a> and not the service API. It's documented on the <a href="https://kubernetes.github.io/ingress-nginx/user-guide/miscellaneous/#why-endpoints-and-not-services" rel="nofollow noreferrer">nginx ingress controller page</a> and the <a href="https://docs.traefik.io/routing/providers/kubernetes-ingress/#communication-between-traefik-and-pods" rel="nofollow noreferrer">Traefik ingress controller</a>. (Maybe not on some other ingresses)</p>
<p>Another alternative would be using <a href="https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/#endpointslice-resource" rel="nofollow noreferrer">EndpointSlices</a> but as of today, the ingress controllers don't support that yet.</p>
<p>I believe the path forward here is for the ingress controllers to <a href="https://github.com/kubernetes/ingress-nginx/issues/6017" rel="nofollow noreferrer">start supporting EndpointSlices</a>.</p>
<p>Update:</p>
<p>The nginx ingress controller has a way to bypass the Endpoint behavior with the <a href="https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#service-upstream" rel="nofollow noreferrer">nginx.ingress.kubernetes.io/service-upstream</a> annotation. &quot;But then you cannot have custom LB algorithms or sticky sessions&quot;.</p>
<p>✌️</p>
