Upstreams, health, and failover
An upstream is a named pool. It has one backend source, selection policy, optional active probes, passive outlier ejection, and connection policy.
Static pool
upstreams:
api:
algorithm: power_of_two
backends:
- { addr: "10.0.0.11:8080", weight: 1 }
- { addr: "10.0.0.12:8080", weight: 2 }
health_check:
kind: http
path: /healthz
host: api.internal
expected_status: 200
interval: 5s
timeout: 2s
healthy_threshold: 2
unhealthy_threshold: 2
outlier: { enabled: true, consecutive_errors: 5, ejection_time: 30s }
retry: { enabled: true, max_retries: 1, retry_on_connect_error: true }
timeout: { connect: 5s, read: 30s, write: 30s } Algorithms are round_robin (weighted), random, power_of_two (also p2c/least_conn), and consistent (also ketama). Backends support addr, optional weight, and TLS with tls: true plus an optional sni.
TCP health checks are the default. HTTP checks need a path and can set a Host header and expected status. A backend changes readiness only after the configured consecutive success or failure threshold. Passive outlier detection independently ejects a backend after consecutive gateway errors or timeouts, then retries it after ejection_time. A retry is to a different backend and is primarily for connection failures; use idempotent request semantics when enabling retries.
Discovery: DNS SRV and Consul
upstreams:
# Resolve this fully-qualified SRV owner on the refresh interval.
catalog:
discovery:
dns-srv: { service: "_http._tcp.catalog.internal.", refresh_interval: 15s }
# Query the Consul health/service API. Keep the ACL token out of YAML.
payments:
discovery:
consul:
address: "https://consul.internal:8501"
service: payments
tags: [edge]
datacenter: dc1
token_file: /run/secrets/consul-token
refresh_interval: 15s
max_wait: 30s Discovery is shipped for DNS SRV and Consul. It is mutually exclusive with a static backends list and a managed pool. DNS SRV discovery uses the configured service owner. Consul uses its HTTP(S) API, optional tag and datacenter filters, and a file-backed ACL token. Neither source changes through a hot config reload; restart after changing discovery configuration.
Docker managed pools
upstreams:
worker:
managed:
provider: docker
selector: "omlb.pool=worker"
port: 8080
network: appnet
replicas: 3
interval: 5s
recreate_grace: 10s
restart_backoff: 5s
max_actions_per_min: 6
min_healthy: 1
health_check: { kind: http, path: /healthz } Managed pools are single-host Docker supervision, not a container orchestrator. OMLB adopts containers selected with Docker’s label-filter syntax, derives backend addresses from their selected network, and can maintain the requested healthy replica count. It deliberately pauses lifecycle actions after the configured per-minute limit instead of continuing a crash loop. Managed mode is mutually exclusive with static and discovery sources.
Drain before maintenance
Use the local admin API to disable one existing static backend, wait for in-flight work to finish, maintain it, then enable it again. Draining is runtime state and does not rewrite YAML:
curl -X POST http://127.0.0.1:9090/pools/api/backends/10.0.0.11:8080/drain
curl -X POST http://127.0.0.1:9090/pools/api/backends/10.0.0.11:8080/undrain