Traffic

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