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

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