Linkerd2: Header based routing

Created on 31 Jul 2019  路  18Comments  路  Source: linkerd/linkerd2

Feature Request

What problem are you trying to solve?

We would like to route requests to a service via headers on inbound requests!

How should the problem be solved?

There exists an open issue on the SMI spec that details how A/B testing could be extended to support cookies/headers/etc, instead of just weights: https://github.com/deislabs/smi-spec/issues/17.

As the SMI spec evolves beyond weighted traffic routing ie A/B or canary deployments like the linked issue above describes, it would be useful to be able to route traffic to backing services based on headers. At present, Linkerd does not support this feature, but Istio's virtualservice does - but we'd much rather use linkerd than take on istio.

Our use case, I think, is straightforward:

  1. An inbound request is decorated with a header via an ingress controller (that maps the inbound request to a header via some identity provider ie Azure Active Directory/okta/etc.)
  2. The inbound request is passed along into a service mesh, which maps the request to a backing service via the header set in 1.

This issue was opened, and it seems like the Traffic Split SMI resource mostly resolved issues in this situation, but in it's current form will not be sufficient to address the implementation we desire.

Any alternatives you've considered?

  • We've looked at flagger, which is better suited for automated container promotion.
  • Istio, but it's not an SMI compliant service mesh, and will likely not be for the nebulous future
  • Routing service to service traffic through a traefik2 ingress controller, which can match requests to services based on headers.

How would users interact with this feature?

If the API described in this issue is comprehensive enough, it would be sufficient.

Here is an example of usage that I'd like to see; an example of traffic split between 3 backing services:

apiVersion: v1beta1
kind: TrafficSplit
metadata:
  name: frontend
spec:
  service: frontend
  backends:
  - service: primary-frontend
  - service: beta-frontend
    matchRegex:
      - name: "beta users"
        x-group: "beta-users" # users who signed up for the beta
  - service: alpha-frontend
    matchRegex:
      - name: "alpha users"
        x-group: "alpha-users" # users who want to live on the bleeding edge
arecli arecontroller areproxy help wanted needrfc

Most helpful comment

SMI has officially merged header based routing into the spec!!!

All 18 comments

This would be awesome!

Thanks for filing this and for all the good context, @bnookala. Definitely on our radar as something we'd like Linkerd to be able to do.

@bnookala - This looks great!
@wmorgan - Would you have any pointers to when this could be considered or otherwise maybe how it could work in the current iteration of Linkerd2?

@migolfi work isn't scheduled yet, the SMI spec will need to be updated first. There are some tracking issues in the repo over there around it.

Currently, if you want to do something like this, flagger has some great docs on it.

This would be amazing

Our usecase is little different. For example request contains header Version: 1 will be routed to app-v1 and Version: 2 will be routed to app-v2.

This will make the uri little cleaner because we don't need to add version number in request uri.

We would also like to be able to re-route traffic by header, although I'm most interested in this capability being supported in the destination API and proxy.

I think this would let us build a drop in replacement for our linkerd 1.x setup which does routing based on path (e.g., discover endpoints based off of grpc service name). FWIW, we aren't concerned about this being SMI-supported.

I think this is also a prerequisite for explicitly routing traffic to canaries using headers as well, which is something we're also interested in.

We need header based routing in our company, we need an estimate for this feature, can you tell us a date(or milestone)?

@alirajabi there's no one working on this right now, we'd love your help!

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.

Some discussion happening in SMI towards this end.

SMI has officially merged header based routing into the spec!!!

@clintberry we'd love help getting this implemented!

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.

@grampelberg I see you added area/cli label. What CLI changes would need to be made for this to work? I'm going to start down the road of area/controller and see how far I can get.

@clintberry without thinking about it a ton, stat and check changes primarily.

See RFC #34

I want to routing the biz service based on the path or grpc service, I don't know dose header based routing solved this, pure routing, not about rollout deployment.

In kuerbnets, the service or deployment is application level. Biz service level I mean, com.example.test.PingService, when using this service, app don't care about which application provide this.

In consul, using service-router can achieve this.

Kind = "service-router"
// virtual service
Name = "service"
Routes = [
  {
    // biz level service routings
    Match {
      HTTP {
        PathPrefix = "/api/service/com.example.test.PingService"
      }
    }
    Destination {
      Service       = "pinging"
    },
  },
  {
    // routings for v2
    Match {
      HTTP {
        PathPrefix = "/api/service/com.example.test.PingService"
        Header = [
          {
            Name  = "x-version"
            Exact = "2"
          },
        ]
      }
    }
    Destination {
      Service       = "pinging"
      ServiceSubset = "v2"
    },
  },
  {
    // another biz service
    Match {
      HTTP {
        PathPrefix = "/api/service/com.example.user.UserService"
      }
    }
    Destination {
      Service       = "user-v1"
    },
  },
]

With this config, using the biz service become way easier.

# with connect, the routing is resolved by sidecar

# request com.example.test.PingService.ping()
curl -X POST http://service.service.consul/api/service/com.example.test.PingService/ping

# request com.example.user.UserService.list()
curl -X POST http://service.service.consul/api/service/com.example.user.UserService/list

I don't expect linkerd support the service register, I hope linkerd support the routing function.Maybe something like this

kind: VirtualServiceProfile
apiVersion: linkerd.io/v1alpha1
metadata:
  # how to access the virtual service
  name: service.default.svc.cluster.local
  namespace: default
spec:
  routes:
    - condition:
        pathRegex: /api/service/com.example.test.PingService
      destination: pinging.default.svc.cluster.local
    - condition:
        pathRegex: /api/service/com.example.user.UserService
      destination: user-v1.default.svc.cluster.local

really hope linkerd support better routing.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

geekmush picture geekmush  路  4Comments

klingerf picture klingerf  路  3Comments

manimaul picture manimaul  路  3Comments

alpeb picture alpeb  路  3Comments

vikas027 picture vikas027  路  4Comments