-
Notifications
You must be signed in to change notification settings - Fork 335
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Traffic Route L7 proposal #2013
Conversation
Signed-off-by: Jakub Dyszkiewicz <jakub.dyszkiewicz@gmail.com>
kuma.io/service: '*' | ||
conf: | ||
http: | ||
- match: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need this match
object?
L7 traffic route finally gives an ability to define more
|
A few comments:
conf:
http:
headers:
canary: "^true$"
method: "GET"
destination:
kuma.io/service: backend
version: "1.1" and conf:
http:
headers:
canary: "^true$"
method: "GET"
split:
- weight: 0.5
destination:
kuma.io/service: backend
version: "1.1"
- weight: 0.5
destination:
kuma.io/service: backend
version: "2.1"
conf:
- http:
headers:
canary: "^true$"
method: "GET"
split:
- weight: 0.5
destination:
kuma.io/service: backend
version: "1.1"
- weight: 0.5
destination:
kuma.io/service: backend
version: "2.1"
- destination:
kuma.io/service: backend
version: "0.1" Thoughts? |
1 + 2 I like the idea. So there is either destination or split, right? Should we also expand this on L4? So the default policy is
X. I think |
For http, the destinations are chosen by certain condition. For example So the initial 'destinations' seems extra for http workload and can be ignored. destinations:
Later point in time you may also have to extend them with timeouts, retry, rate limit, auth etc. |
Thanks for the feedback @sudeeptoroy
do you mean top level? I don't think we can get rid of this. How would you then apply L4 rules? What about
I'd very much like to keep this in a separate policy like we do this right now. |
In this case, do we even need
@subnetmarco that's why I'd like to have |
I can see why getting rid of top level destinations is tough as all the other spec is based on source and destination pair. For TCP traffic, it makes a lot of sense - one to one. However http has one to many relation, depending on match criteria. I find the present spec a bit confusing, select a top source and destination and later select another destination using matching rules. May be you should introduce a 'selector' as you have for Proxytemplate? ex:
finer policies like per route retry will need many attributes creation. what does * signify in case of http? in what scenario you would want a * for source.
|
@sudeeptoroy in your example: selectors:
- match:
kuma.io/service: 'web' is essentially: sources:
- match:
kuma.io/service: 'web'
destinations:
- match:
kuma.io/service: '*' Making things explicit has been usually reduced the risk of errors, from our experience. Is the goal that you are trying to achieve a less verbose syntax? |
conf:
loadBalancer:
roundRobin: {}
http:
headers:
canary: "^true$"
method: "GET"
split:
- weight: 0.5
destination:
kuma.io/service: backend
version: "1.1"
- weight: 0.5
destination:
kuma.io/service: backend
version: "2.1"
destination:
kuma.io/service: backend
version: "0.1" Basically, the final catch-all implements suggestion (1) and turns into the above. If they do want to split, then it becomes: conf:
loadBalancer:
roundRobin: {}
http:
headers:
canary: "^true$"
method: "GET"
split:
- weight: 0.5
destination:
kuma.io/service: backend
version: "1.1"
- weight: 0.5
destination:
kuma.io/service: backend
version: "2.1"
split:
- weight: 100
destination:
kuma.io/service: backend
version: "0.1" |
More comments:
loadBalancer:
roundRobin: {}
http:
headers:
canary: "^true$"
method: "GET"
split:
- weight: 0.5
destination:
kuma.io/service: backend
version: "1.1"
- weight: 0.5
destination:
kuma.io/service: backend
version: "2.1" What happens then? Should we return
|
Hi @subnetmarco, I would suggest taking a few more opinion before concluding the top part of the spec. I find * in the destinations not explicit nor very intuitive. |
@sudeeptoroy perhaps there are two different topics:
So I think that we can still implement the L7 functionality while at the same time open up a conversation to support both |
@subnetmarco thank-you for the explanation. Kindly relook at this when you feel it's appropriate. |
That's a good point about "catch-all". I checked that Envoy returns 404 if it cannot find a route. I think we should stick to this behavior ProtocolsI don't think it is a good idea to add validation on An example. Let's say we've got header modification in place (discussed in the comments above). We have a default policy but with modified
now, if we want to add a capability to remove headers we can do this
If we had validation that in order to use This will also be "symmetric" with Healthcheck that has two sections in one policy. Additionally, this will be difficult to implement since we only allow |
I agree with @jakubdyszkiewicz that "match" section inside "http" looks kinda easier to read and understand what's going on |
Okay for (1) and (2). For (3) I suggest that we show both This in addition to the other comments that we agreed on. |
Signed-off-by: Jakub Dyszkiewicz <jakub.dyszkiewicz@gmail.com>
Updated the proposal with discussed changes |
With this example
With your example, does it mean that
You raised good point that the policy is getting more complicated, but keep in mind that we are trying to support many different use-cases. |
Hi @jakubdyszkiewicz, I mean (1) |
path: # one of either prefix, exact or regex will be allowed | ||
prefix: /users | ||
exact: /users/user-1 | ||
regex: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest a match-type field:
path:
type: exact
value: /users/
This is consistent with Kubernetes API conventions and allows valid match types to be automatically validated by API annotations. It also makes validation check unambigious.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However, there is a feature of protobuf called "oneof" and providing a couple of options and picking one of them is a convention of Envoy. We use this already in many places. Even loadBalancer
in TrafficRoute
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Were they also migrating from "oneof" convention?
Validation on API annotations? I don't think I'm familiar with this, can you tell me more? We have our own unified validators for both Kubernetes and Universal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The kubernetes CRD generator support validation that will propagate checks into the openapi spec (see kubebuilder docs).
I'm confide about the protobuf reference. Is this a protobuf API? If so, shouldn't it be in proto3 rather than in yaml?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kuma API is described in protobuf and then translated between JSON / YAML (but also sent between control planes in multizone deployment as serialized protobuf). In proposals, we tend to use YAML examples so it's easier to read, but you might be right that maybe we should also include proto schemas.
Protobuf also has a builtin validation functionality but we found this to not be flexible enough (descriptive messages) for our needs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see. I'd probably design a YAML-oriented API differently than a protobuf-oriented API :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW, Kubernetes CRD validation doesn't support unions, or one-of. There are generator annotations for it, but they don't do anything 😂
some-header: # one of either prefix, exact or regex will be allowed | ||
exact: some-value | ||
prefix: some- | ||
regex |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gateway API just moved away from this pattern, to a style that is more consistent with Kubernetes API guidelines:
headers:
- name: some-header
value: some-value
matchType: exact
Similar reasons as for path matches. This structure is also consistent with the structure you have in the modify section.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's the kubernetes rationale for avoiding maps, https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#lists-of-named-subobjects-preferred-over-maps
|
||
## Protocol | ||
|
||
If we have `http` section, it will be only applied on HTTP traffic. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assume that "HTTP" in this context means, http, https, http/2 and so on?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https
yes, but only when mTLS is provided by Kuma. Otherwise, we cannot decrypt the traffic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok you confused me with mtls :) why is mtls required here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Imagine there is a client and server with sidecars
A <-> A's sidecar <-> B's sidecar <-> B
If A itself does not encrypt the traffic then even with mTLS A's sidecar can redirect the traffic because it can read the request metadata (it happens before encrypting the traffic)
However, if A encrypts the traffic with TLS itself (for example old service when migrating to mesh), then A's sidecar cannot decrypt the traffic and we cannot route it by matching path, headers, etc.
Signed-off-by: Jakub Dyszkiewicz <jakub.dyszkiewicz@gmail.com>
Proposal on how we can introduce L7 HTTP routing to Kuma.