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

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