github.com/projectcontour/contour@v1.28.2/site/content/docs/1.25/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`, `header` or a `queryParameter` condition. `prefix` and `exact` 80 conditions cannot be used together in one condition block. 81 82 #### Prefix conditions 83 84 Paths defined are matched using prefix conditions. 85 Up to one prefix condition may be present in any condition block. 86 87 Prefix conditions **must** start with a `/` if they are present. 88 89 #### Exact conditions 90 91 Paths defined are matched using exact conditions. 92 Up to one exact condition may be present in any condition block. Any condition block can 93 either have an exact condition or prefix condition, but not both together. Exact conditions are 94 only allowed in route match conditions and not in include match conditions. 95 96 Exact conditions **must** start with a `/` if they are present. 97 98 #### Header conditions 99 100 For `header` conditions there is one required field, `name`, and six operator fields: `present`, `notpresent`, `contains`, `notcontains`, `exact`, and `notexact`. 101 102 - `present` is a boolean and checks that the header is present. The value will not be checked. 103 104 - `notpresent` similarly checks that the header is *not* present. 105 106 - `contains` is a string, and checks that the header contains the string. `notcontains` similarly checks that the header does *not* contain the string. 107 108 - `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. 109 110 #### Query parameter conditions 111 112 Similar to the `header` conditions, `queryParameter` conditions also require the 113 `name` field to be specified, which represents the name of the query parameter 114 e.g. `search` when the query string looks like `/?search=term` and `term` 115 representing the value. 116 117 There are six operator fields: `exact`, `prefix`, `suffix`, `regex`, `contains` 118 and `present` and a modifier `ignoreCase` which can be used together with all of 119 the operator fields except `regex` and `present`. 120 121 - `exact` is a string, and checks that the query parameter value exactly matches 122 the whole string. 123 124 - `prefix` is a string, and checks that the query parameter value is prefixed by 125 the given value. 126 127 - `suffix` is a string, and checks that the query parameter value is suffixed by 128 the given value. 129 130 - `regex` is a string representing a regular expression, and checks that the 131 query parameter value matches against the given regular expression. 132 133 - `contains` is a string, and checks that the query parameter value contains 134 the given string. 135 136 - `present` is a boolean, and checks that the query parameter is present. The 137 value will not be checked. 138 139 - `ignoreCase` is a boolean, and if set to `true` it will enable case 140 insensitive matching for any of the string operator matching methods. 141 142 ## Request Redirection 143 144 HTTP redirects can be implemented in HTTPProxy using `requestRedirectPolicy` on a route. 145 In the following basic example, requests to `example.com` are redirected to `www.example.com`. 146 We configure a root HTTPProxy for `example.com` that contains redirect configuration. 147 We also configure a root HTTPProxy for `www.example.com` that represents the destination of the redirect. 148 149 ```yaml 150 apiVersion: projectcontour.io/v1 151 kind: HTTPProxy 152 metadata: 153 name: example-com 154 spec: 155 virtualhost: 156 fqdn: example.com 157 routes: 158 - conditions: 159 - prefix: / 160 requestRedirectPolicy: 161 hostname: www.example.com 162 ``` 163 164 ```yaml 165 apiVersion: projectcontour.io/v1 166 kind: HTTPProxy 167 metadata: 168 name: www-example-com 169 spec: 170 virtualhost: 171 fqdn: www.example.com 172 routes: 173 - conditions: 174 - prefix: / 175 services: 176 - name: s1 177 port: 80 178 ``` 179 180 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. 181 Configuration of the path or a path prefix replacement to modify the path of the returned `location` can be included as well. 182 See [the API specification][3] for more detail. 183 184 ## Multiple Upstreams 185 186 One of the key HTTPProxy features is the ability to support multiple services for a given path: 187 188 ```yaml 189 # httpproxy-multiple-upstreams.yaml 190 apiVersion: projectcontour.io/v1 191 kind: HTTPProxy 192 metadata: 193 name: multiple-upstreams 194 namespace: default 195 spec: 196 virtualhost: 197 fqdn: multi.bar.com 198 routes: 199 - services: 200 - name: s1 201 port: 80 202 - name: s2 203 port: 80 204 ``` 205 206 In this example, requests for `multi.bar.com/` will be load balanced across two Kubernetes Services, `s1`, and `s2`. 207 This is helpful when you need to split traffic for a given URL across two different versions of an application. 208 209 ### Upstream Weighting 210 211 Building on multiple upstreams is the ability to define relative weights for upstream Services. 212 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. 213 214 ```yaml 215 # httpproxy-weight-shifting.yaml 216 apiVersion: projectcontour.io/v1 217 kind: HTTPProxy 218 metadata: 219 name: weight-shifting 220 namespace: default 221 spec: 222 virtualhost: 223 fqdn: weights.bar.com 224 routes: 225 - services: 226 - name: s1 227 port: 80 228 weight: 10 229 - name: s2 230 port: 80 231 weight: 90 232 ``` 233 234 In this example, we are sending 10% of the traffic to Service `s1`, while Service `s2` receives the remaining 90% of traffic. 235 236 HTTPProxy weighting follows some specific rules: 237 238 - If no weights are specified for a given route, it's assumed even distribution across the Services. 239 - 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). 240 - 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. 241 242 ### Traffic mirroring 243 244 Per route, a service can be nominated as a mirror. 245 The mirror service will receive a copy of the read traffic sent to any non mirror service. 246 The mirror traffic is considered _read only_, any response by the mirror will be discarded. 247 248 This service can be useful for recording traffic for later replay or for smoke testing new deployments. 249 250 ```yaml 251 apiVersion: projectcontour.io/v1 252 kind: HTTPProxy 253 metadata: 254 name: traffic-mirror 255 namespace: default 256 spec: 257 virtualhost: 258 fqdn: www.example.com 259 routes: 260 - conditions: 261 - prefix: / 262 services: 263 - name: www 264 port: 80 265 - name: www-mirror 266 port: 80 267 mirror: true 268 ``` 269 270 ## Response Timeouts 271 272 Each Route can be configured to have a timeout policy and a retry policy as shown: 273 274 ```yaml 275 # httpproxy-response-timeout.yaml 276 apiVersion: projectcontour.io/v1 277 kind: HTTPProxy 278 metadata: 279 name: response-timeout 280 namespace: default 281 spec: 282 virtualhost: 283 fqdn: timeout.bar.com 284 routes: 285 - timeoutPolicy: 286 response: 1s 287 idle: 10s 288 idleConnection: 60s 289 retryPolicy: 290 count: 3 291 perTryTimeout: 150ms 292 services: 293 - name: s1 294 port: 80 295 ``` 296 297 In this example, requests to `timeout.bar.com/` will have a response timeout policy of 1s. 298 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. 299 300 - `timeoutPolicy.response` Timeout for receiving a response from the server after processing a request from client. 301 If not supplied, Envoy's default value of 15s applies. 302 More information can be found in [Envoy's documentation][4]. 303 - `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). 304 Timeout will not trigger while HTTP/1.1 connection is idle between two consecutive requests. 305 If not specified, there is no per-route idle timeout, though a connection manager-wide stream idle timeout default of 5m still applies. 306 More information can be found in [Envoy's documentation][6]. 307 - `timeoutPolicy.idleConnection` Timeout for how long connection from the proxy to the upstream service is kept when there are no active requests. 308 If not supplied, Envoy’s default value of 1h applies. 309 More information can be found in [Envoy's documentation][8]. 310 311 TimeoutPolicy durations are expressed in the Go [Duration format][5]. 312 Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". 313 The string "infinity" is also a valid input and specifies no timeout. 314 A value of "0s" will be treated as if the field were not set, i.e. by using Envoy's default behavior. 315 Example input values: "300ms", "5s", "1m". 316 317 - `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. 318 319 - `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. 320 321 - `retryPolicy.perTryTimeout` specifies the timeout per retry. If this field is greater than the request timeout, it is ignored. This parameter is optional. 322 If left unspecified, `timeoutPolicy.request` will be used. 323 324 ## Load Balancing Strategy 325 326 Each route can have a load balancing strategy applied to determine which of its Endpoints is selected for the request. 327 The following list are the options available to choose from: 328 329 - `RoundRobin`: Each healthy upstream Endpoint is selected in round-robin order (Default strategy if none selected). 330 - `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. 331 - `Random`: The random strategy selects a random healthy Endpoints. 332 - `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. 333 - `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. 334 335 More information on the load balancing strategy can be found in [Envoy's documentation][7]. 336 337 The following example defines the strategy for the route `/` as `WeightedLeastRequest`. 338 339 ```yaml 340 # httpproxy-lb-strategy.yaml 341 apiVersion: projectcontour.io/v1 342 kind: HTTPProxy 343 metadata: 344 name: lb-strategy 345 namespace: default 346 spec: 347 virtualhost: 348 fqdn: strategy.bar.com 349 routes: 350 - conditions: 351 - prefix: / 352 services: 353 - name: s1-strategy 354 port: 80 355 - name: s2-strategy 356 port: 80 357 loadBalancerPolicy: 358 strategy: WeightedLeastRequest 359 ``` 360 361 The below example demonstrates how request hash load balancing policies can be configured: 362 363 Request hash headers 364 ```yaml 365 # httpproxy-lb-request-hash.yaml 366 apiVersion: projectcontour.io/v1 367 kind: HTTPProxy 368 metadata: 369 name: lb-request-hash 370 namespace: default 371 spec: 372 virtualhost: 373 fqdn: request-hash.bar.com 374 routes: 375 - conditions: 376 - prefix: / 377 services: 378 - name: httpbin 379 port: 8080 380 loadBalancerPolicy: 381 strategy: RequestHash 382 requestHashPolicies: 383 - headerHashOptions: 384 headerName: X-Some-Header 385 terminal: true 386 - headerHashOptions: 387 headerName: User-Agent 388 - hashSourceIP: true 389 ``` 390 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. 391 392 393 Request hash source ip 394 ```yaml 395 # httpproxy-lb-request-hash-ip.yaml 396 apiVersion: projectcontour.io/v1 397 kind: HTTPProxy 398 metadata: 399 name: lb-request-hash 400 namespace: default 401 spec: 402 virtualhost: 403 fqdn: request-hash.bar.com 404 routes: 405 - conditions: 406 - prefix: / 407 services: 408 - name: httpbin 409 port: 8080 410 loadBalancerPolicy: 411 strategy: RequestHash 412 requestHashPolicies: 413 - hashSourceIP: true 414 ``` 415 416 Request hash query parameters 417 ```yaml 418 # httpproxy-lb-request-hash.yaml 419 apiVersion: projectcontour.io/v1 420 kind: HTTPProxy 421 metadata: 422 name: lb-request-hash 423 namespace: default 424 spec: 425 virtualhost: 426 fqdn: request-hash.bar.com 427 routes: 428 - conditions: 429 - prefix: / 430 services: 431 - name: httpbin 432 port: 8080 433 loadBalancerPolicy: 434 strategy: RequestHash 435 requestHashPolicies: 436 - queryParameterHashOptions: 437 prameterName: param1 438 terminal: true 439 - queryParameterHashOptions: 440 parameterName: param2 441 ``` 442 443 ## Session Affinity 444 445 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. 446 Contour supports session affinity on a per-route basis with `loadBalancerPolicy` `strategy: Cookie`. 447 448 ```yaml 449 # httpproxy-sticky-sessions.yaml 450 apiVersion: projectcontour.io/v1 451 kind: HTTPProxy 452 metadata: 453 name: httpbin 454 namespace: default 455 spec: 456 virtualhost: 457 fqdn: httpbin.davecheney.com 458 routes: 459 - services: 460 - name: httpbin 461 port: 8080 462 loadBalancerPolicy: 463 strategy: Cookie 464 ``` 465 466 Session affinity is based on the premise that the backend servers are robust, do not change ordering, or grow and shrink according to load. 467 None of these properties are guaranteed by a Kubernetes cluster and will be visible to applications that rely heavily on session affinity. 468 469 Any perturbation in the set of pods backing a service risks redistributing backends around the hash ring. 470 471 ## Internal Redirects 472 473 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. 474 475 Internal redirects can be enabled in HTTPProxy by defining an `internalRedirectPolicy` on a route. 476 477 ```yaml 478 apiVersion: projectcontour.io/v1 479 kind: HTTPProxy 480 metadata: 481 name: myservice 482 namespace: prod 483 spec: 484 virtualhost: 485 fqdn: foo.com 486 routes: 487 - conditions: 488 - prefix: /download 489 services: 490 - name: foo 491 port: 8080 492 internalRedirectPolicy: 493 maxInternalRedirects: 5 494 redirectResponseCodes: [ 302 ] 495 allowCrossSchemeRedirect: SafeOnly 496 denyRepeatedRouteRedirect: true 497 ``` 498 499 In this example, a sample redirect flow might look like this: 500 501 1. Client sends a `GET` request for http://foo.com/download. 502 2. Upstream `foo` returns a `302` response with `location: http://foo.com/myfile`. 503 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`. 504 4. Envoy proxies the response data for http://foo.com/myfile to the client as the response to the original request. 505 506 See [the API specification][9] and [Envoy's documentation][10] for more detail. 507 508 [3]: /docs/{{< param version >}}/config/api/#projectcontour.io/v1.HTTPRequestRedirectPolicy 509 [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 510 [5]: https://godoc.org/time#ParseDuration 511 [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 512 [7]: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/overview 513 [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 514 [9] /docs/{{< param version >}}/config/api/#projectcontour.io/v1.HTTPInternalRedirectPolicy 515 [10] https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/http/http_connection_management.html#internal-redirects