<p>We are just getting started with k8s (bare metal on Ubuntu 20.04). Is it possible for ingress traffic arriving at a host for a load balanced service to go to a pod running on that host (if one is available)?</p>
<p>We have some apps that use client side consistent hashing (using customer ID) to select a service instance to call. The service instances are stateless but maintain in memory ML models for each customer. So it is useful (but not essential) to have repeated requests for a given customer go to the same service. Then we can just use antiAffinity to have one pod per host.</p>
<p>Our existing service discovery mechanism lets the clients find all the instances of the service and the nodes they are running on. All our k8s nodes are running the Nginx ingress controller.</p>

<p>I finally got this figured out. This was way harder than it should be IMO! <strong>Update: It's not working. Traffic frequently goes to the wrong pod.</strong></p>
<p>The service needs <code>externalTrafficPolicy: Local</code> (see <a href="https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip" rel="nofollow noreferrer">docs</a>).</p>
<pre><code>apiVersion: v1
kind: Service
metadata:
  name: starterservice
spec:
  type: LoadBalancer
  selector:
    app: starterservice
  ports:
    - port: 8168
  externalTrafficPolicy: Local
</code></pre>
<p>The Ingress needs <code>nginx.ingress.kubernetes.io/service-upstream: &quot;true&quot;</code> (<a href="https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#service-upstream" rel="nofollow noreferrer">service-upstream docs</a>).</p>
<p>The <code>nginx.ingress.kubernetes.io/server-alias: &quot;~^starterservice-[a-z0-9]+\\.example\\.com&quot;</code> bit is because our service discovery updates DNS so each instance of the service includes the name of the host it is running on in its DNS name.</p>
<pre><code>apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: starterservice
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/server-alias: &quot;~^starterservice-[a-z0-9]+\\.example\\.com&quot;
    nginx.ingress.kubernetes.io/service-upstream: &quot;true&quot;
spec:
  rules:
    - host:  starterservice.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: starterservice
                port:
                  number: 8168
</code></pre>
<p>So now a call <code>https://starterservice-foo.example.com</code> will go to the instance running on k8s host foo.</p>
