diff --git a/contrib/terraform/openstack/README.md b/contrib/terraform/openstack/README.md
index 0ff6ed360d41a9b2eac189c8ee43b46c3857daac..923aa3140742dfc748bcc52c458fc92f6bfa7026 100644
--- a/contrib/terraform/openstack/README.md
+++ b/contrib/terraform/openstack/README.md
@@ -98,9 +98,10 @@ binaries available on hyperkube v1.4.3_coreos.0 or higher.
 
 ## Module Architecture
 
-The configuration is divided into three modules:
+The configuration is divided into four modules:
 
 - Network
+- Loadbalancer
 - IPs
 - Compute
 
@@ -298,6 +299,10 @@ For your cluster, edit `inventory/$CLUSTER/cluster.tfvars`.
 |`force_null_port_security` | Set `null` instead of `true` or `false` for `port_security`. `false` by default |
 |`k8s_nodes` | Map containing worker node definition, see explanation below |
 |`k8s_masters` | Map containing master node definition, see explanation for k8s_nodes and `sample-inventory/cluster.tfvars` |
+| `k8s_master_loadbalancer_enabled`| Enable and use an Octavia load balancer for the K8s master nodes |
+| `k8s_master_loadbalancer_listener_port` | Define via which port the K8s Api should be exposed. `6443` by default  |
+| `k8s_master_loadbalancer_server_port` | Define via which port the K8S api is available on the mas. `6443` by default |
+| `k8s_master_loadbalancer_public_ip` | Specify if an existing floating IP should be used for the load balancer. A new floating IP is assigned by default  |
 
 ##### k8s_nodes
 
diff --git a/contrib/terraform/openstack/kubespray.tf b/contrib/terraform/openstack/kubespray.tf
index 32c00bd8617fa97bf549ca2c3132120ff859b64c..556fa54340f64e2202c1a423b1d950f8274649de 100644
--- a/contrib/terraform/openstack/kubespray.tf
+++ b/contrib/terraform/openstack/kubespray.tf
@@ -112,6 +112,24 @@ module "compute" {
   ]
 }
 
+module "loadbalancer" {
+  source = "./modules/loadbalancer"
+
+  cluster_name                          = var.cluster_name
+  subnet_id                             = module.network.subnet_id
+  floatingip_pool                       = var.floatingip_pool
+  k8s_master_ips                        = module.compute.k8s_master_ips
+  k8s_master_loadbalancer_enabled       = var.k8s_master_loadbalancer_enabled
+  k8s_master_loadbalancer_listener_port = var.k8s_master_loadbalancer_listener_port
+  k8s_master_loadbalancer_server_port   = var.k8s_master_loadbalancer_server_port
+  k8s_master_loadbalancer_public_ip     = var.k8s_master_loadbalancer_public_ip
+
+  depends_on = [
+    module.compute.k8s_master
+  ]
+}
+
+
 output "private_subnet_id" {
   value = module.network.subnet_id
 }
diff --git a/contrib/terraform/openstack/modules/compute/outputs.tf b/contrib/terraform/openstack/modules/compute/outputs.tf
new file mode 100644
index 0000000000000000000000000000000000000000..741e9f035dfb27c1ad5ad310586f4f4282ed3a0e
--- /dev/null
+++ b/contrib/terraform/openstack/modules/compute/outputs.tf
@@ -0,0 +1,3 @@
+output "k8s_master_ips" {
+  value = concat(openstack_compute_instance_v2.k8s_master_no_floating_ip.*, openstack_compute_instance_v2.k8s_master_no_floating_ip_no_etcd.*)
+}
diff --git a/contrib/terraform/openstack/modules/loadbalancer/main.tf b/contrib/terraform/openstack/modules/loadbalancer/main.tf
new file mode 100644
index 0000000000000000000000000000000000000000..12fa225ea6e306864be6b6f2286544ee27141c9e
--- /dev/null
+++ b/contrib/terraform/openstack/modules/loadbalancer/main.tf
@@ -0,0 +1,54 @@
+resource "openstack_lb_loadbalancer_v2" "k8s_lb" {
+  count             = var.k8s_master_loadbalancer_enabled ? 1 : 0
+  name              = "${var.cluster_name}-api-loadbalancer"
+  vip_subnet_id     = var.subnet_id
+}
+
+resource "openstack_lb_listener_v2" "api_listener"{
+  count             = var.k8s_master_loadbalancer_enabled ? 1 : 0
+  name              = "api-listener"
+  protocol          = "TCP"
+  protocol_port     = var.k8s_master_loadbalancer_listener_port
+  loadbalancer_id   = openstack_lb_loadbalancer_v2.k8s_lb[0].id
+  depends_on        = [ openstack_lb_loadbalancer_v2.k8s_lb ]
+}
+
+resource "openstack_lb_pool_v2" "api_pool" {
+  count             = var.k8s_master_loadbalancer_enabled ? 1 : 0
+  name              = "api-pool"
+  protocol          = "TCP"
+  lb_method         = "ROUND_ROBIN"
+  listener_id       = openstack_lb_listener_v2.api_listener[0].id
+  depends_on        = [ openstack_lb_listener_v2.api_listener ]
+}
+
+resource "openstack_lb_member_v2" "lb_member" {
+  count             = var.k8s_master_loadbalancer_enabled ? length(var.k8s_master_ips) : 0
+  name              = var.k8s_master_ips[count.index].name
+  pool_id           = openstack_lb_pool_v2.api_pool[0].id
+  address           = var.k8s_master_ips[count.index].access_ip_v4
+  protocol_port     = var.k8s_master_loadbalancer_server_port
+  depends_on        = [ openstack_lb_pool_v2.api_pool ]
+}
+
+resource "openstack_lb_monitor_v2" "monitor" {
+  count       = var.k8s_master_loadbalancer_enabled ? 1 : 0
+  name        = "Api Monitor"
+  pool_id     = openstack_lb_pool_v2.api_pool[0].id
+  type        = "TCP"
+  delay       = 10
+  timeout     = 5
+  max_retries = 5
+}
+
+resource "openstack_networking_floatingip_v2" "floatip_1" {
+  count = var.k8s_master_loadbalancer_enabled && var.k8s_master_loadbalancer_public_ip == "" ? 1 : 0
+  pool = var.floatingip_pool
+}
+
+resource "openstack_networking_floatingip_associate_v2" "public_ip" {
+  count             = var.k8s_master_loadbalancer_enabled ? 1 : 0
+  floating_ip       = var.k8s_master_loadbalancer_public_ip != "" ? var.k8s_master_loadbalancer_public_ip : openstack_networking_floatingip_v2.floatip_1[0].address
+  port_id           = openstack_lb_loadbalancer_v2.k8s_lb[0].vip_port_id
+  depends_on        = [ openstack_lb_loadbalancer_v2.k8s_lb ]
+}
diff --git a/contrib/terraform/openstack/modules/loadbalancer/variables.tf b/contrib/terraform/openstack/modules/loadbalancer/variables.tf
new file mode 100644
index 0000000000000000000000000000000000000000..40b1b588ceff03b95cc6058f2444a245472a9455
--- /dev/null
+++ b/contrib/terraform/openstack/modules/loadbalancer/variables.tf
@@ -0,0 +1,15 @@
+variable "cluster_name" {}
+
+variable "subnet_id" {}
+
+variable "floatingip_pool" {}
+
+variable "k8s_master_ips" {}
+
+variable "k8s_master_loadbalancer_enabled" {}
+
+variable "k8s_master_loadbalancer_listener_port" {}
+
+variable "k8s_master_loadbalancer_server_port" {}
+
+variable "k8s_master_loadbalancer_public_ip" {}
diff --git a/contrib/terraform/openstack/modules/loadbalancer/versions.tf b/contrib/terraform/openstack/modules/loadbalancer/versions.tf
new file mode 100644
index 0000000000000000000000000000000000000000..6c942790da8e7c15c82a55463526de10cefe23ed
--- /dev/null
+++ b/contrib/terraform/openstack/modules/loadbalancer/versions.tf
@@ -0,0 +1,8 @@
+terraform {
+  required_providers {
+    openstack = {
+      source = "terraform-provider-openstack/openstack"
+    }
+  }
+  required_version = ">= 0.12.26"
+}
diff --git a/contrib/terraform/openstack/variables.tf b/contrib/terraform/openstack/variables.tf
index ef99c77134affb38751ebc782d195b37503d1556..90416df50d09de22d107499a926f8736394a2a61 100644
--- a/contrib/terraform/openstack/variables.tf
+++ b/contrib/terraform/openstack/variables.tf
@@ -389,3 +389,23 @@ variable "group_vars_path" {
   type        = string
   default     = "./group_vars"
 }
+
+variable "k8s_master_loadbalancer_enabled" {
+  type    = bool
+  default = "false"
+}
+
+variable "k8s_master_loadbalancer_listener_port" {
+  type    = string
+  default = "6443"
+}
+
+variable "k8s_master_loadbalancer_server_port" {
+  type    = string
+  default = 6443
+}
+
+variable "k8s_master_loadbalancer_public_ip" {
+  type    = string
+  default = ""
+}