diff --git a/contrib/terraform/openstack/README.md b/contrib/terraform/openstack/README.md
index 2b7ca0ef029b15a5cc6657efc9cad78746dde655..62f57db3bccede444276483d59ae0f783eb2bf06 100644
--- a/contrib/terraform/openstack/README.md
+++ b/contrib/terraform/openstack/README.md
@@ -283,6 +283,7 @@ For your cluster, edit `inventory/$CLUSTER/cluster.tfvars`.
 |`node_server_group_policy` | Enable and use openstack nova servergroups for nodes with set policy, default: "" (disabled) |
 |`etcd_server_group_policy` | Enable and use openstack nova servergroups for etcd with set policy, default: "" (disabled) |
 |`use_access_ip` | If 1, nodes with floating IPs will transmit internal cluster traffic via floating IPs; if 0 private IPs will be used instead. Default value is 1. |
+|`port_security_enabled` | Allow to disable port security by setting this to `false`. `true` by default |
 |`k8s_nodes` | Map containing worker node definition, see explanation below |
 
 ##### k8s_nodes
@@ -411,7 +412,7 @@ plugins. This is accomplished as follows:
 
 ```ShellSession
 cd inventory/$CLUSTER
-terraform init ../../contrib/terraform/openstack
+terraform -chdir="../../contrib/terraform/openstack" init
 ```
 
 This should finish fairly quickly telling you Terraform has successfully initialized and loaded necessary modules.
@@ -443,7 +444,7 @@ You can apply the Terraform configuration to your cluster with the following com
 issued from your cluster's inventory directory (`inventory/$CLUSTER`):
 
 ```ShellSession
-terraform apply -var-file=cluster.tfvars ../../contrib/terraform/openstack
+terraform -chdir="../../contrib/terraform/openstack" apply -var-file=cluster.tfvars
 ```
 
 if you chose to create a bastion host, this script will create
@@ -458,7 +459,7 @@ pick it up automatically.
 You can destroy your new cluster with the following command issued from the cluster's inventory directory:
 
 ```ShellSession
-terraform destroy -var-file=cluster.tfvars ../../contrib/terraform/openstack
+terraform -chdir="../../contrib/terraform/openstack" destroy -var-file=cluster.tfvars
 ```
 
 If you've started the Ansible run, it may also be a good idea to do some manual cleanup:
diff --git a/contrib/terraform/openstack/kubespray.tf b/contrib/terraform/openstack/kubespray.tf
index aadb001b3fce206122d81b4f5c4efdb4dc7536e8..583a213d8fe610bad82c4b6b675d4848e53db7ad 100644
--- a/contrib/terraform/openstack/kubespray.tf
+++ b/contrib/terraform/openstack/kubespray.tf
@@ -1,14 +1,15 @@
 module "network" {
   source = "./modules/network"
 
-  external_net       = var.external_net
-  network_name       = var.network_name
-  subnet_cidr        = var.subnet_cidr
-  cluster_name       = var.cluster_name
-  dns_nameservers    = var.dns_nameservers
-  network_dns_domain = var.network_dns_domain
-  use_neutron        = var.use_neutron
-  router_id          = var.router_id
+  external_net          = var.external_net
+  network_name          = var.network_name
+  subnet_cidr           = var.subnet_cidr
+  cluster_name          = var.cluster_name
+  dns_nameservers       = var.dns_nameservers
+  network_dns_domain    = var.network_dns_domain
+  use_neutron           = var.use_neutron
+  port_security_enabled = var.port_security_enabled
+  router_id             = var.router_id
 }
 
 module "ips" {
@@ -88,6 +89,7 @@ module "compute" {
   extra_sec_groups                             = var.extra_sec_groups
   extra_sec_groups_name                        = var.extra_sec_groups_name
   group_vars_path                              = var.group_vars_path
+  port_security_enabled                        = var.port_security_enabled
 
   network_id = module.network.router_id
 }
diff --git a/contrib/terraform/openstack/modules/compute/main.tf b/contrib/terraform/openstack/modules/compute/main.tf
index 5e0ba546a340f898544f75796332b220cd02072f..03a3edaebe4698cc165d4a80548e79154cd5f109 100644
--- a/contrib/terraform/openstack/modules/compute/main.tf
+++ b/contrib/terraform/openstack/modules/compute/main.tf
@@ -164,6 +164,15 @@ locals {
     openstack_networking_secgroup_v2.worker.name,
     var.extra_sec_groups ? openstack_networking_secgroup_v2.worker_extra[0].name : "",
   ])
+# bastion groups
+  bastion_sec_groups = compact(concat([
+    openstack_networking_secgroup_v2.k8s.name,
+    openstack_networking_secgroup_v2.bastion[0].name,
+  ]))
+# etcd groups
+  etcd_sec_groups = compact([openstack_networking_secgroup_v2.k8s.name])
+# glusterfs groups
+  gfs_sec_groups = compact([openstack_networking_secgroup_v2.k8s.name])
 
 # Image uuid
   image_to_use_node = var.image_uuid != "" ? var.image_uuid : data.openstack_images_image_v2.vm_image[0].id
@@ -197,9 +206,7 @@ resource "openstack_compute_instance_v2" "bastion" {
     name = var.network_name
   }
 
-  security_groups = [openstack_networking_secgroup_v2.k8s.name,
-    element(openstack_networking_secgroup_v2.bastion.*.name, count.index),
-  ]
+  security_groups = var.port_security_enabled ? local.bastion_sec_groups : null
 
   metadata = {
     ssh_user         = var.ssh_user
@@ -240,7 +247,7 @@ resource "openstack_compute_instance_v2" "k8s_master" {
     name = var.network_name
   }
 
-  security_groups = local.master_sec_groups
+  security_groups = var.port_security_enabled ? local.master_sec_groups : null
 
   dynamic "scheduler_hints" {
     for_each = var.master_server_group_policy != "" ? [openstack_compute_servergroup_v2.k8s_master[0]] : []
@@ -288,7 +295,7 @@ resource "openstack_compute_instance_v2" "k8s_master_no_etcd" {
     name = var.network_name
   }
 
-  security_groups = local.master_sec_groups
+  security_groups = var.port_security_enabled ? local.master_sec_groups : null
 
   dynamic "scheduler_hints" {
     for_each = var.master_server_group_policy != "" ? [openstack_compute_servergroup_v2.k8s_master[0]] : []
@@ -334,7 +341,7 @@ resource "openstack_compute_instance_v2" "etcd" {
     name = var.network_name
   }
 
-  security_groups = [openstack_networking_secgroup_v2.k8s.name]
+  security_groups = var.port_security_enabled ? local.etcd_sec_groups : null
 
   dynamic "scheduler_hints" {
     for_each = var.etcd_server_group_policy ? [openstack_compute_servergroup_v2.k8s_etcd[0]] : []
@@ -376,7 +383,7 @@ resource "openstack_compute_instance_v2" "k8s_master_no_floating_ip" {
     name = var.network_name
   }
 
-  security_groups = local.master_sec_groups
+  security_groups = var.port_security_enabled ? local.master_sec_groups : null
 
   dynamic "scheduler_hints" {
     for_each = var.master_server_group_policy != "" ? [openstack_compute_servergroup_v2.k8s_master[0]] : []
@@ -419,7 +426,7 @@ resource "openstack_compute_instance_v2" "k8s_master_no_floating_ip_no_etcd" {
     name = var.network_name
   }
 
-  security_groups = local.master_sec_groups
+  security_groups = var.port_security_enabled ? local.master_sec_groups : null
 
   dynamic "scheduler_hints" {
     for_each = var.master_server_group_policy != "" ? [openstack_compute_servergroup_v2.k8s_master[0]] : []
@@ -462,7 +469,7 @@ resource "openstack_compute_instance_v2" "k8s_node" {
     name = var.network_name
   }
 
-  security_groups = local.worker_sec_groups
+  security_groups = var.port_security_enabled ? local.worker_sec_groups : null
 
   dynamic "scheduler_hints" {
     for_each = var.node_server_group_policy != "" ? [openstack_compute_servergroup_v2.k8s_node[0]] : []
@@ -509,7 +516,7 @@ resource "openstack_compute_instance_v2" "k8s_node_no_floating_ip" {
     name = var.network_name
   }
 
-  security_groups = local.worker_sec_groups
+  security_groups = var.port_security_enabled ? local.worker_sec_groups : null
 
   dynamic "scheduler_hints" {
     for_each = var.node_server_group_policy != "" ? [openstack_compute_servergroup_v2.k8s_node[0]] : []
@@ -552,7 +559,7 @@ resource "openstack_compute_instance_v2" "k8s_nodes" {
     name = var.network_name
   }
 
-  security_groups = local.worker_sec_groups
+  security_groups = var.port_security_enabled ? local.worker_sec_groups : null
 
   dynamic "scheduler_hints" {
     for_each = var.node_server_group_policy != "" ? [openstack_compute_servergroup_v2.k8s_node[0]] : []
@@ -597,7 +604,7 @@ resource "openstack_compute_instance_v2" "glusterfs_node_no_floating_ip" {
     name = var.network_name
   }
 
-  security_groups = [openstack_networking_secgroup_v2.k8s.name]
+  security_groups = var.port_security_enabled ? local.gfs_sec_groups : null
 
   dynamic "scheduler_hints" {
     for_each = var.node_server_group_policy != "" ? [openstack_compute_servergroup_v2.k8s_node[0]] : []
diff --git a/contrib/terraform/openstack/modules/compute/variables.tf b/contrib/terraform/openstack/modules/compute/variables.tf
index 378345495b41178dc86606e27573c651ceda17f7..61a614e86caf0e5b6ca217c478df44f772db5a51 100644
--- a/contrib/terraform/openstack/modules/compute/variables.tf
+++ b/contrib/terraform/openstack/modules/compute/variables.tf
@@ -165,3 +165,7 @@ variable "image_master_uuid" {
 variable "group_vars_path" {
   type = string
 }
+
+variable "port_security_enabled" {
+  type = bool
+}
diff --git a/contrib/terraform/openstack/modules/network/main.tf b/contrib/terraform/openstack/modules/network/main.tf
index ec97322f8cf28e3083d0c1019eab57dc3d7f844c..a6324d7edab60ed378ca2453ef41fdadd7a4e21a 100644
--- a/contrib/terraform/openstack/modules/network/main.tf
+++ b/contrib/terraform/openstack/modules/network/main.tf
@@ -11,10 +11,11 @@ data "openstack_networking_router_v2" "k8s" {
 }
 
 resource "openstack_networking_network_v2" "k8s" {
-  name           = var.network_name
-  count          = var.use_neutron
-  dns_domain     = var.network_dns_domain != null ? var.network_dns_domain : null
-  admin_state_up = "true"
+  name                  = var.network_name
+  count                 = var.use_neutron
+  dns_domain            = var.network_dns_domain != null ? var.network_dns_domain : null
+  admin_state_up        = "true"
+  port_security_enabled = var.port_security_enabled
 }
 
 resource "openstack_networking_subnet_v2" "k8s" {
diff --git a/contrib/terraform/openstack/modules/network/variables.tf b/contrib/terraform/openstack/modules/network/variables.tf
index f8eb64884ed8a9efed9bc47855c85d5e2b4a4679..6cd7ff72e5b3ec602e8acbe426a51e2eb94da626 100644
--- a/contrib/terraform/openstack/modules/network/variables.tf
+++ b/contrib/terraform/openstack/modules/network/variables.tf
@@ -10,6 +10,10 @@ variable "dns_nameservers" {
   type = list
 }
 
+variable "port_security_enabled" {
+  type = bool
+}
+
 variable "subnet_cidr" {}
 
 variable "use_neutron" {}
diff --git a/contrib/terraform/openstack/variables.tf b/contrib/terraform/openstack/variables.tf
index fe66b3709346a21b581b64d0d73dd08d5fc3e1a8..350e5bcae69f7ee2bf17938ab3fc34a3f682a996 100644
--- a/contrib/terraform/openstack/variables.tf
+++ b/contrib/terraform/openstack/variables.tf
@@ -148,6 +148,12 @@ variable "use_neutron" {
   default     = 1
 }
 
+variable "port_security_enabled" {
+  description = "Enable port security on the internal network"
+  type        = bool
+  default     = "true"
+}
+
 variable "subnet_cidr" {
   description = "Subnet CIDR block."
   type        = string