โ† Back to Tutorials
3 June 2026ยท4 min read

Set Up an Octavia Load Balancer in OpenStack

Make apps highly available with Octavia: create a load balancer, add a listener and a member pool, attach health monitors, and expose it with a floating IP.

A single web server is a single point of failure. Octavia, OpenStack's load-balancing service, solves this by distributing traffic across a pool of backend instances and steering it away from any that fail a health check. It is the cloud-scale successor to the single-host Nginx reverse proxy โ€” same idea, but elastic, API-driven, and highly available.

This tutorial builds a working HTTP load balancer end to end: a load balancer on a subnet, a listener on port 80, a member pool of two instances, and a health monitor that removes unhealthy members automatically. It assumes you already have tenant networking and at least two running instances serving a web app.

Prerequisites

  • A running OpenStack 2025.2 cloud with the Octavia (load-balancer) service enabled.
  • The openstack client with the python-octaviaclient plugin installed.
  • Two instances on acme-subnet running a web server on port 80, plus their private IPs.
source ~/acme-openrc
openstack loadbalancer provider list
openstack server list -c Name -c Networks

The Octavia object model

Four objects stack together. A load balancer owns a VIP on a subnet. A listener binds a protocol and port (for example HTTP:80) on that VIP. A pool defines how traffic is balanced and groups the backends. Members are the backend instances in the pool, and a health monitor probes them so only healthy members receive traffic.

Step 1: Create the load balancer

Create the load balancer on your tenant subnet. Octavia provisions an Amphora VM (or driver-specific resource) to host the VIP, so this step takes a minute or two:

openstack loadbalancer create --name acme-lb --vip-subnet-id acme-subnet
openstack loadbalancer show acme-lb -c provisioning_status -c vip_address

Wait until provisioning_status reads ACTIVE before continuing. You can poll it, or watch the operating status:

openstack loadbalancer list -c name -c provisioning_status -c operating_status

Step 2: Add a listener

The listener accepts client connections. Create an HTTP listener on port 80 attached to the load balancer:

openstack loadbalancer listener create --name acme-listener \
  --protocol HTTP --protocol-port 80 acme-lb

Step 3: Create a pool

The pool decides the balancing algorithm and holds the members. ROUND_ROBIN is a sensible default; LEAST_CONNECTIONS suits long-lived connections:

openstack loadbalancer pool create --name acme-pool \
  --lb-algorithm ROUND_ROBIN --listener acme-listener --protocol HTTP

Step 4: Add members

Add each backend instance to the pool by its private IP and the subnet it lives on. Repeat for every backend:

openstack loadbalancer member create --name web-01 \
  --address 10.0.0.42 --protocol-port 80 --subnet-id acme-subnet acme-pool
openstack loadbalancer member create --name web-02 \
  --address 10.0.0.43 --protocol-port 80 --subnet-id acme-subnet acme-pool

Step 5: Attach a health monitor

The health monitor periodically probes each member and pulls failing ones out of rotation. An HTTP monitor that expects a 200 on / is a good start:

openstack loadbalancer healthmonitor create --name acme-hm \
  --delay 5 --timeout 3 --max-retries 3 --type HTTP --url-path / acme-pool

Step 6: Expose the VIP and test

The VIP is on the private subnet. Attach a floating IP to it so clients on the outside can reach the load balancer, then test that requests are distributed:

openstack floating ip create ext-net
openstack loadbalancer show acme-lb -c vip_port_id
openstack floating ip set --port <vip_port_id> 203.0.113.80

from outside, repeat requests โ€” responses should alternate between backends

for i in $(seq 1 6); do curl -s http://203.0.113.80/ | grep -o 'web-0[12]'; done

Verification

Confirm everything is healthy. Both the load balancer and the pool members should report a healthy operating status:

openstack loadbalancer status show acme-lb
openstack loadbalancer member list acme-pool -c name -c operating_status

operating_status should be ONLINE for healthy members

To prove failover works, stop the web server on one backend and watch its member flip to ERROR while traffic continues uninterrupted to the other.

Common errors and troubleshooting

Load balancer stuck in PENDING_CREATE

Octavia is still building the Amphora, or the service cannot schedule one. Give it a few minutes; if it never goes ACTIVE, an admin should check the Octavia worker logs and that the management network and image for Amphorae exist.

Members show as ERROR / offline

The health monitor cannot reach the backend. Confirm the web server is actually listening on port 80, and that a security group on the members allows traffic from the load balancer subnet on that port.

Curl times out on the VIP

Usually the floating IP is not associated with the VIP port, or no security group permits port 80 inbound. Re-check the floating IP association and the listener protocol/port.

All traffic hits one backend

Persistent connections or session stickiness can mask round-robin. Use separate requests (as in the loop above) and confirm the pool algorithm is ROUND_ROBIN.

Cleaning up

openstack loadbalancer delete acme-lb --cascade

openstack floating ip delete 203.0.113.80

Conclusion

You have built a highly available HTTP service: a load balancer with a listener, a balanced pool, health-checked members, and a public VIP โ€” all provisioned through the API and resilient to a backend failure. This is the cloud-scale version of fronting an app with a reverse proxy, and it is how production workloads stay online during deploys and outages. Combine it with persistent volumes and multiple instances for a complete, resilient stack.

Running Octavia in production โ€” with redundant Amphorae, TLS termination, and capacity to spare โ€” is part of the managed platform clouditiv operates on a sovereign on-premise cloud, so your apps get cloud-grade high availability without you maintaining the load-balancing fleet.