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