diff --git a/app/_gateway_entities/target.md b/app/_gateway_entities/target.md index 5091b1db8d..72c3dceffc 100644 --- a/app/_gateway_entities/target.md +++ b/app/_gateway_entities/target.md @@ -64,6 +64,10 @@ For example, let's say you add `api.host.com:123` with `weight=100`: The balancer honors the DNS record's `ttl` setting. Upon expiry, it queries the nameserver and updates the balancer. When a DNS record has `ttl=0`, the hostname is added as a single target, with the specified weight. The nameserver is queried for every request, adding latency to the request. +## Managing failover Targets {% new_in 3.12 %} + +{% include_cached /gateway/failover-targets.md %} + ## Schema {% entity_schema %} diff --git a/app/_gateway_entities/upstream.md b/app/_gateway_entities/upstream.md index 6754205119..f9d4bdace0 100644 --- a/app/_gateway_entities/upstream.md +++ b/app/_gateway_entities/upstream.md @@ -296,6 +296,10 @@ rows: hashing: "Avoids routing to unhealthy or terminating pods." {% endtable %} +### Managing failover Targets {% new_in 3.12 %} + +{% include_cached /gateway/failover-targets.md %} + ## Schema {% entity_schema %} diff --git a/app/_how-tos/route-requests-to-backup-targets.md b/app/_how-tos/route-requests-to-backup-targets.md new file mode 100644 index 0000000000..d93f3079d6 --- /dev/null +++ b/app/_how-tos/route-requests-to-backup-targets.md @@ -0,0 +1,171 @@ +--- +title: Route requests to backup Targets during failures +content_type: how_to + +description: Use the Route by Header plugin to route requests based on a header value. + +products: + - gateway + +works_on: + - on-prem + +min_version: + gateway: '3.12' + +entities: + - service + - route + - upstream + - target + +tags: + - failover +search_aliases: + - backup target + +tldr: + q: How do I route requests to different Targets in case my other Targets are unhealthy? + a: "Create a Service, a Route, and an Upstream with one of the `latency`, `least-connections`, or `round-robin` load balancing strategies. Configure primary Targets on the Upstream with `failover: false` and a failover Target with `failover: true`." + +tools: + - deck +related_resources: + - text: Upstream entity + url: /gateway/entities/upstream/ + - text: Target entity + url: /gateway/entities/target/ + +cleanup: + inline: + - title: Destroy the {{site.base_gateway}} container + include_content: cleanup/products/gateway + icon_url: /assets/icons/gateway.svg + +faqs: + - q: Can I set more than one failover Target? + a: Yes, Upstream supports multiple failover Targets. +--- + +## Start three Target backends + +In this tutorial, we're going to have two primary Targets and one [failover Target](/gateway/entities/target/#managing-failover-targets). In this configuration, traffic will be routed to only the primary Targets if they are both healthy. If they are *both* unhealthy, traffic will be routed to the failover Target. + +We'll use three backends to represent our three Targets using Docker’s ultra-small `hashicorp/http-echo` image: + +```sh +docker run -d --rm --name primary1 -p 9001:5678 hashicorp/http-echo -text "PRIMARY-1" +docker run -d --rm --name primary2 -p 9002:5678 hashicorp/http-echo -text "PRIMARY-2" +docker run -d --rm --name failover -p 9003:5678 hashicorp/http-echo -text "FAILOVER" +``` + +## Configure a Gateway Service, Route, and Upstream + +Configure a Gateway Service and Route to point to the Upstream: +{% entity_examples %} +entities: + upstreams: + - name: example-upstream + services: + - name: example-service + host: example-upstream + protocol: http + routes: + - name: example-route + paths: + - "/anything" + service: + name: example-service +{% endentity_examples %} + +## Configure the Upstream Targets + +Now, you can configure Upstream with the two primary Targets `failover: false` and one failover Target `failover: true`. + +1. Configure the first primary Target: +{% capture primary %} + +{% control_plane_request %} +url: /upstreams/example-upstream/targets/ +method: POST +headers: + - 'Accept: application/json' +body: + target: host.docker.internal:9001 + weight: 100 + failover: false +{% endcontrol_plane_request %} + +{% endcapture %} +{{ primary | indent: 3}} + +1. Configure the second primary Target: +{% capture secondary %} + +{% control_plane_request %} +url: /upstreams/example-upstream/targets/ +method: POST +headers: + - 'Accept: application/json' +body: + target: host.docker.internal:9002 + weight: 100 + failover: false +{% endcontrol_plane_request %} + +{% endcapture %} +{{ secondary | indent: 3}} + +1. Configure the failover Target: +{% capture failover %} + +{% control_plane_request %} +url: /upstreams/example-upstream/targets/ +method: POST +headers: + - 'Accept: application/json' +body: + target: host.docker.internal:9003 + weight: 50 + failover: true +{% endcontrol_plane_request %} + +{% endcapture %} +{{ failover | indent: 3}} + +## Verify that the primary Targets handle traffic + +Run the following to verify that only the primary Targets handle traffic because they are both healthy: + +```sh +for i in {1..10}; do curl -sS http://localhost:8000/anything; echo; done +``` + +You'll get an output like the following, where you can see the Targets cycling between `PRIMARY-1` and `PRIMARY-2`: +```sh +PRIMARY-2 + +PRIMARY-1 + +PRIMARY-1 + +PRIMARY-2 + +PRIMARY-2 + +PRIMARY-2 +``` +{:.no-copy-code} + +## Validate failover + +To validate that the failover Target works, let's mark the primary Targets as unhealthy by shutting down the hosts. Run the following: +```sh +docker stop primary1 primary2 +``` + +You can now validate that since the primary Targets are *both* unhealthy, only the failover Target routes traffic: +```sh +for i in {1..6}; do curl -s http://localhost:8000/anything; echo; done +``` +This time, the response should show the `FAILOVER` Target instead of `PRIMARY`. diff --git a/app/_includes/gateway/failover-targets.md b/app/_includes/gateway/failover-targets.md new file mode 100644 index 0000000000..a9f148fc4e --- /dev/null +++ b/app/_includes/gateway/failover-targets.md @@ -0,0 +1,19 @@ + +You can set `failover: true` to indicate that a Target should be used as a failover (backup) Target in case the other, regular targets (`failover: false`) associated with an Upstream are unhealthy. The failover Target is only used when *all* regular Targets are unhealthy. You can set one or multiple failover Targets for an Upstream. + +Failover Targets are supported by the [latency](/gateway/entities/upstream/#latency), [least-connections](/gateway/entities/upstream/#least-connections), and [round-robin](/gateway/entities/upstream/#round-robin) load balancing algorithms. + +{:.info} +> **Note**: If you set failover Targets for Upstreams with the [consistent-hashing](/gateway/entities/upstream/#consistent-hashing) or [sticky session](/gateway/entities/upstream/#sticky-sessions) load balancing algorithms, they *won't* be used for regular load balancing or as a failover. + +The following is an example failover Target configuration: + +{% entity_example %} +type: target +data: + target: 192.168.1.3:8080 + weight: 50 + failover: true +{% endentity_example %} + +For a complete tutorial, see [Route requests to backup Targets during failures](/how-to/route-requests-to-backup-targets/). \ No newline at end of file