Overview

You learned about how to organize routes into delegated route tables and manage those route tables with labels. Now, consider how routes are impacted by workspaces and policies, and then review basic, delegated, and advanced scenarios.

Workspaces

You can implement multi-tenancy for your teams by organizing the Kubernetes, Gloo, and other custom resources for each team into Gloo workspaces.

Workspaces can share resources with other workspaces by setting up mutual import and export rules. These resources include route tables and their backing destinations, such as Kubernetes services or Gloo virtual destinations. For more information, see the Concept docs about import and export.

In general, Gloo workspaces are set up to give you control of your microservices. When it comes to sharing policies across workspaces, policies generally still apply the rules of the source workspace to routes, destinations, or workspaces, even when those resources are shared across workspaces.

For a parent route table to forward requests to a delegated route in a different workspace:

  • The parent’s workspace must export ROUTE_TABLE to all of its descendants’ workspaces. This includes when the parent has multiple level of descendants, such as child and grandchild route tables.
  • All descendent workspaces must import the ROUTE_TABLE from the parent workspace.
  • The parent’s workspace can optionally import back the ROUTE_TABLE of any children workspaces. For example, the parent workspace might be for the host domain’s ingress gateway and the children workspaces are for apps at specific paths along the host domain. This way, the parent gateway workspace gets the translated Istio VirtualDestination and can set up routing rules to the apps.
  • To route to a destination, the parent workspace must have the destination in its workspace. If not, the parent must import the destination, such as SERVICE or VIRTUAL_DESTINATION from the child workspace (and the child must export the destination to the parent). The reason is that, without importing the route tables and backing resources, the source workspace has nothing to delegate the routes to.

If these import and export rules are not met, the route is considered invalid. The route table status has an error message, and users get back a direct response error.

Policies

You can manage and protect traffic along your routes by applying Gloo policies.

Typically, you apply policies through label selectors. The advantage of labels is that you can apply policies to many routes at once. On the other hand, such bulk selection can also make it harder for you to keep track of which policies are applied to the routes.

For example, you might apply a val:foo label at the table-level. Then, the routes within the table get this label. Also, any delegated routes in a sub-table inherit this label from the parent route table. As such, policies in a different namespace and workspace might apply to your route. However, you might not have visibility into that source namespace and workspace which can make troubleshooting routing issues more difficult. Policies can also cause seemingly conflicting behavior. You might know of an external auth policy that selects your route and enforces authentication via the configured method. However, if a JWT policy also selects the route, you might also need a valid JWT before getting access to the app along the route.

In case of conflicting policies, the oldest policy by creationTimestamp takes precedence. Other policies might get created but do not apply and have a warning on their status.

Basic routing scenarios

Review the following scenarios that show how route- and table-level labels work, including in cases of conflicting values.

  1. Policy selects route by label
  2. Policy applies to many routes with table labels
  3. Conflicting route and table labels

Basic scenario 1: Policy selects route by label

Policies can select routes by label.

Basic scenario 1: Policy selects route by label
Figure: Basic scenario 1: Policy selects route by label
Basic scenario 1: Policy selects route by label
Figure: Basic scenario 1: Policy selects route by label

Two policies exist that apply to routes with either the label val:foo or val:bar. The route table has a Route A with the val:foo label.

Route A ends up with the following labels and policies:

  • Label val:foo, specified on the route
  • Policy 1 applied to routes with label val:foo

Back to scenarios

Basic scenario 2: Policy applies to many routes with table labels

With table labels, you can apply the same policy to many routes at once.

Basic scenario 2: Apply policy to many routes with table labels
Figure: Basic scenario 2: Apply policy to many routes with table labels
Basic scenario 2: Apply policy to many routes with table labels
Figure: Basic scenario 2: Apply policy to many routes with table labels

Two policies apply to routes with either the label val:foo or val:bar. The route table has the env:prod label. Route A has the val:foo label. Route B does not have route-specific labels.

Route A ends up with the following labels and policies:

  • env:prod, inherited from the table
  • val:foo, specified on the route
  • Policy 1 applied to routes with the val:foo label
  • Policy 2 applied to routes with the env:prod label

Route B ends up with the following labels and policies:

  • env:prod, inherited from the table
  • Policy 2 applied to routes with the env:prod label

Back to scenarios

Basic scenario 3: Conflicting route and table labels

Remember that in case of conflict, the route label overwrites any table labels.

Basic scenario 3: Conflicting route and table labels
Figure: Basic scenario 3: Conflicting route and table labels
Basic scenario 3: Conflicting route and table labels
Figure: Basic scenario 3: Conflicting route and table labels

Three policies apply to routes with different labels. The route table has the env:prod and val:bar labels. Route A has the val:foo label. Route B does not have route-specific labels.

Route A ends up with the following labels and policies:

  • env:prod, inherited from the table
  • val:foo, specified on the route, which overwrites the val:bar table label
  • Policy 1 applied to routes with the val:foo label
  • Policy 2 applied to routes with the env:prod label

Route B ends up with the following labels and policies:

  • env:prod, inherited from the table
  • val:bar, inherited from the table
  • Policy 2 applied to routes with the env:prod label
  • Policy 3 applied to routes with the val:bar label

Back to scenarios

Delegated routing across workspaces

Review the following scenarios that show how label inheritance and policy attachment work with delegated routes. In general, the precedence of labels and policies are the same, but the parent-child relationship can be harder to figure out than in non-delegated, basic scenarios.

  1. Label inheritance
  2. Multiple policies
  3. Conflicting labels
  4. Workspace boundaries prevent child policy attachment

Delegated scenario 1: Label inheritance

Delegated routes inherit labels similarly to non-delegated routes, as described in the Route label inheritance concept. Policies are applied based on the labels that the route ends up with. Child routes even get policies from the parent workspace, as long as workspace import and export rules are set up correctly.

Delegated scenario 1: Label inheritance
Figure: Delegated scenario 1: Label inheritance
Delegated scenario 1: Label inheritance
Figure: Delegated scenario 1: Label inheritance

One policy applies to routes with the val:foo label. The parent route has the val:foo label. The route is delegated to a child route table that has neither table nor route labels.

Delegated route A ends up with the following labels and policies:

  • Label val:foo, inherited from the parent route
  • Policy 1 applied to routes with label val:foo

Back to scenarios

Delegated scenario 2: Multiple policies

As you saw in the previous example, policies in parent workspaces might get applied to delegated routes that exist in other workspaces. Policies in the child workspace can also apply to the routes.

In case of conflicting policies, the oldest policy by creationTimestamp takes precedence. Other policies might get created but do not apply and have a warning on their status.

Delegated scenario 2: Multiple policies
Figure: Delegated scenario 2: Multiple policies
Delegated scenario 2: Multiple policies
Figure: Delegated scenario 2: Multiple policies

Policies that select routes with the val:foo label are in both workspaces. The parent route has the val:foo label. The route is delegated to a child route table that has neither table nor route labels.

Delegated route A ends up with the following labels and policies:

  • Label val:foo, specified on the route
  • Policy 1 applied to routes with label val:foo
  • Policy 2 applied to routes with label val:foo

Back to scenarios

Delegated scenario 3: Conflicting labels

Sometimes, it can be tricky to figure out which policies apply when you have many policies, delegated routes, and labels at both table- and route-levels. As you consider the following scenario, keep in mind the precedence of delegated label inheritance that you learned about in the Route label inheritance concept.

Delegated scenario 3: Conflicting labels
Figure: Delegated scenario 3: Conflicting labels
Delegated scenario 3: Conflicting labels
Figure: Delegated scenario 3: Conflicting labels

Policies that select routes with the val:foo label are in both workspaces, and a policy that selects val:bar is in the target workspace. The parent route has the val:foo route label. The route is delegated to a child route table that has a val:bar table label.

The val:foo policy in the parent workspace does not apply, because the child route table has a val:bar table label that takes precedence. For more information, see the Route label inheritance concept.

Delegated route A ends up with the following labels and policies:

  • Label val:bar, specified on the child table, which overwrites the inherited val:foo parent route label
  • Policy 3 applied to routes with label val:bar

Back to scenarios

Delegated scenario 4: Workspace boundaries prevent child policy attachment

Workspace boundaries are another factor in determining which policies apply to routes. In previous examples, you saw that a policy in a parent workspace can apply to the final route in the child workspace. However, the reverse is not always true, as the following scenario demonstrates.

Delegated scenario 4: Workspace boundaries prevent child policy attachment
Figure: Delegated scenario 4: Workspace boundaries prevent child policy attachment
Delegated scenario 4: Workspace boundaries prevent child policy attachment
Figure: Delegated scenario 4: Workspace boundaries prevent child policy attachment

Policies that select routes with the val:foo label are in both workspaces. The parent route table has two routes and the val:foo table label. Route A is delegated to a child route table in a different workspace. Route B is not delegated.

Because you have mutual import and export rules, you might be tempted to think that both workspaces’ policies apply to routes with the matching labels. However, policies themselves are not shareable resources, but only as attached to an imported route. Because Route B is not imported, policies from other workspaces are not applied.

Delegated route A ends up with the following labels and policies:

  • Label val:foo, inherited from the parent table
  • Policy 1 from the parent workspace, applied to routes with label val:foo
  • Policy 2 from the child workspace, applied to routes with label val:foo

Route B ends up with the following labels and policies:

  • Label val:foo, inherited from the parent table
  • Policy 1 from the same parent workspace, applied to routes with label val:foo

Back to scenarios

Advanced delegation scenarios

Review the following scenarios that show more advanced considerations for delegation. In general, the precedence of labels and policies are the same, but the relationships for these corner cases can be harder to figure out than in non-delegated, basic scenarios.

  1. Imported routes
  2. Multiple workspaces
  3. Multi-level delegation (parent-child-grandchild)
  4. Workload selectors

Advanced scenario 1: Imported routes

Building off the workspace boundaries scenario, let’s consider how this scenario changes when Route B is imported to the child workspace. Imported routes still get policies from the parent workspace, but the policies from the child workspace do not apply.

Advanced scenario 1: Imported routes
Figure: Advanced scenario 1: Imported routes
Advanced scenario 1: Imported routes
Figure: Advanced scenario 1: Imported routes

Policies that select routes with the val:foo label are in both workspaces. The parent route table has two routes and the val:foo table label. Route A is delegated to a child route table in a different workspace. Route B is not delegated, but is imported by the child workspace.

Delegated route A ends up with the following labels and policies:

  • Label val:foo, inherited from the parent table
  • Policy 1 from the parent workspace, applied to routes with label val:foo
  • Policy 2 from the child workspace, applied to routes with label val:foo

Imported route B ends up with the following labels and policies:

  • Label val:foo, inherited from the parent table
  • Policy 1 from the parent workspace, applied to routes with label val:foo

Note that if Route B were delegated to the child route table, and not just imported, then both the source and target workspaces’ policies would apply, similar to Route A.

Back to scenarios

Advanced scenario 2: Multiple workspaces

The previous scenarios consider a simple workspace scenario of two workspaces only. But what if you have many workspaces? In general, the same principles of workspace boundaries and label inheritance apply.

Advanced scenario 2: Multiple workspaces
Figure: Advanced scenario 2: Multiple workspaces
Advanced scenario 2: Multiple workspaces
Figure: Advanced scenario 2: Multiple workspaces

The environment has three workspaces, a Source workspace and two Target A and Target B workspaces. Each workspace has its own policy. The parent route table in the Source workspace has three routes and the val:foo table label. Route A is delegated to a child route table in Target A workspace. Route B is delegated to a child route table in Target B workspace. Route B’s child route table has a table label that conflicts with the inherited parent table label. Route C is not delegated and stays in the Source workspace.

Delegated route A ends up with the following labels and policies:

  • Label val:foo, inherited from the parent table
  • Policy 1 from the parent Source workspace, applied to routes with label val:foo
  • Policy 2 from the child Target A workspace, applied to routes with label val:foo

Route B ends up with the following labels and policies:

  • Label val:bar, specified on the child table, which overwrites the inherited val:foo label
  • Policy 3 from the child Target B workspace, applied to routes with label val:bar

Route C ends up with the following labels and policies:

  • Label val:foo, specified on the parent table
  • Policy 1 from the parent Source workspace, applied to routes with label val:foo

Back to scenarios

Advanced scenario 3: Multi-level delegation (parent-child-grandchild)

The previous scenarios consider a parent-child relationship for delegation. But what if you delegate a route to one sub-table, only to delegate the route again in that sub-table to another sub-table? In general, the same principles of workspace boundaries and label inheritance apply.

Advanced scenario 3: Multi-level delegation (parent-child-grandchild)
Figure: Advanced scenario 3: Multi-level delegation (parent-child-grandchild)
Advanced scenario 3: Multi-level delegation (parent-child-grandchild)
Figure: Advanced scenario 3: Multi-level delegation (parent-child-grandchild)

Source workspace: The parent route table has two routes and the val:foo table label. Route A is delegated to a child route table in Sub Target 1 workspace. Route B is not delegated. The workspace has a policy that applies to routes with the val:foo label.

Sub Target 1 workspace: The child route table also has the val:foo table label and delegates Route A to another grandchild route table in Sub Target 2 workspace. The child route table has another route, Route C, which is not delegated. The workspace has a policy that applies to routes with the val:foo label.

Sub Target 2 workspace: The grandchild route table has no table labels, and does not delegate Route A anymore. The grandchild route table has another route, Route D, which is not delegated and has a val:bar label. The workspace has a policy that applies to routes with the val:bar label.

Delegated route A ends up with the following labels and policies:

  • Label val:foo, inherited from the parent table and not overwritten by any subsequent sub-tables
  • Policy 1 from the parent Source workspace, applied to routes with label val:foo
  • Policy 2 from the child Sub Target 1 workspace, applied to routes with label val:foo. Note that this policy gets attached because the route was first delegated to the child route table in Sub Target 1. If the parent table delegated the route directly to the grandchild route table in Sub Target 2, Policy 2 from Sub Target 1 would not apply.

Route B ends up with the following labels and policies:

  • Label val:foo, specified on the parent table
  • Policy 1 from the same Source workspace, applied to routes with label val:foo

Route C ends up with the following labels and policies:

  • Label val:foo, specified on the child table
  • Policy 1, inherited from the parent Source workspace, applied to routes with the label val:foo. Note that this policy applies because Route C is in a route table that the parent route table delegates to. If Route C were in a different route table that did not have a parent route table in the Source workspace, then policies from the Source workspace would not apply.
  • Policy 2 from the same Sub Target 1 workspace, applied to routes with label val:foo.

Route D ends up with the following labels and policies:

  • Label val:bar, specified on the grandchild route
  • Policy 3 from the same Sub Target 2 workspace, applied to routes with the label val:bar.

Back to scenarios

Advanced scenario 4: Workload selectors

You can use workload selectors to restrict traffic routing along the host and path to the selected backing workloads. With delegation, each child route table can select its own workloads. This way, you can apply custom policies to select workloads, such as retries that are unique per zone. For more information, see Gateways to route traffic.

Advanced scenario 4: Workload selectors
Advanced scenario 4: Workload selectors
Advanced scenario 4: Workload selectors
Advanced scenario 4: Workload selectors

In Source workspace:

  • The parent route table delegates Route A to two child route tables, as well as configures a default Route A.
  • A default Policy 1 applies to routes with the default label.

In Target A workspace:

  • The child route table has a label and workload selector for its region, us-east.
  • Route A matches requests with the region:us-east header.
  • Policy 2 applies to routes with the us-east label.

In Target B workspace:

  • The child route table has a label and workload selector for its region, apac.
  • Route A matches requests with the region:apac header.
  • Policy 3 applies to routes with the apac label.

Requests to Route A are processed as follows:

  • With the region:us-east header, the request gets Policy 1 and 2 applied. The request is fulfilled only by workloads with the us-east label.
  • With the region:apac header, the request gets Policy 1 and 3 applied. The request is fulfilled only by workloads with the apac label.
  • For requests to the route without those headers, the request gets Policy 1 applied. The request can be fulfilled by any workload, because the parent route table does not specify a workload selector.
  # Example of workload selector inheritance
# Parent table with two matchers
apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: parent
  namespace: source-apps
  labels:
    # Default label for applying policies
    policy: default
spec:
  hosts:
    - www.example.com
  # Select all workloads by default. Child route tables can specify their own workloads.
  workloadSelectors:
  - {}
  virtualGateways:
    - name: istio-ingressgateway
      namespace: gloo-mesh-gateways
  http:
    - name: route-a
      # Match requests along the path `www.example.com/route-a`
      matchers:
      - uri:
          prefix: /route-a
          ignoreCase: true
      # Delegate requests that match this path to child-tracks
      delegate:
        routeTables:
        - labels:
            table: child-a-overrides
    - name: route-a
      # Also matches requests along the path `www.example.com/route-a` as a default route
      matchers:
      - uri:
          prefix: /route-a
          ignoreCase: true
      # Forward to a default app
      forwardTo:
        destinations:
        - ref:
            name: default-a
            namespace: source-apps
          port:
            number: 8080
          kind: VIRTUAL_DESTINATION
---
# Child 1 route table for US East
apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: child-1-us-east
  namespace: target-a-apps
  labels:
    # Matches label in parent route table to for delegation
    table: child-a-overrides
    # Label for applying policies
    policy: us-east
spec:
  # Restricts matching traffic to workloads with the label 'region: us-east'
  workloadSelectors:
  - selector:
      labels:
        region: us-east
  http:
  # Table routes matching requests along the path `www.example.com/route-a` with a us-east header
  - name: route-a
    matchers:
    - headers:
      - name: region
        value: us-east
    forwardTo:
      destinations:
      - ref:
          name: default-a
          namespace: target-a-apps
        port:
          number: 8080
        kind: VIRTUAL_DESTINATION
---
# Child 2 route table for APAC
apiVersion: networking.gloo.solo.io/v2
kind: RouteTable
metadata:
  name: child-2-apac
  namespace: target-b-apps
  labels:
    # Matches label in parent route table to for delegation
    table: child-a-overrides
    # Label for applying policies
    policy: apac
spec:
  # Restricts matching traffic to workloads with the label 'region: apac'
  workloadSelectors:
  - selector:
      labels:
        region: apac
  http:
  # Table routes matching requests along the path `www.example.com/route-a` with an apac header
  - name: route-a
    matchers:
    - headers:
      - name: region
        value: apac
    forwardTo:
      destinations:
      - ref:
          name: default-a
          namespace: target-b-apps
        port:
          number: 8080
        kind: VIRTUAL_DESTINATION
  

Back to scenarios

Next steps

Now that you are done learning about route table delegation, try it out! The following guides include examples of delegating routes.

  • Delegate requests to child route tables, including examples for sorting delegated routes by weight and specificity.
  • Deny requests to routes with the gatewayDefaultDenyAllHTTPRequests feature gate. This example makes use of label inheritance.
  • Bundle APIs into API products that you can expose in a developer portal by using delegated route tables. This example shows how route table delegation can manage routes under the same host domain. You also make use of the labels in the sub-table routes to do other things, like attach policies and expose APIs securely in a developer portal.