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