About session affinity

Session affinity, also referred to as sticky session, allows you to route requests for a particular session to the same upstream service instance that served the initial request. This setup is particularly useful if you have an upstream service that performs expensive operations and caches the output or data for subsequent requests. With session affinity, you make sure that the expensive operation is performed once and that subsequent requests can be served from the upstream’s cache, which can significantly improve operational cost and response times for your clients.

About consistent hashing

Gloo Gateway allows you to set up soft session affinity between a client and an upstream service by using the Ringhash or Maglev consistent hashing algorithm. The hashing algorithm uses a property of the request, such as a header, and hashes this property with the address of an upstream service instance that served the initial request. In subsequent requests, as long as the client sends the same header, the request is routed to the same upstream service instance.

Before you begin

  1. Follow the Get started guide to install Gloo Gateway, set up a gateway resource, and deploy the httpbin sample app.

  2. Get the external address of the gateway and save it in an environment variable.

Set up Ringhash and Maglev hashing

  1. Scale the httpbin app up to 2 instances.

      kubectl scale deployment httpbin -n httpbin --replicas=2
      
  2. Verify that another instance of the httpbin app is created and note the IP addresses of both httpbin instances. In the following example, you have an httpbin instance available at the 10.0.43.175 and 10.0.38.52 IP addresses.

      kubectl get pods -n httpbin -o wide
      

    Example output

      NAME                      READY   STATUS        RESTARTS   AGE    IP            NODE                          NOMINATED NODE   READINESS GATES
    httpbin-8d557795f-86hzg   3/3     Running       0          54m    10.0.43.175   ip-10-0-34-108.ec2.internal   <none>           <none>
    httpbin-8d557795f-h8ks9   3/3     Running       0          126m   10.0.38.52    ip-10-0-39-74.ec2.internal    <none>           <none>
      
  3. Create an Upstream for the httpbin app. An Upstream is required to later configure the Ringhash or Maglev hashing algorithm.

      kubectl apply -f- <<EOF
    apiVersion: gloo.solo.io/v1
    kind: Upstream
    metadata:
      name: httpbin 
      namespace: gloo-system
    spec:
      kube:
        serviceName: httpbin 
        serviceNamespace: httpbin
        servicePort: 8000
    EOF
      
  4. Create an HTTPRoute that routes requests on the httpbin.example domain to the httpbin Upstream.

      kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
     name: httpbin-upstream
     namespace: gloo-system
    spec:
      parentRefs:
      - name: http
        namespace: gloo-system
      hostnames:
        - httpbin.example
      rules:
       - backendRefs:
         - name: httpbin
           kind: Upstream
           group: gloo.solo.io
    EOF
      
  5. Send a request to the httpbin.example domain and verify that you can route traffic to the httpbin Upstream.

    Example output:

      HTTP/1.1 200 OK
    access-control-allow-credentials: true
    access-control-allow-origin: *
    content-type: application/json; encoding=utf-8
    date: Wed, 05 Mar 2025 20:42:32 GMT
    x-envoy-upstream-service-time: 1
    server: envoy
    transfer-encoding: chunked 
      
  6. Update the httpbin Upstream to configure a Ringhash or Maglev hashing algorithm for the Upstream.

  7. Create a RouteOption to store the hashed value in the hashbasedcookie cookie. The cookie is valid for 60 seconds. The RouteOption is applied to the httpbin-upstream HTTPRoute that you created earlier.

      kubectl apply -f- <<EOF
    apiVersion: gateway.solo.io/v1
    kind: RouteOption
    metadata: 
      name: lbhash
      namespace: gloo-system
    spec:
      targetRefs: 
      - group: gateway.networking.k8s.io
        kind: HTTPRoute
        name: httpbin-upstream
      options:
        lbHash:
          hashPolicies:
            - cookie:
                name: hashbasedcookie
                ttl: 60s
                path: /
    EOF
      
  8. Send a request to the httpbin app and verify that you see the hashbasedcookie cookie in the set-cookie header of your response. The -c option stores the cookie in a local file on your machine so that you can use it in subsequent requests.

    Example output:

      < set-cookie: hashbasedcookie="298b1ac340fdea97"; Max-Age=60; Path=/; HttpOnly
    set-cookie: hashbasedcookie="298b1ac340fdea97"; Max-Age=60; Path=/; HttpOnly
    < server: envoy
    server: envoy
    < 
    
    {
      "headers": {
        "Accept": [
         "*/*"
        ],
        "Host": [
          "httpbin.example:8080"
        ],
        "User-Agent": [
          "curl/8.7.1"
        ],
        "X-Envoy-Expected-Rq-Timeout-Ms": [
          "15000"
        ],
        "X-Forwarded-Proto": [
          "http"
        ],
        "X-Request-Id": [
          "fe080d74-2b6e-4954-8bde-54bed3e71dde"
        ]
      }
    }
      
  9. Repeat the request a few more times. Include the cookie that you stored in the local file by using the -b option. Make sure to send these requests within the 60 second cookie validity period.

  10. Get the logs of the httpbin instance that served the initial request. Verify that all subsequent requests were also served by the same instance.

      kubectl logs <httpbin-pod> -n httpbin
      

Cleanup

You can optionally remove the resources that you created in this guide.

  kubectl delete routeoption lbhash -n gloo-system
kubectl delete httproute httpbin-upstream -n gloo-system
kubectl delete upstream httpbin -n gloo-system
kubectl scale deployment httpbin -n httpbin --replicas=1