A HTTPProxy object must have at least one route or include defined. In this example, any requests to multi-path.bar.com/blog or multi-path.bar.com/blog/* will be routed to the Service s2. All other requests to the host multi-path.bar.com will be routed to the Service s1.
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: multiple-paths
namespace: default
spec:
virtualhost:
fqdn: multi-path.bar.com
routes:
- conditions:
- prefix: / # matches everything else
services:
- name: main-service
port: 80
- conditions:
- prefix: /blog # matches `multi-path.bar.com/blog` or `multi-path.bar.com/blog/*`
services:
- name: blog-service
port: 80
One of the key HTTPProxy features is the ability to support multiple services for a given path:
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: multiple-upstreams
namespace: default
spec:
virtualhost:
fqdn: multi.bar.com
routes:
- services:
- name: main-service-1
port: 80
- name: main-service-2 #same functionality as main-service-1, just calls a different external host for load balancing purposes.
port: 80
Building on multiple upstreams is the ability to define relative weights for upstream Services. 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.
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: weight-shifting
namespace: default
spec:
virtualhost:
fqdn: weights.bar.com
routes:
- services:
- name: main-service-1
port: 80
weight: 10
- name: main-service-2
port: 80
weight: 90
In this example, we are sending 10% of the traffic to Service s1, while Service s2 receives the remaining 90% of traffic.
If no weights are specified for a given route, it’s assumed even distribution across the Services.
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).
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.
Per route, a service can be nominated as a mirror. The mirror service will receive a copy of the read traffic sent to any non mirror service. The mirror traffic is considered read only, any response by the mirror will be discarded.
This service can be useful for recording traffic for later replay or for smoke testing new deployments.
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: traffic-mirror
namespace: default
spec:
virtualhost:
fqdn: www.example.com
routes:
- conditions:
- prefix: /
services:
- name: www
port: 80
- name: www-mirror
port: 80
mirror: true
Each Route can be configured to have a timeout policy and a retry policy as shown:
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: response-timeout
namespace: default
spec:
virtualhost:
fqdn: timeout.bar.com
routes:
- timeoutPolicy:
response: 1s
idle: 10s
retryPolicy:
count: 3
retryOn:
- 5xx
- reset
- connect-failure
- refused-stream
perTryTimeout: 150ms
services:
- name: s1
port: 80
In this example, requests to timeout.bar.com/ will have a response timeout policy of 1s. 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.
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.
Each route can have a load balancing strategy applied to determine which of its Endpoints is selected for the request. The following list are the options available to choose from:
Each healthy upstream Endpoint is selected in round robin order (Default strategy if none selected).
The least request strategy uses an O(1) algorithm which selects two random healthy Endpoints and picks the Endpoint which has fewer active requests. Note: This algorithm is simple and sufficient for load testing. It should not be used where true weighted least request behavior is desired.
The random strategy selects a random healthy Endpoints.
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. Requests that contain a consistent value in a HTTP request header for example will be routed to the same upstream Endpoint. Currently only hashing of HTTP request headers is supported.
The cookie load balancing strategy is similar to the request hash strategy and is a convenience feature to implement session affinity, as described below.
The following example defines the strategy for the route / as WeightedLeastRequest.
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: lb-strategy
namespace: default
spec:
virtualhost:
fqdn: strategy.bar.com
routes:
- conditions:
- prefix: /
services:
- name: s1-strategy
port: 80
- name: s2-strategy
port: 80
loadBalancerPolicy:
strategy: WeightedLeastRequest
The below example demonstrates how header hash load balancing policies can be configured:
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 to calculate a hash. If X-Some-Header is not present, Envoy will use the User-Agent header value to make a routing decision.
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: lb-request-hash
namespace: default
spec:
virtualhost:
fqdn: request-hash.bar.com
routes:
- conditions:
- prefix: /
services:
- name: httpbin
port: 8080
loadBalancerPolicy:
strategy: RequestHash
requestHashPolicies:
- headerHashOptions:
headerName: X-Some-Header
terminal: true
- headerHashOptions:
headerName: User-Agent
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. Contour supports session affinity on a per route basis with loadBalancerPolicy strategy: Cookie.
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: httpbin
namespace: default
spec:
virtualhost:
fqdn: httpbin.davecheney.com
routes:
- services:
- name: httpbin
port: 8080
loadBalancerPolicy:
strategy: Cookie
Session affinity is based on the premise that the backend servers are robust, do not change ordering, or grow and shrink according to load. None of these properties are guaranteed by a Kubernetes cluster and will be visible to applications that rely heavily on session affinity.