Introduction to request routing

Introduction to request routing

By default, traffic addressed to a destination will be routed to that destination, with load balancing provided by ztunnel or the destination’s waypoint, if one is configured. Because the waypoint proxy sees the entire request as it passes, routing decisions can be made, similar to those that can be made when traffic enters the mesh through a gateway.

For example, you can:

  • select a backend based on host, header or path fields (routing)
  • direct a percentage of traffic to a different service as part of A/B testing or a “canary” deployment (traffic splitting)
  • respond with an HTTP redirect (redirect/rewrite)
  • apply a different load balancing policy to traffic for a particular set of service instances (destination rule)

You can also configure various rules relating to resilience:

  • define timeouts and retries
  • set limits for calls to individual hosts within a service, such as the number of concurrent connections or how many times calls to this host have failed
  • mirror traffic from one destination to another

Route objects, gateways and waypoints

Routes are configured with the Gateway API.

Two main types of routes are available:

  • HTTPRoute, the most commonly used route
  • GRPCRoute, a version of HTTPRoute which supports matching on gRPC request service and/or method

A further two are in the Gateway API experimental channel, and require you to configure Istio to enable their use:

  • TCPRoute, for managing TCP traffic
  • TLSRoute, for managing TLS traffic

The same API is used to describe a route attached to a gateway, or a route for service mesh, which will be enacted by a waypoint. The primary difference is the parentRef field, which is set to the name of the gateway in a north/south use case, is set to the name of a service in an east/west use case.

Using routes for gateways

When attaching a route to a gateway (sometimes referred to as an ingress route), set the parentRefs field to the name of the Gateway resource. Note that the target Gateway needs to allow HTTPRoutes from the route’s namespace to be attached for the attachment to be successful.

Here is a sample route that connects the specified paths to the productpage service:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: bookinfo
spec:
  parentRefs:
  - name: bookinfo-gateway
  rules:
  - matches:
    - path:
        type: Exact
        value: /productpage
    - path:
        type: PathPrefix
        value: /static
    - path:
        type: Exact
        value: /login
    - path:
        type: Exact
        value: /logout
    - path:
        type: PathPrefix
        value: /api/v1/products
    backendRefs:
    - name: productpage
      port: 9080

Using routes for waypoints

Like with a gateway, a mesh route is attached to a service using the parentRefs field. However:

  • kind must be set to Service
  • group must be set to the empty string1.

Here is a sample route that takes traffic directed to the reviews service, and directs 10% of it to reviews-v2.

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: reviews
spec:
  parentRefs:
  - group: ""
    kind: Service
    name: reviews
    port: 9080
  rules:
  - backendRefs:
    - name: reviews-v1
      port: 9080
      weight: 90
    - name: reviews-v2
      port: 9080
      weight: 10

Consideration when writing routes

Be aware of some differences in how you write a HTTPRoute for use with a gateway vs. to use within the mesh:

  • As above, gateway routes are attached with a parentRef naming the gateway, and mesh routes are attached with a parentRef naming the service.
  • The hostname field has no effect in a mesh route.
  • When one or more mesh routes are attached to a service, requests that do not match at least one rule in one of the routes will be rejected. If you wish to only act on certain traffic to a service (for example, rewriting based on matching a path prefix) you probably want to pass the rest of the traffic through as before, which you can achieve by having a second rule with a backendRefs field and no matches field.

  1. This is to imply the “core” group, as opposed to the default gateway.networking.k8s.io group used when referencing Gateway objects. ↩︎