How can we implement subset hashing with F5 NGINX Ingress Controller?

Subject

How can we implement subset hashing with F5 NGINX Ingress Controller?

Detailed Question

We are migrating from the community ingress-nginx controller to the F5 NGINX Ingress Controller.

Our existing setup uses the following community ingress-nginx annotations:

nginx.ingress.kubernetes.io/upstream-hash-by: $http_hs_id$arg_language
nginx.ingress.kubernetes.io/upstream-hash-by-subset: "true"
nginx.ingress.kubernetes.io/upstream-hash-by-subset-size: "5"

The requirement is:

  • The backend Service has multiple pods, for example, 5 pods.

  • Requests should be hashed using:

    hs_id + language
    
    
  • For each unique key, a stable subset of 3 pods should be selected.

  • Requests with the same key should continue using the same subset.

  • One pod from that subset should receive the request.

  • If the selected pod becomes unavailable, traffic should fail over to another healthy pod within the same subset.

  • NGINX response caching must continue to work.

  • Cache should be stored on persistent storage attached to the F5 NGINX Ingress Controller.

  • Cache keys should include request-specific values such as:

    host + URI + hs_id + language
    
    

Current F5 Configuration

We are using an F5 NGINX VirtualServer similar to:

apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
  name: playback-production-subset
  namespace: f5-demo
spec:
  host: example.com
  ingressClassName: f5-demo-cache-nginx

  upstreams:
    - name: playback
      service: playback-echo
      port: 5678
      lb-method: "hash $http_hs_id$arg_language"

  routes:
    - path: /
      action:
        pass: playback

The lb-method: hash provides consistent hashing to a single backend, but it does not appear to provide subset hashing.

Hi @Ashutosh_Pathania

You use case of caching should be supported by the Cache policy. Please refer to the documentation for the usage.

For subset hashing, the migration guide notes this:

Note: The F5 NGINX Ingress Controller has no dedicated upstream-hash-by equivalent. Instead, the hash key is specified as part of the lb-method value (e.g., hash $request_uri consistent). Subset hashing (upstream-hash-by-subset) is not supported; use consistent hashing for similar distribution.

I think the distinction is that consistent maps each key to one upstream server, whereas your use case maps each key to a subset of servers and distributes requests within that subset. So consistent hashing may be a useful alternative if you are willing to consider, but it doesn’t appear to provide the exact hash-by-subset behaviour you described.

While ingress-nginx passes the annotation upstream-hash-by 's value to a lua balancer, NIC writes the lb-method string verbatim into the NGINX configuration as a load-balancing directive. in your case, it is the hash directive. I don’t think NGINX’s native load-balancing methods support balancing between server groups.

Therefore, NIC will need extra NGINX logic and potentially new CRD fields for your use case. I will create an issue on our GitHub repo and investigate the next steps.

Hello @hshannon
We need to understand whether F5 NGINX Ingress Controller plans to support dynamic subset hashing similar to ingress-nginx:

hash(hs_id + language)
→ select deterministic N pods from all ready upstream pods
→ load-balance within the selected subset

Currently, NIC supports consistent hashing to a single upstream server, but does not support upstream-hash-by-subset or configurable subset sizes.

Could you please clarify:

  1. Is this feature planned for NIC?
  2. Has a GitHub issue or product roadmap item been created for it?
  3. What is the expected timeline or target release?

Issue created: Support upstream hash by subset · Issue #11260 · nginx/kubernetes-ingress · GitHub
It is not on our roadmap yet, but it will be triaged during the next community call. I have linked your PR to the issue, and we are happy to review it when it is ready.