Skip to main content
An upstream normally lists its servers. Since DNZ v2 a load balancer can take them from a DNS name instead: every address of the name is a server, and the list follows the name as addresses come and go. It is how DNZ follows a Docker Swarm without being given Docker API credentials. The upstream dialog’s Servers from has three cards:

Every address of a DNS name

DNZ asks its own DNS server, as a client on the same machine would: DNZ’s zones and views first, then the cache and forwarding. A name in one of DNZ’s zones needs nothing else, and CNAMEs are followed. Each address becomes one server, reached with the scheme (HTTP: http, https or h2c) and the port you give, from IPv4 (A), IPv6 (AAAA) or both. Each server has a weight of 1. With https, Skip TLS verification accepts any certificate from all of them.
  • When. Again when the answer’s TTL ends, but not sooner than Not sooner than every (30 seconds by default, 5 to 3,600) and at least once an hour. The proxies get new servers only when the set of addresses changes; Traefik and Caddy pick them up at their next poll.
  • Errors keep the last servers. No answer, SERVFAIL or a name without addresses never empties an upstream: the list says stale since … with the error, and the proxies keep sending visits to the last servers found.
  • A name that stops existing. After 10 minutes of NXDOMAIN the upstream is emptied, an incident is recorded and a proxy alert (origins) goes out; another one follows when the name answers again.
  • Loops are refused. Addresses of the proxies themselves (their own addresses and their DNZ Proxy nodes’), on a port the proxies serve (80, 443 or an entry point’s), are left out: such a server would send visits back into the proxy. The list and Test name the addresses left out.
  • Saving looks the name up at once, so a new upstream has its servers when the proxies get it.
  • In a cluster, only the leader looks names up. A DNZ secondary following a primary doesn’t: proxies aren’t replicated, and nothing here changes a DNS answer.

Setting the name up

The dialog’s guide offers The name exists or Set it up. For a Swarm behind its routing mesh, give every Swarm node’s address: each one answers on the service’s published port. The guide writes the record set for the zone the name is in, for example:
When that zone is one of DNZ’s, Add 3 records to example.local adds them. A short TTL lets a Swarm node that leaves or joins reach the proxies within a minute. The upstream is then the name and the published port: swarm-nodes.example.local, port 8080.
Proxy → Upstreams → Add upstream → Load balancer → Servers from → Every address of a DNS name, then the name, port and scheme. Test shows the servers the name gives now, without saving.

Docker Swarm tasks

tasks.<service> lists a Swarm service’s running tasks, but only Docker’s DNS inside the service’s overlay network answers it, so DNZ can’t. Each proxy looks the name up itself instead:
  • DNZ Proxy nodes look the name up every 10 seconds (and whenever a new configuration arrives) and make each address a server of its own, with its own health checks, weight, sticky sessions and line in the node’s report, rather than one server for the whole name. A failed lookup keeps the last set, with a warning in the node’s report. A changed set never interrupts traffic: visits in flight finish on the server they started with.
  • Caddy looks the name up itself every 10 seconds (dynamic upstreams from A records). Caddy takes such an upstream only on its own: inside a Split, Fallback or Mirror only the name’s servers are used and the other upstreams are left out, with a warning.
  • Traefik can’t make each address of a name a server, so DNZ refuses such an upstream on a Traefik proxy, both when saving it and when a route there picks it. Use Every address of a DNS name instead, or Traefik’s own Docker Swarm provider.
Task addresses are overlay addresses: only nodes in that network reach them. For proxy nodes outside the Swarm, use Every address of a DNS name with the Swarm nodes’ addresses and the service’s published port instead.

Setting the Swarm up

The dialog’s guide (Set it up) is copy-paste, with DNZ’s address and the connect key filled in, and never assumes the Swarm runs next to DNZ:
1

An attachable overlay network

On a Swarm manager (skip it when the service already has a network the nodes may join):
2

The service in that network

Or add the network under the service’s networks: in its stack file.
3

The DNZ Proxy nodes in that network

In the Swarm stack the nodes run from, add the network to the service and declare it as external:
dnz-proxy-stack.yml
A node started with docker run gets --network dnz-apps; with Compose, the same networks: as above.
4

The upstream

The service’s name (web) and the port its tasks listen on:
In the dashboard: Servers from → Docker Swarm tasks. Test shows what each DNZ Proxy node found for it, from their reports.

In the upstream list

The list says where the servers come from, for example 3 servers from swarm-nodes.example.local, 2 min ago, or that they are stale while lookups fail. dnz proxy upstreams list shows NAME:PORT (3 found) (or each proxy for Swarm tasks) as the servers, and show the name, how many servers it gave and when, and the error while lookups fail. Everywhere else:
  • Configuration as code: from_dns takes the place of servers in the proxy’s YAML; the servers found are never in the file. See Configuration as code.
  • Route history shows the upstream’s name, not the servers found.
  • Topology: an upstream’s node says the name it follows. See Topology map.
  • Prometheus: dnz_proxy_upstream_discovered_servers{upstream, stale} and dnz_proxy_upstream_discovery_errors_total. See Prometheus.
  • AI assistants: proxy_upstreams shows where the servers come from and what was found, set_proxy_upstream takes from_dns, and discover_proxy_upstream looks a name up. See AI assistants.
  • API: see Upstreams.
DNZ doesn’t ask a Swarm manager’s API for services, tasks and nodes. That would need a Docker API client certificate, which gives root over the whole Swarm; the two ways above need no credentials.