Learn OpenStack · core/load-balancing
Octavia Operations
Prerequisites
Confirm the Octavia endpoint is reachable and the amphora image is registered:
openstack loadbalancer provider list
openstack image list --tag amphora
All openstack loadbalancer commands require the python-openstackclient package with the python-octaviaclient plugin. Operations that change state (create, update, delete, failover) are asynchronous — poll provisioning_status until ACTIVE.
Load Balancers
Create
# Minimal: specify a subnet for the VIP
openstack loadbalancer create \
--name web-lb \
--vip-subnet-id private-subnet
# Specify a fixed VIP address on the subnet
openstack loadbalancer create \
--name web-lb \
--vip-subnet-id private-subnet \
--vip-address 192.168.1.100
# Use an HA topology via a flavor
openstack loadbalancer create \
--name web-lb-ha \
--vip-subnet-id private-subnet \
--flavor ha-medium
# Use the OVN provider for lightweight internal LB
openstack loadbalancer create \
--name internal-lb \
--vip-subnet-id private-subnet \
--provider ovn
List and Show
openstack loadbalancer list
openstack loadbalancer list --name web-lb
openstack loadbalancer show web-lb
# Watch until ACTIVE (poll every 5 s)
watch -n 5 openstack loadbalancer show web-lb
Update
# Rename
openstack loadbalancer set web-lb --name prod-lb
# Add a description
openstack loadbalancer set prod-lb --description "Production web tier LB"
Delete
# Delete LB and all its child resources (listeners, pools, members)
openstack loadbalancer delete web-lb --cascade
# Without --cascade, delete fails if child resources exist
openstack loadbalancer delete web-lb
Assign a Floating IP to the VIP
# Get the Neutron port ID of the VIP
VIP_PORT=$(openstack loadbalancer show web-lb -f value -c vip_port_id)
# Allocate a floating IP
FIP=$(openstack floating ip create provider-net -f value -c floating_ip_address)
# Associate with the VIP port
openstack floating ip set --port $VIP_PORT $FIP
echo "Load balancer reachable at $FIP"
Listeners
Listeners define the front-end protocol and port that the load balancer accepts traffic on.
Create
# HTTP listener on port 80
openstack loadbalancer listener create \
--name http-listener \
--protocol HTTP \
--protocol-port 80 \
web-lb
# HTTPS passthrough (TCP) on port 443 — back-end handles TLS
openstack loadbalancer listener create \
--name https-passthrough \
--protocol TCP \
--protocol-port 443 \
web-lb
# TLS termination at the load balancer (Barbican secret required)
openstack loadbalancer listener create \
--name https-listener \
--protocol TERMINATED_HTTPS \
--protocol-port 443 \
--default-tls-container-ref $(openstack secret list --name web-cert -f value -c "Secret href") \
web-lb
# UDP listener (e.g., for DNS)
openstack loadbalancer listener create \
--name dns-listener \
--protocol UDP \
--protocol-port 53 \
dns-lb
# Set connection limit (-1 = unlimited)
openstack loadbalancer listener create \
--name http-listener \
--protocol HTTP \
--protocol-port 80 \
--connection-limit 10000 \
web-lb
List and Show
openstack loadbalancer listener list
openstack loadbalancer listener list --loadbalancer web-lb
openstack loadbalancer listener show http-listener
Update and Delete
openstack loadbalancer listener set http-listener --connection-limit 5000
openstack loadbalancer listener delete http-listener
Pools
Pools hold the back-end members and define the load-balancing algorithm.
Create
# Attach directly to a listener
openstack loadbalancer pool create \
--name web-pool \
--protocol HTTP \
--lb-algorithm ROUND_ROBIN \
--listener http-listener
# Attach to the load balancer (not a listener) — for use as a default pool
openstack loadbalancer pool create \
--name generic-pool \
--protocol TCP \
--lb-algorithm LEAST_CONNECTIONS \
--loadbalancer web-lb
# Session persistence: SOURCE_IP
openstack loadbalancer pool create \
--name sticky-pool \
--protocol HTTP \
--lb-algorithm ROUND_ROBIN \
--session-persistence type=SOURCE_IP \
--listener http-listener
# Session persistence: HTTP cookie
openstack loadbalancer pool create \
--name cookie-pool \
--protocol HTTP \
--lb-algorithm ROUND_ROBIN \
--session-persistence type=HTTP_COOKIE,cookie_name=SERVERID \
--listener http-listener
Supported algorithms:
| Algorithm | Behaviour |
|---|---|
ROUND_ROBIN |
Requests distributed in turn |
LEAST_CONNECTIONS |
Requests sent to member with fewest active connections |
SOURCE_IP |
Requests from same client IP always go to same member |
SOURCE_IP_PORT |
Requests from same client IP+port always go to same member |
List, Show, Update, Delete
openstack loadbalancer pool list
openstack loadbalancer pool show web-pool
openstack loadbalancer pool set web-pool --lb-algorithm LEAST_CONNECTIONS
openstack loadbalancer pool delete web-pool
Members
Members are the back-end servers that receive traffic from the pool.
Add Members
# Add a member by IP address and port
openstack loadbalancer member create \
--name web-1 \
--address 192.168.1.10 \
--protocol-port 8080 \
web-pool
openstack loadbalancer member create \
--name web-2 \
--address 192.168.1.11 \
--protocol-port 8080 \
web-pool
# Add with a custom weight (higher = more traffic)
openstack loadbalancer member create \
--name web-heavy \
--address 192.168.1.12 \
--protocol-port 8080 \
--weight 5 \
web-pool
# Add a backup member (only used when all primary members are down)
openstack loadbalancer member create \
--name web-backup \
--address 192.168.1.20 \
--protocol-port 8080 \
--backup \
web-pool
# Specify the subnet for members on a different subnet than the VIP
openstack loadbalancer member create \
--name web-3 \
--address 10.0.2.15 \
--protocol-port 8080 \
--subnet-id backend-subnet \
web-pool
Batch Update (replace entire member list)
# Replace all members in one API call (PUT /lbaas/pools/{pool_id}/members)
openstack loadbalancer member batch update web-pool \
--members '[{"address":"192.168.1.10","protocol_port":8080},{"address":"192.168.1.11","protocol_port":8080}]'
List, Show, Update, Delete
openstack loadbalancer member list web-pool
openstack loadbalancer member show web-pool web-1
openstack loadbalancer member set web-pool web-1 --weight 2
openstack loadbalancer member delete web-pool web-1
Drain a Member
Set weight to 0 to stop sending new connections while existing ones complete:
openstack loadbalancer member set web-pool web-1 --weight 0
# Wait for connections to drain, then remove
openstack loadbalancer member delete web-pool web-1
Health Monitors
Health monitors probe back-end members and mark them ONLINE or ERROR based on responses.
Create
# HTTP health check — GET /healthz, expect 200
openstack loadbalancer healthmonitor create \
--name hm-http \
--type HTTP \
--delay 5 \
--timeout 3 \
--max-retries 3 \
--url-path /healthz \
--expected-codes 200 \
web-pool
# HTTPS health check
openstack loadbalancer healthmonitor create \
--name hm-https \
--type HTTPS \
--delay 5 \
--timeout 3 \
--max-retries 3 \
--url-path /health \
--expected-codes 200,204 \
web-pool
# TCP health check (just checks TCP connect)
openstack loadbalancer healthmonitor create \
--name hm-tcp \
--type TCP \
--delay 10 \
--timeout 5 \
--max-retries 3 \
web-pool
# UDP-CONNECT health check
openstack loadbalancer healthmonitor create \
--name hm-udp \
--type UDP-CONNECT \
--delay 5 \
--timeout 3 \
--max-retries 3 \
dns-pool
# Set max-retries-down separately (failures before marking ERROR)
openstack loadbalancer healthmonitor create \
--name hm-strict \
--type HTTP \
--delay 5 \
--timeout 3 \
--max-retries 3 \
--max-retries-down 2 \
--url-path / \
--expected-codes 200 \
web-pool
Health monitor parameters:
| Parameter | Meaning |
|---|---|
--delay |
Seconds between probes |
--timeout |
Seconds to wait for a probe response |
--max-retries |
Consecutive successes to mark member ONLINE |
--max-retries-down |
Consecutive failures to mark member ERROR (default = --max-retries) |
List, Show, Update, Delete
openstack loadbalancer healthmonitor list
openstack loadbalancer healthmonitor show hm-http
openstack loadbalancer healthmonitor set hm-http --delay 10
openstack loadbalancer healthmonitor delete hm-http
L7 Policies and Rules
L7 policies allow content-based routing based on HTTP headers, URLs, or cookies.
Create an L7 Policy
# Redirect /api/** to a different pool
openstack loadbalancer l7policy create \
--name api-policy \
--listener http-listener \
--action REDIRECT_TO_POOL \
--redirect-pool api-pool \
--position 1
# Redirect a path to a URL
openstack loadbalancer l7policy create \
--name old-path-redirect \
--listener http-listener \
--action REDIRECT_TO_URL \
--redirect-url https://new.example.com/ \
--position 2
# Reject requests matching a rule
openstack loadbalancer l7policy create \
--name block-policy \
--listener http-listener \
--action REJECT \
--position 3
Create L7 Rules
Each L7 policy requires one or more rules. All rules in a policy must match (AND logic) for the policy to trigger.
# Match requests where path starts with /api
openstack loadbalancer l7rule create \
--compare-type STARTS_WITH \
--type PATH \
--value /api \
api-policy
# Match on HTTP header
openstack loadbalancer l7rule create \
--compare-type EQUAL_TO \
--type HEADER \
--key X-API-Version \
--value v2 \
api-policy
# Match on cookie value
openstack loadbalancer l7rule create \
--compare-type EQUAL_TO \
--type COOKIE \
--key canary \
--value true \
canary-policy
# Invert a rule (NOT match)
openstack loadbalancer l7rule create \
--compare-type STARTS_WITH \
--type PATH \
--value /public \
--invert \
private-policy
L7 rule types: HOST_NAME, PATH, FILE_TYPE, HEADER, COOKIE
L7 compare types: REGEX, STARTS_WITH, ENDS_WITH, CONTAINS, EQUAL_TO
List and Delete L7 Resources
openstack loadbalancer l7policy list --listener http-listener
openstack loadbalancer l7policy show api-policy
openstack loadbalancer l7rule list api-policy
openstack loadbalancer l7policy delete api-policy
Stats and Status
Load Balancer Stats
# Traffic statistics for the load balancer
openstack loadbalancer stats show web-lb
# Statistics for a specific listener
openstack loadbalancer listener stats show http-listener
# Statistics for a pool
openstack loadbalancer pool stats show web-pool
Stats fields returned:
| Field | Meaning |
|---|---|
active_connections |
Current open connections |
bytes_in |
Total bytes received from clients |
bytes_out |
Total bytes sent to clients |
request_errors |
HTTP requests that resulted in errors |
total_connections |
Total connections since last reset |
Operational Status
# Check all resources in one command (shows tree)
openstack loadbalancer status show web-lb
Amphora Failover
Trigger a manual failover (replaces the amphora VM with a new one):
# Fail over the amphora backing a specific load balancer
openstack loadbalancer failover web-lb
# List amphorae to find specific IDs
openstack loadbalancer amphora list
openstack loadbalancer amphora show <amphora-id>
# Fail over a specific amphora by ID
openstack loadbalancer amphora failover <amphora-id>
Failover workflow: Octavia boots a new amphora, configures it identically to the failed one, then deletes the old VM. During failover the load balancer's provisioning_status is PENDING_UPDATE.
Quotas
# Show quotas for the current project
openstack loadbalancer quota show
# Show quotas for a specific project (admin)
openstack loadbalancer quota show --project my-project
# Set quotas (admin)
openstack loadbalancer quota set \
--loadbalancer 10 \
--listener 50 \
--pool 50 \
--member 200 \
--healthmonitor 50 \
my-project
# Reset to defaults
openstack loadbalancer quota delete my-project
Flavors
# List available load balancer flavors
openstack loadbalancer flavor list
# Show flavor details
openstack loadbalancer flavor show large
# Create a flavor profile (admin)
openstack loadbalancer flavorprofile create \
--name ha-large-profile \
--provider amphora \
--flavor-data '{"compute_flavor": "m1.xlarge", "loadbalancer_topology": "ACTIVE_STANDBY"}'
# Create a flavor (admin)
openstack loadbalancer flavor create \
--name ha-large \
--flavorprofile ha-large-profile \
--description "HA load balancer on xlarge compute"
# Use the flavor
openstack loadbalancer create \
--name prod-lb \
--vip-subnet-id private-subnet \
--flavor ha-large
Availability Zones
# List availability zones
openstack loadbalancer availabilityzone list
# Create an availability zone profile (admin)
openstack loadbalancer availabilityzoneprofile create \
--name az1-profile \
--provider amphora \
--availability-zone-data '{"compute_zone": "nova-az1"}'
# Create an availability zone (admin)
openstack loadbalancer availabilityzone create \
--name az1 \
--availabilityzoneprofile az1-profile
# Pin a load balancer to an availability zone
openstack loadbalancer create \
--name az1-lb \
--vip-subnet-id private-subnet \
--availability-zone az1
Common Troubleshooting
# Check overall service health
openstack loadbalancer amphora list
# Find amphorae in ERROR state
openstack loadbalancer amphora list --status ERROR
# Check logs on the amphora (requires SSH access to management network)
ssh -i /etc/octavia/ssh/octavia_ssh_key ubuntu@<amphora-mgmt-ip>
sudo journalctl -u amphora-agent
sudo haproxy -c -f /var/lib/octavia/<lb-uuid>/haproxy.cfg
# Check health-manager is receiving heartbeats
# (on health-manager host)
sudo tcpdump -i any udp port 5555
# Check octavia-worker logs
journalctl -u octavia-worker --since "10 minutes ago"
# Reset a stuck load balancer (admin)
openstack loadbalancer set web-lb --provisioning-status ACTIVE