gloo icon indicating copy to clipboard operation
gloo copied to clipboard

Support RouteTable delegation where the RT path is more general than the parent VS Route path

Open bdecoste opened this issue 1 year ago • 8 comments

Is your feature request related to a problem? Please describe.

I would like to have 1 RouteTable owned by each application team. This RT would be delegated from multiple VirtualServices where each VS would map to a single domain. The paths for the RT will vary depending on the domain. The RT paths may be more general than the VS route delegateAction path. For example:

VS1 domain: foo.com path: / name: slash

VS2 domains: bar.com path /bar name: bar

Shared RT: path: / name: slash

path:/bar name: bar

However, this results in invalid route: route table matchers must begin with the prefix of their parent route's matcher

Describe the solution you'd like

Allow RTs to have more general paths than the parent VS

Describe alternatives you've considered

Multiple RTs or use VSs only

┆Issue is synchronized with this Asana task by Unito

bdecoste avatar Apr 24 '23 22:04 bdecoste

Firming up the desired design ...

The relaxed validation would require that the route(s) in the VS(s) and RT(s) 1) would be named and 2) that the parent and child names and paths would need to match to be valid. This would not require any changes to the CRDs.

With the attached sample config envoy would be configured with 2 routes: foo.com/user/inbox bar.com/

config.tar.gz

bdecoste avatar Apr 25 '23 17:04 bdecoste

@bdecoste can we either here or in slack write up some user stories around this. While the ask is not crazy before we tackle the relaxation there might be some other implementation details that really wont be done correctly if we dont understand the different ways that we are intending to interact with this.

nfuden avatar May 01 '23 12:05 nfuden

route tables can select other route tables. how would this design prevent cycles?

perhaps we can allow child route tables to have many matches, and if any work then we generate the appropriate route. this way there can be several parents with different parent routes, and still only one route defined on one route table.

kdorosh avatar May 10 '23 17:05 kdorosh

The key to the suggested config change is only match the VS parent routes with the RT child routes that have the same name. Then you never get a more general child matcher

bdecoste avatar May 10 '23 17:05 bdecoste

I have another customer that could be interested in this (legacy purpose). They would like to be able to handle /api/v1 and /v1 by the same RT (and strip the /api at the same time when it exists). Using regex or multiple prefix is not working with delegated RT as expressed here. Their workaround for now is to have a vanilla envoy in front of GE gateway to be able to strip the /api before getting to the gateway so the routing can be done by an unique route (on /v1). The only workaround without 3rd part would be to avoid the use of RT but with very large routing configuration this solution is not confortable.

Here is an example of what could answer their problematic (alternative to multiple prefix could be regex matchers on ^(/api)?/v1/.* and ^(/api)?/v2/.*, but the customer is used to prefix, more generally regex would be more flexible but less efficient) :

apiVersion: gateway.solo.io/v1
kind: VirtualService
metadata:
  name: vs-ssl
  namespace: gloo-system
spec:
  virtualHost:
    domains:
    - '*'
    routes:
    - matchers:
      - prefix: /api/v1
      - prefix: /v1
      options:
        regexRewrite:
          pattern:
            regex: ^/api
          substitution: ""
      delegateAction:
        ref:
          name: 'v1-routes'
          namespace: 'gloo-system'
    - matchers:
      - prefix: /api/v2
      - prefix: /v2
      options:
        regexRewrite:
          pattern:
            regex: ^/api
          substitution: ""
      delegateAction:
        ref:
          name: 'v2-routes'
          namespace: 'gloo-system'
  sslConfig:
    secretRef:
      name: upstream-tls
      namespace: gloo-system

And delegated RT :

apiVersion: gateway.solo.io/v1
kind: RouteTable
metadata:
  name: 'v1-routes'
  namespace: 'gloo-system'
spec:
  routes:
    - matchers:
      - prefix: '/v1'
      routeAction:
        single:
          upstream:
            name: httpbin-httpbin-8000
            namespace: gloo-system
apiVersion: gateway.solo.io/v1
kind: RouteTable
metadata:
  name: 'v2-routes'
  namespace: 'gloo-system'
spec:
  routes:
    - matchers:
      - prefix: '/v2'
      routeAction:
        single:
          upstream:
            name: httpbin-httpbin-8000
            namespace: gloo-system

Ati59 avatar May 23 '23 12:05 Ati59

@sam-heilbron to look at this issue for scope/estimation.

nrjpoddar avatar Jul 02 '24 19:07 nrjpoddar

One thing we should make sure is that we don't allow child-routes to expose apps/services on paths that are not defined in the parent route. I.e, when we expose the following on the VS:

domain: api.example.com
- matchers:
  - prefix: /foo

And the following on the child:

- matchers:
  - prefix: /foo
     ......
  - prefix: /bar
    .......

we should only create a route for /foo on the given VS for api.example.com. If we would also create a route for /bar, we would give teams owning the child rt to expose routes on the GW that team that owns the parent is not aware of.

DuncanDoyle avatar Jul 22 '24 17:07 DuncanDoyle

Repository with an example how this can be implement with Gloo Gateway 1.17 and the K8S Gateway API: https://github.com/DuncanDoyle/gg-8134

So this requirement can already be implemented with the relative/inheritable path matchers in the K8S Gateway API. The "classic" Gloo Edge API does not (yet) support this.

DuncanDoyle avatar Oct 11 '24 14:10 DuncanDoyle