github.com/projectcontour/contour@v1.28.2/site/content/docs/1.24/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`. 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 ``` 29 30 In the following example, we match on headers and send to different services, with a default route if those do not match. 31 32 ```yaml 33 # httpproxy-multiple-headers.yaml 34 apiVersion: projectcontour.io/v1 35 kind: HTTPProxy 36 metadata: 37 name: multiple-paths 38 namespace: default 39 spec: 40 virtualhost: 41 fqdn: multi-path.bar.com 42 routes: 43 - conditions: 44 - header: 45 name: x-os 46 contains: ios 47 services: 48 - name: s1 49 port: 80 50 - conditions: 51 - header: 52 name: x-os 53 contains: android 54 services: 55 - name: s2 56 port: 80 57 - services: 58 - name: s3 59 port: 80 60 ``` 61 62 ## Conditions 63 64 Each Route entry in a HTTPProxy **may** contain one or more conditions. 65 These conditions are combined with an AND operator on the route passed to Envoy. 66 Conditions can be either a `prefix` or a `header` condition. 67 68 #### Prefix conditions 69 70 Paths defined are matched using prefix conditions. 71 Up to one prefix condition may be present in any condition block. 72 73 Prefix conditions **must** start with a `/` if they are present. 74 75 #### Header conditions 76 77 For `header` conditions there is one required field, `name`, and six operator fields: `present`, `notpresent`, `contains`, `notcontains`, `exact`, and `notexact`. 78 79 - `present` is a boolean and checks that the header is present. The value will not be checked. 80 81 - `notpresent` similarly checks that the header is *not* present. 82 83 - `contains` is a string, and checks that the header contains the string. `notcontains` similarly checks that the header does *not* contain the string. 84 85 - `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. 86 87 ## Request Redirection 88 89 HTTP redirects can be implemented in HTTPProxy using `requestRedirectPolicy` on a route. 90 In the following basic example, requests to `example.com` are redirected to `www.example.com`. 91 We configure a root HTTPProxy for `example.com` that contains redirect configuration. 92 We also configure a root HTTPProxy for `www.example.com` that represents the destination of the redirect. 93 94 ```yaml 95 apiVersion: projectcontour.io/v1 96 kind: HTTPProxy 97 metadata: 98 name: example-com 99 spec: 100 virtualhost: 101 fqdn: example.com 102 routes: 103 - conditions: 104 - prefix: / 105 requestRedirectPolicy: 106 hostname: www.example.com 107 ``` 108 109 ```yaml 110 apiVersion: projectcontour.io/v1 111 kind: HTTPProxy 112 metadata: 113 name: www-example-com 114 spec: 115 virtualhost: 116 fqdn: www.example.com 117 routes: 118 - conditions: 119 - prefix: / 120 services: 121 - name: s1 122 port: 80 123 ``` 124 125 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. 126 Configuration of the path or a path prefix replacement to modify the path of the returned `location` can be included as well. 127 See [the API specification][3] for more detail. 128 129 ## Multiple Upstreams 130 131 One of the key HTTPProxy features is the ability to support multiple services for a given path: 132 133 ```yaml 134 # httpproxy-multiple-upstreams.yaml 135 apiVersion: projectcontour.io/v1 136 kind: HTTPProxy 137 metadata: 138 name: multiple-upstreams 139 namespace: default 140 spec: 141 virtualhost: 142 fqdn: multi.bar.com 143 routes: 144 - services: 145 - name: s1 146 port: 80 147 - name: s2 148 port: 80 149 ``` 150 151 In this example, requests for `multi.bar.com/` will be load balanced across two Kubernetes Services, `s1`, and `s2`. 152 This is helpful when you need to split traffic for a given URL across two different versions of an application. 153 154 ### Upstream Weighting 155 156 Building on multiple upstreams is the ability to define relative weights for upstream Services. 157 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. 158 159 ```yaml 160 # httpproxy-weight-shifting.yaml 161 apiVersion: projectcontour.io/v1 162 kind: HTTPProxy 163 metadata: 164 name: weight-shifting 165 namespace: default 166 spec: 167 virtualhost: 168 fqdn: weights.bar.com 169 routes: 170 - services: 171 - name: s1 172 port: 80 173 weight: 10 174 - name: s2 175 port: 80 176 weight: 90 177 ``` 178 179 In this example, we are sending 10% of the traffic to Service `s1`, while Service `s2` receives the remaining 90% of traffic. 180 181 HTTPProxy weighting follows some specific rules: 182 183 - If no weights are specified for a given route, it's assumed even distribution across the Services. 184 - 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). 185 - 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. 186 187 ### Traffic mirroring 188 189 Per route, a service can be nominated as a mirror. 190 The mirror service will receive a copy of the read traffic sent to any non mirror service. 191 The mirror traffic is considered _read only_, any response by the mirror will be discarded. 192 193 This service can be useful for recording traffic for later replay or for smoke testing new deployments. 194 195 ```yaml 196 apiVersion: projectcontour.io/v1 197 kind: HTTPProxy 198 metadata: 199 name: traffic-mirror 200 namespace: default 201 spec: 202 virtualhost: 203 fqdn: www.example.com 204 routes: 205 - conditions: 206 - prefix: / 207 services: 208 - name: www 209 port: 80 210 - name: www-mirror 211 port: 80 212 mirror: true 213 ``` 214 215 ## Response Timeouts 216 217 Each Route can be configured to have a timeout policy and a retry policy as shown: 218 219 ```yaml 220 # httpproxy-response-timeout.yaml 221 apiVersion: projectcontour.io/v1 222 kind: HTTPProxy 223 metadata: 224 name: response-timeout 225 namespace: default 226 spec: 227 virtualhost: 228 fqdn: timeout.bar.com 229 routes: 230 - timeoutPolicy: 231 response: 1s 232 idle: 10s 233 idleConnection: 60s 234 retryPolicy: 235 count: 3 236 perTryTimeout: 150ms 237 services: 238 - name: s1 239 port: 80 240 ``` 241 242 In this example, requests to `timeout.bar.com/` will have a response timeout policy of 1s. 243 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. 244 245 - `timeoutPolicy.response` Timeout for receiving a response from the server after processing a request from client. 246 If not supplied, Envoy's default value of 15s applies. 247 More information can be found in [Envoy's documentation][4]. 248 - `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). 249 Timeout will not trigger while HTTP/1.1 connection is idle between two consecutive requests. 250 If not specified, there is no per-route idle timeout, though a connection manager-wide stream idle timeout default of 5m still applies. 251 More information can be found in [Envoy's documentation][6]. 252 - `timeoutPolicy.idleConnection` Timeout for how long connection from the proxy to the upstream service is kept when there are no active requests. 253 If not supplied, Envoy’s default value of 1h applies. 254 More information can be found in [Envoy's documentation][8]. 255 256 TimeoutPolicy durations are expressed in the Go [Duration format][5]. 257 Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". 258 The string "infinity" is also a valid input and specifies no timeout. 259 A value of "0s" will be treated as if the field were not set, i.e. by using Envoy's default behavior. 260 Example input values: "300ms", "5s", "1m". 261 262 - `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. 263 264 - `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. 265 266 - `retryPolicy.perTryTimeout` specifies the timeout per retry. If this field is greater than the request timeout, it is ignored. This parameter is optional. 267 If left unspecified, `timeoutPolicy.request` will be used. 268 269 ## Load Balancing Strategy 270 271 Each route can have a load balancing strategy applied to determine which of its Endpoints is selected for the request. 272 The following list are the options available to choose from: 273 274 - `RoundRobin`: Each healthy upstream Endpoint is selected in round-robin order (Default strategy if none selected). 275 - `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. 276 - `Random`: The random strategy selects a random healthy Endpoints. 277 - `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. 278 - `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. 279 280 More information on the load balancing strategy can be found in [Envoy's documentation][7]. 281 282 The following example defines the strategy for the route `/` as `WeightedLeastRequest`. 283 284 ```yaml 285 # httpproxy-lb-strategy.yaml 286 apiVersion: projectcontour.io/v1 287 kind: HTTPProxy 288 metadata: 289 name: lb-strategy 290 namespace: default 291 spec: 292 virtualhost: 293 fqdn: strategy.bar.com 294 routes: 295 - conditions: 296 - prefix: / 297 services: 298 - name: s1-strategy 299 port: 80 300 - name: s2-strategy 301 port: 80 302 loadBalancerPolicy: 303 strategy: WeightedLeastRequest 304 ``` 305 306 The below example demonstrates how request hash load balancing policies can be configured: 307 308 Request hash headers 309 ```yaml 310 # httpproxy-lb-request-hash.yaml 311 apiVersion: projectcontour.io/v1 312 kind: HTTPProxy 313 metadata: 314 name: lb-request-hash 315 namespace: default 316 spec: 317 virtualhost: 318 fqdn: request-hash.bar.com 319 routes: 320 - conditions: 321 - prefix: / 322 services: 323 - name: httpbin 324 port: 8080 325 loadBalancerPolicy: 326 strategy: RequestHash 327 requestHashPolicies: 328 - headerHashOptions: 329 headerName: X-Some-Header 330 terminal: true 331 - headerHashOptions: 332 headerName: User-Agent 333 - hashSourceIP: true 334 ``` 335 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. 336 337 338 Request hash source ip 339 ```yaml 340 # httpproxy-lb-request-hash-ip.yaml 341 apiVersion: projectcontour.io/v1 342 kind: HTTPProxy 343 metadata: 344 name: lb-request-hash 345 namespace: default 346 spec: 347 virtualhost: 348 fqdn: request-hash.bar.com 349 routes: 350 - conditions: 351 - prefix: / 352 services: 353 - name: httpbin 354 port: 8080 355 loadBalancerPolicy: 356 strategy: RequestHash 357 requestHashPolicies: 358 - hashSourceIP: true 359 ``` 360 361 Request hash query parameters 362 ```yaml 363 # httpproxy-lb-request-hash.yaml 364 apiVersion: projectcontour.io/v1 365 kind: HTTPProxy 366 metadata: 367 name: lb-request-hash 368 namespace: default 369 spec: 370 virtualhost: 371 fqdn: request-hash.bar.com 372 routes: 373 - conditions: 374 - prefix: / 375 services: 376 - name: httpbin 377 port: 8080 378 loadBalancerPolicy: 379 strategy: RequestHash 380 requestHashPolicies: 381 - queryParameterHashOptions: 382 prameterName: param1 383 terminal: true 384 - queryParameterHashOptions: 385 parameterName: param2 386 ``` 387 388 ## Session Affinity 389 390 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. 391 Contour supports session affinity on a per-route basis with `loadBalancerPolicy` `strategy: Cookie`. 392 393 ```yaml 394 # httpproxy-sticky-sessions.yaml 395 apiVersion: projectcontour.io/v1 396 kind: HTTPProxy 397 metadata: 398 name: httpbin 399 namespace: default 400 spec: 401 virtualhost: 402 fqdn: httpbin.davecheney.com 403 routes: 404 - services: 405 - name: httpbin 406 port: 8080 407 loadBalancerPolicy: 408 strategy: Cookie 409 ``` 410 411 Session affinity is based on the premise that the backend servers are robust, do not change ordering, or grow and shrink according to load. 412 None of these properties are guaranteed by a Kubernetes cluster and will be visible to applications that rely heavily on session affinity. 413 414 Any perturbation in the set of pods backing a service risks redistributing backends around the hash ring. 415 416 [3]: /docs/{{< param version >}}/config/api/#projectcontour.io/v1.HTTPRequestRedirectPolicy 417 [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 418 [5]: https://godoc.org/time#ParseDuration 419 [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 420 [7]: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/overview 421 [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