Load Balancers (OVN)
Early Access
The OVN load balancer provider is currently in a pre-release state and is not yet final. It may be updated or changed without prior notice. As it is still being refined, you may encounter occasional inaccuracies or bugs.
Important: In its current state we recommend use for evaluation and testing purposes only and not for production environments. For any questions or to report issues, please contact our support team.
The OVN provider is currently only available in the regions DUS2, HAM1 and FES.
The OVN provider (ovn) implements load balancers natively in the OVN software-defined network.
Instead of provisioning a virtual machine per load balancer, the OVN provider creates OVN load
balancer objects. These objects are distributed across all hypervisors of the cluster, so the load
balancer has no single point of failure and does not consume any additional compute resources.
Compared to the Amphora provider, the OVN provider offers
- No additional virtual machines are consumed by the load balancer
- Faster provisioning, because no virtual machine needs to be created and configured
- A distributed load balancer without a single point of failure
- L4 load balancing for
TCP
The following features are not available with the OVN provider
- Listener protocols other than
TCP - L7 policies
- Session persistence types other than
SOURCE_IP - Health monitors types other than
TCP
The provider is selected when the load balancer is created and can not be changed afterwards.
- Load Balancers - general information and provider comparison
- Load Balancers (Amphora) - the amphora-based implementation
Create a Load Balancer
You can create a Load Balancer along with all resources at once, including a Listener, a Pool with
Pool Members. An OVN load balancer is created the same way as an Amphora load balancer, except that
you have to select the provider ovn when creating the load balancer.
Creation of Load Balancer with Listener, Pool and Pool Members
Usage
openstack loadbalancer create --name <LOADBALANCER_NAME> --vip-subnet-id <SUBNET_ID or SUBNET_NAME> --provider ovn --wait
openstack loadbalancer listener create --name <LISTENER_NAME> --protocol <PROTOCOL> --protocol-port <PORT> --wait <LOADBALANCER_NAME>
openstack loadbalancer pool create --name <POOL_NAME> --lb-algorithm <METHOD> --listener <LISTENER_NAME> --protocol <PROTOCOL> --wait
openstack loadbalancer member create --subnet-id <SUBNET_ID or SUBNET_NAME> --address <ADDRESS> --protocol-port <PORT> --wait <POOL_NAME>
--name: The name you assign to your resources.--provider: The provider used to implement the load balancer. Options areamphorav2andovn.--vip-subnet-id: The ID of the subnet where the virtual IP (VIP) of the load balancer will be created.--lb-algorithm: The load balancing method used (e.g., SOURCE_IP_PORT).--protocol: The protocol used by the listener and the pool members. Current option isTCP.--address: The IP address of the pool member.--protocol-port: The port on which the pool member will accept traffic.--wait: awaits the creation of the prior resource in order to use it for creation of the next one.
Example
openstack loadbalancer create --name ovn-lb-01 --vip-subnet-id private-subnet-01 --provider ovn --wait
openstack loadbalancer listener create --name ovn-list-01 --protocol TCP --protocol-port 80 --wait ovn-lb-01
openstack loadbalancer pool create --name ovn-pl-01 --lb-algorithm SOURCE_IP_PORT --listener ovn-list-01 --protocol TCP --wait
openstack loadbalancer member create --subnet-id private-subnet-01 --address 192.0.2.199 --protocol-port 80 --wait ovn-pl-01
openstack loadbalancer member create --subnet-id private-subnet-01 --address 192.0.2.241 --protocol-port 80 --wait ovn-pl-01
Output
openstack loadbalancer show ovn-lb-01
+---------------------+--------------------------------------+
| Field | Value |
+---------------------+--------------------------------------+
| admin_state_up | True |
| availability_zone | None |
| created_at | 2025-03-12T09:15:04 |
| description | |
| flavor_id | None |
| id | 3c7d8e2b-4f1a-4b6c-9d5e-8a2c1f0e7b93 |
| listeners | |
| name | ovn-lb-01 |
| operating_status | ONLINE |
| pools | |
| project_id | 0c12ce74a0084c0b8fef8e15d4a3377d |
| provider | ovn |
| provisioning_status | ACTIVE |
| updated_at | 2025-03-12T09:15:08 |
| vip_address | 192.0.2.110 |
| vip_network_id | 245a6750-77c5-4701-8df3-4b4ac55295d3 |
| vip_port_id | c81f2a64-9b3d-4e07-a5c1-6d4e8f2a9c05 |
| vip_qos_policy_id | None |
| vip_subnet_id | a7d7e676-d668-4ec7-8b7d-3c28f68caab3 |
| vip_vnic_type | normal |
| tags | |
| additional_vips | |
+---------------------+--------------------------------------+
Example: Create complete Load Balancer
# versions.tf
terraform {
required_version = ">= 1.3.0"
required_providers {
openstack = {
source = "terraform-provider-openstack/openstack"
version = "~> 3.4.0"
}
}
}
# vars.tf
variable "ssh_publickey" {
type = string
description = "ssh-rsa public key in authorized_keys format (ssh-rsa AAAAB3Nz [...] ABAAACAC62Lw== user@host)"
}
# main.tf
provider "openstack" {
}
data "openstack_images_image_v2" "image" {
most_recent = true
visibility = "public"
properties = {
os_distro = "ubuntu"
os_version = "24.04"
}
}
data "openstack_networking_network_v2" "ext-net" {
name = "ext-net"
}
resource "openstack_compute_keypair_v2" "keypair" {
name = "lb_keypair"
public_key = var.ssh_publickey
}
resource "openstack_networking_secgroup_v2" "sg_ssh" {
name = "allow_ssh_and_icmp"
description = "Allow inbound SSH/ICMP for IPv4 and IPv6"
}
resource "openstack_networking_secgroup_rule_v2" "ssh" {
direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = 22
port_range_max = 22
remote_ip_prefix = "0.0.0.0/0"
security_group_id = openstack_networking_secgroup_v2.sg_ssh.id
}
resource "openstack_networking_secgroup_rule_v2" "icmp" {
direction = "ingress"
ethertype = "IPv4"
protocol = "icmp"
remote_ip_prefix = "0.0.0.0/0"
security_group_id = openstack_networking_secgroup_v2.sg_ssh.id
}
resource "openstack_networking_secgroup_v2" "sg_web" {
name = "sg_web"
description = "Allow inbound HTTP"
}
resource "openstack_networking_secgroup_rule_v2" "http" {
direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = 80
port_range_max = 80
remote_ip_prefix = "0.0.0.0/0"
security_group_id = openstack_networking_secgroup_v2.sg_web.id
}
resource "openstack_networking_network_v2" "net_lbdemo" {
name = "net_lbdemo"
admin_state_up = true
}
resource "openstack_networking_subnet_v2" "subnet_lbdemo" {
name = "subnet_lbdemo"
network_id = openstack_networking_network_v2.net_lbdemo.id
cidr = "192.168.1.0/24"
dns_nameservers = ["37.123.105.116", "37.123.105.117"]
ip_version = 4
}
resource "openstack_networking_router_v2" "router_lbdemo" {
name = "router_lbdemo"
admin_state_up = true
external_network_id = data.openstack_networking_network_v2.ext-net.id
}
resource "openstack_networking_router_interface_v2" "routerint_lbdemo" {
router_id = openstack_networking_router_v2.router_lbdemo.id
subnet_id = openstack_networking_subnet_v2.subnet_lbdemo.id
}
resource "openstack_compute_instance_v2" "instance_lbdemo" {
count = 3
name = "App Instance ${count.index + 1}"
image_id = data.openstack_images_image_v2.image.id
flavor_name = "m2.tiny"
key_pair = openstack_compute_keypair_v2.keypair.name
user_data = templatefile("${path.module}/assets/cloud.cfg", {
init_app_sh = base64encode(file("${path.module}/assets/init-app.sh"))
})
security_groups = [
"default",
openstack_networking_secgroup_v2.sg_web.name
]
network {
uuid = openstack_networking_network_v2.net_lbdemo.id
}
lifecycle {
ignore_changes = [image_id]
}
}
resource "openstack_compute_instance_v2" "instance_jumphost" {
name = "Jumphost"
image_id = data.openstack_images_image_v2.image.id
flavor_name = "m2.tiny"
key_pair = openstack_compute_keypair_v2.keypair.name
security_groups = [
"default",
openstack_networking_secgroup_v2.sg_ssh.name,
]
network {
uuid = openstack_networking_network_v2.net_lbdemo.id
}
lifecycle {
ignore_changes = [image_id]
}
}
resource "openstack_networking_floatingip_v2" "fip_lbdemo_jumphost" {
pool = "ext-net"
}
data "openstack_networking_port_v2" "port_instance_1" {
device_id = openstack_compute_instance_v2.instance_jumphost.id
network_id = openstack_compute_instance_v2.instance_jumphost.network.0.uuid
}
resource "openstack_networking_floatingip_associate_v2" "fipas_lbdemo" {
floating_ip = openstack_networking_floatingip_v2.fip_lbdemo_jumphost.address
port_id = data.openstack_networking_port_v2.port_instance_1.id
}
resource "openstack_lb_loadbalancer_v2" "lb_app" {
vip_subnet_id = openstack_networking_subnet_v2.subnet_lbdemo.id
name = "application loadbalancer"
loadbalancer_provider = "ovn"
}
resource "openstack_lb_listener_v2" "lb_app_listener" {
protocol = "TCP"
protocol_port = 80
loadbalancer_id = openstack_lb_loadbalancer_v2.lb_app.id
}
resource "openstack_lb_pool_v2" "lb_app_pool" {
protocol = "TCP"
lb_method = "SOURCE_IP_PORT"
listener_id = openstack_lb_listener_v2.lb_app_listener.id
}
resource "openstack_lb_member_v2" "lb_app_pool_members" {
count = length(openstack_compute_instance_v2.instance_lbdemo)
address = element(
openstack_compute_instance_v2.instance_lbdemo.*.access_ip_v4,
count.index
)
protocol_port = 80
pool_id = openstack_lb_pool_v2.lb_app_pool.id
name = element(
openstack_compute_instance_v2.instance_lbdemo.*.name,
count.index
)
subnet_id = openstack_networking_subnet_v2.subnet_lbdemo.id
}
resource "openstack_lb_monitor_v2" "lb_app_monitor" {
pool_id = openstack_lb_pool_v2.lb_app_pool.id
type = "TCP"
delay = 10
timeout = 5
max_retries = 2
# url_path = "/"
# expected_codes = "200"
}
resource "openstack_networking_floatingip_v2" "fip_lbdemo_lb" {
pool = "ext-net"
port_id = openstack_lb_loadbalancer_v2.lb_app.vip_port_id
}
output "loadbalancer_http" {
value = "http://${openstack_networking_floatingip_v2.fip_lbdemo_lb.address}"
}
The complete example, including the cloud-init assets for the app instances, is available in our terraform-examples repository.
Manage Listeners, Pools, Pool Members and Health Monitors
Listeners, pools, pool members and health monitors of an OVN load balancer are managed the same way as for Amphora load balancers
With the OVN provider you can attach listeners with the TCP protocol to your load balancer.
Health monitors can be attached to pools, but only with type TCP.
Supported Settings
The OVN provider supports only a subset of the settings available with the Amphora provider. When
you create or modify resources of an OVN load balancer, use only the following options. General
options such as --name and --description behave the same as with the Amphora provider.
| Resource | Supported options |
|---|---|
| Listener | --protocol TCP, --protocol-port |
| Pool | --protocol TCP, --lb-algorithm SOURCE_IP_PORT, --persistence SOURCE_IP |
| Pool Member | --name, --address, --protocol-port, --subnet-id |
| Health Monitor | --type TCP, --delay, --timeout, --max-retries, --max-retries-down |
The following options are not supported by the OVN provider and must not be used
- Listener: TLS termination, insert headers, L7 policies, connection limit and timeout settings
- Pool: session persistence types other than
SOURCE_IP(APP_COOKIE,HTTP_COOKIE) and load balancing methods other thanSOURCE_IP_PORT - Pool Member:
--weight,--backup,--monitor-addressand--monitor-port - Health Monitor:
--url-path,--http-methodand--expected-codes(only relevant forHTTP/HTTPStypes) and monitor types other thanTCP
States
The provisioning and operating states of load balancers are documented on the Load Balancers page.