diff --git a/README.md b/README.md
index ddca85dd9262b20e7fa764e2c775ff8c347787fd..8110d4ed3ad568fffdacb9a9eeb5a5422159fe6a 100644
--- a/README.md
+++ b/README.md
@@ -3,15 +3,15 @@
 
 | Name | Version |
 |------|---------|
-| <a name="requirement_local"></a> [local](#requirement\_local) | ~> 2.4.0 |
-| <a name="requirement_openstack"></a> [openstack](#requirement\_openstack) | ~> 1.52.1 |
+| <a name="requirement_local"></a> [local](#requirement\_local) | ~> 2.4.1 |
+| <a name="requirement_openstack"></a> [openstack](#requirement\_openstack) | ~> 1.54.1 |
 
 ## Providers
 
 | Name | Version |
 |------|---------|
-| <a name="provider_local"></a> [local](#provider\_local) | ~> 2.4.0 |
-| <a name="provider_openstack"></a> [openstack](#provider\_openstack) | ~> 1.52.1 |
+| <a name="provider_local"></a> [local](#provider\_local) | ~> 2.4.1 |
+| <a name="provider_openstack"></a> [openstack](#provider\_openstack) | ~> 1.54.1 |
 
 ## Modules
 
@@ -78,10 +78,7 @@ No modules.
 | <a name="input_router_creation_enable"></a> [router\_creation\_enable](#input\_router\_creation\_enable) | Create dedicated router instance. true/false ~ create new / reuse existing personal router | `bool` | `true` | no |
 | <a name="input_ssh_public_key"></a> [ssh\_public\_key](#input\_ssh\_public\_key) | n/a | `string` | `"~/.ssh/id_rsa.pub"` | no |
 | <a name="input_ssh_user_name"></a> [ssh\_user\_name](#input\_ssh\_user\_name) | n/a | `string` | `"ubuntu"` | no |
-| <a name="input_worker_nodes_count"></a> [worker\_nodes\_count](#input\_worker\_nodes\_count) | ######################## worker nodes settings # ######################## | `number` | `8` | no |
-| <a name="input_worker_nodes_flavor"></a> [worker\_nodes\_flavor](#input\_worker\_nodes\_flavor) | n/a | `string` | `"standard.small"` | no |
-| <a name="input_worker_nodes_name"></a> [worker\_nodes\_name](#input\_worker\_nodes\_name) | Use a-z, 0-9 and the hyphen (-) only. | `string` | `"worker"` | no |
-| <a name="input_worker_nodes_volume_size"></a> [worker\_nodes\_volume\_size](#input\_worker\_nodes\_volume\_size) | The size of the volume to create (in gigabytes) for root filesystem. | `string` | `"30"` | no |
+| <a name="input_worker_nodes"></a> [worker\_nodes](#input\_worker\_nodes) | ######################## worker nodes settings # ######################## | <pre>list(object({<br>    name        = string<br>    flavor      = string<br>    count       = number<br>    volume_size = number<br>  }))</pre> | n/a | yes |
 
 ## Outputs
 
diff --git a/instances.tf b/instances.tf
index fc55dcf786fa70ed853263199e7c1f47223bbfbb..7f878293f6abae6a5eae678b20773517a2b1cc3e 100644
--- a/instances.tf
+++ b/instances.tf
@@ -43,28 +43,40 @@ resource "openstack_compute_instance_v2" "control_nodes" {
     delete_on_termination = true
   }
 }
+locals {
+  all_instances = flatten([
+    for group in var.worker_nodes : [
+      for i in range(group.count) : {
+        name        = "${var.infra_name}-${group.name}-${i + 1}"
+        flavor      = group.flavor
+        volume_size = group.volume_size
+      }
+    ]
+  ])
+}
 
 resource "openstack_compute_instance_v2" "worker_nodes" {
-  count           = var.worker_nodes_count
-  name            = "${var.infra_name}-${var.worker_nodes_name}-${count.index + 1}"
+
+  for_each = { for inst in local.all_instances : inst.name => inst }
+
+  name            = each.value.name
   image_id        = var.image
-  flavor_name     = var.worker_nodes_flavor
+  flavor_name     = each.value.flavor
   key_pair        = openstack_compute_keypair_v2.pubkey.name
   security_groups = [openstack_networking_secgroup_v2.secgroup_default.name]
-  user_data       = "#cloud-config\nhostname: ${var.infra_name}-${var.worker_nodes_name}-${count.index + 1}.local\n${file("${path.cwd}/nodes-cloudinit.txt")}"
+  user_data       = "#cloud-config\nhostname: ${var.infra_name}-${each.value.name}.local\n${file("${path.cwd}/nodes-cloudinit.txt")}"
 
   network {
     uuid = openstack_networking_network_v2.network_default[0].id
-    port = element(openstack_networking_port_v2.worker_ports.*.id, count.index)
+    port = openstack_networking_port_v2.worker_ports[each.value.name].id
   }
 
   block_device {
     uuid                  = var.image
     source_type           = "image"
-    volume_size           = var.worker_nodes_volume_size
+    volume_size           = each.value.volume_size
     destination_type      = "local"
     boot_index            = 0
     delete_on_termination = true
   }
-
 }
diff --git a/inventory.tf b/inventory.tf
index 443b9b3d3278226da64273cf422ac80b4e466e51..117a9894ecf1abd7cb17825013a55e73a10fbca6 100644
--- a/inventory.tf
+++ b/inventory.tf
@@ -6,8 +6,8 @@ resource "local_file" "k8s_inventory" {
       k8s_bastion_ip_internal = openstack_compute_instance_v2.bastion.access_ip_v4
       k8s_control_name        = openstack_compute_instance_v2.control_nodes.*.name
       k8s_control_ip          = openstack_compute_instance_v2.control_nodes.*.access_ip_v4
-      k8s_worker_name         = openstack_compute_instance_v2.worker_nodes.*.name
-      k8s_worker_ip           = openstack_compute_instance_v2.worker_nodes.*.access_ip_v4
+      k8s_worker_name         = [for nodes in openstack_compute_instance_v2.worker_nodes : nodes.name]
+      k8s_worker_ip           = [for nodes in openstack_compute_instance_v2.worker_nodes : nodes.access_ip_v4]
     }
 
   )
diff --git a/networks.tf b/networks.tf
index b018718d76e3b100f7d181b8df546cfdb8b3c2d9..10a1220045233c7d2d7a096b2c22dcdfb79832d2 100644
--- a/networks.tf
+++ b/networks.tf
@@ -46,7 +46,7 @@ resource "openstack_networking_router_interface_v2" "router_available_interface"
 
 # Ports
 resource "openstack_networking_port_v2" "bastion_port" {
-  name               = "${var.infra_name}-${var.bastion_name}-port"
+  name               = "${var.infra_name}-${var.bastion_name}"
   network_id         = openstack_networking_network_v2.network_default[0].id
   admin_state_up     = "true"
   security_group_ids = [openstack_networking_secgroup_v2.secgroup_default.id]
@@ -57,7 +57,7 @@ resource "openstack_networking_port_v2" "bastion_port" {
 
 resource "openstack_networking_port_v2" "vip_port" {
   count              = var.kube_fip_create_port && var.kube_fip ? 1 : 0
-  name               = "${var.infra_name}_vip_port"
+  name               = "${var.infra_name}-vip"
   network_id         = openstack_networking_network_v2.network_default[0].id
   admin_state_up     = "true"
   security_group_ids = [openstack_networking_secgroup_v2.secgroup_default.id]
@@ -66,10 +66,11 @@ resource "openstack_networking_port_v2" "vip_port" {
     ip_address = var.kube_vip
   }
 }
-
 resource "openstack_networking_port_v2" "worker_ports" {
-  count              = var.worker_nodes_count
-  name               = "${var.infra_name}_worker_port_${count.index + 1}"
+
+  for_each = { for inst in local.all_instances : inst.name => inst }
+
+  name               = each.value.name
   network_id         = openstack_networking_network_v2.network_default[0].id
   admin_state_up     = "true"
   security_group_ids = [openstack_networking_secgroup_v2.secgroup_default.id]
@@ -89,7 +90,7 @@ resource "openstack_networking_port_v2" "worker_ports" {
 
 resource "openstack_networking_port_v2" "control_ports" {
   count              = var.control_nodes_count
-  name               = "${var.infra_name}_control_port_${count.index + 1}"
+  name               = "${var.infra_name}-control-${count.index + 1}"
   network_id         = openstack_networking_network_v2.network_default[0].id
   admin_state_up     = "true"
   security_group_ids = [openstack_networking_secgroup_v2.secgroup_default.id]
diff --git a/output.tf b/output.tf
index c1cf9a68768974b8ae8b0a528783b0829e0008a9..3da1a366a7138b5492c532a598fabf6edb9ab167 100644
--- a/output.tf
+++ b/output.tf
@@ -7,7 +7,7 @@ output "control_instance_ip" {
 }
 
 output "worker_instance_ip" {
-  value = openstack_compute_instance_v2.worker_nodes[*].access_ip_v4
+  value = [for nodes in openstack_compute_instance_v2.worker_nodes : nodes.access_ip_v4]
 }
 
 output "vip_ip" {
diff --git a/providers.tf b/providers.tf
index 8bbbdfaef1eb32b85c5da35179b6dd6d605f7ea9..f711bab5aa1c1e184188f6d5529ef793d2d4c9c7 100644
--- a/providers.tf
+++ b/providers.tf
@@ -2,11 +2,11 @@ terraform {
   required_providers {
     openstack = {
       source  = "terraform-provider-openstack/openstack"
-      version = "~> 1.52.1"
+      version = "~> 1.54.1"
     }
     local = {
       source  = "hashicorp/local"
-      version = "~> 2.4.0"
+      version = "~> 2.4.1"
     }
   }
 }
diff --git a/variables.tf b/variables.tf
index 259c479fc868a42f07333f5a33989d8a7f0b1924..10360c7be9c9a767ff1ed2f22d95ae25b03958f7 100644
--- a/variables.tf
+++ b/variables.tf
@@ -87,22 +87,13 @@ variable "control_nodes_volume_size" {
 #########################
 # worker nodes settings #
 #########################
-variable "worker_nodes_count" {
-  default = 8
-}
-
-variable "worker_nodes_name" {
-  description = "Use a-z, 0-9 and the hyphen (-) only."
-  default     = "worker"
-}
-
-variable "worker_nodes_flavor" {
-  default = "standard.small"
-}
-
-variable "worker_nodes_volume_size" {
-  description = "The size of the volume to create (in gigabytes) for root filesystem. "
-  default     = "30"
+variable "worker_nodes" {
+  type = list(object({
+    name        = string
+    flavor      = string
+    count       = number
+    volume_size = number
+  }))
 }
 
 variable "image" {