Skip to content

Commit

Permalink
Add more hosting/health check doc. Fixes #535
Browse files Browse the repository at this point in the history
  • Loading branch information
plorenz committed Aug 24, 2023
1 parent 493bfe3 commit eb91cac
Show file tree
Hide file tree
Showing 2 changed files with 290 additions and 1 deletion.
289 changes: 289 additions & 0 deletions docusaurus/docs/guides/service-hosting/service-hosting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
---
title: Service Hosting
sidebar_label: Service Hosting
sidebar_position: 10
---

# Service Hosting

1. Review of terminators, cost and precedence
2. Manual terminator creation
3. App embedded
4. ER/T
5. SDK

### Edge Router Tunneler Hosting

#### Single Application Endpoint

Hosting services with the edge router tunneler combination requires a service configuration. The
initial setup will be simple, with one service endpoint. Following examples will build up from
there.

The example application server is going to be on a local subnet at IP 192.168.3.136, port 8080. For
the `test` service, create an initial service configuration using the CLI as follows:

```
ziti edge create config test-host-config host.v2 '
{
"terminators" : [
{
"address": "192.168.3.136",
"port" : 8080,
"protocol": "tcp"
},
]
}
'
ziti edge create service test -c test-host-config --terminator-strategy smartrouting
ziti edge create edge-router edge-router-1 --tunneler-enabled
ziti edge create edge-router edge-router-2 --tunneler-enabled
# skipping router enrollment steps
ziti edge update identity edge-router-1 --role-attributes 'test-host'
ziti edge update identity edge-router-2 --role-attributes 'test-host'
ziti edge create service-edge-router-policy test-serp --service-roles '@test' --edge-router-roles '#all'
ziti edge create service-policy test-bind Bind --service-roles '@test' --identity-roles '#test-host'
```

This will provide basic access to the service with one or many edge routers. All edge routers are
hitting the same endpoint, so they don't need any customized configurations. Each edge router
hosting the service will create a terminator for the service and traffic will get load-balanced
across them.

#### Setting Per-Identity Precedence and Cost

Cost and precedence can be used to give preference to specific identities. For example, given two
edge routers,
`edge-router-1` and `edge-router-2`, all traffic can be sent to `edge-router-1` while it's online
and available by using the `--service-precedences` flag of the `ziti edge update identity` command:

```
ziti edge update identity edge-router-1 --service-precedences test=required
```

Giving the terminator on `edge-router-2` a higher cost, so it gets used less often, can be done with
the
`--service-costs` flag:

```
ziti edge update identity edge-router-2 --service-costs test=100
```

The default cost and precedence for an identity can also be set.

```
ziti edge update identity edge-router-1 --default-hosting-precedence required --default-hosting-cost 100
```

#### Multiple Application Endpoints

Hosting configurations can support multiple application server endpoints. If a second endpoint is
added to the example configuration, traffic will be load balanced across the endpoints based on
their precedence and cost. Since in this case they have the same precedence and cost, traffic should
be routed fairly evenly across the two of them.

```
ziti edge update config test-host-config host.v2 --data '
{
"terminators" : [
{
"address": "192.168.3.136",
"port" : 8080,
"protocol": "tcp"
},
{
"address": "192.168.3.137",
"port" : 8080,
"protocol": "tcp"
}
]
}
'
```

Now each edge router will create two terminators, one for each endpoint, for a total of four
terminators. When multiple endpoints exist, it is important to know if each endpoint is healthy, so
that traffic is routed to only to healthy endpoints. This is accomplished by adding health checks to
the configuration.

```
ziti edge update config test-host-config host.v2 --data '
{
"terminators" : [
{
"address": "192.168.3.136",
"port" : 8080,
"protocol": "tcp",
"portChecks" : [
{
"address" : "192.168.3.136:8080",
"interval" : "5s",
"timeout" : "100ms",
"actions" : [
{
"trigger" : "fail",
"consecutiveEvents" : 3,
"action" : "mark unhealthy"
},
{
"trigger" : "pass",
"consecutiveEvents" : 3,
"action" : "mark healthy"
}
]
}
]
},
{
"address": "192.168.3.137",
"port" : 8080,
"protocol": "tcp",
"portChecks" : [
{
"address" : "192.168.3.137:8080",
"interval" : "5s",
"timeout" : "100ms",
"actions" : [
{
"trigger" : "fail",
"consecutiveEvents" : 3,
"action" : "mark unhealthy"
},
{
"trigger" : "pass",
"consecutiveEvents" : 3,
"action" : "mark healthy"
}
]
}
]
}
]
}
'
```

The application servers will now be pinged every five seconds. If a the health check fails three
times in a row, the associated terminator will be marked unhealthy, which means its precedence will
be set to `failed`. If subsequently the health check passes three times in a row, its precedence
will be reset to its original value.

This example uses simple port checks, but http checks are also supported. The checks are
per-terminator, so if the network fails between `edge-router-1` and the first application endpoint,
that terminator will be marked as failed. However, if `edge-router-2` can still reach it, then that
terminator will remain in `default` or `required`, depending on how it's configured.

This configuration now has multiple edge routers and multiple application endpoints, removing all
single points of failures. This setup should work well for applications which are horizontally
scalable.

#### Active/Passive Fail-over

Configurations for environments with primary and fail-over instances are also supported. These can
be configured by setting the precedence in the config, rather than on the identity, as follows:

```
ziti edge update config test-host-config host.v2 --data '
{
"terminators" : [
{
"address": "192.168.3.136",
"port" : 8080,
"protocol": "tcp",
"portChecks" : [ "health check definitions not shown for brevity" ],
"listenOptions" : {
"precedence" : "required"
}
},
{
"address": "192.168.3.137",
"port" : 8080,
"protocol": "tcp",
"portChecks" : [ "health check definitions not shown for brevity" ],
"listenOptions" : {
"precedence" : "default"
}
}
]
}
'
```

This example doesn't show the health checks in this example in order to highlight the important
change, namely the addition of the `listenOptions` section. The first terminator is set
to `required` and the second is set to `default`. Should the health check for the primary endpoint
fail, the terminator precedence will be dropped to `failed` and new traffic will start flowing to
the fail-over server. Should the primary recover, the health check will detect this and the
precedence will be reset to `required`.

Note that in addition to precedence, cost may also be set in the `listenOptions`.

### Standalone Tunneler Hosting

Most of the above applies to standalone tunnelers as well. The primary difference is in placement.
Generally a tunneler will be running on the same machine as the application server. This means that
there would be two tunnelers running, one on each of the hosts. The configuration could then
reference `localhost`, with only a single terminator in the host config. The configuration would
looking something like the following:

:::note Not all tunneler implementations have support for the full `host.v1` and `host.v2` configs.
The Go based tunneler, which is included in the edge router, has full support. Support in tunnelers
for other languages may be partial, or non-existent.
:::

```
ziti edge update config test-host-config host.v2 --data '
{
"terminators" : [
{
"address": "localhost",
"port" : 8080,
"protocol": "tcp",
"portChecks" : [
{
"address" : "localhost:8080",
"interval" : "5s",
"timeout" : "100ms",
"actions" : [
{
"trigger" : "fail",
"consecutiveEvents" : 3,
"action" : "mark unhealthy"
},
{
"trigger" : "pass",
"consecutiveEvents" : 3,
"action" : "mark healthy"
}
]
}
]
}
]
}
'
```

For fail-over setups, the precedence would be set on the identity, rather than in the configuration.

### SDK Hosted

SDK hosted applications do not require any configs. When they bind a service, a terminator is
created on their behalf. The SDKs have controls allowing cost and precedence to be set from the
hosting application. Finally, the connection to the edge router acts as a built in health check. If
the SDK loses its connection to the edge router, the edge router will remove any associated
terminators. When the SDK reconnects, it will re-bind and a new terminator will be established.

### Other Health Check Options

If the health checks provided by `host.v2` configs are not adequate, there are a few options.

1. A custom proxy using one of the SDKs. This allows adjusting cost and precedence based on
arbitrarily complex custom health checks.
2. A sidecar which runs the health checks and translates those into an HTTP health check that the
tunnelers can understand.
2 changes: 1 addition & 1 deletion publish.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ if [ "${GIT_BRANCH:-}" == "main" ]; then

./gendoc.sh # clone and build companion microsites and build Docusaurus

wget https://github.com/netfoundry/ziti-ci/releases/latest/download/ziti-ci # fetch latest release
wget https://github.com/openziti/ziti-ci/releases/latest/download/ziti-ci # fetch latest release
install ./ziti-ci /usr/local/bin/ # set executable bit and copy to executable search path

echo "configuring git..."
Expand Down

0 comments on commit eb91cac

Please sign in to comment.