github.com/projectcontour/contour@v1.28.2/site/content/docs/v1.1.0/httpproxy.md (about)

     1  # HTTPProxy Reference
     2  
     3  <div id="toc" class="navigation"></div>
     4  
     5  The [Ingress][1] object was added to Kubernetes in version 1.1 to describe properties of a cluster-wide reverse HTTP proxy.
     6  Since that time, the Ingress object has not progressed beyond the beta stage, and its stagnation inspired an [explosion of annotations][2] to express missing properties of HTTP routing.
     7  
     8  The goal of the `HTTPProxy` (previously `IngressRoute`) Custom Resource Definition (CRD) is to expand upon the functionality of the Ingress API to allow for a richer user experience as well addressing the limitations of the latter's use in multi tenent environments.
     9  
    10  ## Key HTTPProxy Benefits
    11  
    12  - Safely supports multi-team Kubernetes clusters, with the ability to limit which Namespaces may configure virtual hosts and TLS credentials.
    13  - Enables including of routing configuration for a path or domain from another HTTPProxy, possibly in another Namespace.
    14  - Accepts multiple services within a single route and load balances traffic across them.
    15  - Natively allows defining service weighting and load balancing strategy without annotations.
    16  - Validation of HTTPProxy objects at creation time and status reporting for post-creation validity.
    17  
    18  ## Ingress to HTTPProxy
    19  
    20  A minimal Ingress object might look like:
    21  
    22  ```yaml
    23  # ingress.yaml
    24  apiVersion: networking.k8s.io/v1beta1
    25  kind: Ingress
    26  metadata:
    27    name: basic
    28  spec:
    29    rules:
    30    - host: foo-basic.bar.com
    31      http:
    32        paths:
    33        - backend:
    34            serviceName: s1
    35            servicePort: 80
    36  ```
    37  
    38  This Ingress object, named `basic`, will route incoming HTTP traffic with a `Host:` header for `foo-basic.bar.com` to a Service named `s1` on port `80`.
    39  Implementing similar behavior using an HTTPProxy looks like this:
    40  
    41  {% highlight yaml linenos %}
    42  # httpproxy.yaml
    43  apiVersion: projectcontour.io/v1
    44  kind: HTTPProxy
    45  metadata:
    46    name: basic
    47  spec:
    48    virtualhost:
    49      fqdn: foo-basic.bar.com
    50    routes:
    51      - conditions:
    52        - prefix: /
    53        services:
    54          - name: s1
    55            port: 80
    56  {% endhighlight %}
    57  
    58  **Lines 1-5**: As with all other Kubernetes objects, an HTTPProxy needs apiVersion, kind, and metadata fields.
    59  
    60  **Lines 7-8**: The presence of the `virtualhost` field indicates that this is a root HTTPProxy that is the top level entry point for this domain.
    61  The `fqdn` field specifies the fully qualified domain name that will be used to match against `Host:` HTTP headers.
    62  
    63  **Lines 9-14**: Each HTTPProxy **must** have one or more routes, each of which **must** have one or more services which will handle the HTTP traffic. In addition, each route **may** have one or more conditions to match against.
    64  
    65  **Lines 12-14**: The `services` field is an array of named Service & Port combinations that will be used for this HTTPProxy path.
    66  HTTP traffic will be sent directly to the Endpoints corresponding to the Service.
    67  
    68  ## Interacting with HTTPProxies
    69  
    70  As with all Kubernetes objects, you can use `kubectl` to create, list, describe, edit, and delete HTTPProxy CRDs.
    71  
    72  Creating an HTTPProxy:
    73  
    74  ```bash
    75  $ kubectl create -f basic.httpproxy.yaml
    76  httpproxy "basic" created
    77  ```
    78  
    79  Listing HTTPProxies:
    80  
    81  ```bash
    82  $ kubectl get httpproxy
    83  NAME      AGE
    84  basic     24s
    85  ```
    86  
    87  Describing HTTPProxy:
    88  
    89  ```bash
    90  $ kubectl describe httpproxy basic
    91  Name:         basic
    92  Namespace:    default
    93  Labels:       <none>
    94  API Version:  projectcontour.io/v1
    95  Kind:         HTTPProxy
    96  Metadata:
    97    Cluster Name:
    98    Creation Timestamp:  2019-07-05T19:26:54Z
    99    Resource Version:    19373717
   100    Self Link:           /apis/projectcontour.io/v1/namespaces/default/httpproxy/basic
   101    UID:                 6036a9d7-8089-11e8-ab00-f80f4182762e
   102  Spec:
   103    Routes:
   104      Conditions:
   105        Prefix: /
   106      Services:
   107        Name:  s1
   108        Port:  80
   109    Virtualhost:
   110      Fqdn:  foo-basic.bar.com
   111  Events:    <none>
   112  ```
   113  
   114  Deleting HTTPProxies:
   115  
   116  ```bash
   117  $ kubectl delete httpproxy basic
   118  httpproxy "basic" deleted
   119  ```
   120  
   121  ## HTTPProxy API Specification
   122  
   123  There are a number of [working examples][3] of HTTPProxy objects in the `examples/example-workload` directory.
   124  
   125  We will use these examples as a mechanism to describe HTTPProxy API functionality.
   126  
   127  ### Virtual Host Configuration
   128  
   129  #### Fully Qualified Domain Name
   130  
   131  Similar to Ingress, HTTPProxy support name-based virtual hosting.
   132  Name-based virtual hosts use multiple host names with the same IP address.
   133  
   134  ```
   135  foo.bar.com --|                 |-> foo.bar.com s1:80
   136                | 178.91.123.132  |
   137  bar.foo.com --|                 |-> bar.foo.com s2:80
   138  ```
   139  
   140  Unlike Ingress, HTTPProxy only support a single root domain per HTTPProxy object.
   141  As an example, this Ingress object:
   142  
   143  ```yaml
   144  # ingress-name.yaml
   145  apiVersion: extensions/v1beta1
   146  kind: Ingress
   147  metadata:
   148    name: name-example
   149  spec:
   150    rules:
   151    - host: foo1.bar.com
   152      http:
   153        paths:
   154        - backend:
   155            serviceName: s1
   156            servicePort: 80
   157    - host: bar1.bar.com
   158      http:
   159        paths:
   160        - backend:
   161            serviceName: s2
   162            servicePort: 80
   163  ```
   164  
   165  must be represented by two different HTTPProxy objects:
   166  
   167  ```yaml
   168  # httpproxy-name.yaml
   169  apiVersion: projectcontour.io/v1
   170  kind: HTTPProxy
   171  metadata:
   172    name: name-example-foo
   173    namespace: default
   174  spec:
   175    virtualhost:
   176      fqdn: foo1.bar.com
   177    routes:
   178      - services:
   179        - name: s1
   180          port: 80
   181  ---
   182  apiVersion: projectcontour.io/v1
   183  kind: HTTPProxy
   184  metadata:
   185    name: name-example-bar
   186    namespace: default
   187  spec:
   188    virtualhost:
   189      fqdn: bar1.bar.com
   190    routes:
   191      - services:
   192          - name: s2
   193            port: 80
   194  ```
   195  
   196  #### TLS
   197  
   198  HTTPProxy follows a similar pattern to Ingress for configuring TLS credentials.
   199  
   200  You can secure a HTTPProxy by specifying a Secret that contains TLS private key and certificate information.
   201  Contour (via Envoy) uses the SNI TLS extension to handle this behavior.
   202  If multiple HTTPProxy's utilize the same Secret, the certificate must include the necessary Subject Authority Name (SAN) for each fqdn.
   203  
   204  Contour also follows a "secure first" approach.
   205  When TLS is enabled for a virtual host any request to the insecure port is redirected to the secure interface with a 301 redirect.
   206  Specific routes can be configured to override this behavior and handle insecure requests by enabling the `spec.routes.permitInsecure` parameter on a Route.
   207  
   208  The TLS secret must contain keys named tls.crt and tls.key that contain the certificate and private key to use for TLS, e.g.:
   209  
   210  ```yaml
   211  # ingress-tls.secret.yaml
   212  apiVersion: v1
   213  data:
   214    tls.crt: base64 encoded cert
   215    tls.key: base64 encoded key
   216  kind: Secret
   217  metadata:
   218    name: testsecret
   219    namespace: default
   220  type: kubernetes.io/tls
   221  ```
   222  
   223  The HTTPProxy can be configured to use this secret using `tls.secretName` property:
   224  
   225  ```yaml
   226  # httpproxy-tls.yaml
   227  apiVersion: projectcontour.io/v1
   228  kind: HTTPProxy
   229  metadata:
   230    name: tls-example
   231    namespace: default
   232  spec:
   233    virtualhost:
   234      fqdn: foo2.bar.com
   235      tls:
   236        secretName: testsecret
   237    routes:
   238      - services:
   239          - name: s1
   240            port: 80
   241  ```
   242  
   243  If the `tls.secretName` property contains a slash, eg. `somenamespace/somesecret` then, subject to TLS Certificate Delegation, the TLS certificate will be read from `somesecret` in `somenamespace`.
   244  See TLS Certificate Delegation below for more information.
   245  
   246  The TLS **Minimum Protocol Version** a vhost should negotiate can be specified by setting the `spec.virtualhost.tls.minimumProtocolVersion`:
   247  
   248  - 1.3
   249  - 1.2
   250  - 1.1 (Default)
   251  
   252  #### Upstream TLS
   253  
   254  A HTTPProxy can proxy to an upstream TLS connection by first annotating the upstream Kubernetes service with: `projectcontour.io/upstream-protocol.tls: "443,https"`.
   255  This annotation tells Contour which port should be used for the TLS connection.
   256  In this example, the upstream service is named `https` and uses port `443`.
   257  Additionally, it is possible for Envoy to verify the backend service's certificate.
   258  The service of an HTTPProxy can optionally specify a `validation` struct which has a mandatory `caSecret` key as well as an mandatory `subjectName`.
   259  
   260  Note: If `spec.routes.services[].validation` is present, `spec.routes.services[].{name,port}` must point to a Service with a matching `projectcontour.io/upstream-protocol.tls` Service annotation.
   261  
   262  ##### Sample YAML
   263  
   264  ```yaml
   265  apiVersion: projectcontour.io/v1
   266  kind: HTTPProxy
   267  metadata:
   268    name: secure-backend
   269  spec:
   270    virtualhost:
   271      fqdn: www.example.com
   272    routes:
   273      - services:
   274          - name: service
   275            port: 8443
   276            validation:
   277              caSecret: my-certificate-authority
   278              subjectName: backend.example.com
   279  ```
   280  
   281  ##### Error conditions
   282  
   283  If the `validation` spec is defined on a service, but the secret which it references does not exist, Contour will reject the update and set the status of the HTTPProxy object accordingly.
   284  This helps prevent the case of proxying to an upstream where validation is requested, but not yet available.
   285  
   286  ```yaml
   287  Status:
   288    Current Status:  invalid
   289    Description:     route "/": service "tls-nginx": upstreamValidation requested but secret not found or misconfigured
   290  ```
   291  
   292  #### TLS Certificate Delegation
   293  
   294  In order to support wildcard certificates, TLS certificates for a `*.somedomain.com`, which are stored in a namespace controlled by the cluster administrator, Contour supports a facility known as TLS Certificate Delegation.
   295  This facility allows the owner of a TLS certificate to delegate, for the purposes of referencing the TLS certificate, permission to Contour to read the Secret object from another namespace.
   296  
   297  The `TLSCertificateDelegation` resource defines a set of `delegations` in the `spec`.
   298  Each delegation references a `secretName` from the namespace where the `TLSCertificateDelegation` is created as well as describing a set of `targetNamespaces` in which the certificate can be referenced.
   299  If all namespaces should be able to reference the secret, then set `"*"` as the value of `targetNamespaces` (see example below).
   300  
   301  ```yaml
   302  apiVersion: projectcontour.io/v1
   303  kind: TLSCertificateDelegation
   304  metadata:
   305    name: example-com-wildcard
   306    namespace: www-admin
   307  spec:
   308    delegations:
   309      - secretName: example-com-wildcard
   310        targetNamespaces:
   311        - example-com
   312      - secretName: another-com-wildcard
   313        targetNamespaces:
   314        - "*"
   315  ---
   316  apiVersion: projectcontour.io/v1
   317  kind: HTTPProxy
   318  metadata:
   319    name: www
   320    namespace: example-com
   321  spec:
   322    virtualhost:
   323      fqdn: foo2.bar.com
   324      tls:
   325        secretName: www-admin/example-com-wildcard
   326    routes:
   327      - services:
   328          - name: s1
   329            port: 80
   330  ```
   331  
   332  In this example, the permission for Contour to reference the Secret `example-com-wildcard` in the `admin` namespace has been delegated to HTTPProxy objects in the `example-com` namespace.
   333  Also, the permission for Contour to reference the Secret `another-com-wildcard` from all namespaces has been delegated to all HTTPProxy objects in the cluster.
   334  
   335  ### Conditions
   336  
   337  Each Route entry in a HTTPProxy **may** contain one or more conditions.
   338  These conditions are combined with an AND operator on the route passed to Envoy.
   339  
   340  Conditions can be either a `prefix` or a `header` condition.
   341  
   342  #### Prefix conditions
   343  
   344  For `prefix`, this adds a path prefix.
   345  
   346  Up to one prefix condition may be present in any condition block.
   347  
   348  Prefix conditions **must** start with a `/` if they are present.
   349  
   350  #### Header conditions
   351  
   352  For `header` conditions there is one required field, `name`, and five operator fields: `present`, `contains`, `notcontains`, `exact`, and `notexact`.
   353  
   354  - `present` is a boolean and checks that the header is present. The value will not be checked.
   355  
   356  - `contains` is a string, and checks that the header contains the string. `notcontains` similarly checks that the header does *not* contain the string.
   357  
   358  - `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.
   359  
   360  ### Routes
   361  
   362  HTTPProxy must have at least one route or include defined.
   363  Paths defined are matched using prefix conditions.
   364  In this example, any requests to `multi-path.bar.com/blog` or `multi-path.bar.com/blog/*` will be routed to the Service `s2`.
   365  All other requests to the host `multi-path.bar.com` will be routed to the Service `s1`.
   366  
   367  ```yaml
   368  # httpproxy-multiple-paths.yaml
   369  apiVersion: projectcontour.io/v1
   370  kind: HTTPProxy
   371  metadata:
   372    name: multiple-paths
   373    namespace: default
   374  spec:
   375    virtualhost:
   376      fqdn: multi-path.bar.com
   377    routes:
   378      - conditions:
   379        - prefix: / # matches everything else
   380        services:
   381          - name: s1
   382            port: 80
   383      - conditions:
   384        - prefix: /blog # matches `multi-path.bar.com/blog` or `multi-path.bar.com/blog/*`
   385        services:
   386          - name: s2
   387            port: 80
   388  ```
   389  
   390  In the following example, we match on headers and send to different services, with a default route if those do not match.
   391  
   392  ```yaml
   393  # httpproxy-multiple-headers.yaml
   394  apiVersion: projectcontour.io/v1
   395  kind: HTTPProxy
   396  metadata:
   397    name: multiple-paths
   398    namespace: default
   399  spec:
   400    virtualhost:
   401      fqdn: multi-path.bar.com
   402    routes:
   403      - conditions:
   404        - header:
   405            name: x-os
   406            contains: ios
   407        services:
   408          - name: s1
   409            port: 80
   410      - conditions:
   411        - header:
   412            name: x-os
   413            contains: android
   414        services:
   415          - name: s2
   416            port: 80
   417      - services:
   418          - name: s3
   419            port: 80
   420  ```
   421  
   422  #### Multiple Upstreams
   423  
   424  One of the key HTTPProxy features is the ability to support multiple services for a given path:
   425  
   426  ```yaml
   427  # httpproxy-multiple-upstreams.yaml
   428  apiVersion: projectcontour.io/v1
   429  kind: HTTPProxy
   430  metadata:
   431    name: multiple-upstreams
   432    namespace: default
   433  spec:
   434    virtualhost:
   435      fqdn: multi.bar.com
   436    routes:
   437      - services:
   438          - name: s1
   439            port: 80
   440          - name: s2
   441            port: 80
   442  ```
   443  
   444  In this example, requests for `multi.bar.com/` will be load balanced across two Kubernetes Services, `s1`, and `s2`.
   445  This is helpful when you need to split traffic for a given URL across two different versions of an application.
   446  
   447  #### Upstream Weighting
   448  
   449  Building on multiple upstreams is the ability to define relative weights for upstream Services.
   450  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.
   451  
   452  ```yaml
   453  # httpproxy-weight-shfiting.yaml
   454  apiVersion: projectcontour.io/v1
   455  kind: HTTPProxy
   456  metadata:
   457    name: weight-shifting
   458    namespace: default
   459  spec:
   460    virtualhost:
   461      fqdn: weights.bar.com
   462    routes:
   463      - services:
   464          - name: s1
   465            port: 80
   466            weight: 10
   467          - name: s2
   468            port: 80
   469            weight: 90
   470  ```
   471  
   472  In this example, we are sending 10% of the traffic to Service `s1`, while Service `s2` receives the remaining 90% of traffic.
   473  
   474  HTTPProxy weighting follows some specific rules:
   475  
   476  - If no weights are specified for a given route, it's assumed even distribution across the Services.
   477  - 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).
   478  - 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.
   479  
   480  #### Request and Response Header Policies
   481  
   482  Manipulating headers is also supported per-Service or per-Route.  Headers can be set or
   483  removed from the request or response as follows:
   484  
   485  per-Service:
   486  
   487  ```yaml
   488  apiVersion: projectcontour.io/v1
   489  kind: HTTPProxy
   490  metadata:
   491    name: header-manipulation
   492    namespace: default
   493  spec:
   494    virtualhost:
   495      fqdn: headers.bar.com
   496    routes:
   497      - services:
   498          - name: s1
   499            port: 80
   500            requestHeadersPolicy:
   501              set:
   502                - name: X-Foo
   503                  value: bar
   504              remove:
   505                - X-Baz
   506            responseHeaderPolicy:
   507              set:
   508                - name: X-Service-Name
   509                  value: s1
   510              remove:
   511                - X-Internal-Secret
   512  ```
   513  
   514  per-Route:
   515  
   516  ```yaml
   517  apiVersion: projectcontour.io/v1
   518  kind: HTTPProxy
   519  metadata:
   520    name: header-manipulation
   521    namespace: default
   522  spec:
   523    virtualhost:
   524      fqdn: headers.bar.com
   525    routes:
   526      - services:
   527          - name: s1
   528            port: 80
   529        requestHeadersPolicy:
   530          set:
   531            - name: X-Foo
   532              value: bar
   533          remove:
   534            - X-Baz
   535        responseHeadersPolicy:
   536          set:
   537            - name: X-Service-Name
   538              value: s1
   539          remove:
   540            - X-Internal-Secret
   541  ```
   542  
   543  In these examples we are setting the header `X-Foo` with value `baz` on requests
   544  and stripping `X-Baz`.  We are then setting `X-Service-Name` on the response with
   545  value `s1`, and removing `X-Internal-Secret`.
   546  
   547  #### Traffic mirroring
   548  
   549  Per route a service can be nominated as a mirror.
   550  The mirror service will receive a copy of the read traffic sent to any non mirror service.
   551  The mirror traffic is considered _read only_, any response by the mirror will be discarded.
   552  
   553  This service can be useful for recording traffic for later replay or for smoke testing new deployments.
   554  
   555  ```yaml
   556  apiVersion: projectcontour.io/v1
   557  kind: HTTPProxy
   558  metadata:
   559    name: traffic-mirror
   560    namespace: default
   561  spec:
   562    virtualhost:
   563      fqdn: www.example.com
   564    routes:
   565      - conditions:
   566        - prefix: /
   567        services:
   568          - name: www
   569            port: 80
   570          - name: www-mirror
   571            port: 80
   572            mirror: true
   573  ```
   574  
   575  #### Response Timeout
   576  
   577  Each Route can be configured to have a timeout policy and a retry policy as shown:
   578  
   579  ```yaml
   580  # httpproxy-response-timeout.yaml
   581  apiVersion: projectcontour.io/v1
   582  kind: HTTPProxy
   583  metadata:
   584    name: response-timeout
   585    namespace: default
   586  spec:
   587    virtualhost:
   588      fqdn: timeout.bar.com
   589    routes:
   590    - timeoutPolicy:
   591        response: 1s
   592        idle: 10s
   593      retryPolicy:
   594        count: 3
   595        perTryTimeout: 150ms
   596      services:
   597      - name: s1
   598        port: 80
   599  ```
   600  
   601  In this example, requests to `timeout.bar.com/` will have a response timeout policy of 1s.
   602  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.
   603  
   604  - `timeoutPolicy.response` This field can be any positive time period or "infinity".
   605  The time period of **0s** will also be treated as infinity.
   606  This timeout covers the time from the *end of the client request* to the *end of the upstream response*.
   607  By default, Envoy has a 15 second value for this timeout.
   608  More information can be found in [Envoy's documentation][4].
   609  - `timeoutPolicy.idle` This field can be any positive time period or "infinity".
   610  The time period of **0s** will also be treated as infinity.
   611  By default, there is no per-route idle timeout.
   612  Note that the default connection manager idle timeout of 5 minutes will apply if this is not set.
   613  
   614  TimeoutPolicy durations are expressed as per the format specified in the [ParseDuration documentation][5].
   615  Example input values: "300ms", "5s", "1m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
   616  The string 'infinity' is also a valid input and specifies no timeout.
   617  
   618  More information can be found in [Envoy's documentation][6]
   619  - `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.
   620    - `retryPolicy.count` specifies the maximum number of retries allowed. This parameter is optional and defaults to 1.
   621    - `retryPolicy.perTryTimeout` specifies the timeout per retry. If this field is greater than the request timeout, it is ignored. This parameter is optional.
   622    If left unspecified, `timeoutPolicy.request` will be used.
   623  
   624  #### Load Balancing Strategy
   625  
   626  Each route can have a load balancing strategy applied to determine which of its Endpoints is selected for the request.
   627  The following list are the options available to choose from:
   628  
   629  - `RoundRobin`: Each healthy upstream Endpoint is selected in round robin order (Default strategy if none selected).
   630  - `WeightedLeastRequest`: 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.
   631  - `Random`: The random strategy selects a random healthy Endpoints.
   632  
   633  More information on the load balancing strategy can be found in [Envoy's documentation][7].
   634  
   635  The following example defines the strategy for the route `/` as `WeightedLeastRequest`.
   636  
   637  ```yaml
   638  # httpproxy-lb-strategy.yaml
   639  apiVersion: projectcontour.io/v1
   640  kind: HTTPProxy
   641  metadata:
   642    name: lb-strategy
   643    namespace: default
   644  spec:
   645    virtualhost:
   646      fqdn: strategy.bar.com
   647    routes:
   648      - conditions:
   649        - prefix: /
   650        services:
   651          - name: s1-strategy
   652            port: 80
   653          - name: s2-strategy
   654            port: 80
   655        loadBalancerPolicy:
   656          strategy: WeightedLeastRequest
   657  ```
   658  
   659  #### Session Affinity
   660  
   661  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.
   662  Contour supports session affinity on a per route basis with `loadBalancerPolicy` `strategy: Cookie`.
   663  
   664  ```yaml
   665  # httpproxy-sticky-sessions.yaml
   666  apiVersion: projectcontour.io/v1
   667  kind: HTTPProxy
   668  metadata:
   669    name: httpbin
   670    namespace: default
   671  spec:
   672    virtualhost:
   673      fqdn: httpbin.davecheney.com
   674    routes:
   675    - services:
   676      - name: httpbin
   677        port: 8080
   678      loadBalancerPolicy:
   679        strategy: Cookie
   680  ```
   681  
   682  ##### Limitations
   683  
   684  Session affinity is based on the premise that the backend servers are robust, do not change ordering, or grow and shrink according to load.
   685  None of these properties are guaranteed by a Kubernetes cluster and will be visible to applications that rely heavily on session affinity.
   686  
   687  Any perturbation in the set of pods backing a service risks redistributing backends around the hash ring.
   688  
   689  #### Per route health checking
   690  
   691  Active health checking can be configured on a per route basis.
   692  Contour supports HTTP health checking and can be configured with various settings to tune the behavior.
   693  
   694  During HTTP health checking Envoy will send an HTTP request to the upstream Endpoints.
   695  It expects a 200 response if the host is healthy.
   696  The upstream host can return 503 if it wants to immediately notify Envoy to no longer forward traffic to it.
   697  It is important to note that these are health checks which Envoy implements and are separate from any other system such as those that exist in Kubernetes.
   698  
   699  ```yaml
   700  # httpproxy-health-checks.yaml
   701  apiVersion: projectcontour.io/v1
   702  kind: HTTPProxy
   703  metadata:
   704    name: health-check
   705    namespace: default
   706  spec:
   707    virtualhost:
   708      fqdn: health.bar.com
   709    routes:
   710    - conditions:
   711      - prefix: /
   712      healthCheckPolicy:
   713        path: /healthy
   714        intervalSeconds: 5
   715        timeoutSeconds: 2
   716        unhealthyThresholdCount: 3
   717        healthyThresholdCount: 5
   718      services:
   719        - name: s1-health
   720          port: 80
   721        - name: s2-health
   722          port: 80
   723  ```
   724  
   725  Health check configuration parameters:
   726  
   727  - `path`: HTTP endpoint used to perform health checks on upstream service (e.g. `/healthz`). It expects a 200 response if the host is healthy. The upstream host can return 503 if it wants to immediately notify downstream hosts to no longer forward traffic to it.
   728  - `host`: The value of the host header in the HTTP health check request. If left empty (default value), the name "contour-envoy-healthcheck" will be used.
   729  - `intervalSeconds`: The interval (seconds) between health checks. Defaults to 5 seconds if not set.
   730  - `timeoutSeconds`: The time to wait (seconds) for a health check response. If the timeout is reached the health check attempt will be considered a failure. Defaults to 2 seconds if not set.
   731  - `unhealthyThresholdCount`: The number of unhealthy health checks required before a host is marked unhealthy. Note that for http health checking if a host responds with 503 this threshold is ignored and the host is considered unhealthy immediately. Defaults to 3 if not defined.
   732  - `healthyThresholdCount`: The number of healthy health checks required before a host is marked healthy. Note that during startup, only a single successful health check is required to mark a host healthy.
   733  
   734  #### WebSocket Support
   735  
   736  WebSocket support can be enabled on specific routes using the `enableWebsockets` field:
   737  
   738  ```yaml
   739  # httpproxy-websockets.yaml
   740  apiVersion: projectcontour.io/v1
   741  kind: HTTPProxy
   742  metadata:
   743    name: chat
   744    namespace: default
   745  spec:
   746    virtualhost:
   747      fqdn: chat.example.com
   748    routes:
   749      - services:
   750          - name: chat-app
   751            port: 80
   752      - conditions:
   753        - prefix: /websocket
   754        enableWebsockets: true # Setting this to true enables websocket for all paths that match /websocket
   755        services:
   756          - name: chat-app
   757            port: 80
   758  ```
   759  
   760  #### Permit Insecure
   761  
   762  A HTTPProxy can be configured to permit insecure requests to specific Routes.
   763  In this example, any request to `foo2.bar.com/blog` will not receive a 301 redirect to HTTPS, but the `/` route will:
   764  
   765  ```yaml
   766  apiVersion: projectcontour.io/v1
   767  kind: HTTPProxy
   768  metadata:
   769    name: tls-example-insecure
   770    namespace: default
   771  spec:
   772    virtualhost:
   773      fqdn: foo2.bar.com
   774      tls:
   775        secretName: testsecret
   776    routes:
   777      - services:
   778          - name: s1
   779            port: 80
   780      - conditions:
   781        - prefix: /blog
   782        permitInsecure: true
   783        services:
   784          - name: s2
   785            port: 80
   786  ```
   787  
   788  #### Path Rewriting
   789  
   790  HTTPProxy supports rewriting the HTTP request URL path prior to delivering the request to the backend service.
   791  Rewriting is performed after a routing decision has been made, and never changes the request destination.
   792  
   793  The `pathRewritePolicy` field specifies how the path prefix should be rewritten.
   794  The `replacePrefix` rewrite policy specifies a replacement string for a HTTP request path prefix match.
   795  When this field is present, the path prefix that the request matched is replaced by the text specified in the `replacement` field.
   796  If the HTTP request path is longer than the matched prefix, the remainder of the path is unchanged.
   797  
   798  ```yaml
   799  apiVersion: projectcontour.io/v1
   800  kind: HTTPProxy
   801  metadata:
   802    name: rewrite-example
   803    namespace: default
   804  spec:
   805    virtualhost:
   806      fqdn: rewrite.bar.com
   807    routes:
   808    - services:
   809      - name: s1
   810        port: 80
   811      pathRewritePolicy:
   812        replacePrefix:
   813        - replacement: /new/prefix
   814  ```
   815  
   816  The `replacePrefix` field accepts an array of possible replacements.
   817  When more than one `replacePrefix` array element is present, the `prefix` field can be used to disambiguate which replacement to apply.
   818  
   819  If no `prefix` field is present, the replacement is applied to all prefix matches made against the route.
   820  If a `prefix` field is present, the replacement is applied only to routes that have an exactly matching [prefix condition](#prefix-conditions).
   821  Specifying more than one `replacePrefix` entry is mainly useful when a HTTPProxy document is included into multiple parent documents.
   822  
   823  ```yaml
   824  apiVersion: projectcontour.io/v1
   825  kind: HTTPProxy
   826  metadata:
   827    name: rewrite-example
   828    namespace: default
   829  spec:
   830    virtualhost:
   831      fqdn: rewrite.bar.com
   832    routes:
   833    - services:
   834      - name: s1
   835        port: 80
   836      conditions:
   837      - prefix: /v1/api
   838      pathRewritePolicy:
   839        replacePrefix:
   840        - prefix: /v1/api
   841          replacement: /app/api/v1
   842        - prefix: /
   843          replacement: /app
   844  ```
   845  
   846  ### Header Policy
   847  
   848  HTTPProxy supports rewriting the `Host` header after first handling a request and before proxying to an upstream service.
   849  A common use-case for this is to use Contour to proxy to a resource outside the cluster referenced by an `externalName` service.
   850  
   851  The `requestHeadersPolicy` supports a list of `Set` options that currently only supports rewriting `Host` headers defined via a `name` and `value`.
   852  
   853  ```yaml
   854  apiVersion: projectcontour.io/v1
   855  kind: HTTPProxy
   856  metadata:
   857    name: header-rewrite-example
   858  spec:
   859    virtualhost:
   860      fqdn: header.bar.com
   861    routes:
   862    - services:
   863      - name: s1
   864        port: 80
   865      requestHeadersPolicy:
   866        set:
   867        - name: Host
   868          value: external.dev
   869  ```
   870  
   871  ### ExternalName
   872  
   873  HTTPProxy supports routing traffic to service types `ExternalName`.
   874  Contour looks at the `spec.externalName` field of the service and configures the route to use that DNS name instead of utilizing EDS.
   875  
   876  There's nothing specific in the HTTPProxy object that needs to be configured other than referencing a service of type `ExternalName`.
   877  
   878  NOTE: The ports are required to be specified.
   879  
   880  ```yaml
   881  # httpproxy-externalname.yaml
   882  apiVersion: v1
   883  kind: Service
   884  metadata:
   885    labels:
   886      run: externaldns
   887    name: externaldns
   888    namespace: default
   889  spec:
   890    externalName: foo-basic.bar.com
   891    ports:
   892    - name: http
   893      port: 80
   894      protocol: TCP
   895      targetPort: 80
   896    type: ExternalName
   897  ```
   898  
   899  #### Proxy to external resource
   900  
   901  To proxy to another resource outside the cluster (e.g. A hosted object store bucket for example), configure that external resource in a service type `externalName`.
   902  Then define a `headerRequestPolicy` which replaces the `Host` header with the value of the external name service defined previously.
   903  Finally, if the upstream service is served over TLS, set the `protocol` field on the service to `tls` or annotate the external name service with: `projectcontour.io/upstream-protocol.tls: 443,https` assuming your service had a port 443 and name `https`.
   904  
   905  ## HTTPProxy inclusion
   906  
   907  HTTPProxy permits the splitting of a system's configuration into separate HTTPProxy instances using **inclusion**.
   908  
   909  Inclusion, as the name implies, allows for one HTTPProxy object to be included in another, optionally with some conditions inherited from the parent.
   910  Contour reads the inclusion tree and merges the included routes into one big object internally before rendering Envoy config.
   911  Importantly, the included HTTPProxy objects do not have to be in the same namespace, so this is functionally the same as the delegation feature of the now-deprecated IngressRoute.
   912  
   913  Each tree of HTTPProxy starts with a root, the top level object of the configuration for a particular virtual host.
   914  Each root HTTPProxy defines a `virtualhost` key, which describes properties such as the fully qualified name of the virtual host, TLS configuration, etc.
   915  
   916  HTTPProxies included from the root must not contain a virtualhost key.
   917  Root objects cannot include other roots either transitively or directly.
   918  This permits the owner of an HTTPProxy root to allow the inclusion of a portion of the route space inside a virtual host, and to allow that route space to be further subdivided with inclusions.
   919  Because the path is not necessarily used as the only key, the route space can be multi-dimensional.
   920  
   921  ### Conditions and Inclusion
   922  
   923  Like Routes, Inclusion may specify a set of [conditions][8].
   924  These conditions are added to any conditions on the routes included.
   925  This process is recursive.
   926  
   927  Conditions are sets of individual condition statements, for example `prefix: /blog` is the condition that the matching request's path must start with `/blog`.
   928  When conditions are combined through inclusion Contour merges the conditions inherited via inclusion with any conditions specified on the route.
   929  This may result in duplicates, for example two `prefix:` conditions, or two header match conditions with the same name and value.
   930  To resolve this Contour applies the following logic.
   931  
   932  - `prefix:` conditions are concatenated together in the order they were applied from the root object. For example the conditions, `prefix: /api`, `prefix: /v1` becomes a single `prefix: /api/v1` conditions. Note: Multiple prefixes cannot be supplied on a single set of Route conditions.
   933  - Proxies with repeated identical `header:` conditions of type "exact match" (the same header keys exactly) are marked as "Invalid" since they create an un-routable configuration.
   934  
   935  ### Configuring inclusion
   936  
   937  Inclusion is a top-level part of the HTTPProxy `spec` element.
   938  It requires one field, `name`, and has two optional fields:
   939  
   940  - `namespace`. This will assume the included HTTPProxy is in the same namespace if it's not specified.
   941  - a `conditions` block.
   942  
   943  #### Within the same namespace
   944  
   945  HTTPProxies can include other HTTPProxy objects in the namespace by specifying the name of the object and its namespace in the top-level `includes` block.
   946  Note that `includes` is a list, and so it must use the YAML list construct.
   947  
   948  In this example, the HTTPProxy `include-root` has included the configuration for paths matching `/service2` from the HTTPPRoxy named `service2` in the same namespace as `include-root` (the `default` namespace).
   949  It's important to note that `service2` HTTPProxy has not defined a `virtualhost` property as it is NOT a root HTTPProxy.
   950  
   951  ```yaml
   952  # httpproxy-inclusion-samenamespace.yaml
   953  apiVersion: projectcontour.io/v1
   954  kind: HTTPProxy
   955  metadata:
   956    name: include-root
   957    namespace: default
   958  spec:
   959    virtualhost:
   960      fqdn: root.bar.com
   961    includes:
   962    # Includes the /service2 path from service2 in the same namespace
   963    - name: www
   964      namespace: default
   965      conditions:
   966      - prefix: /service2
   967    routes:
   968      - conditions:
   969        - prefix: /
   970        services:
   971          - name: s1
   972            port: 80
   973  ---
   974  apiVersion: projectcontour.io/v1
   975  kind: HTTPProxy
   976  metadata:
   977    name: service2
   978    namespace: default
   979  spec:
   980    routes:
   981      - conditions:
   982        - prefix: / # matches /service2
   983        services:
   984          - name: s2
   985            port: 80
   986      - conditions:
   987        - prefix: /blog # matches /service2/blog
   988        services:
   989          - name: blog
   990            port: 80
   991  ```
   992  
   993  #### Virtualhost aliases
   994  
   995  To present the same set of routes under multiple dns entries, for example www.example.com and example.com, including a service with a `prefix` condition of `/` can be used.
   996  
   997  ```yaml
   998  # httpproxy-inclusion-multipleroots.yaml
   999  ---
  1000  apiVersion: projectcontour.io/v1
  1001  kind: HTTPProxy
  1002  metadata:
  1003    name: multiple-root
  1004    namespace: default
  1005  spec:
  1006    virtualhost:
  1007      fqdn: bar.com
  1008    includes:
  1009    - name: main
  1010      namespace: default
  1011  ---
  1012  apiVersion: projectcontour.io/v1
  1013  kind: HTTPProxy
  1014  metadata:
  1015    name: multiple-root-www
  1016    namespace: default
  1017  spec:
  1018    virtualhost:
  1019      fqdn: www.bar.com
  1020    includes:
  1021    - name: main
  1022      namespace: default
  1023  ---
  1024  apiVersion: projectcontour.io/v1
  1025  kind: HTTPProxy
  1026  metadata:
  1027    name: main
  1028    namespace: default
  1029  spec:
  1030    routes:
  1031    - services:
  1032      - name: s2
  1033        port: 80
  1034  ```
  1035  
  1036  #### Across namespaces
  1037  
  1038  Inclusion can also happen across Namespaces by specifying a `namespace` in the `inclusion`.
  1039  This is a particularly powerful paradigm for enabling multi-team Ingress management.
  1040  
  1041  In this example, the root HTTPProxy has included configuration for paths matching `/blog` to the `blog` HTTPProxy object in the `marketing` namespace.
  1042  
  1043  ```yaml
  1044  # httpproxy-inclusion-across-namespaces.yaml
  1045  ---
  1046  apiVersion: projectcontour.io/v1
  1047  kind: HTTPProxy
  1048  metadata:
  1049    name: namespace-include-root
  1050    namespace: default
  1051  spec:
  1052    virtualhost:
  1053      fqdn: ns-root.bar.com
  1054    includes:
  1055    # delegate the subpath, `/blog` to the IngressRoute object in the marketing namespace with the name `blog`
  1056    - name: blog
  1057      namespace: marketing
  1058      conditions:
  1059      - prefix: /blog
  1060    routes:
  1061      - services:
  1062          - name: s1
  1063            port: 80
  1064  
  1065  ---
  1066  apiVersion: projectcontour.io/v1
  1067  kind: HTTPProxy
  1068  metadata:
  1069    name: blog
  1070    namespace: marketing
  1071  spec:
  1072    routes:
  1073      - services:
  1074          - name: s2
  1075            port: 80
  1076  ```
  1077  
  1078  ### Orphaned HTTPProxy children
  1079  
  1080  It is possible for HTTPProxy objects to exist that have not been delegated to by another HTTPProxy.
  1081  These objects are considered "orphaned" and will be ignored by Contour in determining ingress configuration.
  1082  
  1083  ### Restricted root namespaces
  1084  
  1085  HTTPProxy inclusion allows for Administrators to limit which users/namespaces may configure routes for a given domain, but it does not restrict where root HTTPProxy may be created.
  1086  Contour has an enforcing mode which accepts a list of namespaces where root HTTPProxy are valid.
  1087  Only users permitted to operate in those namespaces can therefore create HTTPProxy with the `virtualhost` field.
  1088  
  1089  This restricted mode is enabled in Contour by specifying a command line flag, `--root-namespaces`, which will restrict Contour to only searching the defined namespaces for root HTTPProxy. This CLI flag accepts a comma separated list of namespaces where HTTPProxy are valid (e.g. `--root-namespaces=default,kube-system,my-admin-namespace`).
  1090  
  1091  HTTPProxy with a defined `virtualhost` field that are not in one of the allowed root namespaces will be flagged as `invalid` and will be ignored by Contour.
  1092  
  1093  Additionally, when defined, Contour will only watch for Kubernetes secrets in these namespaces ignoring changes in all other namespaces.
  1094  Proper RBAC rules should also be created to restrict what namespaces Contour has access matching the namespaces passed to the command line flag.
  1095  An example of this is included in the [examples directory][1] and shows how you might create a namespace called `root-httproxies`.
  1096  
  1097  > **NOTE: The restricted root namespace feature is only supported for HTTPProxy CRDs.
  1098  > `--root-namespaces` does not affect the operation of `v1beta1.Ingress` objects**
  1099  
  1100  ## TCP Proxying
  1101  
  1102  HTTPProxy supports proxying of TLS encapsulated TCP sessions.
  1103  
  1104  _Note_: The TCP session must be encrypted with TLS.
  1105  This is necessary so that Envoy can use SNI to route the incoming request to the correct service.
  1106  
  1107  ### TLS Termination at the edge
  1108  
  1109  If `spec.virtualhost.tls.secretName` is present then that secret will be used to decrypt the TCP traffic at the edge.
  1110  
  1111  ```yaml
  1112  # httpproxy-tls-termination.yaml
  1113  apiVersion: projectcontour.io/v1
  1114  kind: HTTPProxy
  1115  metadata:
  1116    name: example
  1117    namespace: default
  1118  spec:
  1119    virtualhost:
  1120      fqdn: tcp.example.com
  1121      tls:
  1122        secretName: secret
  1123    tcpproxy:
  1124      services:
  1125      - name: tcpservice
  1126        port: 8080
  1127      - name: otherservice
  1128        port: 9999
  1129        weight: 20
  1130  ```
  1131  
  1132  The `spec.tcpproxy` key indicates that this _root_ HTTPProxy will forward the de-encrypted TCP traffic to the backend service.
  1133  
  1134  ### TLS passthrough to the backend service
  1135  
  1136  If you wish to handle the TLS handshake at the backend service set `spec.virtualhost.tls.passthrough: true` indicates that once SNI demuxing is performed, the encrypted connection will be forwarded to the backend service.
  1137  The backend service is expected to have a key which matches the SNI header received at the edge, and be capable of completing the TLS handshake. This is called SSL/TLS Passthrough.
  1138  
  1139  ```yaml
  1140  # httpproxy-tls-passthrough.yaml
  1141  apiVersion: projectcontour.io/v1
  1142  kind: HTTPProxy
  1143  metadata:
  1144    name: example
  1145    namespace: default
  1146  spec:
  1147    virtualhost:
  1148      fqdn: tcp.example.com
  1149      tls:
  1150        passthrough: true
  1151    tcpproxy:
  1152      services:
  1153      - name: tcpservice
  1154        port: 8080
  1155      - name: otherservice
  1156        port: 9999
  1157        weight: 20
  1158  ```
  1159  
  1160  ### TCPProxy delegation
  1161  
  1162  There can be at most one TCPProxy stanza per root HTTPProxy, however that TCPProxy does not need to be defined in the root HTTPProxy object.
  1163  HTTPProxy authors can delegate the configuration of a TCPProxy to the TCPProxy configuration defined in a HTTPProxy child object.
  1164  
  1165  ```yaml
  1166  # httpproxy-parent-termination.yaml
  1167  apiVersion: projectcontour.io/v1
  1168  kind: HTTPProxy
  1169  metadata:
  1170    name: parent
  1171    namespace: default
  1172  spec:
  1173    virtualhost:
  1174      fqdn: tcp.example.com
  1175      tls:
  1176        secretName: secret
  1177    tcpproxy:
  1178      include:
  1179        name: child
  1180        namespace: app
  1181  ---
  1182  # httpproxy-child-termination.yaml
  1183  apiVersion: projectcontour.io/v1
  1184  kind: HTTPProxy
  1185  metadata:
  1186    name: child
  1187    namespace: app
  1188  spec:
  1189    tcpproxy:
  1190       services:
  1191      - name: tcpservice
  1192        port: 8080
  1193      - name: otherservice
  1194        port: 9999
  1195        weight: 20
  1196  ```
  1197  In this example `default/parent` delegates the configuration of the TCPProxy services to `app/child`.
  1198  
  1199  ## Upstream Validation
  1200  
  1201  When defining upstream services on a route, it's possible to configure the connection from Envoy to the backend endpoint to communicate over TLS.
  1202  Two configuration items are required, a CA certificate and a `SubjectName` which are both used to verify the backend endpoint's identity.
  1203  
  1204  The CA certificate bundle for the backend service should be supplied in a Kubernetes Secret.
  1205  The referenced Secret must be of type "Opaque" and have a data key named `ca.crt`.
  1206  This data value must be a PEM-encoded certificate bundle.
  1207  
  1208  In addition to the CA certificate and the subject name, the Kubernetes service must also be annotated with a Contour specific annotation: `projectcontour.io/upstream-protocol.tls: <port>` ([see annotations section][9])
  1209  
  1210  _Note: This annotation is applied to the Service not the Ingress or HTTPProxy object._
  1211  
  1212  ```yaml
  1213  apiVersion: projectcontour.io/v1
  1214  kind: HTTPProxy
  1215  metadata:
  1216    name: blog
  1217    namespace: marketing
  1218  spec:
  1219    routes:
  1220      - services:
  1221          - name: s2
  1222            port: 80
  1223            validation:
  1224              caSecret: foo-ca-cert
  1225              subjectName: foo.marketing
  1226  ```
  1227  
  1228  ## Status Reporting
  1229  
  1230  There are many misconfigurations that could cause an HTTPProxy or delegation to be invalid.
  1231  To aid users in resolving these issues, Contour updates a `status` field in all HTTPProxy objects.
  1232  In the current specification, invalid HTTPProxy are ignored by Contour and will not be used in the ingress routing configuration.
  1233  
  1234  If an HTTPProxy object is valid, it will have a status property that looks like this:
  1235  
  1236  ```yaml
  1237  status:
  1238    currentStatus: valid
  1239    description: valid HTTPProxy
  1240  ```
  1241  
  1242  If the HTTPProxy is invalid, the `currentStatus` field will be `invalid` and the `description` field will provide a description of the issue.
  1243  
  1244  As an example, if an HTTPProxy object has specified a negative value for weighting, the HTTPProxy status will be:
  1245  
  1246  ```yaml
  1247  status:
  1248    currentStatus: invalid
  1249    description: "route '/foo': service 'home': weight must be greater than or equal to zero"
  1250  ```
  1251  
  1252  Some examples of invalid configurations that Contour provides statuses for:
  1253  
  1254  - Negative weight provided in the route definition.
  1255  - Invalid port number provided for service.
  1256  - Prefix in parent does not match route in delegated route.
  1257  - Root HTTPProxy created in a namespace other than the allowed root namespaces.
  1258  - A given Route of an HTTPProxy both delegates to another HTTPProxy and has a list of services.
  1259  - Orphaned route.
  1260  - Delegation chain produces a cycle.
  1261  - Root HTTPProxy does not specify fqdn.
  1262  - Multiple prefixes cannot be specified on the same set of route conditions.
  1263  - Multiple header conditions of type "exact match" with the same header key.
  1264  
  1265   [1]: https://kubernetes.io/docs/concepts/services-networking/ingress/
  1266   [2]: https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md
  1267   [3]: {{< param github_url >}}/tree/{{page.version}}/examples/example-workload/httpproxy
  1268   [4]: https://www.envoyproxy.io/docs/envoy/v1.11.2/api-v2/api/v2/route/route.proto.html#envoy-api-field-route-routeaction-timeout
  1269   [5]: https://godoc.org/time#ParseDuration
  1270   [6]: https://www.envoyproxy.io/docs/envoy/v1.11.2/api-v2/api/v2/route/route.proto.html#envoy-api-field-route-routeaction-idle-timeout
  1271   [7]: https://www.envoyproxy.io/docs/envoy/v1.11.2/intro/arch_overview/upstream/load_balancing/overview
  1272   [8]: #conditions
  1273   [9]: annotations.md