Skip to content

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.

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.

Configure CLI

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 are amphorav2 and ovn.
  • --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 is TCP.
  • --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     |                                      |
+---------------------+--------------------------------------+

OpenStack Terraform Provider

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 than SOURCE_IP_PORT
  • Pool Member: --weight, --backup, --monitor-address and --monitor-port
  • Health Monitor: --url-path, --http-method and --expected-codes (only relevant for HTTP/HTTPS types) and monitor types other than TCP

States

The provisioning and operating states of load balancers are documented on the Load Balancers page.