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