github.com/projectcontour/contour@v1.28.2/site/content/docs/v1.9.0/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 (which replaces the now-removed 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 tenant 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 If multiple HTTPProxies utilize the same Secret, the certificate must include the necessary Subject Authority Name (SAN) for each fqdn. 202 203 Contour (via Envoy) requires that clients send the Server Name Indication (SNI) TLS extension so that requests can be routed to the correct virtual host. 204 Virtual hosts are strongly bound to SNI names. 205 This means that the Host header in HTTP requests must match the SNI name that was sent at the start of the TLS session. 206 207 Contour also follows a "secure first" approach. 208 When TLS is enabled for a virtual host, any request to the insecure port is redirected to the secure interface with a 301 redirect. 209 Specific routes can be configured to override this behavior and handle insecure requests by enabling the `spec.routes.permitInsecure` parameter on a Route. 210 211 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.: 212 213 ```yaml 214 # ingress-tls.secret.yaml 215 apiVersion: v1 216 data: 217 tls.crt: base64 encoded cert 218 tls.key: base64 encoded key 219 kind: Secret 220 metadata: 221 name: testsecret 222 namespace: default 223 type: kubernetes.io/tls 224 ``` 225 226 The HTTPProxy can be configured to use this secret using `tls.secretName` property: 227 228 ```yaml 229 # httpproxy-tls.yaml 230 apiVersion: projectcontour.io/v1 231 kind: HTTPProxy 232 metadata: 233 name: tls-example 234 namespace: default 235 spec: 236 virtualhost: 237 fqdn: foo2.bar.com 238 tls: 239 secretName: testsecret 240 routes: 241 - services: 242 - name: s1 243 port: 80 244 ``` 245 246 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`. 247 See TLS Certificate Delegation below for more information. 248 249 The TLS **Minimum Protocol Version** a vhost should negotiate can be specified by setting the `spec.virtualhost.tls.minimumProtocolVersion`: 250 251 - 1.3 252 - 1.2 253 - 1.1 (Default) 254 255 ##### Fallback Certificate 256 257 Contour provides virtual host based routing, so that any TLS request is routed to the appropriate service based on both the server name requested by the TLS client and the HOST header in the HTTP request. 258 259 As the HOST Header is encrypted during TLS handshake, it can’t be used for virtual host based routing unless the client sends HTTPS requests specifying hostname using the TLS server name, or the request is first decrypted using a default TLS certificate. 260 261 Some legacy TLS clients do not send the server name, so Envoy does not know how to select the right certificate. A fallback certificate is needed for these clients. 262 263 _Note: The minimum TLS protocol version for any fallback request is defined by the `minimum TLS protocol version` set in the Contour configuration file. Enabling the fallback certificate is not compatible with TLS client authentication._ 264 265 ###### Configuration 266 267 First define the `namespace/name` in the [Contour configuration file][11] of a Kubernetes secret which will be used as the fallback certificate. 268 Any HTTPProxy which enables fallback certificate delegation must have the fallback certificate delegated to the namespace in which the HTTPProxy object resides. 269 270 To do that, configure `TLSCertificateDelegation` to delegate the fallback certificate to specific or all namespaces (e.g. `*`) which should be allowed to enable the fallback certificate. 271 Finally, for each root HTTPProxy, set the `Spec.TLS.enableFallbackCertificate` parameter to allow that HTTPProxy to opt-in to the fallback certificate routing. 272 273 ```yaml 274 apiVersion: projectcontour.io/v1 275 kind: HTTPProxy 276 metadata: 277 name: fallback-tls-example 278 namespace: defaultub 279 spec: 280 virtualhost: 281 fqdn: fallback.bar.com 282 tls: 283 secretName: testsecret 284 enableFallbackCertificate: true 285 routes: 286 - services: 287 - name: s1 288 port: 80 289 --- 290 apiVersion: projectcontour.io/v1 291 kind: TLSCertificateDelegation 292 metadata: 293 name: fallback-delegation 294 namespace: www-admin 295 spec: 296 delegations: 297 - secretName: fallback-secret-name 298 targetNamespaces: 299 - "*" 300 ``` 301 302 303 304 #### Upstream TLS 305 306 A HTTPProxy can proxy to an upstream TLS connection by annotating the upstream Kubernetes Service or by specifying the upstream protocol in the HTTPProxy [`services`][10] field. 307 Applying the `projectcontour.io/upstream-protocol.tls` annotation to a Service object tells Contour that TLS should be enabled and which port should be used for the TLS connection. 308 The same configuration can be specified by setting the protocol name in the `spec.routes.services[].protocol` field on the HTTPProxy object. 309 If both the annotation and the protocol field are specified, the protocol field takes precedence. 310 By default, the upstream TLS server certificate will not be validated, but validation can be requested by setting the `spec.routes.services[].validation` field. 311 This field has mandatory `caSecret` and `subjectName` fields, which specify the trusted root certificates with which to validate the server certificate and the expected server name. 312 313 _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._ 314 315 In the example below, the upstream service is named `secure-backend` and uses port `8443`: 316 317 ```yaml 318 # httpproxy-example.yaml 319 apiVersion: projectcontour.io/v1 320 kind: HTTPProxy 321 metadata: 322 name: example 323 spec: 324 virtualhost: 325 fqdn: www.example.com 326 routes: 327 - services: 328 - name: secure-backend 329 port: 8443 330 validation: 331 caSecret: my-certificate-authority 332 subjectName: backend.example.com 333 ``` 334 335 ```yaml 336 # service-secure-backend.yaml 337 apiVersion: v1 338 kind: Service 339 metadata: 340 name: secure-backend 341 annotations: 342 projectcontour.io/upstream-protocol.tls: "8443" 343 spec: 344 ports: 345 - name: https 346 port: 8443 347 selector: 348 app: secure-backend 349 350 ``` 351 352 ##### Envoy Client Certificate 353 354 Contour can be configured with a `namespace/name` in the [Contour configuration file][11] of a Kubernetes secret which Envoy uses as a client certificate when upstream TLS is configured for the backend. 355 Envoy will send the certificate during TLS handshake when the backend applications request the client to present its certificate. 356 Backend applications can validate the certificate to ensure that the connection is coming from Envoy. 357 358 ##### Error conditions 359 360 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. 361 This helps prevent the case of proxying to an upstream where validation is requested, but not yet available. 362 363 ```yaml 364 Status: 365 Current Status: invalid 366 Description: route "/": service "tls-nginx": upstreamValidation requested but secret not found or misconfigured 367 ``` 368 369 #### TLS Certificate Delegation 370 371 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. 372 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. Delegation works for both HTTPProxy and Ingress resources. 373 374 The `TLSCertificateDelegation` resource defines a set of `delegations` in the `spec`. 375 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. 376 If all namespaces should be able to reference the secret, then set `"*"` as the value of `targetNamespaces` (see example below). 377 378 ```yaml 379 apiVersion: projectcontour.io/v1 380 kind: TLSCertificateDelegation 381 metadata: 382 name: example-com-wildcard 383 namespace: www-admin 384 spec: 385 delegations: 386 - secretName: example-com-wildcard 387 targetNamespaces: 388 - example-com 389 - secretName: another-com-wildcard 390 targetNamespaces: 391 - "*" 392 --- 393 apiVersion: projectcontour.io/v1 394 kind: HTTPProxy 395 metadata: 396 name: www 397 namespace: example-com 398 spec: 399 virtualhost: 400 fqdn: foo2.bar.com 401 tls: 402 secretName: www-admin/example-com-wildcard 403 routes: 404 - services: 405 - name: s1 406 port: 80 407 ``` 408 409 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. 410 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. 411 412 #### CORS policy 413 414 A CORS (Cross-origin resource sharing) policy can be set for a HTTPProxy in order to allow cross-domain requests for trusted sources. If a policy is set, it will be applied to all the routes of the virtual host. 415 416 Contour allows configuring the headers involved in cross-domain requests. In this example, cross-domain requests will be allowed for any domain (note the `*` value). 417 418 ```yaml 419 apiVersion: projectcontour.io/v1 420 kind: HTTPProxy 421 spec: 422 virtualhost: 423 fqdn: www.example.com 424 corsPolicy: 425 allowCredentials: true 426 allowOrigin: 427 - "*" # allows any origin 428 allowMethods: 429 - GET 430 - POST 431 - OPTIONS 432 allowHeaders: 433 - authorization 434 - cache-control 435 exposeHeaders: 436 - Content-Length 437 - Content-Range 438 maxAge: "10m" # preflight requests can be cached for 10 minutes. 439 routes: 440 - conditions: 441 - prefix: / 442 services: 443 - name: s1 444 port: 80 445 ``` 446 447 In the following example, cross-domain requests are restricted to https://client.example.com only. 448 449 ```yaml 450 apiVersion: projectcontour.io/v1 451 kind: HTTPProxy 452 spec: 453 virtualhost: 454 fqdn: www.example.com 455 corsPolicy: 456 allowCredentials: true 457 allowOrigin: 458 - "https://client.example.com" 459 allowMethods: 460 - GET 461 - POST 462 - OPTIONS 463 allowHeaders: 464 - authorization 465 - cache-control 466 exposeHeaders: 467 - Content-Length 468 - Content-Range 469 maxAge: "10m" 470 routes: 471 - conditions: 472 - prefix: / 473 services: 474 - name: s1 475 port: 80 476 ``` 477 478 `MaxAge` durations are expressed in the Go [duration format](https://godoc.org/time#ParseDuration). Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". Only positive values are allowed and 0 disables the cache requiring a preflight OPTIONS check for all cross-origin requests. 479 480 ### Conditions 481 482 Each Route entry in a HTTPProxy **may** contain one or more conditions. 483 These conditions are combined with an AND operator on the route passed to Envoy. 484 485 Conditions can be either a `prefix` or a `header` condition. 486 487 #### Prefix conditions 488 489 For `prefix`, this adds a path prefix. 490 491 Up to one prefix condition may be present in any condition block. 492 493 Prefix conditions **must** start with a `/` if they are present. 494 495 #### Header conditions 496 497 For `header` conditions there is one required field, `name`, and five operator fields: `present`, `contains`, `notcontains`, `exact`, and `notexact`. 498 499 - `present` is a boolean and checks that the header is present. The value will not be checked. 500 501 - `contains` is a string, and checks that the header contains the string. `notcontains` similarly checks that the header does *not* contain the string. 502 503 - `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. 504 505 ### Routes 506 507 HTTPProxy must have at least one route or include defined. 508 Paths defined are matched using prefix conditions. 509 In this example, any requests to `multi-path.bar.com/blog` or `multi-path.bar.com/blog/*` will be routed to the Service `s2`. 510 All other requests to the host `multi-path.bar.com` will be routed to the Service `s1`. 511 512 ```yaml 513 # httpproxy-multiple-paths.yaml 514 apiVersion: projectcontour.io/v1 515 kind: HTTPProxy 516 metadata: 517 name: multiple-paths 518 namespace: default 519 spec: 520 virtualhost: 521 fqdn: multi-path.bar.com 522 routes: 523 - conditions: 524 - prefix: / # matches everything else 525 services: 526 - name: s1 527 port: 80 528 - conditions: 529 - prefix: /blog # matches `multi-path.bar.com/blog` or `multi-path.bar.com/blog/*` 530 services: 531 - name: s2 532 port: 80 533 ``` 534 535 In the following example, we match on headers and send to different services, with a default route if those do not match. 536 537 ```yaml 538 # httpproxy-multiple-headers.yaml 539 apiVersion: projectcontour.io/v1 540 kind: HTTPProxy 541 metadata: 542 name: multiple-paths 543 namespace: default 544 spec: 545 virtualhost: 546 fqdn: multi-path.bar.com 547 routes: 548 - conditions: 549 - header: 550 name: x-os 551 contains: ios 552 services: 553 - name: s1 554 port: 80 555 - conditions: 556 - header: 557 name: x-os 558 contains: android 559 services: 560 - name: s2 561 port: 80 562 - services: 563 - name: s3 564 port: 80 565 ``` 566 567 #### Multiple Upstreams 568 569 One of the key HTTPProxy features is the ability to support multiple services for a given path: 570 571 ```yaml 572 # httpproxy-multiple-upstreams.yaml 573 apiVersion: projectcontour.io/v1 574 kind: HTTPProxy 575 metadata: 576 name: multiple-upstreams 577 namespace: default 578 spec: 579 virtualhost: 580 fqdn: multi.bar.com 581 routes: 582 - services: 583 - name: s1 584 port: 80 585 - name: s2 586 port: 80 587 ``` 588 589 In this example, requests for `multi.bar.com/` will be load balanced across two Kubernetes Services, `s1`, and `s2`. 590 This is helpful when you need to split traffic for a given URL across two different versions of an application. 591 592 #### Upstream Weighting 593 594 Building on multiple upstreams is the ability to define relative weights for upstream Services. 595 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. 596 597 ```yaml 598 # httpproxy-weight-shfiting.yaml 599 apiVersion: projectcontour.io/v1 600 kind: HTTPProxy 601 metadata: 602 name: weight-shifting 603 namespace: default 604 spec: 605 virtualhost: 606 fqdn: weights.bar.com 607 routes: 608 - services: 609 - name: s1 610 port: 80 611 weight: 10 612 - name: s2 613 port: 80 614 weight: 90 615 ``` 616 617 In this example, we are sending 10% of the traffic to Service `s1`, while Service `s2` receives the remaining 90% of traffic. 618 619 HTTPProxy weighting follows some specific rules: 620 621 - If no weights are specified for a given route, it's assumed even distribution across the Services. 622 - 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). 623 - 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. 624 625 #### Request and Response Header Policies 626 627 Manipulating headers is also supported per-Service or per-Route. Headers can be set or 628 removed from the request or response as follows: 629 630 per-Service: 631 632 ```yaml 633 apiVersion: projectcontour.io/v1 634 kind: HTTPProxy 635 metadata: 636 name: header-manipulation 637 namespace: default 638 spec: 639 virtualhost: 640 fqdn: headers.bar.com 641 routes: 642 - services: 643 - name: s1 644 port: 80 645 requestHeadersPolicy: 646 set: 647 - name: X-Foo 648 value: bar 649 remove: 650 - X-Baz 651 responseHeadersPolicy: 652 set: 653 - name: X-Service-Name 654 value: s1 655 remove: 656 - X-Internal-Secret 657 ``` 658 659 per-Route: 660 661 ```yaml 662 apiVersion: projectcontour.io/v1 663 kind: HTTPProxy 664 metadata: 665 name: header-manipulation 666 namespace: default 667 spec: 668 virtualhost: 669 fqdn: headers.bar.com 670 routes: 671 - services: 672 - name: s1 673 port: 80 674 requestHeadersPolicy: 675 set: 676 - name: X-Foo 677 value: bar 678 remove: 679 - X-Baz 680 responseHeadersPolicy: 681 set: 682 - name: X-Service-Name 683 value: s1 684 remove: 685 - X-Internal-Secret 686 ``` 687 688 In these examples we are setting the header `X-Foo` with value `baz` on requests 689 and stripping `X-Baz`. We are then setting `X-Service-Name` on the response with 690 value `s1`, and removing `X-Internal-Secret`. 691 692 #### Traffic mirroring 693 694 Per route a service can be nominated as a mirror. 695 The mirror service will receive a copy of the read traffic sent to any non mirror service. 696 The mirror traffic is considered _read only_, any response by the mirror will be discarded. 697 698 This service can be useful for recording traffic for later replay or for smoke testing new deployments. 699 700 ```yaml 701 apiVersion: projectcontour.io/v1 702 kind: HTTPProxy 703 metadata: 704 name: traffic-mirror 705 namespace: default 706 spec: 707 virtualhost: 708 fqdn: www.example.com 709 routes: 710 - conditions: 711 - prefix: / 712 services: 713 - name: www 714 port: 80 715 - name: www-mirror 716 port: 80 717 mirror: true 718 ``` 719 720 #### Response Timeout 721 722 Each Route can be configured to have a timeout policy and a retry policy as shown: 723 724 ```yaml 725 # httpproxy-response-timeout.yaml 726 apiVersion: projectcontour.io/v1 727 kind: HTTPProxy 728 metadata: 729 name: response-timeout 730 namespace: default 731 spec: 732 virtualhost: 733 fqdn: timeout.bar.com 734 routes: 735 - timeoutPolicy: 736 response: 1s 737 idle: 10s 738 retryPolicy: 739 count: 3 740 perTryTimeout: 150ms 741 services: 742 - name: s1 743 port: 80 744 ``` 745 746 In this example, requests to `timeout.bar.com/` will have a response timeout policy of 1s. 747 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. 748 749 - `timeoutPolicy.response` This field can be any positive time period or "infinity". 750 This timeout covers the time from the *end of the client request* to the *end of the upstream response*. 751 By default, Envoy has a 15 second value for this timeout. 752 More information can be found in [Envoy's documentation][4]. 753 Note that a value of **0s** will be treated as if the field were not set, i.e. by using Envoy's default behavior. 754 - `timeoutPolicy.idle` This field can be any positive time period or "infinity". 755 By default, there is no per-route idle timeout. 756 Note that the default connection manager idle timeout of 5 minutes will apply if this is not set. 757 More information can be found in [Envoy's documentation][6]. 758 Note that a value of **0s** will be treated as if the field were not set, i.e. by using Envoy's default behavior. 759 760 TimeoutPolicy durations are expressed as per the format specified in the [ParseDuration documentation][5]. 761 Example input values: "300ms", "5s", "1m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". 762 The string 'infinity' is also a valid input and specifies no timeout. 763 764 - `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. 765 - `retryPolicy.count` specifies the maximum number of retries allowed. This parameter is optional and defaults to 1. 766 - `retryPolicy.perTryTimeout` specifies the timeout per retry. If this field is greater than the request timeout, it is ignored. This parameter is optional. 767 If left unspecified, `timeoutPolicy.request` will be used. 768 769 #### Load Balancing Strategy 770 771 Each route can have a load balancing strategy applied to determine which of its Endpoints is selected for the request. 772 The following list are the options available to choose from: 773 774 - `RoundRobin`: Each healthy upstream Endpoint is selected in round robin order (Default strategy if none selected). 775 - `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. 776 - `Random`: The random strategy selects a random healthy Endpoints. 777 778 More information on the load balancing strategy can be found in [Envoy's documentation][7]. 779 780 The following example defines the strategy for the route `/` as `WeightedLeastRequest`. 781 782 ```yaml 783 # httpproxy-lb-strategy.yaml 784 apiVersion: projectcontour.io/v1 785 kind: HTTPProxy 786 metadata: 787 name: lb-strategy 788 namespace: default 789 spec: 790 virtualhost: 791 fqdn: strategy.bar.com 792 routes: 793 - conditions: 794 - prefix: / 795 services: 796 - name: s1-strategy 797 port: 80 798 - name: s2-strategy 799 port: 80 800 loadBalancerPolicy: 801 strategy: WeightedLeastRequest 802 ``` 803 804 #### Session Affinity 805 806 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. 807 Contour supports session affinity on a per route basis with `loadBalancerPolicy` `strategy: Cookie`. 808 809 ```yaml 810 # httpproxy-sticky-sessions.yaml 811 apiVersion: projectcontour.io/v1 812 kind: HTTPProxy 813 metadata: 814 name: httpbin 815 namespace: default 816 spec: 817 virtualhost: 818 fqdn: httpbin.davecheney.com 819 routes: 820 - services: 821 - name: httpbin 822 port: 8080 823 loadBalancerPolicy: 824 strategy: Cookie 825 ``` 826 827 ##### Limitations 828 829 Session affinity is based on the premise that the backend servers are robust, do not change ordering, or grow and shrink according to load. 830 None of these properties are guaranteed by a Kubernetes cluster and will be visible to applications that rely heavily on session affinity. 831 832 Any perturbation in the set of pods backing a service risks redistributing backends around the hash ring. 833 834 #### Per route health checking 835 836 Active health checking can be configured on a per route basis. 837 Contour supports HTTP health checking and can be configured with various settings to tune the behavior. 838 839 During HTTP health checking Envoy will send an HTTP request to the upstream Endpoints. 840 It expects a 200 response if the host is healthy. 841 The upstream host can return 503 if it wants to immediately notify Envoy to no longer forward traffic to it. 842 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. 843 844 ```yaml 845 # httpproxy-health-checks.yaml 846 apiVersion: projectcontour.io/v1 847 kind: HTTPProxy 848 metadata: 849 name: health-check 850 namespace: default 851 spec: 852 virtualhost: 853 fqdn: health.bar.com 854 routes: 855 - conditions: 856 - prefix: / 857 healthCheckPolicy: 858 path: /healthy 859 intervalSeconds: 5 860 timeoutSeconds: 2 861 unhealthyThresholdCount: 3 862 healthyThresholdCount: 5 863 services: 864 - name: s1-health 865 port: 80 866 - name: s2-health 867 port: 80 868 ``` 869 870 Health check configuration parameters: 871 872 - `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. 873 - `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. 874 - `intervalSeconds`: The interval (seconds) between health checks. Defaults to 5 seconds if not set. 875 - `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. 876 - `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. 877 - `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. 878 879 #### WebSocket Support 880 881 WebSocket support can be enabled on specific routes using the `enableWebsockets` field: 882 883 ```yaml 884 # httpproxy-websockets.yaml 885 apiVersion: projectcontour.io/v1 886 kind: HTTPProxy 887 metadata: 888 name: chat 889 namespace: default 890 spec: 891 virtualhost: 892 fqdn: chat.example.com 893 routes: 894 - services: 895 - name: chat-app 896 port: 80 897 - conditions: 898 - prefix: /websocket 899 enableWebsockets: true # Setting this to true enables websocket for all paths that match /websocket 900 services: 901 - name: chat-app 902 port: 80 903 ``` 904 905 #### Permit Insecure 906 907 A HTTPProxy can be configured to permit insecure requests to specific Routes. 908 In this example, any request to `foo2.bar.com/blog` will not receive a 301 redirect to HTTPS, but the `/` route will: 909 910 ```yaml 911 apiVersion: projectcontour.io/v1 912 kind: HTTPProxy 913 metadata: 914 name: tls-example-insecure 915 namespace: default 916 spec: 917 virtualhost: 918 fqdn: foo2.bar.com 919 tls: 920 secretName: testsecret 921 routes: 922 - services: 923 - name: s1 924 port: 80 925 - conditions: 926 - prefix: /blog 927 permitInsecure: true 928 services: 929 - name: s2 930 port: 80 931 ``` 932 933 #### Path Rewriting 934 935 HTTPProxy supports rewriting the HTTP request URL path prior to delivering the request to the backend service. 936 Rewriting is performed after a routing decision has been made, and never changes the request destination. 937 938 The `pathRewritePolicy` field specifies how the path prefix should be rewritten. 939 The `replacePrefix` rewrite policy specifies a replacement string for a HTTP request path prefix match. 940 When this field is present, the path prefix that the request matched is replaced by the text specified in the `replacement` field. 941 If the HTTP request path is longer than the matched prefix, the remainder of the path is unchanged. 942 943 ```yaml 944 apiVersion: projectcontour.io/v1 945 kind: HTTPProxy 946 metadata: 947 name: rewrite-example 948 namespace: default 949 spec: 950 virtualhost: 951 fqdn: rewrite.bar.com 952 routes: 953 - services: 954 - name: s1 955 port: 80 956 pathRewritePolicy: 957 replacePrefix: 958 - replacement: /new/prefix 959 ``` 960 961 The `replacePrefix` field accepts an array of possible replacements. 962 When more than one `replacePrefix` array element is present, the `prefix` field can be used to disambiguate which replacement to apply. 963 964 If no `prefix` field is present, the replacement is applied to all prefix matches made against the route. 965 If a `prefix` field is present, the replacement is applied only to routes that have an exactly matching [prefix condition](#prefix-conditions). 966 Specifying more than one `replacePrefix` entry is mainly useful when a HTTPProxy document is included into multiple parent documents. 967 968 ```yaml 969 apiVersion: projectcontour.io/v1 970 kind: HTTPProxy 971 metadata: 972 name: rewrite-example 973 namespace: default 974 spec: 975 virtualhost: 976 fqdn: rewrite.bar.com 977 routes: 978 - services: 979 - name: s1 980 port: 80 981 conditions: 982 - prefix: /v1/api 983 pathRewritePolicy: 984 replacePrefix: 985 - prefix: /v1/api 986 replacement: /app/api/v1 987 - prefix: / 988 replacement: /app 989 ``` 990 991 ### Header Policy 992 993 HTTPProxy supports rewriting HTTP request and response headers. 994 The `Set` operation sets a HTTP header value, creating it if it doesn't already exist or overwriting it if it does. 995 The `Remove` operation removes a HTTP header. 996 The `requestHeadersPolicy` field is used to rewrite headers on a HTTP request, and the `responseHeadersPolicy` is used to rewrite headers on a HTTP response. 997 These fields can be specified on a route or on a specific service, depending on the rewrite granularity you need. 998 999 1000 ```yaml 1001 apiVersion: projectcontour.io/v1 1002 kind: HTTPProxy 1003 metadata: 1004 name: header-rewrite-example 1005 spec: 1006 virtualhost: 1007 fqdn: header.bar.com 1008 routes: 1009 - services: 1010 - name: s1 1011 port: 80 1012 requestHeadersPolicy: 1013 set: 1014 - name: Host 1015 value: external.dev 1016 remove: 1017 - Some-Header 1018 - Some-Other-Header 1019 ``` 1020 1021 ### ExternalName 1022 1023 HTTPProxy supports routing traffic to `ExternalName` service types. 1024 Contour looks at the `spec.externalName` field of the service and configures the route to use that DNS name instead of utilizing EDS. 1025 1026 There's nothing specific in the HTTPProxy object that needs to be configured other than referencing a service of type `ExternalName`. 1027 HTTPProxy supports the `requestHeadersPolicy` field to rewrite the `Host` header after first handling a request and before proxying to an upstream service. 1028 This field can be used to ensure that the forwarded HTTP request contains the hostname that the external resource is expecting. 1029 1030 NOTE: The ports are required to be specified. 1031 1032 ```yaml 1033 # httpproxy-externalname.yaml 1034 apiVersion: v1 1035 kind: Service 1036 metadata: 1037 labels: 1038 run: externaldns 1039 name: externaldns 1040 namespace: default 1041 spec: 1042 externalName: foo-basic.bar.com 1043 ports: 1044 - name: http 1045 port: 80 1046 protocol: TCP 1047 targetPort: 80 1048 type: ExternalName 1049 ``` 1050 1051 #### Proxy to external resource 1052 1053 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`. 1054 Then define a `requestHeadersPolicy` which replaces the `Host` header with the value of the external name service defined previously. 1055 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`. 1056 1057 ## HTTPProxy inclusion 1058 1059 HTTPProxy permits the splitting of a system's configuration into separate HTTPProxy instances using **inclusion**. 1060 1061 Inclusion, as the name implies, allows for one HTTPProxy object to be included in another, optionally with some conditions inherited from the parent. 1062 Contour reads the inclusion tree and merges the included routes into one big object internally before rendering Envoy config. 1063 Importantly, the included HTTPProxy objects do not have to be in the same namespace. 1064 1065 Each tree of HTTPProxy starts with a root, the top level object of the configuration for a particular virtual host. 1066 Each root HTTPProxy defines a `virtualhost` key, which describes properties such as the fully qualified name of the virtual host, TLS configuration, etc. 1067 1068 HTTPProxies included from the root must not contain a virtualhost key. 1069 Root objects cannot include other roots either transitively or directly. 1070 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. 1071 Because the path is not necessarily used as the only key, the route space can be multi-dimensional. 1072 1073 ### Conditions and Inclusion 1074 1075 Like Routes, Inclusion may specify a set of [conditions][8]. 1076 These conditions are added to any conditions on the routes included. 1077 This process is recursive. 1078 1079 Conditions are sets of individual condition statements, for example `prefix: /blog` is the condition that the matching request's path must start with `/blog`. 1080 When conditions are combined through inclusion Contour merges the conditions inherited via inclusion with any conditions specified on the route. 1081 This may result in duplicates, for example two `prefix:` conditions, or two header match conditions with the same name and value. 1082 To resolve this Contour applies the following logic. 1083 1084 - `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. 1085 - 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. 1086 1087 ### Configuring inclusion 1088 1089 Inclusion is a top-level part of the HTTPProxy `spec` element. 1090 It requires one field, `name`, and has two optional fields: 1091 1092 - `namespace`. This will assume the included HTTPProxy is in the same namespace if it's not specified. 1093 - a `conditions` block. 1094 1095 #### Within the same namespace 1096 1097 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. 1098 Note that `includes` is a list, and so it must use the YAML list construct. 1099 1100 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). 1101 It's important to note that `service2` HTTPProxy has not defined a `virtualhost` property as it is NOT a root HTTPProxy. 1102 1103 ```yaml 1104 # httpproxy-inclusion-samenamespace.yaml 1105 apiVersion: projectcontour.io/v1 1106 kind: HTTPProxy 1107 metadata: 1108 name: include-root 1109 namespace: default 1110 spec: 1111 virtualhost: 1112 fqdn: root.bar.com 1113 includes: 1114 # Includes the /service2 path from service2 in the same namespace 1115 - name: service2 1116 namespace: default 1117 conditions: 1118 - prefix: /service2 1119 routes: 1120 - conditions: 1121 - prefix: / 1122 services: 1123 - name: s1 1124 port: 80 1125 --- 1126 apiVersion: projectcontour.io/v1 1127 kind: HTTPProxy 1128 metadata: 1129 name: service2 1130 namespace: default 1131 spec: 1132 routes: 1133 - services: # matches /service2 1134 - name: s2 1135 port: 80 1136 - conditions: 1137 - prefix: /blog # matches /service2/blog 1138 services: 1139 - name: blog 1140 port: 80 1141 ``` 1142 1143 #### Virtualhost aliases 1144 1145 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. 1146 1147 ```yaml 1148 # httpproxy-inclusion-multipleroots.yaml 1149 --- 1150 apiVersion: projectcontour.io/v1 1151 kind: HTTPProxy 1152 metadata: 1153 name: multiple-root 1154 namespace: default 1155 spec: 1156 virtualhost: 1157 fqdn: bar.com 1158 includes: 1159 - name: main 1160 namespace: default 1161 --- 1162 apiVersion: projectcontour.io/v1 1163 kind: HTTPProxy 1164 metadata: 1165 name: multiple-root-www 1166 namespace: default 1167 spec: 1168 virtualhost: 1169 fqdn: www.bar.com 1170 includes: 1171 - name: main 1172 namespace: default 1173 --- 1174 apiVersion: projectcontour.io/v1 1175 kind: HTTPProxy 1176 metadata: 1177 name: main 1178 namespace: default 1179 spec: 1180 routes: 1181 - services: 1182 - name: s2 1183 port: 80 1184 ``` 1185 1186 #### Across namespaces 1187 1188 Inclusion can also happen across Namespaces by specifying a `namespace` in the `inclusion`. 1189 This is a particularly powerful paradigm for enabling multi-team Ingress management. 1190 1191 In this example, the root HTTPProxy has included configuration for paths matching `/blog` to the `blog` HTTPProxy object in the `marketing` namespace. 1192 1193 ```yaml 1194 # httpproxy-inclusion-across-namespaces.yaml 1195 --- 1196 apiVersion: projectcontour.io/v1 1197 kind: HTTPProxy 1198 metadata: 1199 name: namespace-include-root 1200 namespace: default 1201 spec: 1202 virtualhost: 1203 fqdn: ns-root.bar.com 1204 includes: 1205 # delegate the subpath, `/blog` to the HTTPProxy object in the marketing namespace with the name `blog` 1206 - name: blog 1207 namespace: marketing 1208 conditions: 1209 - prefix: /blog 1210 routes: 1211 - services: 1212 - name: s1 1213 port: 80 1214 1215 --- 1216 apiVersion: projectcontour.io/v1 1217 kind: HTTPProxy 1218 metadata: 1219 name: blog 1220 namespace: marketing 1221 spec: 1222 routes: 1223 - services: 1224 - name: s2 1225 port: 80 1226 ``` 1227 1228 ### Orphaned HTTPProxy children 1229 1230 It is possible for HTTPProxy objects to exist that have not been delegated to by another HTTPProxy. 1231 These objects are considered "orphaned" and will be ignored by Contour in determining ingress configuration. 1232 1233 ### Restricted root namespaces 1234 1235 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. 1236 Contour has an enforcing mode which accepts a list of namespaces where root HTTPProxy are valid. 1237 Only users permitted to operate in those namespaces can therefore create HTTPProxy with the `virtualhost` field. 1238 1239 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`). 1240 1241 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. 1242 1243 Additionally, when defined, Contour will only watch for Kubernetes secrets in these namespaces ignoring changes in all other namespaces. 1244 Proper RBAC rules should also be created to restrict what namespaces Contour has access matching the namespaces passed to the command line flag. 1245 An example of this is included in the [examples directory][12] and shows how you might create a namespace called `root-httproxy`. 1246 1247 > **NOTE: The restricted root namespace feature is only supported for HTTPProxy CRDs. 1248 > `--root-namespaces` does not affect the operation of `v1beta1.Ingress` objects** 1249 1250 ## TCP Proxying 1251 1252 HTTPProxy supports proxying of TLS encapsulated TCP sessions. 1253 1254 _Note_: The TCP session must be encrypted with TLS. 1255 This is necessary so that Envoy can use SNI to route the incoming request to the correct service. 1256 1257 ### TLS Termination at the edge 1258 1259 If `spec.virtualhost.tls.secretName` is present then that secret will be used to decrypt the TCP traffic at the edge. 1260 1261 ```yaml 1262 # httpproxy-tls-termination.yaml 1263 apiVersion: projectcontour.io/v1 1264 kind: HTTPProxy 1265 metadata: 1266 name: example 1267 namespace: default 1268 spec: 1269 virtualhost: 1270 fqdn: tcp.example.com 1271 tls: 1272 secretName: secret 1273 tcpproxy: 1274 services: 1275 - name: tcpservice 1276 port: 8080 1277 - name: otherservice 1278 port: 9999 1279 weight: 20 1280 ``` 1281 1282 The `spec.tcpproxy` key indicates that this _root_ HTTPProxy will forward the de-encrypted TCP traffic to the backend service. 1283 1284 ### TLS passthrough to the backend service 1285 1286 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. 1287 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. 1288 1289 ```yaml 1290 # httpproxy-tls-passthrough.yaml 1291 apiVersion: projectcontour.io/v1 1292 kind: HTTPProxy 1293 metadata: 1294 name: example 1295 namespace: default 1296 spec: 1297 virtualhost: 1298 fqdn: tcp.example.com 1299 tls: 1300 passthrough: true 1301 tcpproxy: 1302 services: 1303 - name: tcpservice 1304 port: 8080 1305 - name: otherservice 1306 port: 9999 1307 weight: 20 1308 ``` 1309 1310 ### TCPProxy delegation 1311 1312 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. 1313 HTTPProxy authors can delegate the configuration of a TCPProxy to the TCPProxy configuration defined in a HTTPProxy child object. 1314 1315 ```yaml 1316 # httpproxy-parent-termination.yaml 1317 apiVersion: projectcontour.io/v1 1318 kind: HTTPProxy 1319 metadata: 1320 name: parent 1321 namespace: default 1322 spec: 1323 virtualhost: 1324 fqdn: tcp.example.com 1325 tls: 1326 secretName: secret 1327 tcpproxy: 1328 include: 1329 name: child 1330 namespace: app 1331 --- 1332 # httpproxy-child-termination.yaml 1333 apiVersion: projectcontour.io/v1 1334 kind: HTTPProxy 1335 metadata: 1336 name: child 1337 namespace: app 1338 spec: 1339 tcpproxy: 1340 services: 1341 - name: tcpservice 1342 port: 8080 1343 - name: otherservice 1344 port: 9999 1345 weight: 20 1346 ``` 1347 In this example `default/parent` delegates the configuration of the TCPProxy services to `app/child`. 1348 1349 #### TCP Proxy health checking 1350 1351 Active health checking can be configured on a per route basis. 1352 Contour supports TCP health checking and can be configured with various settings to tune the behavior. 1353 1354 During TCP health checking Envoy will send a connect-only health check to the upstream Endpoints. 1355 It is important to note that these are health checks which Envoy implements and are separate from any 1356 other system such as those that exist in Kubernetes. 1357 1358 ```yaml 1359 apiVersion: projectcontour.io/v1 1360 kind: HTTPProxy 1361 metadata: 1362 name: tcp-health-check 1363 namespace: default 1364 spec: 1365 virtualhost: 1366 fqdn: health.bar.com 1367 tcpproxy: 1368 healthCheckPolicy: 1369 intervalSeconds: 5 1370 timeoutSeconds: 2 1371 unhealthyThresholdCount: 3 1372 healthyThresholdCount: 5 1373 services: 1374 - name: s1-health 1375 port: 80 1376 - name: s2-health 1377 port: 80 1378 ``` 1379 1380 TCP Health check policy configuration parameters: 1381 1382 - `intervalSeconds`: The interval (seconds) between health checks. Defaults to 5 seconds if not set. 1383 - `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. 1384 - `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. 1385 - `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. 1386 1387 ## Upstream Validation 1388 1389 When defining upstream services on a route, it's possible to configure the connection from Envoy to the backend endpoint to communicate over TLS. 1390 Two configuration items are required, a CA certificate and a `SubjectName` which are both used to verify the backend endpoint's identity. 1391 1392 The CA certificate bundle for the backend service should be supplied in a Kubernetes Secret. 1393 The referenced Secret must be of type "Opaque" and have a data key named `ca.crt`. 1394 This data value must be a PEM-encoded certificate bundle. 1395 1396 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]) 1397 1398 _Note: This annotation is applied to the Service not the Ingress or HTTPProxy object._ 1399 1400 ```yaml 1401 apiVersion: projectcontour.io/v1 1402 kind: HTTPProxy 1403 metadata: 1404 name: blog 1405 namespace: marketing 1406 spec: 1407 routes: 1408 - services: 1409 - name: s2 1410 port: 80 1411 validation: 1412 caSecret: foo-ca-cert 1413 subjectName: foo.marketing 1414 ``` 1415 1416 ## Client Certificate Validation 1417 1418 It is possible to protect the backend service from unauthorized external clients by requiring the client to present a valid TLS certificate. 1419 Envoy will validate the client certificate by verifying that it is not expired and that a chain of trust can be established to the configured trusted root CA certificate. 1420 Only those requests with a valid client certificate will be accepted and forwarded to the backend service. 1421 1422 ```yaml 1423 apiVersion: projectcontour.io/v1 1424 kind: HTTPProxy 1425 metadata: 1426 name: with-client-auth 1427 spec: 1428 virtualhost: 1429 fqdn: www.example.com 1430 tls: 1431 secretName: secret 1432 clientValidation: 1433 caSecret: client-root-ca 1434 routes: 1435 - services: 1436 - name: s1 1437 port: 80 1438 ``` 1439 1440 The preceding example enables validation by setting the optional `clientValidation` attribute. 1441 Its mandatory attribute `caSecret` contains a name of an existing Kubernetes Secret that must be of type "Opaque" and have a data key named `ca.crt`. 1442 The data value of the key `ca.crt` must be a PEM-encoded certificate bundle and it must contain all the trusted CA certificates that are to be used for validating the client certificate. 1443 1444 ## Status Reporting 1445 1446 There are many misconfigurations that could cause an HTTPProxy or delegation to be invalid. 1447 To aid users in resolving these issues, Contour updates a `status` field in all HTTPProxy objects. 1448 In the current specification, invalid HTTPProxy are ignored by Contour and will not be used in the ingress routing configuration. 1449 1450 If an HTTPProxy object is valid, it will have a status property that looks like this: 1451 1452 ```yaml 1453 status: 1454 currentStatus: valid 1455 description: valid HTTPProxy 1456 ``` 1457 1458 If the HTTPProxy is invalid, the `currentStatus` field will be `invalid` and the `description` field will provide a description of the issue. 1459 1460 As an example, if an HTTPProxy object has specified a negative value for weighting, the HTTPProxy status will be: 1461 1462 ```yaml 1463 status: 1464 currentStatus: invalid 1465 description: "route '/foo': service 'home': weight must be greater than or equal to zero" 1466 ``` 1467 1468 Some examples of invalid configurations that Contour provides statuses for: 1469 1470 - Negative weight provided in the route definition. 1471 - Invalid port number provided for service. 1472 - Prefix in parent does not match route in delegated route. 1473 - Root HTTPProxy created in a namespace other than the allowed root namespaces. 1474 - A given Route of an HTTPProxy both delegates to another HTTPProxy and has a list of services. 1475 - Orphaned route. 1476 - Delegation chain produces a cycle. 1477 - Root HTTPProxy does not specify fqdn. 1478 - Multiple prefixes cannot be specified on the same set of route conditions. 1479 - Multiple header conditions of type "exact match" with the same header key. 1480 - Contradictory header conditions on a route, e.g. a "contains" and "notcontains" condition for the same header and value. 1481 1482 [1]: https://kubernetes.io/docs/concepts/services-networking/ingress/ 1483 [2]: https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md 1484 [3]: {{< param github_url >}}/tree/{{< param version >}}/examples/example-workload/httpproxy 1485 [4]: https://www.envoyproxy.io/docs/envoy/v1.14.2/api-v2/api/v2/route/route_components.proto#envoy-api-field-route-routeaction-timeout 1486 [5]: https://godoc.org/time#ParseDuration 1487 [6]: https://www.envoyproxy.io/docs/envoy/v1.14.2/api-v2/api/v2/route/route_components.proto#envoy-api-field-route-routeaction-idle-timeout 1488 [7]: https://www.envoyproxy.io/docs/envoy/v1.14.2/intro/arch_overview/upstream/load_balancing/overview 1489 [8]: #conditions 1490 [9]: {% link docs/{{< param version >}}/annotations.md %} 1491 [10]: /docs/{{< param version >}}/api/#projectcontour.io/v1.Service 1492 [11]: configuration.md#fallback-certificate 1493 [12]: {{< param github_url >}}/tree/{{< param version >}}/examples/root-rbac