diff --git a/contrib/terraform/upcloud/README.md b/contrib/terraform/upcloud/README.md
index 5689831ff49356116b44530b36569e00cf5784f8..c893c34acb414f0a068eb8b42aa4144486dadddd 100644
--- a/contrib/terraform/upcloud/README.md
+++ b/contrib/terraform/upcloud/README.md
@@ -136,4 +136,8 @@ terraform destroy --var-file cluster-settings.tfvars \
 * `loadbalancer_plan`: Plan to use for load balancer *(development|production-small)*
 * `loadbalancers`: Ports to load balance and which machines to forward to. Key of this object will be used as the name of the load balancer frontends/backends
   * `port`: Port to load balance.
+  * `target_port`: Port to the backend servers.
   * `backend_servers`: List of servers that traffic to the port should be forwarded to.
+* `server_groups`: Group servers together
+  * `servers`: The servers that should be included in the group.
+  * `anti_affinity`: If anti-affinity should be enabled, try to spread the VMs out on separate nodes.
diff --git a/contrib/terraform/upcloud/cluster-settings.tfvars b/contrib/terraform/upcloud/cluster-settings.tfvars
index 873150b31d49b5e9fb4c646072b66fc17c65ae2f..d88945f65e255e3d5976736209ffa70cc269e779 100644
--- a/contrib/terraform/upcloud/cluster-settings.tfvars
+++ b/contrib/terraform/upcloud/cluster-settings.tfvars
@@ -121,6 +121,7 @@ loadbalancer_plan    = "development"
 loadbalancers = {
   # "http" : {
   #   "port" : 80,
+  #   "target_port" : 80,
   #   "backend_servers" : [
   #     "worker-0",
   #     "worker-1",
@@ -128,3 +129,20 @@ loadbalancers = {
   #   ]
   # }
 }
+
+server_groups = {
+  # "control-plane" = {
+  #   servers = [
+  #     "master-0"
+  #   ]
+  #   anti_affinity = true
+  # },
+  # "workers" = {
+  #   servers = [
+  #     "worker-0",
+  #     "worker-1",
+  #     "worker-2"
+  #   ]
+  #   anti_affinity = true
+  # }
+}
\ No newline at end of file
diff --git a/contrib/terraform/upcloud/main.tf b/contrib/terraform/upcloud/main.tf
index 9904ce291e913279a59dbc5245fe1441c30a5a79..93483a94e4836f2631afd0e34b179fac4cd2ee7b 100644
--- a/contrib/terraform/upcloud/main.tf
+++ b/contrib/terraform/upcloud/main.tf
@@ -34,6 +34,8 @@ module "kubernetes" {
   loadbalancer_enabled = var.loadbalancer_enabled
   loadbalancer_plan    = var.loadbalancer_plan
   loadbalancers        = var.loadbalancers
+
+  server_groups = var.server_groups
 }
 
 #
diff --git a/contrib/terraform/upcloud/modules/kubernetes-cluster/main.tf b/contrib/terraform/upcloud/modules/kubernetes-cluster/main.tf
index d638c3e74d504def110daee2f3b1bfb87d2eca63..c2d43a3aced039cb560d7e759e30006067e891c7 100644
--- a/contrib/terraform/upcloud/modules/kubernetes-cluster/main.tf
+++ b/contrib/terraform/upcloud/modules/kubernetes-cluster/main.tf
@@ -13,7 +13,7 @@ locals {
   lb_backend_servers = flatten([
     for lb_name, loadbalancer in var.loadbalancers : [
       for backend_server in loadbalancer.backend_servers : {
-        port = loadbalancer.port
+        port = loadbalancer.target_port
         lb_name = lb_name
         server_name = backend_server
       }
@@ -548,3 +548,11 @@ resource "upcloud_loadbalancer_static_backend_member" "lb_backend_member" {
   max_sessions = var.loadbalancer_plan == "production-small" ? 50000 : 1000
   enabled      = true
 }
+
+resource "upcloud_server_group" "server_groups" {
+  for_each      = var.server_groups
+  title         = each.key
+  anti_affinity = each.value.anti_affinity
+  labels        = {}
+  members       = [for server in each.value.servers : merge(upcloud_server.master, upcloud_server.worker)[server].id]
+}
\ No newline at end of file
diff --git a/contrib/terraform/upcloud/modules/kubernetes-cluster/variables.tf b/contrib/terraform/upcloud/modules/kubernetes-cluster/variables.tf
index 1b334440d7705110fb8ae9d08a5ae65bd64b4278..8c492ae2a30fd3cbd9bfd8c13d3a107346550638 100644
--- a/contrib/terraform/upcloud/modules/kubernetes-cluster/variables.tf
+++ b/contrib/terraform/upcloud/modules/kubernetes-cluster/variables.tf
@@ -90,6 +90,16 @@ variable "loadbalancers" {
 
   type = map(object({
     port            = number
+    target_port     = number
     backend_servers = list(string)
   }))
 }
+
+variable "server_groups" {
+  description = "Server groups"
+
+  type = map(object({
+    anti_affinity   = bool
+    servers = list(string)
+  }))
+}
\ No newline at end of file
diff --git a/contrib/terraform/upcloud/modules/kubernetes-cluster/versions.tf b/contrib/terraform/upcloud/modules/kubernetes-cluster/versions.tf
index 447ba84da235c13085ba96e93e4e42363adf41b9..75230b949073192cb66eb449dfa568eb83a71635 100644
--- a/contrib/terraform/upcloud/modules/kubernetes-cluster/versions.tf
+++ b/contrib/terraform/upcloud/modules/kubernetes-cluster/versions.tf
@@ -3,7 +3,7 @@ terraform {
   required_providers {
     upcloud = {
       source = "UpCloudLtd/upcloud"
-      version = "~>2.5.0"
+      version = "~>2.7.1"
     }
   }
   required_version = ">= 0.13"
diff --git a/contrib/terraform/upcloud/sample-inventory/cluster.tfvars b/contrib/terraform/upcloud/sample-inventory/cluster.tfvars
index b98a853974d41c027fc44183779f70c70fdfb27f..4e8ade831a9c3576dccbc170112e353ffddbc132 100644
--- a/contrib/terraform/upcloud/sample-inventory/cluster.tfvars
+++ b/contrib/terraform/upcloud/sample-inventory/cluster.tfvars
@@ -122,6 +122,7 @@ loadbalancer_plan = "development"
 loadbalancers = {
   # "http" : {
   #   "port" : 80,
+  #   "target_port" : 80,
   #   "backend_servers" : [
   #     "worker-0",
   #     "worker-1",
@@ -129,3 +130,20 @@ loadbalancers = {
   #   ]
   # }
 }
+
+server_groups = {
+  # "control-plane" = {
+  #   servers = [
+  #     "master-0"
+  #   ]
+  #   anti_affinity = true
+  # },
+  # "workers" = {
+  #   servers = [
+  #     "worker-0",
+  #     "worker-1",
+  #     "worker-2"
+  #   ]
+  #   anti_affinity = true
+  # }
+}
\ No newline at end of file
diff --git a/contrib/terraform/upcloud/variables.tf b/contrib/terraform/upcloud/variables.tf
index 5a360487849c60a2fda0ebc3804b6c603251961d..3b2c55804a6729097f09e3d142d82232d8ce7122 100644
--- a/contrib/terraform/upcloud/variables.tf
+++ b/contrib/terraform/upcloud/variables.tf
@@ -126,7 +126,19 @@ variable "loadbalancers" {
 
   type = map(object({
     port            = number
+    target_port     = number
     backend_servers = list(string)
   }))
   default = {}
 }
+
+variable "server_groups" {
+  description = "Server groups"
+
+  type = map(object({
+    anti_affinity = bool
+    servers       = list(string)
+  }))
+
+  default = {}
+}
diff --git a/contrib/terraform/upcloud/versions.tf b/contrib/terraform/upcloud/versions.tf
index 48e6820eea78cd846bc071e2de0e9844f9ab0189..99507471cbae5575d63489f8678fb884a1f2f030 100644
--- a/contrib/terraform/upcloud/versions.tf
+++ b/contrib/terraform/upcloud/versions.tf
@@ -3,7 +3,7 @@ terraform {
   required_providers {
     upcloud = {
       source  = "UpCloudLtd/upcloud"
-      version = "~>2.5.0"
+      version = "~>2.7.1"
     }
   }
   required_version = ">= 0.13"