Set Up a Network Load Balancer
Prerequisites
Before setting up a network load balancer, ensure the following prerequisites are met:
- Create a private network and a router connecting the virtual network to the provider network (public).
- Create 3 virtual machines (for the example scenario).
- The user account used for configuring the load balancer must have the
load-balancer_memberrole assigned. - Ensure you have the
python-octaviaclientinstalled when using the CLI:
Create a Load Balancer and Assign a VIP in Horizon Dashboard
Navigate to Project → Network → Load Balancers and click Create Load Balancer
This opens a multi-step wizard that walks through the full setup process.
Load Balancer Details
- Name: Enter a name for your load balancer (e.g.,
my-loadbalancer). - IP address: Optionally specify a VIP address. If left blank, one will be auto-assigned from the selected subnet.
- Description: Optionally add a description.
- Provider: Select "ovn".
- Availability Zone: Leave as default.
- Flavor: Leave as default.
- Subnet: Select the subnet your backend instances are connected to.
Click Next to proceed.
Listener Details
- Name: Enter a name for the listener (e.g.,
my-listener-tcp). - Protocol: Select the protocol. With the OVN provider, only Layer 4 protocols are supported:
TCP,UDP, andSCTP. - Port: Enter the port number the load balancer will listen on (e.g.,
80).
Warning
Application-layer protocols such as HTTP, HTTPS, and TERMINATED_HTTPS are not supported with the OVN provider.
Click Next to proceed.
Pool Details
- Name: Enter a name for the pool (e.g.,
my-pool). - Algorithm: Select
SOURCE_IP_PORT. - Session Persistence: Leave default as
None. - TLS Enabled: Leave default as
No - Admin State Up: Leave default as
Yes
Warning
The OVN provider only supports the SOURCE_IP_PORT algorithm. Other algorithms such as ROUND_ROBIN or
LEAST_CONNECTIONS will cause the pool creation to fail.
Click Next to proceed.
Pool Members
Click Add next to the instances you want to include as backend members. For each member:
- IP Address: Should be auto-populated from the instance's port on the selected subnet.
- Port: Enter the port your backend application is listening on (e.g.,
80). - Weight: Leave as
1for equal distribution.
Repeat for all backend instances (e.g., 3 instances in the example scenario).
Click Next to proceed.
Health Monitor (optional)
This step is optional but recommended. Configuring a health monitor ensures that unhealthy members are automatically removed from the pool.
- Name: Enter a name (e.g.,
my-healthmonitor). - Type: Select the monitor type (
TCP,PING,HTTP,HTTPS,TLS-HELLO,UDP-CONNECT, orSCTP). - Delay (seconds): Interval between health checks (e.g.,
5). - Timeout (seconds): Maximum time to wait for a response before marking a member as unresponsive (e.g.,
3). This value should generally be lower than the delay. - Max Retries Down: Number of consecutive failures before marking a member as
ERROR(default:3). - Max Retries: Number of successful checks before marking a member as
ONLINE(e.g.,3).
Click Create Load Balancer to finalize.
Verify Status
After creation, the load balancer will briefly show a Provisioning Status of PENDING_CREATE. Once provisioning
completes, verify that:
- Provisioning Status is
ACTIVE - Operating Status is
ONLINE
You can check this from the Project → Network → Load Balancers list view or by clicking on the load balancer name to view its detail page. The detail page also shows the status of listeners, pools, members, and health monitors.
If all if the Operating Status is marked as DEGRADED or ERROR, it implies that health monitors are failing to
reach the pool members
Associate a Floating IP (optional)
To make the load balancer accessible externally, associate a floating IP with its VIP:
- Navigate to Project → Network → Floating IPs.
- Click Allocate IP to Project and select the external network. Click Allocate IP.
- On the newly allocated floating IP row, click Associate.
- In the Port to be associated dropdown, select the VIP port of your load balancer. It will appear in the format
<vip_address> - <loadbalancer_name>. - Click Associate.
The load balancer is now reachable at the associated floating IP address.
Create a Load Balancer and Assign a VIP using the CLI
Create a load balancer (this will automatically assign a VIP on the same tenant network as the future load balancer backends):
Example output
+---------------------+--------------------------------------+
| Field | Value |
+---------------------+--------------------------------------+
| admin_state_up | True |
| availability_zone | None |
| created_at | 2024-10-28T12:31:11 |
| description | |
| flavor_id | None |
| id | c8f95a99-4504-4a80-a9b4-7a91564b94b1 |
| listeners | |
| name | my-loadbalancer |
| operating_status | OFFLINE |
| pools | |
| project_id | 91876c533032496fb2cdec6508a37022 |
| provider | ovn |
| provisioning_status | PENDING_CREATE |
| updated_at | None |
| vip_address | 192.168.11.146 |
| vip_network_id | be664f78-ffd4-4056-9586-47004665d07d |
| vip_port_id | 22d689b0-9e4f-4026-bf74-96497e3c08ed |
| vip_qos_policy_id | None |
| vip_subnet_id | 98b7db4e-4a37-4716-b9a6-4e68f88a99aa |
| vip_vnic_type | normal |
| tags | |
| additional_vips | [] |
+---------------------+--------------------------------------+
Create Listeners for Different Protocols
Create listeners for different protocols (supported listener protocols are limited to L4 protocols, specifically TCP,
UDP and SCTP):
openstack loadbalancer listener create --name <listener_name> --protocol <protocol> --protocol-port <port_number> <loadbalancer_name>
In the example below, notice operating_status and provisioning_status – we will verify it later.
Example output
+-----------------------------+--------------------------------------+
| Field | Value |
+-----------------------------+--------------------------------------+
| admin_state_up | True |
| connection_limit | -1 |
| created_at | 2024-10-28T14:21:04 |
| default_pool_id | None |
| default_tls_container_ref | None |
| description | |
| id | 1d9da659-b487-48dd-b0ad-b97c467a5736 |
| insert_headers | None |
| l7policies | |
| loadbalancers | c8f95a99-4504-4a80-a9b4-7a91564b94b1 |
| name | my-listener-tcp |
| operating_status | OFFLINE |
| project_id | 91876c533032496fb2cdec6508a37022 |
| protocol | TCP |
| protocol_port | 80 |
| provisioning_status | PENDING_CREATE |
| sni_container_refs | [] |
| timeout_client_data | 50000 |
| timeout_member_connect | 5000 |
| timeout_member_data | 50000 |
| timeout_tcp_inspect | 0 |
| updated_at | None |
| client_ca_tls_container_ref | None |
| client_authentication | NONE |
| client_crl_container_ref | None |
| allowed_cidrs | None |
| tls_ciphers | None |
| tls_versions | None |
| alpn_protocols | None |
| tags | |
| hsts_max_age | |
| hsts_include_subdomains | |
| hsts_preload | |
+-----------------------------+--------------------------------------+
Define Pools and Add Backend Instances
Create a pool (the only supported load-balancing algorithm for OVN is SOURCE_IP_PORT):
openstack loadbalancer pool create --name <pool_name> --lb-algorithm <lb_algorithm> --listener <listener_name> --protocol <protocol>
In the example below, notice operating_status and provisioning_status – we will verify it later.
Example output
+----------------------+--------------------------------------+
| Field | Value |
+----------------------+--------------------------------------+
| admin_state_up | True |
| created_at | 2024-10-28T15:14:35 |
| description | |
| healthmonitor_id | |
| id | b44c510f-4237-4789-9c56-3018f260c4f8 |
| lb_algorithm | SOURCE_IP_PORT |
| listeners | 1d9da659-b487-48dd-b0ad-b97c467a5736 |
| loadbalancers | c8f95a99-4504-4a80-a9b4-7a91564b94b1 |
| members | |
| name | my-pool |
| operating_status | OFFLINE |
| project_id | 91876c533032496fb2cdec6508a37022 |
| protocol | TCP |
| provisioning_status | PENDING_CREATE |
| session_persistence | None |
| updated_at | None |
| tls_container_ref | None |
| ca_tls_container_ref | None |
| crl_container_ref | None |
| tls_enabled | False |
| tls_ciphers | None |
| tls_versions | None |
| tags | |
| alpn_protocols | None |
+----------------------+--------------------------------------+
Add members (backend instances) to the pool (repeat this command for each instance you want to add):
openstack loadbalancer member create --subnet-id <subnet_id> --address <instance_ip> --protocol-port 80 --name <member_name> <pool_name>
In the example below, notice operating_status and provisioning_status – we will verify it later.
Example output
+---------------------+--------------------------------------+
| Field | Value |
+---------------------+--------------------------------------+
| address | 192.168.11.180 |
| admin_state_up | True |
| created_at | 2024-10-28T15:28:24 |
| id | 6d409adc-9de1-416f-b88c-813640713231 |
| name | my-member1 |
| operating_status | NO_MONITOR |
| project_id | 91876c533032496fb2cdec6508a37022 |
| protocol_port | 80 |
| provisioning_status | PENDING_CREATE |
| subnet_id | 98b7db4e-4a37-4716-b9a6-4e68f88a99aa |
| updated_at | None |
| weight | 1 |
| monitor_port | None |
| monitor_address | None |
| backup | False |
| tags | |
| vnic_type | normal |
+---------------------+--------------------------------------+
Attach a Floating IP
To make the load balancer accessible externally in case of IPv4 load balancers, you need to attach a floating IP to the VIP. Create a floating IP:
Example output
+---------------------+--------------------------------------+
| Field | Value |
+---------------------+--------------------------------------+
| created_at | 2024-10-29T13:11:19Z |
| description | |
| dns_domain | |
| dns_name | |
| fixed_ip_address | None |
| floating_ip_address | 86.119.80.170 |
| floating_network_id | 4ee098c1-82aa-4a43-923f-8e3dcb07971b |
| id | 08ae348d-9cd9-4e7a-b754-c4ac0d95e9b9 |
| name | 86.119.80.170 |
| port_details | None |
| port_id | None |
| project_id | 91876c533032496fb2cdec6508a37022 |
| qos_policy_id | None |
| revision_number | 0 |
| router_id | None |
| status | DOWN |
| subnet_id | None |
| tags | [] |
| updated_at | 2024-10-29T13:11:19Z |
+---------------------+--------------------------------------+
Use the below command to associate the floating IP with the load balancer (if successful, no output).
vip_port_id was shown in the output of the openstack loadbalancer create command.
floating_ip_id was shown in the output of the openstack floating ip create command.
You can also retrieve vip_port_id with the below command:
Create a Health Monitor
This is an optional step, but an important one if you want the loadbalancer to automatically monitor its members and make sure they are not used if they are not available. Create a health monitor:
openstack loadbalancer healthmonitor create --name <healthmonitor_name> --delay <delay_seconds> --timeout <timeout_seconds> --max-retries-down <max_retries_down> --max-retries <retry_count> --type <protocol_type> <pool_name_or_id>
Example output
+---------------------+--------------------------------------+
| Field | Value |
+---------------------+--------------------------------------+
| project_id | 91876c533032496fb2cdec6508a37022 |
| name | my-healthmonitor |
| admin_state_up | True |
| pools | b44c510f-4237-4789-9c56-3018f260c4f8 |
| created_at | 2024-10-29T14:08:11 |
| provisioning_status | PENDING_CREATE |
| updated_at | None |
| delay | 5 |
| expected_codes | None |
| max_retries | 3 |
| http_method | None |
| timeout | 3 |
| max_retries_down | 3 |
| url_path | None |
| type | TCP |
| id | f4b111b1-60c9-42bb-ab6b-cbe9aa4e6bfd |
| operating_status | OFFLINE |
| http_version | None |
| domain_name | None |
| tags | |
+---------------------+--------------------------------------+
Explanation:
-
--delay <delay_seconds>specifies the interval between health checks. -
--timeout <timeout_seconds>specifies the maximum time that the health monitor will wait for a response from a pool member before marking it as unresponsive. This value should generally be lower than --delay to avoid excessive delays in detecting unresponsive members. -
--max-retries-down <max_retries_down>specifies the number of allowed check failures before changing the operating status of the member to ERROR. This parameter is optional. If not specified the default value is '3'. -
--max-retries <retry_count>specifies the number of successful checks before changing the operating status of the member to ONLINE. -
--typesets the health monitor type {PING,HTTP,TCP,HTTPS,TLS-HELLO,UDP-CONNECT,SCTP}. -
<pool_name_or_id>sets the pool for the health monitor.
Verification
provisioning_status should be ACTIVE, and operating_status should be ONLINE.
Verify load balancer status:
Example output
+---------------------+--------------------------------------+
| Field | Value |
+---------------------+--------------------------------------+
| admin_state_up | True |
| availability_zone | None |
| created_at | 2024-10-28T12:31:11 |
| description | |
| flavor_id | None |
| id | c8f95a99-4504-4a80-a9b4-7a91564b94b1 |
| listeners | 1d9da659-b487-48dd-b0ad-b97c467a5736 |
| name | my-loadbalancer |
| operating_status | ONLINE |
| pools | b44c510f-4237-4789-9c56-3018f260c4f8 |
| project_id | 91876c533032496fb2cdec6508a37022 |
| provider | ovn |
| provisioning_status | ACTIVE |
| updated_at | 2024-10-29T12:54:26 |
| vip_address | 192.168.11.146 |
| vip_network_id | be664f78-ffd4-4056-9586-47004665d07d |
| vip_port_id | 22d689b0-9e4f-4026-bf74-96497e3c08ed |
| vip_qos_policy_id | None |
| vip_subnet_id | 98b7db4e-4a37-4716-b9a6-4e68f88a99aa |
| vip_vnic_type | normal |
| tags | |
| additional_vips | [] |
+---------------------+--------------------------------------+
Verify listener status:
Example output
+-----------------------------+--------------------------------------+
| Field | Value |
+-----------------------------+--------------------------------------+
| admin_state_up | True |
| connection_limit | -1 |
| created_at | 2024-10-28T14:21:04 |
| default_pool_id | b44c510f-4237-4789-9c56-3018f260c4f8 |
| default_tls_container_ref | None |
| description | |
| id | 1d9da659-b487-48dd-b0ad-b97c467a5736 |
| insert_headers | None |
| l7policies | |
| loadbalancers | c8f95a99-4504-4a80-a9b4-7a91564b94b1 |
| name | my-listener-tcp |
| operating_status | ONLINE |
| project_id | 91876c533032496fb2cdec6508a37022 |
| protocol | TCP |
| protocol_port | 80 |
| provisioning_status | ACTIVE |
| sni_container_refs | [] |
| timeout_client_data | 50000 |
| timeout_member_connect | 5000 |
| timeout_member_data | 50000 |
| timeout_tcp_inspect | 0 |
| updated_at | 2024-10-29T12:54:26 |
| client_ca_tls_container_ref | None |
| client_authentication | NONE |
| client_crl_container_ref | None |
| allowed_cidrs | None |
| tls_ciphers | None |
| tls_versions | None |
| alpn_protocols | None |
| tags | |
| hsts_max_age | |
| hsts_include_subdomains | |
| hsts_preload | |
+-----------------------------+--------------------------------------+
Verify pool status:
Example output
+----------------------+--------------------------------------+
| Field | Value |
+----------------------+--------------------------------------+
| admin_state_up | True |
| created_at | 2024-10-28T15:14:35 |
| description | |
| healthmonitor_id | |
| id | b44c510f-4237-4789-9c56-3018f260c4f8 |
| lb_algorithm | SOURCE_IP_PORT |
| listeners | 1d9da659-b487-48dd-b0ad-b97c467a5736 |
| loadbalancers | c8f95a99-4504-4a80-a9b4-7a91564b94b1 |
| members | edd94119-8704-456c-b9c9-93d663211c4d |
| | 81038d82-034d-4116-ada2-8a831a92ba7d |
| | 6d409adc-9de1-416f-b88c-813640713231 |
| name | my-pool |
| operating_status | ONLINE |
| project_id | 91876c533032496fb2cdec6508a37022 |
| protocol | TCP |
| provisioning_status | ACTIVE |
| session_persistence | None |
| updated_at | 2024-10-29T12:54:26 |
| tls_container_ref | None |
| ca_tls_container_ref | None |
| crl_container_ref | None |
| tls_enabled | False |
| tls_ciphers | None |
| tls_versions | None |
| tags | |
| alpn_protocols | None |
+----------------------+--------------------------------------+
Verify pool members' status:
Example output
+--------------------------------------+------------+----------------------------------+---------------------+----------------+---------------+------------------+--------+
| id | name | project_id | provisioning_status | address | protocol_port | operating_status | weight |
+--------------------------------------+------------+----------------------------------+---------------------+----------------+---------------+------------------+--------+
| 6d409adc-9de1-416f-b88c-813640713231 | my-member1 | 91876c533032496fb2cdec6508a37022 | ACTIVE | 192.168.11.180 | 80 | ONLINE | 1 |
| edd94119-8704-456c-b9c9-93d663211c4d | my-member2 | 91876c533032496fb2cdec6508a37022 | ACTIVE | 192.168.11.150 | 80 | ONLINE | 1 |
| 81038d82-034d-4116-ada2-8a831a92ba7d | my-member3 | 91876c533032496fb2cdec6508a37022 | ACTIVE | 192.168.11.163 | 80 | ONLINE | 1 |
+--------------------------------------+------------+----------------------------------+---------------------+----------------+---------------+------------------+--------+
Verify health monitor status:
Example output
+---------------------+--------------------------------------+
| Field | Value |
+---------------------+--------------------------------------+
| project_id | 91876c533032496fb2cdec6508a37022 |
| name | my-healthmonitor |
| admin_state_up | True |
| pools | b44c510f-4237-4789-9c56-3018f260c4f8 |
| created_at | 2024-10-29T14:08:11 |
| provisioning_status | ACTIVE |
| updated_at | 2024-10-29T14:08:12 |
| delay | 5 |
| expected_codes | None |
| max_retries | 3 |
| http_method | None |
| timeout | 3 |
| max_retries_down | 3 |
| url_path | None |
| type | TCP |
| id | f4b111b1-60c9-42bb-ab6b-cbe9aa4e6bfd |
| operating_status | ONLINE |
| http_version | None |
| domain_name | None |
| tags | |
+---------------------+--------------------------------------+