How to set a hash on Istio based on the URL id?

Viewed 493

In the context of improving an API on Kubernetes, I am considering using a distributed hash table. My API always receives requests to an URL with this scheme:

www.myapi.com/id

Reading the documentation of Istio, it seems pretty direct and easy to get what I want. Indeed, Istio handles a load balancing scheme called ConsistentHashLB. I such a scheme, the service destination is chosen according to a hash computed from several possible fields: HTTP header name, cookie, source IP, and an HTTP query parameter name.

In my case, I would need to compute the hash according to the id associated with the request.

My question is double and conditional:

  1. Is it possible to read the id as an HTTP parameter name?
  2. If affirmative, how should I specify the rule in the manifest? (the doc that I have read is not enough clear in this regard).

If negative, some idea? some trick? For example, I am considering adding the id as an HTTP header with `Nginx, but this would add an additional step.

2 Answers

As I mentioned in comments if I understand correctly you're looking for a ConsistenHashLB path, there is documentation about that.

There is also github issue about that.


As for the http header question, you should be able to add it wither with:

  1. Virtual Service

There is Headers part on the istio documentation which shows how to add/remove headers with an example.

Message headers can be manipulated when Envoy forwards requests to, or responses from, a destination service. Header manipulation rules can be specified for a specific route destination or for all destinations. The following VirtualService adds a test header with the value true to requests that are routed to any reviews service destination. It also removes the foo response header, but only from responses coming from the v1 subset (version) of the reviews service.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews-route
spec:
  hosts:
  - reviews.prod.svc.cluster.local
  http:
  - headers:
      request:
        set:
          test: "true"
    route:
    - destination:
        host: reviews.prod.svc.cluster.local
        subset: v2
      weight: 25
    - destination:
        host: reviews.prod.svc.cluster.local
        subset: v1
      headers:
        response:
          remove:
          - foo
      weight: 75
  1. Envoy Filter

EnvoyFilter provides a mechanism to customize the Envoy configuration generated by Istio Pilot. Use EnvoyFilter to modify values for certain fields, add specific filters, or even add entirely new listeners, clusters, etc.

Below envoy filter add request header called customer-id with alice value to all request going though istio ingress gateway. I also commented code for response headers.

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: lua-filter
  namespace: istio-system
spec:
  workloadSelector:
    labels:
      istio: ingressgateway
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: GATEWAY
      listener:
        filterChain:
          filter:
            name: "envoy.http_connection_manager"
            subFilter:
              name: "envoy.router"
    patch:
      operation: INSERT_BEFORE
      value:
       name: envoy.lua
       typed_config:
         "@type": "type.googleapis.com/envoy.config.filter.http.lua.v2.Lua"
         inlineCode: |
            function envoy_on_request(request_handle)
                request_handle:headers():add("customer-id", "alice")
            end
           # function envoy_on_response(response_handle)
           #     response_handle:headers():add("customer-id", "alice")
           # end
Related