-
Notifications
You must be signed in to change notification settings - Fork 511
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
GEP 735 L4 Traffic Matching #932
GEP 735 L4 Traffic Matching #932
Conversation
Skipping CI for Draft Pull Request. |
f7f3b40
to
4f73e63
Compare
site-src/geps/gep-735.md
Outdated
// | ||
// +kubebuilder:validation:MinLength=1 | ||
// +kubebuilder:validation:MaxLength=45 | ||
Address string `json:"address"` |
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.
Can we add type? Like listener.address.
The reason is for many cases you don't want to go type out a giant IPv6 address, which is either long or dynamic. However, the controller may have higher level constructs. For example, address: my-gcp-address-with-a-name
or even address: httpbin.default.svc.cluster.local
(ie use the Cluster IP of the service)
If you know what FE80::0202:B3FF:FE1E:8329
is you probably have a name for it somewhere that is more ergonomic to reference.
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.
Just want to make sure I'm clear: are you suggesting:
a) type for IP addresses (v4, v6)
b) type for address (e.g. can include hostnames)
c) both
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.
I think the idea of a "NamedAddress" here makes sense, similar to the address type we have on Gateway. I don't think we'd need to distinguish between v4 and v6 addresses though, but don't feel too strongly about that.
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.
1462088 changes this to support both IPAddress
and NamedAddress
options, let me know your thoughts 🙇
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.
NamedAddress feels a bit like ImplementationSpecific in path match (which we got rid off).
@robscott @howardjohn Does NamedAddress by itself (without the additional context of the provider) enough 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.
That's a good point, NamedAddress is going to have a different meaning to most implementations. That's easier to solve on Gateways because each will only be implemented by a single controller. This feels similar in nature to RegEx path matching - each implementation will have a different take on it, but it means something conceptually similar.
In most cases you would not want to specify a RegEx match on a Route implemented by multiple controllers unless you knew they supported the same variation of RegEx. I think this would come with the same constraints. Although that's not ideal, I do think it's a sufficiently valuable concept to include. We likely need to document the limitations of these implementation-specific types though.
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.
@howardjohn I would like to get your feedback on this: given the contention I'm leaning towards removing the NamedAddress
for now such as to get the groundwork completed more quickly and allow for a follow up to suggest NamedAddress
or something similar as a separate iteration so that we can focus on it specifically, let me know if you have any thoughts or concerns 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.
NamedAddress feels a bit like ImplementationSpecific in path match
@hbagdi I think there's a significant difference here. One of the key problems with "ImplementationSpecific" path matching was that any given implementation may have multiple extended kinds of path matching they'd like to support, and "ImplementationSpecific" could only really support one per implementation. With NamedAddress, I think there will be at most one interpretation per implementation. We already have a "NamedAddress" concept in the API that's fairly well defined, so it's not so much a question of if we should add the concept of a "NamedAddress", but if it makes sense here.
given the contention I'm leaning towards removing the NamedAddress for now
@shaneutt my personal preference is that we leave this in place. I think it's a natural extension point and helps show the purpose of even having an address type here. Although it is something that will have a different meaning per implementation, that matches how NamedAddress already works elsewhere in the API, and seems conceptually similar to RegEx matching.
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, @hbagdi does that sound reasonable to you?
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.
Thanks for your work on this @shaneutt!
site-src/geps/gep-735.md
Outdated
// | ||
// +kubebuilder:validation:MinLength=1 | ||
// +kubebuilder:validation:MaxLength=45 | ||
Address string `json:"address"` |
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.
I think the idea of a "NamedAddress" here makes sense, similar to the address type we have on Gateway. I don't think we'd need to distinguish between v4 and v6 addresses though, but don't feel too strongly about that.
aac6a8c
to
1462088
Compare
Another useful route match type is the TLS matching (according to the SNI), is this also in the plan? |
site-src/geps/gep-735.md
Outdated
```go | ||
type AddressMatch struct { | ||
// Type of the address, either IPAddress or NamedAddress. | ||
// | ||
// If NamedAddress is used this is a custom and specific value for each | ||
// implementation to handle (and add validation for) according to their | ||
// own needs. | ||
// | ||
// For IPAddress the implementor may expect either IPv4 or IPv6. | ||
// | ||
// +optional | ||
// +kubebuilder:validation:Enum=IPAddress;NamedAddress | ||
// +kubebuilder:default=IPAddress | ||
Type *AddressType `json:"type,omitempty"` | ||
|
||
// Value of the address. The validity of the values will depend | ||
// on the type and support by the controller. | ||
// | ||
// Examples: `1.2.3.4`, `128::1`, `my-named-address`. | ||
// | ||
// +kubebuilder:validation:MinLength=1 | ||
// +kubebuilder:validation:MaxLength=253 | ||
Value string `json:"value"` | ||
} | ||
``` |
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.
Have you considered making AddressMatch
a union type, with Type
being the discriminator? Having a generic Value
field looks odd in a Kubernetes API, and it forfeits the opportunity to enforce stricter validation.
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.
I had not as I was very intentionally trying to make this similar to GatewayAddress
so that we didn't end up with two different ways of describing an address, do you have any thoughts on that?
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 can see how making AddressMatch
similar to GatewayAddress
could reduce confusion if the user wanted to specify the same IP address or named address on both the listener and an address match. On the other hand, AddressMatch
is missing Hostname
, the semantics of NamedAddress
across the two types gets a little funny, and I'm wary of making things appear alike superficially when they are fundamentally different.
Elaborating on what I mean by funny semantics, do the names that the user can specify for a NamedAddress
in the listener refer to the same set of things as the names that the user can specify for a NamedAddress
in a source match? What about for destination matches? Is this relationship (or lack thereof) entirely up to the implementation to define?
(I now kind of wish we had used a union type for GatewayAddress
, but it's probably too late to change that now without an extremely compelling need.)
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.
For better or worse, we've used the Type
and Value
pair heavily throughout the API, including path, header, and query param matching. I believe HTTPRoute filters are the only place we've used a proper union type. Although union types are common in upstream Kubernetes, I think the pattern proposed here is also quite common.
Since we're dealing with CRDs and there is not proper union support yet, we'd be stuck with adding additional webhook validation if we transitioned to a union type. My personal preference would be to continue with the proposed approach to more closely match the pattern we've used elsewhere in Gateway 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.
Using union types probably would have made sense in those other contexts (and in hindsight, it would have simplified defining support levels). It makes even more sense for AddressMatch
because we can specify OpenAPI validation to enforce that any value that the user puts in, say, the "address" field must be either an IPv4 or an IPv6 address (the following is incomplete and not tested, but this example should illustrate what I mean):
sourceAddresses:
items:
oneOf:
- properties:
address:
format: ipv4
- properties:
address:
format: ipv6
properties:
address:
type: string
type: object
type: array
Granted, CRD validation may have gaps (if I recall correctly, it admits an object definition that specifies a field that doesn't correspond to the discriminator value). However, I figure that some validation is better than none.
I think we'd need webhook validation anyway to validate that the user provided a valid regexp for the path, header, and query param matching, but regexp support is "Custom" and underspecified anyway, so it's fair to leave that up to implementors.
Using a union type is just a suggestion for enabling slightly improved validation and clarity, so I won't press it if the goal is to make AddressMatch
match GatewayAddress
.
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.
I think the problem with both using a union type and having more interesting OpenAPI validation is that neither fits well through the CRD-validation-shaped hole we have available for now.
I also think that having some more complex validation in either the webhook or an exported library (as we've discussed briefly a few times) would be beneficial.
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.
@Miciah I like your suggestion to use a union type, but I'm also aware of some of the other implications that were brought up by @robscott and @youngnick. I'm inclined to think that the use of union types are generally preferable but given the existing precedents perhaps doing that needs to be a holistic effort and not this specific PR starting some of the APIs in a different direction than the rest and starting an implementation dichotomy. I think a reasonable action and resolution for this comment may be to use what we have now for this PR and create a follow up issue that effectively states "convert everything to union types and significantly improve our CRD validation" what are your thoughts on that?
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.
@Miciah just wanted to double check this?
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.
I agree, please disregard the suggestion to use a union type as far as this PR is concerned.
Gateway API already supports that. Please take a look at TLSRoute. |
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.
I really like the shape of this, but have a couple of small things about the exact field semantics. In general, I think we should add enum fields very carefully, as they are tricky to manage, because adding values to an enum is a breaking API change (by the API guidelines).
site-src/geps/gep-735.md
Outdated
```go | ||
type AddressMatch struct { | ||
// Type of the address, either IPAddress or NamedAddress. | ||
// | ||
// If NamedAddress is used this is a custom and specific value for each | ||
// implementation to handle (and add validation for) according to their | ||
// own needs. | ||
// | ||
// For IPAddress the implementor may expect either IPv4 or IPv6. | ||
// | ||
// +optional | ||
// +kubebuilder:validation:Enum=IPAddress;NamedAddress | ||
// +kubebuilder:default=IPAddress | ||
Type *AddressType `json:"type,omitempty"` | ||
|
||
// Value of the address. The validity of the values will depend | ||
// on the type and support by the controller. | ||
// | ||
// Examples: `1.2.3.4`, `128::1`, `my-named-address`. | ||
// | ||
// +kubebuilder:validation:MinLength=1 | ||
// +kubebuilder:validation:MaxLength=253 | ||
Value string `json:"value"` | ||
} | ||
``` |
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.
I think the problem with both using a union type and having more interesting OpenAPI validation is that neither fits well through the CRD-validation-shaped hole we have available for now.
I also think that having some more complex validation in either the webhook or an exported library (as we've discussed briefly a few times) would be beneficial.
1462088
to
c25e4f6
Compare
LGTM once there is clarity on the proxy protocol. |
ef2dd76
to
3ac0601
Compare
/lgtm /hold for other reviews |
Co-authored-by: Harry <[email protected]>
Thanks! Will leave final LGTM for someone else (cc @bowei @hbagdi @jpeach @youngnick). /approve |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: robscott, shaneutt The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
/lgtm |
Indeed, given the current state this GEP's actual status is closest to being considered |
What type of PR is this?
/kind feature
/kind design
/kind gep
/kind api-change
-->
What this PR does / why we need it:
This adds traffic matching to enable more expressive routing for
TCPRoute
andUDPRoute
.Which issue(s) this PR fixes:
Fixes #735
Does this PR introduce a user-facing change?: