github.com/projectcontour/contour@v1.28.2/site/content/docs/v1.8.2/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 (which replaces the now-removed 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 tenant 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  If multiple HTTPProxies utilize the same Secret, the certificate must include the necessary Subject Authority Name (SAN) for each fqdn.
   202  
   203  Contour (via Envoy) requires that clients send the Server Name Indication (SNI) TLS extension so that requests can be routed to the correct virtual host.
   204  Virtual hosts are strongly bound to SNI names.
   205  This means that the Host header in HTTP requests must match the SNI name that was sent at the start of the TLS session.
   206  
   207  Contour also follows a "secure first" approach.
   208  When TLS is enabled for a virtual host, any request to the insecure port is redirected to the secure interface with a 301 redirect.
   209  Specific routes can be configured to override this behavior and handle insecure requests by enabling the `spec.routes.permitInsecure` parameter on a Route.
   210  
   211  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.:
   212  
   213  ```yaml
   214  # ingress-tls.secret.yaml
   215  apiVersion: v1
   216  data:
   217    tls.crt: base64 encoded cert
   218    tls.key: base64 encoded key
   219  kind: Secret
   220  metadata:
   221    name: testsecret
   222    namespace: default
   223  type: kubernetes.io/tls
   224  ```
   225  
   226  The HTTPProxy can be configured to use this secret using `tls.secretName` property:
   227  
   228  ```yaml
   229  # httpproxy-tls.yaml
   230  apiVersion: projectcontour.io/v1
   231  kind: HTTPProxy
   232  metadata:
   233    name: tls-example
   234    namespace: default
   235  spec:
   236    virtualhost:
   237      fqdn: foo2.bar.com
   238      tls:
   239        secretName: testsecret
   240    routes:
   241      - services:
   242          - name: s1
   243            port: 80
   244  ```
   245  
   246  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`.
   247  See TLS Certificate Delegation below for more information.
   248  
   249  The TLS **Minimum Protocol Version** a vhost should negotiate can be specified by setting the `spec.virtualhost.tls.minimumProtocolVersion`:
   250  
   251  - 1.3
   252  - 1.2
   253  - 1.1 (Default)
   254  
   255  ##### Fallback Certificate
   256  
   257  Contour provides virtual host based routing, so that any TLS request is routed to the appropriate service based on both the server name requested by the TLS client and the HOST header in the HTTP request.
   258  
   259  As the HOST Header is encrypted during TLS handshake, it can’t be used for virtual host based routing unless the client sends HTTPS requests specifying hostname using the TLS server name, or the request is first decrypted using a default TLS certificate.
   260  
   261  Some legacy TLS clients do not send the server name, so Envoy does not know how to select the right certificate. A fallback certificate is needed for these clients.
   262  
   263  _Note: The minimum TLS protocol version for any fallback request is defined by the `minimum TLS protocol version` set in the Contour configuration file. Enabling the fallback certificate is not compatible with TLS client authentication._
   264  
   265  ###### Configuration
   266  
   267  First define the `namespace/name` in the [Contour configuration file][11] of a Kubernetes secret which will be used as the fallback certificate.
   268  Any HTTPProxy which enables fallback certificate delegation must have the fallback certificate delegated to the namespace in which the HTTPProxy object resides.
   269  
   270  To do that, configure `TLSCertificateDelegation` to delegate the fallback certificate to specific or all namespaces (e.g. `*`) which should be allowed to enable the fallback certificate.
   271  Finally, for each root HTTPProxy, set the `Spec.TLS.enableFallbackCertificate` parameter to allow that HTTPProxy to opt-in to the fallback certificate routing.
   272  
   273  ```yaml
   274  apiVersion: projectcontour.io/v1
   275  kind: HTTPProxy
   276  metadata:
   277    name: fallback-tls-example
   278    namespace: defaultub
   279  spec:
   280    virtualhost:
   281      fqdn: fallback.bar.com
   282      tls:
   283        secretName: testsecret
   284        enableFallbackCertificate: true
   285    routes:
   286      - services:
   287          - name: s1
   288            port: 80
   289  ---
   290  apiVersion: projectcontour.io/v1
   291  kind: TLSCertificateDelegation
   292  metadata:
   293    name: fallback-delegation
   294    namespace: www-admin
   295  spec:
   296    delegations:
   297      - secretName: fallback-secret-name
   298        targetNamespaces:
   299        - "*"
   300  ```
   301  
   302  
   303  
   304  #### Upstream TLS
   305  
   306  A HTTPProxy can proxy to an upstream TLS connection by annotating the upstream Kubernetes Service or by specifying the upstream protocol in the HTTPProxy [`services`][10] field.
   307  Applying the `projectcontour.io/upstream-protocol.tls` annotation to a Service object tells Contour that TLS should be enabled and which port should be used for the TLS connection.
   308  The same configuration can be specified by setting the protocol name in the `spec.routes.services[].protocol` field on the HTTPProxy object.
   309  If both the annotation and the protocol field are specified, the protocol field takes precedence.
   310  By default, the upstream TLS server certificate will not be validated, but validation can be requested by setting the `spec.routes.services[].validation` field.
   311  This field has mandatory `caSecret` and `subjectName` fields, which specify the trusted root certificates with which to validate the server certificate and the expected server name.
   312  
   313  _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._
   314  
   315  In the example below, the upstream service is named `secure-backend` and uses port `8443`:
   316  
   317  ```yaml
   318  # httpproxy-example.yaml
   319  apiVersion: projectcontour.io/v1
   320  kind: HTTPProxy
   321  metadata:
   322    name: example
   323  spec:
   324    virtualhost:
   325      fqdn: www.example.com
   326    routes:
   327    - services:
   328      - name: secure-backend
   329        port: 8443
   330        validation:
   331          caSecret: my-certificate-authority
   332          subjectName: backend.example.com
   333  ```
   334  
   335  ```yaml
   336  # service-secure-backend.yaml
   337  apiVersion: v1
   338  kind: Service
   339  metadata:
   340    name: secure-backend
   341    annotations:
   342      projectcontour.io/upstream-protocol.tls: "8443"
   343  spec:
   344    ports:
   345    - name: https
   346      port: 8443
   347    selector:
   348      app: secure-backend
   349  
   350  ```
   351  
   352  ##### Envoy Client Certificate
   353  
   354  Contour can be configured with a `namespace/name` in the [Contour configuration file][11] of a Kubernetes secret which Envoy uses as a client certificate when upstream TLS is configured for the backend.
   355  Envoy will send the certificate during TLS handshake when the backend applications request the client to present its certificate.
   356  Backend applications can validate the certificate to ensure that the connection is coming from Envoy.
   357  
   358  ##### Error conditions
   359  
   360  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.
   361  This helps prevent the case of proxying to an upstream where validation is requested, but not yet available.
   362  
   363  ```yaml
   364  Status:
   365    Current Status:  invalid
   366    Description:     route "/": service "tls-nginx": upstreamValidation requested but secret not found or misconfigured
   367  ```
   368  
   369  #### TLS Certificate Delegation
   370  
   371  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.
   372  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. Delegation works for both HTTPProxy and Ingress resources.
   373  
   374  The `TLSCertificateDelegation` resource defines a set of `delegations` in the `spec`.
   375  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.
   376  If all namespaces should be able to reference the secret, then set `"*"` as the value of `targetNamespaces` (see example below).
   377  
   378  ```yaml
   379  apiVersion: projectcontour.io/v1
   380  kind: TLSCertificateDelegation
   381  metadata:
   382    name: example-com-wildcard
   383    namespace: www-admin
   384  spec:
   385    delegations:
   386      - secretName: example-com-wildcard
   387        targetNamespaces:
   388        - example-com
   389      - secretName: another-com-wildcard
   390        targetNamespaces:
   391        - "*"
   392  ---
   393  apiVersion: projectcontour.io/v1
   394  kind: HTTPProxy
   395  metadata:
   396    name: www
   397    namespace: example-com
   398  spec:
   399    virtualhost:
   400      fqdn: foo2.bar.com
   401      tls:
   402        secretName: www-admin/example-com-wildcard
   403    routes:
   404      - services:
   405          - name: s1
   406            port: 80
   407  ```
   408  
   409  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.
   410  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.
   411  
   412  ### Conditions
   413  
   414  Each Route entry in a HTTPProxy **may** contain one or more conditions.
   415  These conditions are combined with an AND operator on the route passed to Envoy.
   416  
   417  Conditions can be either a `prefix` or a `header` condition.
   418  
   419  #### Prefix conditions
   420  
   421  For `prefix`, this adds a path prefix.
   422  
   423  Up to one prefix condition may be present in any condition block.
   424  
   425  Prefix conditions **must** start with a `/` if they are present.
   426  
   427  #### Header conditions
   428  
   429  For `header` conditions there is one required field, `name`, and five operator fields: `present`, `contains`, `notcontains`, `exact`, and `notexact`.
   430  
   431  - `present` is a boolean and checks that the header is present. The value will not be checked.
   432  
   433  - `contains` is a string, and checks that the header contains the string. `notcontains` similarly checks that the header does *not* contain the string.
   434  
   435  - `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.
   436  
   437  ### Routes
   438  
   439  HTTPProxy must have at least one route or include defined.
   440  Paths defined are matched using prefix conditions.
   441  In this example, any requests to `multi-path.bar.com/blog` or `multi-path.bar.com/blog/*` will be routed to the Service `s2`.
   442  All other requests to the host `multi-path.bar.com` will be routed to the Service `s1`.
   443  
   444  ```yaml
   445  # httpproxy-multiple-paths.yaml
   446  apiVersion: projectcontour.io/v1
   447  kind: HTTPProxy
   448  metadata:
   449    name: multiple-paths
   450    namespace: default
   451  spec:
   452    virtualhost:
   453      fqdn: multi-path.bar.com
   454    routes:
   455      - conditions:
   456        - prefix: / # matches everything else
   457        services:
   458          - name: s1
   459            port: 80
   460      - conditions:
   461        - prefix: /blog # matches `multi-path.bar.com/blog` or `multi-path.bar.com/blog/*`
   462        services:
   463          - name: s2
   464            port: 80
   465  ```
   466  
   467  In the following example, we match on headers and send to different services, with a default route if those do not match.
   468  
   469  ```yaml
   470  # httpproxy-multiple-headers.yaml
   471  apiVersion: projectcontour.io/v1
   472  kind: HTTPProxy
   473  metadata:
   474    name: multiple-paths
   475    namespace: default
   476  spec:
   477    virtualhost:
   478      fqdn: multi-path.bar.com
   479    routes:
   480      - conditions:
   481        - header:
   482            name: x-os
   483            contains: ios
   484        services:
   485          - name: s1
   486            port: 80
   487      - conditions:
   488        - header:
   489            name: x-os
   490            contains: android
   491        services:
   492          - name: s2
   493            port: 80
   494      - services:
   495          - name: s3
   496            port: 80
   497  ```
   498  
   499  #### Multiple Upstreams
   500  
   501  One of the key HTTPProxy features is the ability to support multiple services for a given path:
   502  
   503  ```yaml
   504  # httpproxy-multiple-upstreams.yaml
   505  apiVersion: projectcontour.io/v1
   506  kind: HTTPProxy
   507  metadata:
   508    name: multiple-upstreams
   509    namespace: default
   510  spec:
   511    virtualhost:
   512      fqdn: multi.bar.com
   513    routes:
   514      - services:
   515          - name: s1
   516            port: 80
   517          - name: s2
   518            port: 80
   519  ```
   520  
   521  In this example, requests for `multi.bar.com/` will be load balanced across two Kubernetes Services, `s1`, and `s2`.
   522  This is helpful when you need to split traffic for a given URL across two different versions of an application.
   523  
   524  #### Upstream Weighting
   525  
   526  Building on multiple upstreams is the ability to define relative weights for upstream Services.
   527  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.
   528  
   529  ```yaml
   530  # httpproxy-weight-shfiting.yaml
   531  apiVersion: projectcontour.io/v1
   532  kind: HTTPProxy
   533  metadata:
   534    name: weight-shifting
   535    namespace: default
   536  spec:
   537    virtualhost:
   538      fqdn: weights.bar.com
   539    routes:
   540      - services:
   541          - name: s1
   542            port: 80
   543            weight: 10
   544          - name: s2
   545            port: 80
   546            weight: 90
   547  ```
   548  
   549  In this example, we are sending 10% of the traffic to Service `s1`, while Service `s2` receives the remaining 90% of traffic.
   550  
   551  HTTPProxy weighting follows some specific rules:
   552  
   553  - If no weights are specified for a given route, it's assumed even distribution across the Services.
   554  - 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).
   555  - 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.
   556  
   557  #### Request and Response Header Policies
   558  
   559  Manipulating headers is also supported per-Service or per-Route.  Headers can be set or
   560  removed from the request or response as follows:
   561  
   562  per-Service:
   563  
   564  ```yaml
   565  apiVersion: projectcontour.io/v1
   566  kind: HTTPProxy
   567  metadata:
   568    name: header-manipulation
   569    namespace: default
   570  spec:
   571    virtualhost:
   572      fqdn: headers.bar.com
   573    routes:
   574      - services:
   575          - name: s1
   576            port: 80
   577            requestHeadersPolicy:
   578              set:
   579                - name: X-Foo
   580                  value: bar
   581              remove:
   582                - X-Baz
   583            responseHeadersPolicy:
   584              set:
   585                - name: X-Service-Name
   586                  value: s1
   587              remove:
   588                - X-Internal-Secret
   589  ```
   590  
   591  per-Route:
   592  
   593  ```yaml
   594  apiVersion: projectcontour.io/v1
   595  kind: HTTPProxy
   596  metadata:
   597    name: header-manipulation
   598    namespace: default
   599  spec:
   600    virtualhost:
   601      fqdn: headers.bar.com
   602    routes:
   603      - services:
   604          - name: s1
   605            port: 80
   606        requestHeadersPolicy:
   607          set:
   608            - name: X-Foo
   609              value: bar
   610          remove:
   611            - X-Baz
   612        responseHeadersPolicy:
   613          set:
   614            - name: X-Service-Name
   615              value: s1
   616          remove:
   617            - X-Internal-Secret
   618  ```
   619  
   620  In these examples we are setting the header `X-Foo` with value `baz` on requests
   621  and stripping `X-Baz`.  We are then setting `X-Service-Name` on the response with
   622  value `s1`, and removing `X-Internal-Secret`.
   623  
   624  #### Traffic mirroring
   625  
   626  Per route a service can be nominated as a mirror.
   627  The mirror service will receive a copy of the read traffic sent to any non mirror service.
   628  The mirror traffic is considered _read only_, any response by the mirror will be discarded.
   629  
   630  This service can be useful for recording traffic for later replay or for smoke testing new deployments.
   631  
   632  ```yaml
   633  apiVersion: projectcontour.io/v1
   634  kind: HTTPProxy
   635  metadata:
   636    name: traffic-mirror
   637    namespace: default
   638  spec:
   639    virtualhost:
   640      fqdn: www.example.com
   641    routes:
   642      - conditions:
   643        - prefix: /
   644        services:
   645          - name: www
   646            port: 80
   647          - name: www-mirror
   648            port: 80
   649            mirror: true
   650  ```
   651  
   652  #### Response Timeout
   653  
   654  Each Route can be configured to have a timeout policy and a retry policy as shown:
   655  
   656  ```yaml
   657  # httpproxy-response-timeout.yaml
   658  apiVersion: projectcontour.io/v1
   659  kind: HTTPProxy
   660  metadata:
   661    name: response-timeout
   662    namespace: default
   663  spec:
   664    virtualhost:
   665      fqdn: timeout.bar.com
   666    routes:
   667    - timeoutPolicy:
   668        response: 1s
   669        idle: 10s
   670      retryPolicy:
   671        count: 3
   672        perTryTimeout: 150ms
   673      services:
   674      - name: s1
   675        port: 80
   676  ```
   677  
   678  In this example, requests to `timeout.bar.com/` will have a response timeout policy of 1s.
   679  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.
   680  
   681  - `timeoutPolicy.response` This field can be any positive time period or "infinity".
   682  This timeout covers the time from the *end of the client request* to the *end of the upstream response*.
   683  By default, Envoy has a 15 second value for this timeout.
   684  More information can be found in [Envoy's documentation][4].
   685  Note that a value of **0s** will be treated as if the field were not set, i.e. by using Envoy's default behavior.
   686  - `timeoutPolicy.idle` This field can be any positive time period or "infinity".
   687  By default, there is no per-route idle timeout.
   688  Note that the default connection manager idle timeout of 5 minutes will apply if this is not set.
   689  More information can be found in [Envoy's documentation][6].
   690  Note that a value of **0s** will be treated as if the field were not set, i.e. by using Envoy's default behavior.
   691  
   692  TimeoutPolicy durations are expressed as per the format specified in the [ParseDuration documentation][5].
   693  Example input values: "300ms", "5s", "1m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
   694  The string 'infinity' is also a valid input and specifies no timeout.
   695  
   696  - `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.
   697    - `retryPolicy.count` specifies the maximum number of retries allowed. This parameter is optional and defaults to 1.
   698    - `retryPolicy.perTryTimeout` specifies the timeout per retry. If this field is greater than the request timeout, it is ignored. This parameter is optional.
   699    If left unspecified, `timeoutPolicy.request` will be used.
   700  
   701  #### Load Balancing Strategy
   702  
   703  Each route can have a load balancing strategy applied to determine which of its Endpoints is selected for the request.
   704  The following list are the options available to choose from:
   705  
   706  - `RoundRobin`: Each healthy upstream Endpoint is selected in round robin order (Default strategy if none selected).
   707  - `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.
   708  - `Random`: The random strategy selects a random healthy Endpoints.
   709  
   710  More information on the load balancing strategy can be found in [Envoy's documentation][7].
   711  
   712  The following example defines the strategy for the route `/` as `WeightedLeastRequest`.
   713  
   714  ```yaml
   715  # httpproxy-lb-strategy.yaml
   716  apiVersion: projectcontour.io/v1
   717  kind: HTTPProxy
   718  metadata:
   719    name: lb-strategy
   720    namespace: default
   721  spec:
   722    virtualhost:
   723      fqdn: strategy.bar.com
   724    routes:
   725      - conditions:
   726        - prefix: /
   727        services:
   728          - name: s1-strategy
   729            port: 80
   730          - name: s2-strategy
   731            port: 80
   732        loadBalancerPolicy:
   733          strategy: WeightedLeastRequest
   734  ```
   735  
   736  #### Session Affinity
   737  
   738  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.
   739  Contour supports session affinity on a per route basis with `loadBalancerPolicy` `strategy: Cookie`.
   740  
   741  ```yaml
   742  # httpproxy-sticky-sessions.yaml
   743  apiVersion: projectcontour.io/v1
   744  kind: HTTPProxy
   745  metadata:
   746    name: httpbin
   747    namespace: default
   748  spec:
   749    virtualhost:
   750      fqdn: httpbin.davecheney.com
   751    routes:
   752    - services:
   753      - name: httpbin
   754        port: 8080
   755      loadBalancerPolicy:
   756        strategy: Cookie
   757  ```
   758  
   759  ##### Limitations
   760  
   761  Session affinity is based on the premise that the backend servers are robust, do not change ordering, or grow and shrink according to load.
   762  None of these properties are guaranteed by a Kubernetes cluster and will be visible to applications that rely heavily on session affinity.
   763  
   764  Any perturbation in the set of pods backing a service risks redistributing backends around the hash ring.
   765  
   766  #### Per route health checking
   767  
   768  Active health checking can be configured on a per route basis.
   769  Contour supports HTTP health checking and can be configured with various settings to tune the behavior.
   770  
   771  During HTTP health checking Envoy will send an HTTP request to the upstream Endpoints.
   772  It expects a 200 response if the host is healthy.
   773  The upstream host can return 503 if it wants to immediately notify Envoy to no longer forward traffic to it.
   774  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.
   775  
   776  ```yaml
   777  # httpproxy-health-checks.yaml
   778  apiVersion: projectcontour.io/v1
   779  kind: HTTPProxy
   780  metadata:
   781    name: health-check
   782    namespace: default
   783  spec:
   784    virtualhost:
   785      fqdn: health.bar.com
   786    routes:
   787    - conditions:
   788      - prefix: /
   789      healthCheckPolicy:
   790        path: /healthy
   791        intervalSeconds: 5
   792        timeoutSeconds: 2
   793        unhealthyThresholdCount: 3
   794        healthyThresholdCount: 5
   795      services:
   796        - name: s1-health
   797          port: 80
   798        - name: s2-health
   799          port: 80
   800  ```
   801  
   802  Health check configuration parameters:
   803  
   804  - `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.
   805  - `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.
   806  - `intervalSeconds`: The interval (seconds) between health checks. Defaults to 5 seconds if not set.
   807  - `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.
   808  - `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.
   809  - `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.
   810  
   811  #### WebSocket Support
   812  
   813  WebSocket support can be enabled on specific routes using the `enableWebsockets` field:
   814  
   815  ```yaml
   816  # httpproxy-websockets.yaml
   817  apiVersion: projectcontour.io/v1
   818  kind: HTTPProxy
   819  metadata:
   820    name: chat
   821    namespace: default
   822  spec:
   823    virtualhost:
   824      fqdn: chat.example.com
   825    routes:
   826      - services:
   827          - name: chat-app
   828            port: 80
   829      - conditions:
   830        - prefix: /websocket
   831        enableWebsockets: true # Setting this to true enables websocket for all paths that match /websocket
   832        services:
   833          - name: chat-app
   834            port: 80
   835  ```
   836  
   837  #### Permit Insecure
   838  
   839  A HTTPProxy can be configured to permit insecure requests to specific Routes.
   840  In this example, any request to `foo2.bar.com/blog` will not receive a 301 redirect to HTTPS, but the `/` route will:
   841  
   842  ```yaml
   843  apiVersion: projectcontour.io/v1
   844  kind: HTTPProxy
   845  metadata:
   846    name: tls-example-insecure
   847    namespace: default
   848  spec:
   849    virtualhost:
   850      fqdn: foo2.bar.com
   851      tls:
   852        secretName: testsecret
   853    routes:
   854      - services:
   855          - name: s1
   856            port: 80
   857      - conditions:
   858        - prefix: /blog
   859        permitInsecure: true
   860        services:
   861          - name: s2
   862            port: 80
   863  ```
   864  
   865  #### Path Rewriting
   866  
   867  HTTPProxy supports rewriting the HTTP request URL path prior to delivering the request to the backend service.
   868  Rewriting is performed after a routing decision has been made, and never changes the request destination.
   869  
   870  The `pathRewritePolicy` field specifies how the path prefix should be rewritten.
   871  The `replacePrefix` rewrite policy specifies a replacement string for a HTTP request path prefix match.
   872  When this field is present, the path prefix that the request matched is replaced by the text specified in the `replacement` field.
   873  If the HTTP request path is longer than the matched prefix, the remainder of the path is unchanged.
   874  
   875  ```yaml
   876  apiVersion: projectcontour.io/v1
   877  kind: HTTPProxy
   878  metadata:
   879    name: rewrite-example
   880    namespace: default
   881  spec:
   882    virtualhost:
   883      fqdn: rewrite.bar.com
   884    routes:
   885    - services:
   886      - name: s1
   887        port: 80
   888      pathRewritePolicy:
   889        replacePrefix:
   890        - replacement: /new/prefix
   891  ```
   892  
   893  The `replacePrefix` field accepts an array of possible replacements.
   894  When more than one `replacePrefix` array element is present, the `prefix` field can be used to disambiguate which replacement to apply.
   895  
   896  If no `prefix` field is present, the replacement is applied to all prefix matches made against the route.
   897  If a `prefix` field is present, the replacement is applied only to routes that have an exactly matching [prefix condition](#prefix-conditions).
   898  Specifying more than one `replacePrefix` entry is mainly useful when a HTTPProxy document is included into multiple parent documents.
   899  
   900  ```yaml
   901  apiVersion: projectcontour.io/v1
   902  kind: HTTPProxy
   903  metadata:
   904    name: rewrite-example
   905    namespace: default
   906  spec:
   907    virtualhost:
   908      fqdn: rewrite.bar.com
   909    routes:
   910    - services:
   911      - name: s1
   912        port: 80
   913      conditions:
   914      - prefix: /v1/api
   915      pathRewritePolicy:
   916        replacePrefix:
   917        - prefix: /v1/api
   918          replacement: /app/api/v1
   919        - prefix: /
   920          replacement: /app
   921  ```
   922  
   923  ### Header Policy
   924  
   925  HTTPProxy supports rewriting HTTP request and response headers.
   926  The `Set` operation sets a HTTP header value, creating it if it doesn't already exist or overwriting it if it does.
   927  The `Remove` operation removes a HTTP header.
   928  The `requestHeadersPolicy` field is used to rewrite headers on a HTTP request, and the `responseHeadersPolicy` is used to rewrite headers on a HTTP response.
   929  These fields can be specified on a route or on a specific service, depending on the rewrite granularity you need.
   930  
   931  
   932  ```yaml
   933  apiVersion: projectcontour.io/v1
   934  kind: HTTPProxy
   935  metadata:
   936    name: header-rewrite-example
   937  spec:
   938    virtualhost:
   939      fqdn: header.bar.com
   940    routes:
   941    - services:
   942      - name: s1
   943        port: 80
   944      requestHeadersPolicy:
   945        set:
   946        - name: Host
   947          value: external.dev
   948        remove:
   949        - Some-Header
   950        - Some-Other-Header
   951  ```
   952  
   953  ### ExternalName
   954  
   955  HTTPProxy supports routing traffic to `ExternalName` service types.
   956  Contour looks at the `spec.externalName` field of the service and configures the route to use that DNS name instead of utilizing EDS.
   957  
   958  There's nothing specific in the HTTPProxy object that needs to be configured other than referencing a service of type `ExternalName`.
   959  HTTPProxy supports the `requestHeadersPolicy` field to rewrite the `Host` header after first handling a request and before proxying to an upstream service.
   960  This field can be used to ensure that the forwarded HTTP request contains the hostname that the external resource is expecting.
   961  
   962  NOTE: The ports are required to be specified.
   963  
   964  ```yaml
   965  # httpproxy-externalname.yaml
   966  apiVersion: v1
   967  kind: Service
   968  metadata:
   969    labels:
   970      run: externaldns
   971    name: externaldns
   972    namespace: default
   973  spec:
   974    externalName: foo-basic.bar.com
   975    ports:
   976    - name: http
   977      port: 80
   978      protocol: TCP
   979      targetPort: 80
   980    type: ExternalName
   981  ```
   982  
   983  #### Proxy to external resource
   984  
   985  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`.
   986  Then define a `requestHeadersPolicy` which replaces the `Host` header with the value of the external name service defined previously.
   987  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`.
   988  
   989  ## HTTPProxy inclusion
   990  
   991  HTTPProxy permits the splitting of a system's configuration into separate HTTPProxy instances using **inclusion**.
   992  
   993  Inclusion, as the name implies, allows for one HTTPProxy object to be included in another, optionally with some conditions inherited from the parent.
   994  Contour reads the inclusion tree and merges the included routes into one big object internally before rendering Envoy config.
   995  Importantly, the included HTTPProxy objects do not have to be in the same namespace.
   996  
   997  Each tree of HTTPProxy starts with a root, the top level object of the configuration for a particular virtual host.
   998  Each root HTTPProxy defines a `virtualhost` key, which describes properties such as the fully qualified name of the virtual host, TLS configuration, etc.
   999  
  1000  HTTPProxies included from the root must not contain a virtualhost key.
  1001  Root objects cannot include other roots either transitively or directly.
  1002  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.
  1003  Because the path is not necessarily used as the only key, the route space can be multi-dimensional.
  1004  
  1005  ### Conditions and Inclusion
  1006  
  1007  Like Routes, Inclusion may specify a set of [conditions][8].
  1008  These conditions are added to any conditions on the routes included.
  1009  This process is recursive.
  1010  
  1011  Conditions are sets of individual condition statements, for example `prefix: /blog` is the condition that the matching request's path must start with `/blog`.
  1012  When conditions are combined through inclusion Contour merges the conditions inherited via inclusion with any conditions specified on the route.
  1013  This may result in duplicates, for example two `prefix:` conditions, or two header match conditions with the same name and value.
  1014  To resolve this Contour applies the following logic.
  1015  
  1016  - `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.
  1017  - 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.
  1018  
  1019  ### Configuring inclusion
  1020  
  1021  Inclusion is a top-level part of the HTTPProxy `spec` element.
  1022  It requires one field, `name`, and has two optional fields:
  1023  
  1024  - `namespace`. This will assume the included HTTPProxy is in the same namespace if it's not specified.
  1025  - a `conditions` block.
  1026  
  1027  #### Within the same namespace
  1028  
  1029  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.
  1030  Note that `includes` is a list, and so it must use the YAML list construct.
  1031  
  1032  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).
  1033  It's important to note that `service2` HTTPProxy has not defined a `virtualhost` property as it is NOT a root HTTPProxy.
  1034  
  1035  ```yaml
  1036  # httpproxy-inclusion-samenamespace.yaml
  1037  apiVersion: projectcontour.io/v1
  1038  kind: HTTPProxy
  1039  metadata:
  1040    name: include-root
  1041    namespace: default
  1042  spec:
  1043    virtualhost:
  1044      fqdn: root.bar.com
  1045    includes:
  1046    # Includes the /service2 path from service2 in the same namespace
  1047    - name: service2
  1048      namespace: default
  1049      conditions:
  1050      - prefix: /service2
  1051    routes:
  1052      - conditions:
  1053        - prefix: /
  1054        services:
  1055          - name: s1
  1056            port: 80
  1057  ---
  1058  apiVersion: projectcontour.io/v1
  1059  kind: HTTPProxy
  1060  metadata:
  1061    name: service2
  1062    namespace: default
  1063  spec:
  1064    routes:
  1065      - services: # matches /service2
  1066          - name: s2
  1067            port: 80
  1068      - conditions:
  1069        - prefix: /blog # matches /service2/blog
  1070        services:
  1071          - name: blog
  1072            port: 80
  1073  ```
  1074  
  1075  #### Virtualhost aliases
  1076  
  1077  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.
  1078  
  1079  ```yaml
  1080  # httpproxy-inclusion-multipleroots.yaml
  1081  ---
  1082  apiVersion: projectcontour.io/v1
  1083  kind: HTTPProxy
  1084  metadata:
  1085    name: multiple-root
  1086    namespace: default
  1087  spec:
  1088    virtualhost:
  1089      fqdn: bar.com
  1090    includes:
  1091    - name: main
  1092      namespace: default
  1093  ---
  1094  apiVersion: projectcontour.io/v1
  1095  kind: HTTPProxy
  1096  metadata:
  1097    name: multiple-root-www
  1098    namespace: default
  1099  spec:
  1100    virtualhost:
  1101      fqdn: www.bar.com
  1102    includes:
  1103    - name: main
  1104      namespace: default
  1105  ---
  1106  apiVersion: projectcontour.io/v1
  1107  kind: HTTPProxy
  1108  metadata:
  1109    name: main
  1110    namespace: default
  1111  spec:
  1112    routes:
  1113    - services:
  1114      - name: s2
  1115        port: 80
  1116  ```
  1117  
  1118  #### Across namespaces
  1119  
  1120  Inclusion can also happen across Namespaces by specifying a `namespace` in the `inclusion`.
  1121  This is a particularly powerful paradigm for enabling multi-team Ingress management.
  1122  
  1123  In this example, the root HTTPProxy has included configuration for paths matching `/blog` to the `blog` HTTPProxy object in the `marketing` namespace.
  1124  
  1125  ```yaml
  1126  # httpproxy-inclusion-across-namespaces.yaml
  1127  ---
  1128  apiVersion: projectcontour.io/v1
  1129  kind: HTTPProxy
  1130  metadata:
  1131    name: namespace-include-root
  1132    namespace: default
  1133  spec:
  1134    virtualhost:
  1135      fqdn: ns-root.bar.com
  1136    includes:
  1137    # delegate the subpath, `/blog` to the HTTPProxy object in the marketing namespace with the name `blog`
  1138    - name: blog
  1139      namespace: marketing
  1140      conditions:
  1141      - prefix: /blog
  1142    routes:
  1143      - services:
  1144          - name: s1
  1145            port: 80
  1146  
  1147  ---
  1148  apiVersion: projectcontour.io/v1
  1149  kind: HTTPProxy
  1150  metadata:
  1151    name: blog
  1152    namespace: marketing
  1153  spec:
  1154    routes:
  1155      - services:
  1156          - name: s2
  1157            port: 80
  1158  ```
  1159  
  1160  ### Orphaned HTTPProxy children
  1161  
  1162  It is possible for HTTPProxy objects to exist that have not been delegated to by another HTTPProxy.
  1163  These objects are considered "orphaned" and will be ignored by Contour in determining ingress configuration.
  1164  
  1165  ### Restricted root namespaces
  1166  
  1167  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.
  1168  Contour has an enforcing mode which accepts a list of namespaces where root HTTPProxy are valid.
  1169  Only users permitted to operate in those namespaces can therefore create HTTPProxy with the `virtualhost` field.
  1170  
  1171  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`).
  1172  
  1173  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.
  1174  
  1175  Additionally, when defined, Contour will only watch for Kubernetes secrets in these namespaces ignoring changes in all other namespaces.
  1176  Proper RBAC rules should also be created to restrict what namespaces Contour has access matching the namespaces passed to the command line flag.
  1177  An example of this is included in the [examples directory][12] and shows how you might create a namespace called `root-httproxy`.
  1178  
  1179  > **NOTE: The restricted root namespace feature is only supported for HTTPProxy CRDs.
  1180  > `--root-namespaces` does not affect the operation of `v1beta1.Ingress` objects**
  1181  
  1182  ## TCP Proxying
  1183  
  1184  HTTPProxy supports proxying of TLS encapsulated TCP sessions.
  1185  
  1186  _Note_: The TCP session must be encrypted with TLS.
  1187  This is necessary so that Envoy can use SNI to route the incoming request to the correct service.
  1188  
  1189  ### TLS Termination at the edge
  1190  
  1191  If `spec.virtualhost.tls.secretName` is present then that secret will be used to decrypt the TCP traffic at the edge.
  1192  
  1193  ```yaml
  1194  # httpproxy-tls-termination.yaml
  1195  apiVersion: projectcontour.io/v1
  1196  kind: HTTPProxy
  1197  metadata:
  1198    name: example
  1199    namespace: default
  1200  spec:
  1201    virtualhost:
  1202      fqdn: tcp.example.com
  1203      tls:
  1204        secretName: secret
  1205    tcpproxy:
  1206      services:
  1207      - name: tcpservice
  1208        port: 8080
  1209      - name: otherservice
  1210        port: 9999
  1211        weight: 20
  1212  ```
  1213  
  1214  The `spec.tcpproxy` key indicates that this _root_ HTTPProxy will forward the de-encrypted TCP traffic to the backend service.
  1215  
  1216  ### TLS passthrough to the backend service
  1217  
  1218  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.
  1219  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.
  1220  
  1221  ```yaml
  1222  # httpproxy-tls-passthrough.yaml
  1223  apiVersion: projectcontour.io/v1
  1224  kind: HTTPProxy
  1225  metadata:
  1226    name: example
  1227    namespace: default
  1228  spec:
  1229    virtualhost:
  1230      fqdn: tcp.example.com
  1231      tls:
  1232        passthrough: true
  1233    tcpproxy:
  1234      services:
  1235      - name: tcpservice
  1236        port: 8080
  1237      - name: otherservice
  1238        port: 9999
  1239        weight: 20
  1240  ```
  1241  
  1242  ### TCPProxy delegation
  1243  
  1244  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.
  1245  HTTPProxy authors can delegate the configuration of a TCPProxy to the TCPProxy configuration defined in a HTTPProxy child object.
  1246  
  1247  ```yaml
  1248  # httpproxy-parent-termination.yaml
  1249  apiVersion: projectcontour.io/v1
  1250  kind: HTTPProxy
  1251  metadata:
  1252    name: parent
  1253    namespace: default
  1254  spec:
  1255    virtualhost:
  1256      fqdn: tcp.example.com
  1257      tls:
  1258        secretName: secret
  1259    tcpproxy:
  1260      include:
  1261        name: child
  1262        namespace: app
  1263  ---
  1264  # httpproxy-child-termination.yaml
  1265  apiVersion: projectcontour.io/v1
  1266  kind: HTTPProxy
  1267  metadata:
  1268    name: child
  1269    namespace: app
  1270  spec:
  1271    tcpproxy:
  1272      services:
  1273      - name: tcpservice
  1274        port: 8080
  1275      - name: otherservice
  1276        port: 9999
  1277        weight: 20
  1278  ```
  1279  In this example `default/parent` delegates the configuration of the TCPProxy services to `app/child`.
  1280  
  1281  #### TCP Proxy health checking
  1282  
  1283  Active health checking can be configured on a per route basis.
  1284  Contour supports TCP health checking and can be configured with various settings to tune the behavior.
  1285  
  1286  During TCP health checking Envoy will send a connect-only health check to the upstream Endpoints.
  1287  It is important to note that these are health checks which Envoy implements and are separate from any
  1288  other system such as those that exist in Kubernetes.
  1289  
  1290  ```yaml
  1291  apiVersion: projectcontour.io/v1
  1292  kind: HTTPProxy
  1293  metadata:
  1294    name: tcp-health-check
  1295    namespace: default
  1296  spec:
  1297    virtualhost:
  1298      fqdn: health.bar.com
  1299    tcpproxy:
  1300      healthCheckPolicy:
  1301        intervalSeconds: 5
  1302        timeoutSeconds: 2
  1303        unhealthyThresholdCount: 3
  1304        healthyThresholdCount: 5
  1305      services:
  1306        - name: s1-health
  1307          port: 80
  1308        - name: s2-health
  1309          port: 80
  1310  ```
  1311  
  1312  TCP Health check policy configuration parameters:
  1313  
  1314  - `intervalSeconds`: The interval (seconds) between health checks. Defaults to 5 seconds if not set.
  1315  - `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.
  1316  - `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.
  1317  - `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.
  1318  
  1319  ## Upstream Validation
  1320  
  1321  When defining upstream services on a route, it's possible to configure the connection from Envoy to the backend endpoint to communicate over TLS.
  1322  Two configuration items are required, a CA certificate and a `SubjectName` which are both used to verify the backend endpoint's identity.
  1323  
  1324  The CA certificate bundle for the backend service should be supplied in a Kubernetes Secret.
  1325  The referenced Secret must be of type "Opaque" and have a data key named `ca.crt`.
  1326  This data value must be a PEM-encoded certificate bundle.
  1327  
  1328  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])
  1329  
  1330  _Note: This annotation is applied to the Service not the Ingress or HTTPProxy object._
  1331  
  1332  ```yaml
  1333  apiVersion: projectcontour.io/v1
  1334  kind: HTTPProxy
  1335  metadata:
  1336    name: blog
  1337    namespace: marketing
  1338  spec:
  1339    routes:
  1340      - services:
  1341          - name: s2
  1342            port: 80
  1343            validation:
  1344              caSecret: foo-ca-cert
  1345              subjectName: foo.marketing
  1346  ```
  1347  
  1348  ## Client Certificate Validation
  1349  
  1350  It is possible to protect the backend service from unauthorized external clients by requiring the client to present a valid TLS certificate.
  1351  Envoy will validate the client certificate by verifying that it is not expired and that a chain of trust can be established to the configured trusted root CA certificate.
  1352  Only those requests with a valid client certificate will be accepted and forwarded to the backend service.
  1353  
  1354  ```yaml
  1355  apiVersion: projectcontour.io/v1
  1356  kind: HTTPProxy
  1357  metadata:
  1358    name: with-client-auth
  1359  spec:
  1360    virtualhost:
  1361      fqdn: www.example.com
  1362      tls:
  1363        secretName: secret
  1364        clientValidation:
  1365          caSecret: client-root-ca
  1366    routes:
  1367      - services:
  1368          - name: s1
  1369            port: 80
  1370  ```
  1371  
  1372  The preceding example enables validation by setting the optional `clientValidation` attribute.
  1373  Its mandatory attribute `caSecret` contains a name of an existing Kubernetes Secret that must be of type "Opaque" and have a data key named `ca.crt`.
  1374  The data value of the key `ca.crt` must be a PEM-encoded certificate bundle and it must contain all the trusted CA certificates that are to be used for validating the client certificate.
  1375  
  1376  ## Status Reporting
  1377  
  1378  There are many misconfigurations that could cause an HTTPProxy or delegation to be invalid.
  1379  To aid users in resolving these issues, Contour updates a `status` field in all HTTPProxy objects.
  1380  In the current specification, invalid HTTPProxy are ignored by Contour and will not be used in the ingress routing configuration.
  1381  
  1382  If an HTTPProxy object is valid, it will have a status property that looks like this:
  1383  
  1384  ```yaml
  1385  status:
  1386    currentStatus: valid
  1387    description: valid HTTPProxy
  1388  ```
  1389  
  1390  If the HTTPProxy is invalid, the `currentStatus` field will be `invalid` and the `description` field will provide a description of the issue.
  1391  
  1392  As an example, if an HTTPProxy object has specified a negative value for weighting, the HTTPProxy status will be:
  1393  
  1394  ```yaml
  1395  status:
  1396    currentStatus: invalid
  1397    description: "route '/foo': service 'home': weight must be greater than or equal to zero"
  1398  ```
  1399  
  1400  Some examples of invalid configurations that Contour provides statuses for:
  1401  
  1402  - Negative weight provided in the route definition.
  1403  - Invalid port number provided for service.
  1404  - Prefix in parent does not match route in delegated route.
  1405  - Root HTTPProxy created in a namespace other than the allowed root namespaces.
  1406  - A given Route of an HTTPProxy both delegates to another HTTPProxy and has a list of services.
  1407  - Orphaned route.
  1408  - Delegation chain produces a cycle.
  1409  - Root HTTPProxy does not specify fqdn.
  1410  - Multiple prefixes cannot be specified on the same set of route conditions.
  1411  - Multiple header conditions of type "exact match" with the same header key.
  1412  - Contradictory header conditions on a route, e.g. a "contains" and "notcontains" condition for the same header and value.
  1413  
  1414   [1]: https://kubernetes.io/docs/concepts/services-networking/ingress/
  1415   [2]: https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md
  1416   [3]: {{< param github_url >}}/tree/{{page.version}}/examples/example-workload/httpproxy
  1417   [4]: https://www.envoyproxy.io/docs/envoy/v1.14.2/api-v2/api/v2/route/route_components.proto#envoy-api-field-route-routeaction-timeout
  1418   [5]: https://godoc.org/time#ParseDuration
  1419   [6]: https://www.envoyproxy.io/docs/envoy/v1.14.2/api-v2/api/v2/route/route_components.proto#envoy-api-field-route-routeaction-idle-timeout
  1420   [7]: https://www.envoyproxy.io/docs/envoy/v1.14.2/intro/arch_overview/upstream/load_balancing/overview
  1421   [8]: #conditions
  1422   [9]: {% link docs/{{page.version}}/annotations.md %}
  1423   [10]: /docs/{{page.version}}/api/#projectcontour.io/v1.Service
  1424   [11]: configuration.md#fallback-certificate
  1425   [12]: {{< param github_url >}}/tree/{{page.version}}/examples/root-rbac