Skip to content

Commit

Permalink
HTTPRoute: allow more match clauses (#3205)
Browse files Browse the repository at this point in the history
* HTTPRoute: allow more match clauses

Today, a route is limited to 16 routes with 8 matches each. This is
problematic in real world environments.

While its easy to split a route up (you can easily get the same
behavior, and similar cognitive complexity by having 1 route per
HTTPRoute), its quite hard to split up matches. For instance,
https://github.com/istio/istio/blob/d7a9700d5eaa4e9728274b408623670f48deadb5/samples/bookinfo/gateway-api/bookinfo-gateway.yaml#L23-L38
is an example of a route matching the exposed APIs for a frontend. This
is only a small tivial example, and it already uses 5. In our user
base, we often see far beyond 8.

Splitting these up is both complex for the user, and may actually lead
to different behaviors if implementations treat route groups differently
(for instance, if we add retry budget -- that could now be split; other
core or implementation specific policies may behave similarly, this is
just an example).

The limit on 8 here seems quite small given the context of real usage,
the other limits in the API (16 routes, 64 listeners), and the cost of
manually working around it. Based on this, I propose we raise the limit
to match Gateway listeners.

* Limit aggregate size

* Drop to 128 and add tests

* hacky

* Unroll the loop

* gRPCRoute and update comment

* Fix grpcroute
  • Loading branch information
howardjohn committed Jul 29, 2024
1 parent dbf5a17 commit 397f8c9
Show file tree
Hide file tree
Showing 7 changed files with 193 additions and 5 deletions.
1 change: 1 addition & 0 deletions apis/v1/grpcroute_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ type GRPCRouteSpec struct {
//
// +optional
// +kubebuilder:validation:MaxItems=16
// +kubebuilder:validation:XValidation:message="While 16 rules and 64 matches per rule are allowed, the total number of matches across all rules in a route must be less than 128",rule="(self.size() > 0 ? (has(self[0].matches) ? self[0].matches.size() : 0) : 0) + (self.size() > 1 ? (has(self[1].matches) ? self[1].matches.size() : 0) : 0) + (self.size() > 2 ? (has(self[2].matches) ? self[2].matches.size() : 0) : 0) + (self.size() > 3 ? (has(self[3].matches) ? self[3].matches.size() : 0) : 0) + (self.size() > 4 ? (has(self[4].matches) ? self[4].matches.size() : 0) : 0) + (self.size() > 5 ? (has(self[5].matches) ? self[5].matches.size() : 0) : 0) + (self.size() > 6 ? (has(self[6].matches) ? self[6].matches.size() : 0) : 0) + (self.size() > 7 ? (has(self[7].matches) ? self[7].matches.size() : 0) : 0) + (self.size() > 8 ? (has(self[8].matches) ? self[8].matches.size() : 0) : 0) + (self.size() > 9 ? (has(self[9].matches) ? self[9].matches.size() : 0) : 0) + (self.size() > 10 ? (has(self[10].matches) ? self[10].matches.size() : 0) : 0) + (self.size() > 11 ? (has(self[11].matches) ? self[11].matches.size() : 0) : 0) + (self.size() > 12 ? (has(self[12].matches) ? self[12].matches.size() : 0) : 0) + (self.size() > 13 ? (has(self[13].matches) ? self[13].matches.size() : 0) : 0) + (self.size() > 14 ? (has(self[14].matches) ? self[14].matches.size() : 0) : 0) + (self.size() > 15 ? (has(self[15].matches) ? self[15].matches.size() : 0) : 0) <= 128"
Rules []GRPCRouteRule `json:"rules,omitempty"`
}

Expand Down
3 changes: 2 additions & 1 deletion apis/v1/httproute_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ type HTTPRouteSpec struct {
// +optional
// +kubebuilder:validation:MaxItems=16
// +kubebuilder:default={{matches: {{path: {type: "PathPrefix", value: "/"}}}}}
// +kubebuilder:validation:XValidation:message="While 16 rules and 64 matches per rule are allowed, the total number of matches across all rules in a route must be less than 128",rule="(self.size() > 0 ? self[0].matches.size() : 0) + (self.size() > 1 ? self[1].matches.size() : 0) + (self.size() > 2 ? self[2].matches.size() : 0) + (self.size() > 3 ? self[3].matches.size() : 0) + (self.size() > 4 ? self[4].matches.size() : 0) + (self.size() > 5 ? self[5].matches.size() : 0) + (self.size() > 6 ? self[6].matches.size() : 0) + (self.size() > 7 ? self[7].matches.size() : 0) + (self.size() > 8 ? self[8].matches.size() : 0) + (self.size() > 9 ? self[9].matches.size() : 0) + (self.size() > 10 ? self[10].matches.size() : 0) + (self.size() > 11 ? self[11].matches.size() : 0) + (self.size() > 12 ? self[12].matches.size() : 0) + (self.size() > 13 ? self[13].matches.size() : 0) + (self.size() > 14 ? self[14].matches.size() : 0) + (self.size() > 15 ? self[15].matches.size() : 0) <= 128"
Rules []HTTPRouteRule `json:"rules,omitempty"`
}

Expand Down Expand Up @@ -190,7 +191,7 @@ type HTTPRouteRule struct {
// parent a request is coming from, a HTTP 404 status code MUST be returned.
//
// +optional
// +kubebuilder:validation:MaxItems=8
// +kubebuilder:validation:MaxItems=64
// +kubebuilder:default={{path:{ type: "PathPrefix", value: "/"}}}
Matches []HTTPRouteMatch `json:"matches,omitempty"`

Expand Down
42 changes: 42 additions & 0 deletions config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 32 additions & 2 deletions config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 42 additions & 0 deletions config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 32 additions & 2 deletions config/crd/standard/gateway.networking.k8s.io_httproutes.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 397f8c9

Please sign in to comment.