github.com/projectcontour/contour@v1.28.2/site/content/docs/1.27/config/request-routing.md (about)

     1  # Request Routing
     2  
     3  A HTTPProxy object must have at least one route or include defined.
     4  In this example, any requests to `multi-path.bar.com/blog` or `multi-path.bar.com/blog/*` will be routed to the Service `s2` using the prefix conditions. Requests to `multi-path.bar.com/feed` will be routed to Service `s2` using exact match condition.
     5  All other requests to the host `multi-path.bar.com` will be routed to the Service `s1`.
     6  
     7  ```yaml
     8  # httpproxy-multiple-paths.yaml
     9  apiVersion: projectcontour.io/v1
    10  kind: HTTPProxy
    11  metadata:
    12    name: multiple-paths
    13    namespace: default
    14  spec:
    15    virtualhost:
    16      fqdn: multi-path.bar.com
    17    routes:
    18      - conditions:
    19        - prefix: / # matches everything else
    20        services:
    21          - name: s1
    22            port: 80
    23      - conditions:
    24        - prefix: /blog # matches `multi-path.bar.com/blog` or `multi-path.bar.com/blog/*`
    25        services:
    26          - name: s2
    27            port: 80
    28      - conditions:
    29        - exact: /feed # matches `multi-path.bar.com/feed` only
    30        services:
    31          - name: s2
    32            port: 80
    33  ```
    34  
    35  In the following example, we match on headers and query parameters and send to different services, with a default route if those do not match.
    36  
    37  ```yaml
    38  # httpproxy-multiple-headers.yaml
    39  apiVersion: projectcontour.io/v1
    40  kind: HTTPProxy
    41  metadata:
    42    name: multiple-paths
    43    namespace: default
    44  spec:
    45    virtualhost:
    46      fqdn: multi-path.bar.com
    47    routes:
    48      - conditions:
    49        - header:
    50            name: x-os
    51            contains: ios
    52        services:
    53          - name: s1
    54            port: 80
    55      - conditions:
    56        - header:
    57            name: x-os
    58            contains: android
    59        services:
    60          - name: s2
    61            port: 80
    62      - conditions:
    63        - queryParameter:
    64            name: os
    65            exact: other
    66            ignoreCase: true
    67        services:
    68          - name: s3
    69            port: 80
    70      - services:
    71          - name: s4
    72            port: 80
    73  ```
    74  
    75  ## Conditions
    76  
    77  Each Route entry in a HTTPProxy **may** contain one or more conditions.
    78  These conditions are combined with an AND operator on the route passed to Envoy.
    79  Conditions can be either a `prefix`, `exact`, `regex`, `header` or a `queryParameter` condition. At most one of `prefix`, `exact` or `regex` can be used in one condition block.
    80  
    81  #### Prefix conditions
    82  
    83  Paths defined are matched using prefix conditions.
    84  Up to one prefix condition may be present in any condition block.
    85  
    86  Prefix conditions **must** start with a `/` if they are present.
    87  
    88  #### Exact conditions
    89  
    90  Paths defined are matched using exact conditions.
    91  Up to one exact condition may be present in any condition block. Any condition block can
    92  either have a regex condition, exact condition or prefix condition, but not multiple together. Exact conditions are
    93  only allowed in route match conditions and not in include match conditions.
    94  
    95  Exact conditions **must** start with a `/` if they are present.
    96  
    97  #### Regex conditions
    98  
    99  Paths defined are matched using regex expressions.
   100  Up to one regex condition may be present in any condition block. Any condition block can
   101  either have a regex condition, exact condition or prefix condition, but not multiple together. Regex conditions are
   102  only allowed in route match conditions and not in include match conditions.
   103  
   104  Regex conditions **must** start with a `/` if they are present.
   105  
   106  #### Header conditions
   107  
   108  For `header` conditions there is the following structure:
   109  
   110  1. one required field, `name`
   111  2. six operator fields: `present`, `notpresent`, `contains`, `notcontains`, `exact`, and `notexact`
   112  3. two optional modifiers: `ignoreCase` and `treatMissingAsEmpty`
   113  
   114  Operators:
   115  - `present` is a boolean and checks that the header is present. The value will not be checked.
   116  
   117  - `notpresent` similarly checks that the header is *not* present.
   118  
   119  - `contains` is a string, and checks that the header contains the string. `notcontains` similarly checks that the header does *not* contain the string.
   120  
   121  - `exact` is a string, and checks that the header exactly matches the whole string. `notexact` checks that the header does *not* exactly match the whole string.
   122  
   123  - `regex` is a string representing a regular expression, and checks that the header value matches against the given regular expression.
   124  
   125  Modifiers:
   126  - `ignoreCase`: IgnoreCase specifies that string matching should be case insensitive. It has no effect on the `Regex` parameter.
   127  - `treatMissingAsEmpty`: specifies if the header match rule specified header does not exist, this header value will be treated as empty. Defaults to false. Unlike the underlying Envoy implementation this is **only** supported for negative matches (e.g. NotContains, NotExact).
   128  
   129  #### Query parameter conditions
   130  
   131  Similar to the `header` conditions, `queryParameter` conditions also require the
   132  `name` field to be specified, which represents the name of the query parameter
   133  e.g. `search` when the query string looks like `/?search=term` and `term`
   134  representing the value.
   135  
   136  There are six operator fields: `exact`, `prefix`, `suffix`, `regex`, `contains`
   137  and `present` and a modifier `ignoreCase` which can be used together with all of
   138  the operator fields except `regex` and `present`.
   139  
   140  - `exact` is a string, and checks that the query parameter value exactly matches
   141    the whole string.
   142  
   143  - `prefix` is a string, and checks that the query parameter value is prefixed by
   144    the given value.
   145  
   146  - `suffix` is a string, and checks that the query parameter value is suffixed by
   147    the given value.
   148  
   149  - `regex` is a string representing a regular expression, and checks that the
   150    query parameter value matches against the given regular expression.
   151  
   152  - `contains` is a string, and checks that the query parameter value contains
   153    the given string.
   154  
   155  - `present` is a boolean, and checks that the query parameter is present. The
   156    value will not be checked.
   157  
   158  - `ignoreCase` is a boolean, and if set to `true` it will enable case
   159    insensitive matching for any of the string operator matching methods.
   160  
   161  ## Request Redirection
   162  
   163  HTTP redirects can be implemented in HTTPProxy using `requestRedirectPolicy` on a route.
   164  In the following basic example, requests to `example.com` are redirected to `www.example.com`.
   165  We configure a root HTTPProxy for `example.com` that contains redirect configuration.
   166  We also configure a root HTTPProxy for `www.example.com` that represents the destination of the redirect.
   167  
   168  ```yaml
   169  apiVersion: projectcontour.io/v1
   170  kind: HTTPProxy
   171  metadata:
   172    name: example-com
   173  spec:
   174    virtualhost:
   175      fqdn: example.com
   176    routes:
   177      - conditions:
   178        - prefix: /
   179        requestRedirectPolicy:
   180          hostname: www.example.com
   181  ```
   182  
   183  ```yaml
   184  apiVersion: projectcontour.io/v1
   185  kind: HTTPProxy
   186  metadata:
   187    name: www-example-com
   188  spec:
   189    virtualhost:
   190      fqdn: www.example.com
   191    routes:
   192      - conditions:
   193        - prefix: /
   194        services:
   195          - name: s1
   196            port: 80
   197  ```
   198  
   199  In addition to specifying the hostname to set in the `location` header, the scheme, port, and returned status code of the redirect response can be configured.
   200  Configuration of the path or a path prefix replacement to modify the path of the returned `location` can be included as well.
   201  See [the API specification][3] for more detail.
   202  
   203  ## Multiple Upstreams
   204  
   205  One of the key HTTPProxy features is the ability to support multiple services for a given path:
   206  
   207  ```yaml
   208  # httpproxy-multiple-upstreams.yaml
   209  apiVersion: projectcontour.io/v1
   210  kind: HTTPProxy
   211  metadata:
   212    name: multiple-upstreams
   213    namespace: default
   214  spec:
   215    virtualhost:
   216      fqdn: multi.bar.com
   217    routes:
   218      - services:
   219          - name: s1
   220            port: 80
   221          - name: s2
   222            port: 80
   223  ```
   224  
   225  In this example, requests for `multi.bar.com/` will be load balanced across two Kubernetes Services, `s1`, and `s2`.
   226  This is helpful when you need to split traffic for a given URL across two different versions of an application.
   227  
   228  ### Upstream Weighting
   229  
   230  Building on multiple upstreams is the ability to define relative weights for upstream Services.
   231  This is commonly used for canary testing of new versions of an application when you want to send a small fraction of traffic to a specific Service.
   232  
   233  ```yaml
   234  # httpproxy-weight-shifting.yaml
   235  apiVersion: projectcontour.io/v1
   236  kind: HTTPProxy
   237  metadata:
   238    name: weight-shifting
   239    namespace: default
   240  spec:
   241    virtualhost:
   242      fqdn: weights.bar.com
   243    routes:
   244      - services:
   245          - name: s1
   246            port: 80
   247            weight: 10
   248          - name: s2
   249            port: 80
   250            weight: 90
   251  ```
   252  
   253  In this example, we are sending 10% of the traffic to Service `s1`, while Service `s2` receives the remaining 90% of traffic.
   254  
   255  HTTPProxy weighting follows some specific rules:
   256  
   257  - If no weights are specified for a given route, it's assumed even distribution across the Services.
   258  - Weights are relative and do not need to add up to 100. If all weights for a route are specified, then the "total" weight is the sum of those specified. As an example, if weights are 20, 30, 20 for three upstreams, the total weight would be 70. In this example, a weight of 30 would receive approximately 42.9% of traffic (30/70 = .4285).
   259  - If some weights are specified but others are not, then it's assumed that upstreams without weights have an implicit weight of zero, and thus will not receive traffic.
   260  
   261  ### Traffic mirroring
   262  
   263  Per route,  a service can be nominated as a mirror.
   264  The mirror service will receive a copy of the read traffic sent to any non mirror service.
   265  The mirror traffic is considered _read only_, any response by the mirror will be discarded.
   266  
   267  This service can be useful for recording traffic for later replay or for smoke testing new deployments.
   268  
   269  `weight` can be optionally set (in the space of integers 1-100) to mirror the corresponding percent of traffic (ie. `weight: 5` mirrors 5% of traffic). Omitting the `weight` field results in 100% traffic mirroring. There is unexpected behavior if `weight` is explicitly set to 0, 100% traffic will be mirrored. This occurs because we cannot distinguish undefined variables from explicitly setting them to default values, and omission of a `weight` must mirror full traffic.
   270  ```yaml
   271  apiVersion: projectcontour.io/v1
   272  kind: HTTPProxy
   273  metadata:
   274    name: traffic-mirror
   275    namespace: default
   276  spec:
   277    virtualhost:
   278      fqdn: www.example.com
   279    routes:
   280      - conditions:
   281        - prefix: /
   282        services:
   283          - name: www
   284            port: 80
   285          - name: www-mirror
   286            port: 80
   287            mirror: true
   288  ```
   289  
   290  ## Response Timeouts
   291  
   292  Each Route can be configured to have a timeout policy and a retry policy as shown:
   293  
   294  ```yaml
   295  # httpproxy-response-timeout.yaml
   296  apiVersion: projectcontour.io/v1
   297  kind: HTTPProxy
   298  metadata:
   299    name: response-timeout
   300    namespace: default
   301  spec:
   302    virtualhost:
   303      fqdn: timeout.bar.com
   304    routes:
   305    - timeoutPolicy:
   306        response: 1s
   307        idle: 10s
   308        idleConnection: 60s
   309      retryPolicy:
   310        count: 3
   311        perTryTimeout: 150ms
   312      services:
   313      - name: s1
   314        port: 80
   315  ```
   316  
   317  In this example, requests to `timeout.bar.com/` will have a response timeout policy of 1s.
   318  This refers to the time that spans between the point at which complete client request has been processed by the proxy, and when the response from the server has been completely processed.
   319  
   320  - `timeoutPolicy.response` Timeout for receiving a response from the server after processing a request from client.
   321  If not supplied, Envoy's default value of 15s applies.
   322  More information can be found in [Envoy's documentation][4].
   323  - `timeoutPolicy.idle` Timeout for how long the proxy should wait while there is no activity during single request/response (for HTTP/1.1) or stream (for HTTP/2).
   324  Timeout will not trigger while HTTP/1.1 connection is idle between two consecutive requests.
   325  If not specified, there is no per-route idle timeout, though a connection manager-wide stream idle timeout default of 5m still applies.
   326  More information can be found in [Envoy's documentation][6].
   327  - `timeoutPolicy.idleConnection` Timeout for how long connection from the proxy to the upstream service is kept when there are no active requests.
   328  If not supplied, Envoy’s default value of 1h applies.
   329  More information can be found in [Envoy's documentation][8].
   330  
   331  TimeoutPolicy durations are expressed in the Go [Duration format][5].
   332  Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
   333  The string "infinity" is also a valid input and specifies no timeout.
   334  A value of "0s" will be treated as if the field were not set, i.e. by using Envoy's default behavior.
   335  Example input values: "300ms", "5s", "1m".
   336  
   337  - `retryPolicy`: A retry will be attempted if the server returns an error code in the 5xx range, or if the server takes more than `retryPolicy.perTryTimeout` to process a request.
   338  
   339  - `retryPolicy.count` specifies the maximum number of retries allowed. This parameter is optional and defaults to 1. Set to -1 to disable. If set to 0, the Envoy default of 1 is used.
   340  
   341  - `retryPolicy.perTryTimeout` specifies the timeout per retry. If this field is greater than the request timeout, it is ignored. This parameter is optional.
   342    If left unspecified, `timeoutPolicy.request` will be used.
   343  
   344  ## Load Balancing Strategy
   345  
   346  Each route can have a load balancing strategy applied to determine which of its Endpoints is selected for the request.
   347  The following list are the options available to choose from:
   348  
   349  - `RoundRobin`: Each healthy upstream Endpoint is selected in round-robin order (Default strategy if none selected).
   350  - `WeightedLeastRequest`:  The least request load balancer uses different algorithms depending on whether hosts have the same or different weights in an attempt to route traffic based upon the number of active requests or the load at the time of selection.
   351  - `Random`: The random strategy selects a random healthy Endpoints.
   352  - `RequestHash`: The request hashing strategy allows for load balancing based on request attributes. An upstream Endpoint is selected based on the hash of an element of a request. For example, requests that contain a consistent value in an HTTP request header will be routed to the same upstream Endpoint. Currently, only hashing of HTTP request headers, query parameters and the source IP of a request is supported.
   353  - `Cookie`: The cookie load balancing strategy is similar to the request hash strategy and is a convenience feature to implement session affinity, as described below.
   354  
   355  More information on the load balancing strategy can be found in [Envoy's documentation][7].
   356  
   357  The following example defines the strategy for the route `/` as `WeightedLeastRequest`.
   358  
   359  ```yaml
   360  # httpproxy-lb-strategy.yaml
   361  apiVersion: projectcontour.io/v1
   362  kind: HTTPProxy
   363  metadata:
   364    name: lb-strategy
   365    namespace: default
   366  spec:
   367    virtualhost:
   368      fqdn: strategy.bar.com
   369    routes:
   370      - conditions:
   371        - prefix: /
   372        services:
   373          - name: s1-strategy
   374            port: 80
   375          - name: s2-strategy
   376            port: 80
   377        loadBalancerPolicy:
   378          strategy: WeightedLeastRequest
   379  ```
   380  
   381  The below example demonstrates how request hash load balancing policies can be configured:
   382  
   383  Request hash headers
   384  ```yaml
   385  # httpproxy-lb-request-hash.yaml
   386  apiVersion: projectcontour.io/v1
   387  kind: HTTPProxy
   388  metadata:
   389    name: lb-request-hash
   390    namespace: default
   391  spec:
   392    virtualhost:
   393      fqdn: request-hash.bar.com
   394    routes:
   395    - conditions:
   396      - prefix: /
   397      services:
   398      - name: httpbin
   399        port: 8080
   400      loadBalancerPolicy:
   401        strategy: RequestHash
   402        requestHashPolicies:
   403        - headerHashOptions:
   404            headerName: X-Some-Header
   405          terminal: true
   406        - headerHashOptions:
   407            headerName: User-Agent
   408        - hashSourceIP: true
   409  ```
   410  In this example, if a client request contains the `X-Some-Header` header, the value of the header will be hashed and used to route to an upstream Endpoint. This could be used to implement a similar workflow to cookie-based session affinity by passing a consistent value for this header. If it is present, because it is set as a `terminal` hash option, Envoy will not continue on to process to `User-Agent` header or source IP to calculate a hash. If `X-Some-Header` is not present, Envoy will use the `User-Agent` header value to make a routing decision along with the source IP of the client making the request. These policies can be used alone or as shown for an advanced routing decision.
   411  
   412  
   413  Request hash source ip
   414  ```yaml
   415  # httpproxy-lb-request-hash-ip.yaml
   416  apiVersion: projectcontour.io/v1
   417  kind: HTTPProxy
   418  metadata:
   419    name: lb-request-hash
   420    namespace: default
   421  spec:
   422    virtualhost:
   423      fqdn: request-hash.bar.com
   424    routes:
   425    - conditions:
   426      - prefix: /
   427      services:
   428      - name: httpbin
   429        port: 8080
   430      loadBalancerPolicy:
   431        strategy: RequestHash
   432        requestHashPolicies:
   433        - hashSourceIP: true
   434  ```
   435  
   436  Request hash query parameters
   437  ```yaml
   438  # httpproxy-lb-request-hash.yaml
   439  apiVersion: projectcontour.io/v1
   440  kind: HTTPProxy
   441  metadata:
   442    name: lb-request-hash
   443    namespace: default
   444  spec:
   445    virtualhost:
   446      fqdn: request-hash.bar.com
   447    routes:
   448    - conditions:
   449      - prefix: /
   450      services:
   451      - name: httpbin
   452        port: 8080
   453      loadBalancerPolicy:
   454        strategy: RequestHash
   455        requestHashPolicies:
   456        - queryParameterHashOptions:
   457            prameterName: param1
   458          terminal: true
   459        - queryParameterHashOptions:
   460            parameterName: param2
   461  ```
   462  
   463  ## Session Affinity
   464  
   465  Session affinity, also known as _sticky sessions_, is a load balancing strategy whereby a sequence of requests from a single client are consistently routed to the same application backend.
   466  Contour supports session affinity on a per-route basis with `loadBalancerPolicy` `strategy: Cookie`.
   467  
   468  ```yaml
   469  # httpproxy-sticky-sessions.yaml
   470  apiVersion: projectcontour.io/v1
   471  kind: HTTPProxy
   472  metadata:
   473    name: httpbin
   474    namespace: default
   475  spec:
   476    virtualhost:
   477      fqdn: httpbin.davecheney.com
   478    routes:
   479    - services:
   480      - name: httpbin
   481        port: 8080
   482      loadBalancerPolicy:
   483        strategy: Cookie
   484  ```
   485  
   486  Session affinity is based on the premise that the backend servers are robust, do not change ordering, or grow and shrink according to load.
   487  None of these properties are guaranteed by a Kubernetes cluster and will be visible to applications that rely heavily on session affinity.
   488  
   489  Any perturbation in the set of pods backing a service risks redistributing backends around the hash ring.
   490  
   491  ## Internal Redirects
   492  
   493  HTTPProxy supports handling 3xx redirects internally, that is capturing a configurable 3xx redirect response, synthesizing a new request, sending it to the upstream specified by the new route match, and returning the redirected response as the response to the original request.
   494  
   495  Internal redirects can be enabled in HTTPProxy by defining an `internalRedirectPolicy` on a route.
   496  
   497  ```yaml
   498  apiVersion: projectcontour.io/v1
   499  kind: HTTPProxy
   500  metadata:
   501   name: myservice
   502   namespace: prod
   503  spec:
   504   virtualhost:
   505     fqdn: foo.com
   506     routes:
   507       - conditions:
   508           - prefix: /download
   509         services:
   510           - name: foo
   511             port: 8080
   512         internalRedirectPolicy:
   513           maxInternalRedirects: 5
   514           redirectResponseCodes: [ 302 ]
   515           allowCrossSchemeRedirect: SafeOnly
   516           denyRepeatedRouteRedirect: true
   517  ```
   518  
   519  In this example, a sample redirect flow might look like this:
   520  
   521  1. Client sends a `GET` request for http://foo.com/download.
   522  2. Upstream `foo` returns a `302` response with `location: http://foo.com/myfile`.
   523  3. Envoy lookups a route for http://foo.com/myfile and sends a new `GET` request to the corresponding upstream with the additional request header `x-envoy-original-url: http://foo.com/download`.
   524  4. Envoy proxies the response data for http://foo.com/myfile to the client as the response to the original request.
   525  
   526  See [the API specification][9] and [Envoy's documentation][10] for more detail.
   527  
   528  [3]: /docs/{{< param version >}}/config/api/#projectcontour.io/v1.HTTPRequestRedirectPolicy
   529  [4]: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-field-config-route-v3-routeaction-timeout
   530  [5]: https://godoc.org/time#ParseDuration
   531  [6]: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-field-config-route-v3-routeaction-idle-timeout
   532  [7]: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/overview
   533  [8]: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/protocol.proto#envoy-v3-api-field-config-core-v3-httpprotocoloptions-idle-timeout
   534  [9] /docs/{{< param version >}}/config/api/#projectcontour.io/v1.HTTPInternalRedirectPolicy
   535  [10] https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/http/http_connection_management.html#internal-redirects