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