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