linkerd2
linkerd2 copied to clipboard
Header based routing
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:
- 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.)
- 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
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.
Hello, any news regarding this feature in linkerd2 since the new SMI spec in february 2020 ?
Any updates on this?
stable-2.12 will include new routing primitives that enable this. This feature is tentatively planned for 2.13.
Bases on the recent release schedule, 2.13 would roughly be a year from now. I could not find any better estimation online. Did I mess something or does the comment above really say: If you're lucky, it might be available a year from now, no promises if we'll ever make it or by when.
I'm not saying that that isn't your right, it's just that for me it means I need to adjust my planning an investigate alternatives.
@rspilker there was a long delay between 2.11 and the upcoming 2.12, but that's the exception not the norm. 2.13 should be a relatively fast follow after 2.12.
@olix0r What are those routing primitives you talked about on June 13th? Because the edge-22.8.2 is available (and can be considered as a release candidate for stable-2.12.0) and I did not find anything in the release notes about these primitives.
@cabrinoob the edge release notes typically only cover changes since the prior edge release. we're still working on putting together comprehensive release notes (and docs) for stable-2.12.0. You might refer to the raw HTTPRoute
CRD. In 2.13.0, the CRD will be updated to be closer to that in the Gateway API.
Has there been any traction here? I'm happy to help out but not familiar with the codebase.
@scirner22 Yes, we're actively working on this for the next major release. Most of the API planned at this point (basically, we're using the Gateway API HTTPRoute types that Linkerd started using in 2.12). More details should start showing up on GitHub post-Kubecon.
Any update?
Hi @prajithp13. The work to add support for this in the proxy is in progress. You can follow along with the in-flight work by watching https://github.com/linkerd/linkerd2-proxy/pulls
I'm happy to announce we're already supporting header-based routing in our latest edges, so you can give it a try now and let us know how it goes :slightly_smiling_face: Also there's a tutorial being worked on at linkerd/website#1592; feedback about that doc is welcome as well!