Repository: scylladb/scylla-operator
Pull request #1401 (2023-09-18 12:05:19)

Annotate E2E namespaces with parallel process and full text of a ginkgo node
**Description of your changes:** As proved by https://github.com/scylladb/scylla-operator/issues/1399, the logs printed out by a failed process of out test runner make it difficult to backtrack an issue to a particular test. This PR annotates the Namespaces created in the framework with the number of the parallel process running the spec as well as the full text of the ginkgo node. It should help with backtracking the failure to an offending test.



scylla-operator-bot[bot]: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/scylladb/scylla-operator/pull/1401#" title="Author self-approved">rzetelskik</a>*
**Once this PR has been reviewed and has the lgtm label**, please assign tnozicka for approval. For more information see [the Kubernetes Code Review Process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process).

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=scylladb%2Fscylla-operator).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/scylladb/scylla-operator/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["tnozicka"]} -->
scylla-operator-bot[bot]: @rzetelskik: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
ci/prow/e2e-gke-parallel | 946d79482ec7b0f156abf016a34a0c2beada125c | [link](https://prow.scylla-operator.scylladb.com/view/gs/scylla-operator-prow/pr-logs/pull/scylladb_scylla-operator/1401/pull-scylla-operator-e2e-gke-parallel/1703742000655765504) | true | `/test e2e-gke-parallel`

[Full PR test history](https://prow.scylla-operator.scylladb.com/pr-history?org=scylladb&repo=scylla-operator&pr=1401). [Your PR dashboard](https://prow.scylla-operator.scylladb.com/pr?query=is:pr+state:open+author:rzetelskik).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
scylla-operator-bot[bot]: @rzetelskik: The following tests **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
ci/prow/e2e-gke-parallel | 946d79482ec7b0f156abf016a34a0c2beada125c | [link](https://prow.scylla-operator.scylladb.com/view/gs/scylla-operator-prow/pr-logs/pull/scylladb_scylla-operator/1401/pull-scylla-operator-e2e-gke-parallel/1703742000655765504) | true | `/test e2e-gke-parallel`
ci/prow/e2e-gke-serial | 946d79482ec7b0f156abf016a34a0c2beada125c | [link](https://prow.scylla-operator.scylladb.com/view/gs/scylla-operator-prow/pr-logs/pull/scylladb_scylla-operator/1401/pull-scylla-operator-e2e-gke-serial/1703742000773206016) | true | `/test e2e-gke-serial`

[Full PR test history](https://prow.scylla-operator.scylladb.com/pr-history?org=scylladb&repo=scylla-operator&pr=1401). [Your PR dashboard](https://prow.scylla-operator.scylladb.com/pr?query=is:pr+state:open+author:rzetelskik).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->

Patch:
diff --git a/examples/common/operator.yaml b/examples/common/operator.yaml
index 6e47703cb..927e3bc31 100644
--- a/examples/common/operator.yaml
+++ b/examples/common/operator.yaml
@@ -2697,44 +2697,6 @@ spec:
                 exposeOptions:
                   description: exposeOptions specifies options for exposing ScyllaCluster services. EXPERIMENTAL. Do not rely on any particular behaviour controlled by this field.
                   properties:
-                    broadcastOptions:
-                      description: BroadcastOptions defines how ScyllaDB node publishes its IP address to other nodes and clients.
-                      properties:
-                        clients:
-                          default:
-                            type: ServiceClusterIP
-                          description: clients specifies options related to the address that is broadcasted for communication with clients. This field controls the `broadcast_rpc_address` value in ScyllaDB config.
-                          properties:
-                            podIP:
-                              description: podIP holds options related to Pod IP address.
-                              properties:
-                                source:
-                                  default: Status
-                                  description: sourceType specifies source of the Pod IP.
-                                  type: string
-                              type: object
-                            type:
-                              description: type of the address that is broadcasted.
-                              type: string
-                          type: object
-                        nodes:
-                          default:
-                            type: ServiceClusterIP
-                          description: nodes specifies options related to the address that is broadcasted for communication with other nodes. This field controls the `broadcast_address` value in ScyllaDB config.
-                          properties:
-                            podIP:
-                              description: podIP holds options related to Pod IP address.
-                              properties:
-                                source:
-                                  default: Status
-                                  description: sourceType specifies source of the Pod IP.
-                                  type: string
-                              type: object
-                            type:
-                              description: type of the address that is broadcasted.
-                              type: string
-                          type: object
-                      type: object
                     cql:
                       description: cql specifies expose options for CQL SSL backend. EXPERIMENTAL. Do not rely on any particular behaviour controlled by this field.
                       properties:
@@ -2754,34 +2716,6 @@ spec:
                               type: string
                           type: object
                       type: object
-                    nodeService:
-                      default:
-                        type: ClusterIP
-                      description: nodeService controls properties of Service dedicated for each ScyllaCluster node.
-                      properties:
-                        allocateLoadBalancerNodePorts:
-                          description: allocateLoadBalancerNodePorts controls value of service.spec.allocateLoadBalancerNodePorts of each node Service. Check Kubernetes corev1.Service documentation about semantic of this field.
-                          type: boolean
-                        annotations:
-                          additionalProperties:
-                            type: string
-                          description: annotations is a custom key value map merged with every node Service annotations.
-                          type: object
-                        externalTrafficPolicy:
-                          description: externalTrafficPolicy controls value of service.spec.externalTrafficPolicy of each node Service. Check Kubernetes corev1.Service documentation about semantic of this field.
-                          type: string
-                        internalTrafficPolicy:
-                          description: internalTrafficPolicy controls value of service.spec.internalTrafficPolicy of each node Service. Check Kubernetes corev1.Service documentation about semantic of this field.
-                          type: string
-                        loadBalancerClass:
-                          description: loadBalancerClass controls value of service.spec.loadBalancerClass of each node Service. Check Kubernetes corev1.Service documentation about semantic of this field.
-                          type: string
-                        type:
-                          description: type is the Kubernetes Service type.
-                          type: string
-                      required:
-                        - type
-                      type: object
                   type: object
                 externalSeeds:
                   description: externalSeeds specifies the external seeds to propagate to ScyllaDB binary on startup as "seeds" parameter of seed-provider.
diff --git a/helm/scylla-manager/values.schema.json b/helm/scylla-manager/values.schema.json
index c3257849b..fc656a613 100644
--- a/helm/scylla-manager/values.schema.json
+++ b/helm/scylla-manager/values.schema.json
@@ -240,60 +240,6 @@
         "exposeOptions": {
           "description": "exposeOptions specifies options for exposing ScyllaCluster services. EXPERIMENTAL. Do not rely on any particular behaviour controlled by this field.",
           "properties": {
-            "broadcastOptions": {
-              "description": "BroadcastOptions defines how ScyllaDB node publishes its IP address to other nodes and clients.",
-              "properties": {
-                "clients": {
-                  "default": {
-                    "type": "ServiceClusterIP"
-                  },
-                  "description": "clients specifies options related to the address that is broadcasted for communication with clients. This field controls the `broadcast_rpc_address` value in ScyllaDB config.",
-                  "properties": {
-                    "podIP": {
-                      "description": "podIP holds options related to Pod IP address.",
-                      "properties": {
-                        "source": {
-                          "default": "Status",
-                          "description": "sourceType specifies source of the Pod IP.",
-                          "type": "string"
-                        }
-                      },
-                      "type": "object"
-                    },
-                    "type": {
-                      "description": "type of the address that is broadcasted.",
-                      "type": "string"
-                    }
-                  },
-                  "type": "object"
-                },
-                "nodes": {
-                  "default": {
-                    "type": "ServiceClusterIP"
-                  },
-                  "description": "nodes specifies options related to the address that is broadcasted for communication with other nodes. This field controls the `broadcast_address` value in ScyllaDB config.",
-                  "properties": {
-                    "podIP": {
-                      "description": "podIP holds options related to Pod IP address.",
-                      "properties": {
-                        "source": {
-                          "default": "Status",
-                          "description": "sourceType specifies source of the Pod IP.",
-                          "type": "string"
-                        }
-                      },
-                      "type": "object"
-                    },
-                    "type": {
-                      "description": "type of the address that is broadcasted.",
-                      "type": "string"
-                    }
-                  },
-                  "type": "object"
-                }
-              },
-              "type": "object"
-            },
             "cql": {
               "description": "cql specifies expose options for CQL SSL backend. EXPERIMENTAL. Do not rely on any particular behaviour controlled by this field.",
               "properties": {
@@ -320,45 +266,6 @@
                 }
               },
               "type": "object"
-            },
-            "nodeService": {
-              "default": {
-                "type": "ClusterIP"
-              },
-              "description": "nodeService controls properties of Service dedicated for each ScyllaCluster node.",
-              "properties": {
-                "allocateLoadBalancerNodePorts": {
-                  "description": "allocateLoadBalancerNodePorts controls value of service.spec.allocateLoadBalancerNodePorts of each node Service. Check Kubernetes corev1.Service documentation about semantic of this field.",
-                  "type": "boolean"
-                },
-                "annotations": {
-                  "additionalProperties": {
-                    "type": "string"
-                  },
-                  "description": "annotations is a custom key value map merged with every node Service annotations.",
-                  "type": "object"
-                },
-                "externalTrafficPolicy": {
-                  "description": "externalTrafficPolicy controls value of service.spec.externalTrafficPolicy of each node Service. Check Kubernetes corev1.Service documentation about semantic of this field.",
-                  "type": "string"
-                },
-                "internalTrafficPolicy": {
-                  "description": "internalTrafficPolicy controls value of service.spec.internalTrafficPolicy of each node Service. Check Kubernetes corev1.Service documentation about semantic of this field.",
-                  "type": "string"
-                },
-                "loadBalancerClass": {
-                  "description": "loadBalancerClass controls value of service.spec.loadBalancerClass of each node Service. Check Kubernetes corev1.Service documentation about semantic of this field.",
-                  "type": "string"
-                },
-                "type": {
-                  "description": "type is the Kubernetes Service type.",
-                  "type": "string"
-                }
-              },
-              "required": [
-                "type"
-              ],
-              "type": "object"
             }
           },
           "type": "object"
diff --git a/helm/scylla/values.schema.json b/helm/scylla/values.schema.json
index 93042d5ea..751aa50c0 100644
--- a/helm/scylla/values.schema.json
+++ b/helm/scylla/values.schema.json
@@ -129,60 +129,6 @@
     "exposeOptions": {
       "description": "exposeOptions specifies options for exposing ScyllaCluster services. EXPERIMENTAL. Do not rely on any particular behaviour controlled by this field.",
       "properties": {
-        "broadcastOptions": {
-          "description": "BroadcastOptions defines how ScyllaDB node publishes its IP address to other nodes and clients.",
-          "properties": {
-            "clients": {
-              "default": {
-                "type": "ServiceClusterIP"
-              },
-              "description": "clients specifies options related to the address that is broadcasted for communication with clients. This field controls the `broadcast_rpc_address` value in ScyllaDB config.",
-              "properties": {
-                "podIP": {
-                  "description": "podIP holds options related to Pod IP address.",
-                  "properties": {
-                    "source": {
-                      "default": "Status",
-                      "description": "sourceType specifies source of the Pod IP.",
-                      "type": "string"
-                    }
-                  },
-                  "type": "object"
-                },
-                "type": {
-                  "description": "type of the address that is broadcasted.",
-                  "type": "string"
-                }
-              },
-              "type": "object"
-            },
-            "nodes": {
-              "default": {
-                "type": "ServiceClusterIP"
-              },
-              "description": "nodes specifies options related to the address that is broadcasted for communication with other nodes. This field controls the `broadcast_address` value in ScyllaDB config.",
-              "properties": {
-                "podIP": {
-                  "description": "podIP holds options related to Pod IP address.",
-                  "properties": {
-                    "source": {
-                      "default": "Status",
-                      "description": "sourceType specifies source of the Pod IP.",
-                      "type": "string"
-                    }
-                  },
-                  "type": "object"
-                },
-                "type": {
-                  "description": "type of the address that is broadcasted.",
-                  "type": "string"
-                }
-              },
-              "type": "object"
-            }
-          },
-          "type": "object"
-        },
         "cql": {
           "description": "cql specifies expose options for CQL SSL backend. EXPERIMENTAL. Do not rely on any particular behaviour controlled by this field.",
           "properties": {
@@ -209,45 +155,6 @@
             }
           },
           "type": "object"
-        },
-        "nodeService": {
-          "default": {
-            "type": "ClusterIP"
-          },
-          "description": "nodeService controls properties of Service dedicated for each ScyllaCluster node.",
-          "properties": {
-            "allocateLoadBalancerNodePorts": {
-              "description": "allocateLoadBalancerNodePorts controls value of service.spec.allocateLoadBalancerNodePorts of each node Service. Check Kubernetes corev1.Service documentation about semantic of this field.",
-              "type": "boolean"
-            },
-            "annotations": {
-              "additionalProperties": {
-                "type": "string"
-              },
-              "description": "annotations is a custom key value map merged with every node Service annotations.",
-              "type": "object"
-            },
-            "externalTrafficPolicy": {
-              "description": "externalTrafficPolicy controls value of service.spec.externalTrafficPolicy of each node Service. Check Kubernetes corev1.Service documentation about semantic of this field.",
-              "type": "string"
-            },
-            "internalTrafficPolicy": {
-              "description": "internalTrafficPolicy controls value of service.spec.internalTrafficPolicy of each node Service. Check Kubernetes corev1.Service documentation about semantic of this field.",
-              "type": "string"
-            },
-            "loadBalancerClass": {
-              "description": "loadBalancerClass controls value of service.spec.loadBalancerClass of each node Service. Check Kubernetes corev1.Service documentation about semantic of this field.",
-              "type": "string"
-            },
-            "type": {
-              "description": "type is the Kubernetes Service type.",
-              "type": "string"
-            }
-          },
-          "required": [
-            "type"
-          ],
-          "type": "object"
         }
       },
       "type": "object"
diff --git a/pkg/api/scylla/v1/scylla.scylladb.com_scyllaclusters.yaml b/pkg/api/scylla/v1/scylla.scylladb.com_scyllaclusters.yaml
index 5a27b23b4..c8d0de171 100644
--- a/pkg/api/scylla/v1/scylla.scylladb.com_scyllaclusters.yaml
+++ b/pkg/api/scylla/v1/scylla.scylladb.com_scyllaclusters.yaml
@@ -1741,44 +1741,6 @@ spec:
                 exposeOptions:
                   description: exposeOptions specifies options for exposing ScyllaCluster services. EXPERIMENTAL. Do not rely on any particular behaviour controlled by this field.
                   properties:
-                    broadcastOptions:
-                      description: BroadcastOptions defines how ScyllaDB node publishes its IP address to other nodes and clients.
-                      properties:
-                        clients:
-                          default:
-                            type: ServiceClusterIP
-                          description: clients specifies options related to the address that is broadcasted for communication with clients. This field controls the `broadcast_rpc_address` value in ScyllaDB config.
-                          properties:
-                            podIP:
-                              description: podIP holds options related to Pod IP address.
-                              properties:
-                                source:
-                                  default: Status
-                                  description: sourceType specifies source of the Pod IP.
-                                  type: string
-                              type: object
-                            type:
-                              description: type of the address that is broadcasted.
-                              type: string
-                          type: object
-                        nodes:
-                          default:
-                            type: ServiceClusterIP
-                          description: nodes specifies options related to the address that is broadcasted for communication with other nodes. This field controls the `broadcast_address` value in ScyllaDB config.
-                          properties:
-                            podIP:
-                              description: podIP holds options related to Pod IP address.
-                              properties:
-                                source:
-                                  default: Status
-                                  description: sourceType specifies source of the Pod IP.
-                                  type: string
-                              type: object
-                            type:
-                              description: type of the address that is broadcasted.
-                              type: string
-                          type: object
-                      type: object
                     cql:
                       description: cql specifies expose options for CQL SSL backend. EXPERIMENTAL. Do not rely on any particular behaviour controlled by this field.
                       properties:
@@ -1798,34 +1760,6 @@ spec:
                               type: string
                           type: object
                       type: object
-                    nodeService:
-                      default:
-                        type: ClusterIP
-                      description: nodeService controls properties of Service dedicated for each ScyllaCluster node.
-                      properties:
-                        allocateLoadBalancerNodePorts:
-                          description: allocateLoadBalancerNodePorts controls value of service.spec.allocateLoadBalancerNodePorts of each node Service. Check Kubernetes corev1.Service documentation about semantic of this field.
-                          type: boolean
-                        annotations:
-                          additionalProperties:
-                            type: string
-                          description: annotations is a custom key value map merged with every node Service annotations.
-                          type: object
-                        externalTrafficPolicy:
-                          description: externalTrafficPolicy controls value of service.spec.externalTrafficPolicy of each node Service. Check Kubernetes corev1.Service documentation about semantic of this field.
-                          type: string
-                        internalTrafficPolicy:
-                          description: internalTrafficPolicy controls value of service.spec.internalTrafficPolicy of each node Service. Check Kubernetes corev1.Service documentation about semantic of this field.
-                          type: string
-                        loadBalancerClass:
-                          description: loadBalancerClass controls value of service.spec.loadBalancerClass of each node Service. Check Kubernetes corev1.Service documentation about semantic of this field.
-                          type: string
-                        type:
-                          description: type is the Kubernetes Service type.
-                          type: string
-                      required:
-                        - type
-                      type: object
                   type: object
                 externalSeeds:
                   description: externalSeeds specifies the external seeds to propagate to ScyllaDB binary on startup as "seeds" parameter of seed-provider.
diff --git a/pkg/api/scylla/v1/types_cluster.go b/pkg/api/scylla/v1/types_cluster.go
index 4f6112c17..d3798e55a 100644
--- a/pkg/api/scylla/v1/types_cluster.go
+++ b/pkg/api/scylla/v1/types_cluster.go
@@ -111,104 +111,6 @@ type ScyllaClusterSpec struct {
 	ExternalSeeds []string `json:"externalSeeds,omitempty"`
 }
 
-type PodIPSourceType string
-
-const (
-	// StatusPodIPSource specifies that the PodIP is taken from Pod.Status.PodIP
-	StatusPodIPSource PodIPSourceType = "Status"
-)
-
-type PodIPInterfaceOptions struct {
-	// interfaceName specifies interface name within a Pod from which address is taken from.
-	InterfaceName string `json:"interfaceName,omitempty"`
-}
-
-// PodIPAddressOptions hold options related to Pod IP address.
-type PodIPAddressOptions struct {
-	// sourceType specifies source of the Pod IP.
-	// +kubebuilder:default:="Status"
-	Source PodIPSourceType `json:"source"`
-}
-
-type BroadcastAddressType string
-
-const (
-	// BroadcastAddressTypePodIP selects the IP address from Pod.
-	BroadcastAddressTypePodIP BroadcastAddressType = "PodIP"
-
-	// BroadcastAddressTypeServiceClusterIP selects the IP address from Service.spec.ClusterIP
-	BroadcastAddressTypeServiceClusterIP BroadcastAddressType = "ServiceClusterIP"
-
-	// BroadcastAddressTypeServiceLoadBalancerIngress selects the IP address or Hostname from Service.status.ingress[0]
-	BroadcastAddressTypeServiceLoadBalancerIngress BroadcastAddressType = "ServiceLoadBalancerIngress"
-)
-
-// BroadcastOptions hold options related to address broadcasted by ScyllaDB node.
-type BroadcastOptions struct {
-	// type of the address that is broadcasted.
-	Type BroadcastAddressType `json:"type"`
-
-	// podIP holds options related to Pod IP address.
-	// +optional
-	PodIP *PodIPAddressOptions `json:"podIP,omitempty"`
-}
-
-// NodeBroadcastOptions hold options related to addresses broadcasted by ScyllaDB node.
-type NodeBroadcastOptions struct {
-	// nodes specifies options related to the address that is broadcasted for communication with other nodes.
-	// This field controls the `broadcast_address` value in ScyllaDB config.
-	// +kubebuilder:default:={type:"ServiceClusterIP"}
-	Nodes BroadcastOptions `json:"nodes"`
-
-	// clients specifies options related to the address that is broadcasted for communication with clients.
-	// This field controls the `broadcast_rpc_address` value in ScyllaDB config.
-	// +kubebuilder:default:={type:"ServiceClusterIP"}
-	Clients BroadcastOptions `json:"clients"`
-}
-
-type NodeServiceType string
-
-const (
-	// NodeServiceTypeHeadless means nodes will be exposed via Headless Service.
-	NodeServiceTypeHeadless NodeServiceType = "Headless"
-
-	// NodeServiceTypeClusterIP means nodes will be exposed via ClusterIP Service.
-	NodeServiceTypeClusterIP NodeServiceType = "ClusterIP"
-
-	// NodeServiceTypeLoadBalancer means nodes will be exposed via LoadBalancer Service.
-	NodeServiceTypeLoadBalancer NodeServiceType = "LoadBalancer"
-)
-
-type NodeServiceTemplate struct {
-	// annotations is a custom key value map merged with every node Service annotations.
-	// +optional
-	Annotations map[string]string `json:"annotations,omitempty"`
-
-	// type is the Kubernetes Service type.
-	// +kubebuilder:validation:Required
-	Type NodeServiceType `json:"type"`
-
-	// externalTrafficPolicy controls value of service.spec.externalTrafficPolicy of each node Service.
-	// Check Kubernetes corev1.Service documentation about semantic of this field.
-	// +optional
-	ExternalTrafficPolicy *corev1.ServiceExternalTrafficPolicy `json:"externalTrafficPolicy,omitempty"`
-
-	// allocateLoadBalancerNodePorts controls value of service.spec.allocateLoadBalancerNodePorts of each node Service.
-	// Check Kubernetes corev1.Service documentation about semantic of this field.
-	// +optional
-	AllocateLoadBalancerNodePorts *bool `json:"allocateLoadBalancerNodePorts,omitempty"`
-
-	// loadBalancerClass controls value of service.spec.loadBalancerClass of each node Service.
-	// Check Kubernetes corev1.Service documentation about semantic of this field.
-	// +optional
-	LoadBalancerClass *string `json:"loadBalancerClass,omitempty"`
-
-	// internalTrafficPolicy controls value of service.spec.internalTrafficPolicy of each node Service.
-	// Check Kubernetes corev1.Service documentation about semantic of this field.
-	// +optional
-	InternalTrafficPolicy *corev1.ServiceInternalTrafficPolicy `json:"internalTrafficPolicy,omitempty"`
-}
-
 // ExposeOptions hold options related to exposing ScyllaCluster backends.
 // EXPERIMENTAL. Do not rely on any particular behaviour controlled by this field.
 type ExposeOptions struct {
@@ -216,13 +118,6 @@ type ExposeOptions struct {
 	// EXPERIMENTAL. Do not rely on any particular behaviour controlled by this field.
 	// +optional
 	CQL *CQLExposeOptions `json:"cql,omitempty"`
-
-	// nodeService controls properties of Service dedicated for each ScyllaCluster node.
-	// +kubebuilder:default:={type:"ClusterIP"}
-	NodeService *NodeServiceTemplate `json:"nodeService,omitempty"`
-
-	// BroadcastOptions defines how ScyllaDB node publishes its IP address to other nodes and clients.
-	BroadcastOptions *NodeBroadcastOptions `json:"broadcastOptions,omitempty"`
 }
 
 // CQLExposeOptions hold options related to exposing CQL backend.
diff --git a/pkg/api/scylla/v1/zz_generated.deepcopy.go b/pkg/api/scylla/v1/zz_generated.deepcopy.go
index 7d48e8333..ff76f0c4b 100644
--- a/pkg/api/scylla/v1/zz_generated.deepcopy.go
+++ b/pkg/api/scylla/v1/zz_generated.deepcopy.go
@@ -91,27 +91,6 @@ func (in *BackupTaskStatus) DeepCopy() *BackupTaskStatus {
 	return out
 }
 
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *BroadcastOptions) DeepCopyInto(out *BroadcastOptions) {
-	*out = *in
-	if in.PodIP != nil {
-		in, out := &in.PodIP, &out.PodIP
-		*out = new(PodIPAddressOptions)
-		**out = **in
-	}
-	return
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BroadcastOptions.
-func (in *BroadcastOptions) DeepCopy() *BroadcastOptions {
-	if in == nil {
-		return nil
-	}
-	out := new(BroadcastOptions)
-	in.DeepCopyInto(out)
-	return out
-}
-
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *CQLExposeOptions) DeepCopyInto(out *CQLExposeOptions) {
 	*out = *in
@@ -164,16 +143,6 @@ func (in *ExposeOptions) DeepCopyInto(out *ExposeOptions) {
 		*out = new(CQLExposeOptions)
 		(*in).DeepCopyInto(*out)
 	}
-	if in.NodeService != nil {
-		in, out := &in.NodeService, &out.NodeService
-		*out = new(NodeServiceTemplate)
-		(*in).DeepCopyInto(*out)
-	}
-	if in.BroadcastOptions != nil {
-		in, out := &in.BroadcastOptions, &out.BroadcastOptions
-		*out = new(NodeBroadcastOptions)
-		(*in).DeepCopyInto(*out)
-	}
 	return
 }
 
@@ -248,67 +217,6 @@ func (in *Network) DeepCopy() *Network {
 	return out
 }
 
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *NodeBroadcastOptions) DeepCopyInto(out *NodeBroadcastOptions) {
-	*out = *in
-	in.Nodes.DeepCopyInto(&out.Nodes)
-	in.Clients.DeepCopyInto(&out.Clients)
-	return
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeBroadcastOptions.
-func (in *NodeBroadcastOptions) DeepCopy() *NodeBroadcastOptions {
-	if in == nil {
-		return nil
-	}
-	out := new(NodeBroadcastOptions)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *NodeServiceTemplate) DeepCopyInto(out *NodeServiceTemplate) {
-	*out = *in
-	if in.Annotations != nil {
-		in, out := &in.Annotations, &out.Annotations
-		*out = make(map[string]string, len(*in))
-		for key, val := range *in {
-			(*out)[key] = val
-		}
-	}
-	if in.ExternalTrafficPolicy != nil {
-		in, out := &in.ExternalTrafficPolicy, &out.ExternalTrafficPolicy
-		*out = new(corev1.ServiceExternalTrafficPolicy)
-		**out = **in
-	}
-	if in.AllocateLoadBalancerNodePorts != nil {
-		in, out := &in.AllocateLoadBalancerNodePorts, &out.AllocateLoadBalancerNodePorts
-		*out = new(bool)
-		**out = **in
-	}
-	if in.LoadBalancerClass != nil {
-		in, out := &in.LoadBalancerClass, &out.LoadBalancerClass
-		*out = new(string)
-		**out = **in
-	}
-	if in.InternalTrafficPolicy != nil {
-		in, out := &in.InternalTrafficPolicy, &out.InternalTrafficPolicy
-		*out = new(corev1.ServiceInternalTrafficPolicy)
-		**out = **in
-	}
-	return
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeServiceTemplate.
-func (in *NodeServiceTemplate) DeepCopy() *NodeServiceTemplate {
-	if in == nil {
-		return nil
-	}
-	out := new(NodeServiceTemplate)
-	in.DeepCopyInto(out)
-	return out
-}
-
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *PlacementSpec) DeepCopyInto(out *PlacementSpec) {
 	*out = *in
@@ -347,38 +255,6 @@ func (in *PlacementSpec) DeepCopy() *PlacementSpec {
 	return out
 }
 
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *PodIPAddressOptions) DeepCopyInto(out *PodIPAddressOptions) {
-	*out = *in
-	return
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodIPAddressOptions.
-func (in *PodIPAddressOptions) DeepCopy() *PodIPAddressOptions {
-	if in == nil {
-		return nil
-	}
-	out := new(PodIPAddressOptions)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *PodIPInterfaceOptions) DeepCopyInto(out *PodIPInterfaceOptions) {
-	*out = *in
-	return
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodIPInterfaceOptions.
-func (in *PodIPInterfaceOptions) DeepCopy() *PodIPInterfaceOptions {
-	if in == nil {
-		return nil
-	}
-	out := new(PodIPInterfaceOptions)
-	in.DeepCopyInto(out)
-	return out
-}
-
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *RackCondition) DeepCopyInto(out *RackCondition) {
 	*out = *in
diff --git a/pkg/api/scylla/validation/cluster_validation.go b/pkg/api/scylla/validation/cluster_validation.go
index 2bc2ab224..a97a3f155 100644
--- a/pkg/api/scylla/validation/cluster_validation.go
+++ b/pkg/api/scylla/validation/cluster_validation.go
@@ -7,8 +7,6 @@ import (
 
 	"github.com/scylladb/go-set/strset"
 	scyllav1 "github.com/scylladb/scylla-operator/pkg/api/scylla/v1"
-	"github.com/scylladb/scylla-operator/pkg/helpers/slices"
-	"github.com/scylladb/scylla-operator/pkg/pointer"
 	"github.com/scylladb/scylla-operator/pkg/semver"
 	apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
 	"k8s.io/apimachinery/pkg/util/sets"
@@ -28,12 +26,6 @@ var (
 		AlternatorWriteIsolationForbidRMW,
 		AlternatorWriteIsolationOnlyRMWUsesLWT,
 	}
-
-	SupportedBroadcastAddressTypes = []scyllav1.BroadcastAddressType{
-		scyllav1.BroadcastAddressTypePodIP,
-		scyllav1.BroadcastAddressTypeServiceClusterIP,
-		scyllav1.BroadcastAddressTypeServiceLoadBalancerIngress,
-	}
 )
 
 func ValidateScyllaCluster(c *scyllav1.ScyllaCluster) field.ErrorList {
@@ -120,85 +112,6 @@ func ValidateExposeOptions(options *scyllav1.ExposeOptions, fldPath *field.Path)
 		allErrs = append(allErrs, ValidateIngressOptions(options.CQL.Ingress, fldPath.Child("cql", "ingress"))...)
 	}
 
-	if options.NodeService != nil {
-		allErrs = append(allErrs, ValidateNodeService(options.NodeService, fldPath.Child("nodeService"))...)
-	}
-
-	if options.BroadcastOptions != nil {
-		allErrs = append(allErrs, ValidateNodeBroadcastOptions(options.BroadcastOptions, options.NodeService, fldPath.Child("broadcastOptions"))...)
-	}
-
-	return allErrs
-}
-
-func ValidateNodeBroadcastOptions(options *scyllav1.NodeBroadcastOptions, nodeService *scyllav1.NodeServiceTemplate, fldPath *field.Path) field.ErrorList {
-	allErrs := field.ErrorList{}
-
-	allErrs = append(allErrs, ValidateBroadcastOptions(options.Clients, nodeService, fldPath.Child("clients"))...)
-	allErrs = append(allErrs, ValidateBroadcastOptions(options.Nodes, nodeService, fldPath.Child("nodes"))...)
-
-	return allErrs
-}
-
-func ValidateBroadcastOptions(options scyllav1.BroadcastOptions, nodeService *scyllav1.NodeServiceTemplate, fldPath *field.Path) field.ErrorList {
-	allErrs := field.ErrorList{}
-
-	if !slices.ContainsItem(SupportedBroadcastAddressTypes, options.Type) {
-		allErrs = append(allErrs, field.NotSupported(fldPath.Child("type"), options.Type, slices.ConvertSlice(SupportedBroadcastAddressTypes, slices.ToString[scyllav1.BroadcastAddressType])))
-	}
-
-	var allowedNodeServiceTypesByBroadcastAddressType = map[scyllav1.BroadcastAddressType][]scyllav1.NodeServiceType{
-		scyllav1.BroadcastAddressTypePodIP: {
-			scyllav1.NodeServiceTypeHeadless,
-			scyllav1.NodeServiceTypeClusterIP,
-			scyllav1.NodeServiceTypeLoadBalancer,
-		},
-		scyllav1.BroadcastAddressTypeServiceClusterIP: {
-			scyllav1.NodeServiceTypeClusterIP,
-			scyllav1.NodeServiceTypeLoadBalancer,
-		},
-		scyllav1.BroadcastAddressTypeServiceLoadBalancerIngress: {
-			scyllav1.NodeServiceTypeLoadBalancer,
-		},
-	}
-
-	nodeServiceType := scyllav1.NodeServiceTypeClusterIP
-	if nodeService != nil {
-		nodeServiceType = nodeService.Type
-	}
-
-	// Skipping an error when chosen option type is unsupported as it won't help anyhow users reading it.
-	allowedNodeServiceTypes, ok := allowedNodeServiceTypesByBroadcastAddressType[options.Type]
-	if ok && !slices.ContainsItem(allowedNodeServiceTypes, nodeServiceType) {
-		allErrs = append(allErrs, field.Invalid(fldPath.Child("type"), options.Type, fmt.Sprintf("can't broadcast address unavailable within the selected node service type, allowed types for chosen broadcast address type are: %v", allowedNodeServiceTypes)))
-	}
-
-	return allErrs
-}
-
-func ValidateNodeService(nodeService *scyllav1.NodeServiceTemplate, fldPath *field.Path) field.ErrorList {
-	allErrs := field.ErrorList{}
-
-	var supportedServiceTypes = []scyllav1.NodeServiceType{
-		scyllav1.NodeServiceTypeHeadless,
-		scyllav1.NodeServiceTypeClusterIP,
-		scyllav1.NodeServiceTypeLoadBalancer,
-	}
-
-	if !slices.ContainsItem(supportedServiceTypes, nodeService.Type) {
-		allErrs = append(allErrs, field.NotSupported(fldPath.Child("type"), nodeService.Type, slices.ConvertSlice(supportedServiceTypes, slices.ToString[scyllav1.NodeServiceType])))
-	}
-
-	if nodeService.LoadBalancerClass != nil && len(*nodeService.LoadBalancerClass) != 0 {
-		for _, msg := range apimachineryvalidation.NameIsDNSSubdomain(*nodeService.LoadBalancerClass, false) {
-			allErrs = append(allErrs, field.Invalid(fldPath.Child("loadBalancerClass"), *nodeService.LoadBalancerClass, msg))
-		}
-	}
-
-	if len(nodeService.Annotations) != 0 {
-		allErrs = append(allErrs, apimachineryvalidation.ValidateAnnotations(nodeService.Annotations, fldPath.Child("annotations"))...)
-	}
-
 	return allErrs
 }
 
@@ -322,33 +235,6 @@ func ValidateScyllaClusterSpecUpdate(new, old *scyllav1.ScyllaCluster, fldPath *
 		}
 	}
 
-	var oldClientBroadcastAddressType, newClientBroadcastAddressType *scyllav1.BroadcastAddressType
-	if old.Spec.ExposeOptions != nil && old.Spec.ExposeOptions.BroadcastOptions != nil {
-		oldClientBroadcastAddressType = pointer.Ptr(old.Spec.ExposeOptions.BroadcastOptions.Clients.Type)
-	}
-	if new.Spec.ExposeOptions != nil && new.Spec.ExposeOptions.BroadcastOptions != nil {
-		newClientBroadcastAddressType = pointer.Ptr(new.Spec.ExposeOptions.BroadcastOptions.Clients.Type)
-	}
-	allErrs = append(allErrs, apimachineryvalidation.ValidateImmutableField(newClientBroadcastAddressType, oldClientBroadcastAddressType, fldPath.Child("exposeOptions", "broadcastOptions", "clients", "type"))...)
-
-	var oldNodesBroadcastAddressType, newNodesBroadcastAddressType *scyllav1.BroadcastAddressType
-	if old.Spec.ExposeOptions != nil && old.Spec.ExposeOptions.BroadcastOptions != nil {
-		oldNodesBroadcastAddressType = pointer.Ptr(old.Spec.ExposeOptions.BroadcastOptions.Nodes.Type)
-	}
-	if new.Spec.ExposeOptions != nil && new.Spec.ExposeOptions.BroadcastOptions != nil {
-		newNodesBroadcastAddressType = pointer.Ptr(new.Spec.ExposeOptions.BroadcastOptions.Nodes.Type)
-	}
-	allErrs = append(allErrs, apimachineryvalidation.ValidateImmutableField(newNodesBroadcastAddressType, oldNodesBroadcastAddressType, fldPath.Child("exposeOptions", "broadcastOptions", "nodes", "type"))...)
-
-	var oldNodeServiceType, newNodeServiceType *scyllav1.NodeServiceType
-	if old.Spec.ExposeOptions != nil && old.Spec.ExposeOptions.NodeService != nil {
-		oldNodeServiceType = pointer.Ptr(old.Spec.ExposeOptions.NodeService.Type)
-	}
-	if new.Spec.ExposeOptions != nil && new.Spec.ExposeOptions.NodeService != nil {
-		newNodeServiceType = pointer.Ptr(new.Spec.ExposeOptions.NodeService.Type)
-	}
-	allErrs = append(allErrs, apimachineryvalidation.ValidateImmutableField(newNodeServiceType, oldNodeServiceType, fldPath.Child("exposeOptions", "nodeService", "type"))...)
-
 	return allErrs
 }
 
diff --git a/pkg/cmd/operator/sidecar.go b/pkg/cmd/operator/sidecar.go
index 8d3cf5648..9769ceff0 100644
--- a/pkg/cmd/operator/sidecar.go
+++ b/pkg/cmd/operator/sidecar.go
@@ -10,14 +10,11 @@ import (
 	"syscall"
 	"time"
 
-	scyllav1 "github.com/scylladb/scylla-operator/pkg/api/scylla/v1"
-	"github.com/scylladb/scylla-operator/pkg/api/scylla/validation"
 	scyllaversionedclient "github.com/scylladb/scylla-operator/pkg/client/scylla/clientset/versioned"
 	sidecarcontroller "github.com/scylladb/scylla-operator/pkg/controller/sidecar"
 	"github.com/scylladb/scylla-operator/pkg/controllerhelpers"
 	"github.com/scylladb/scylla-operator/pkg/genericclioptions"
 	"github.com/scylladb/scylla-operator/pkg/helpers"
-	"github.com/scylladb/scylla-operator/pkg/helpers/slices"
 	"github.com/scylladb/scylla-operator/pkg/internalapi"
 	"github.com/scylladb/scylla-operator/pkg/naming"
 	"github.com/scylladb/scylla-operator/pkg/sidecar"
@@ -47,14 +44,9 @@ type SidecarOptions struct {
 	genericclioptions.ClientConfig
 	genericclioptions.InClusterReflection
 
-	ServiceName                       string
-	CPUCount                          int
-	ExternalSeeds                     []string
-	NodesBroadcastAddressTypeString   string
-	ClientsBroadcastAddressTypeString string
-
-	nodesBroadcastAddressType   scyllav1.BroadcastAddressType
-	clientsBroadcastAddressType scyllav1.BroadcastAddressType
+	ServiceName   string
+	CPUCount      int
+	ExternalSeeds []string
 
 	kubeClient   kubernetes.Interface
 	scyllaClient scyllaversionedclient.Interface
@@ -107,8 +99,6 @@ func NewSidecarCmd(streams genericclioptions.IOStreams) *cobra.Command {
 	cmd.Flags().StringVarP(&o.ServiceName, "service-name", "", o.ServiceName, "Name of the service corresponding to the managed node.")
 	cmd.Flags().IntVarP(&o.CPUCount, "cpu-count", "", o.CPUCount, "Number of cpus to use.")
 	cmd.Flags().StringSliceVar(&o.ExternalSeeds, "external-seeds", o.ExternalSeeds, "The external seeds to propagate to ScyllaDB binary on startup as \"seeds\" parameter of seed-provider.")
-	cmd.Flags().StringVarP(&o.NodesBroadcastAddressTypeString, "nodes-broadcast-address-type", "", o.NodesBroadcastAddressTypeString, "Address type that is broadcasted for communication with other nodes.")
-	cmd.Flags().StringVarP(&o.ClientsBroadcastAddressTypeString, "clients-broadcast-address-type", "", o.ClientsBroadcastAddressTypeString, "Address type that is broadcasted for communication with clients.")
 
 	return cmd
 }
@@ -128,14 +118,6 @@ func (o *SidecarOptions) Validate() error {
 		}
 	}
 
-	if !slices.ContainsItem(validation.SupportedBroadcastAddressTypes, scyllav1.BroadcastAddressType(o.NodesBroadcastAddressTypeString)) {
-		errs = append(errs, fmt.Errorf("unsupported value of nodes-broadcast-address-type %q, supported ones are: %v", o.NodesBroadcastAddressTypeString, validation.SupportedBroadcastAddressTypes))
-	}
-
-	if !slices.ContainsItem(validation.SupportedBroadcastAddressTypes, scyllav1.BroadcastAddressType(o.ClientsBroadcastAddressTypeString)) {
-		errs = append(errs, fmt.Errorf("unsupported value of clients-broadcast-address-type %q, supported ones are: %v", o.ClientsBroadcastAddressTypeString, validation.SupportedBroadcastAddressTypes))
-	}
-
 	return utilerrors.NewAggregate(errs)
 }
 
@@ -160,9 +142,6 @@ func (o *SidecarOptions) Complete() error {
 		return fmt.Errorf("can't build scylla clientset: %w", err)
 	}
 
-	o.clientsBroadcastAddressType = scyllav1.BroadcastAddressType(o.ClientsBroadcastAddressTypeString)
-	o.nodesBroadcastAddressType = scyllav1.BroadcastAddressType(o.NodesBroadcastAddressTypeString)
-
 	return nil
 }
 
@@ -230,7 +209,7 @@ func (o *SidecarOptions) Run(streams genericclioptions.IOStreams, cmd *cobra.Com
 			return o.kubeClient.CoreV1().Services(o.Namespace).Watch(ctx, options)
 		},
 	}
-	klog.V(2).InfoS("Waiting for Service availability and IP address", "Service", naming.ManualRef(o.Namespace, o.ServiceName))
+	klog.V(2).InfoS("Waiting for Service", "Service", naming.ManualRef(o.Namespace, o.ServiceName))
 	event, err := watchtools.UntilWithSync(
 		ctx,
 		serviceLW,
@@ -239,19 +218,6 @@ func (o *SidecarOptions) Run(streams genericclioptions.IOStreams, cmd *cobra.Com
 		func(e watch.Event) (bool, error) {
 			switch t := e.Type; t {
 			case watch.Added, watch.Modified:
-				service, ok := e.Object.(*corev1.Service)
-				if !ok {
-					return false, fmt.Errorf("invalid object type in Service watcher, expected *corev1.Service, got %T", e.Object)
-				}
-
-				if o.clientsBroadcastAddressType == scyllav1.BroadcastAddressTypeServiceLoadBalancerIngress ||
-					o.nodesBroadcastAddressType == scyllav1.BroadcastAddressTypeServiceLoadBalancerIngress {
-					if len(service.Status.LoadBalancer.Ingress) == 0 {
-						klog.V(4).InfoS("LoadBalancer Service is awaiting for public endpoint")
-						return false, nil
-					}
-				}
-
 				return true, nil
 			case watch.Error:
 				return true, apierrors.FromObject(e.Object)
@@ -277,7 +243,7 @@ func (o *SidecarOptions) Run(streams genericclioptions.IOStreams, cmd *cobra.Com
 			return o.kubeClient.CoreV1().Pods(o.Namespace).Watch(ctx, options)
 		},
 	}
-	klog.V(2).InfoS("Waiting for Pod to have IP address assigned and scylla ContainerID set", "Pod", naming.ManualRef(o.Namespace, o.ServiceName))
+	klog.V(2).InfoS("Waiting for Pod To have scylla ContainerID set", "Pod", naming.ManualRef(o.Namespace, o.ServiceName))
 	var containerID string
 	var pod *corev1.Pod
 	_, err = watchtools.UntilWithSync(
@@ -290,11 +256,6 @@ func (o *SidecarOptions) Run(streams genericclioptions.IOStreams, cmd *cobra.Com
 			case watch.Added, watch.Modified:
 				pod = e.Object.(*corev1.Pod)
 
-				if len(pod.Status.PodIP) == 0 {
-					klog.V(4).InfoS("PodIP is not yet set", "Pod", klog.KObj(pod))
-					return false, nil
-				}
-
 				containerID, err = controllerhelpers.GetScyllaContainerID(pod)
 				if err != nil {
 					klog.Warningf("can't get scylla container id in pod %q: %w", naming.ObjRef(pod), err)
@@ -320,10 +281,7 @@ func (o *SidecarOptions) Run(streams genericclioptions.IOStreams, cmd *cobra.Com
 		return fmt.Errorf("can't wait for pod's ContainerID: %w", err)
 	}
 
-	member, err := identity.NewMember(service, pod, o.nodesBroadcastAddressType, o.clientsBroadcastAddressType)
-	if err != nil {
-		return fmt.Errorf("can't create new member from objects: %w", err)
-	}
+	member := identity.NewMemberFromObjects(service, pod)
 
 	labelSelector := labels.Set{
 		naming.OwnerUIDLabel:      string(pod.UID),
diff --git a/pkg/controller/scyllacluster/resource.go b/pkg/controller/scyllacluster/resource.go
index 05b8ceaef..6bc026183 100644
--- a/pkg/controller/scyllacluster/resource.go
+++ b/pkg/controller/scyllacluster/resource.go
@@ -67,7 +67,7 @@ func IdentityService(c *scyllav1.ScyllaCluster) *corev1.Service {
 	}
 }
 
-func MemberService(sc *scyllav1.ScyllaCluster, rackName, name string, oldService *corev1.Service, jobs map[string]*batchv1.Job) (*corev1.Service, error) {
+func MemberService(sc *scyllav1.ScyllaCluster, rackName, name string, oldService *corev1.Service, jobs map[string]*batchv1.Job) *corev1.Service {
 	svcLabels := naming.ClusterLabels(sc)
 	svcLabels[naming.DatacenterNameLabel] = sc.Spec.Datacenter.Name
 	svcLabels[naming.RackNameLabel] = rackName
@@ -110,7 +110,7 @@ func MemberService(sc *scyllav1.ScyllaCluster, rackName, name string, oldService
 		}
 	}
 
-	svc := &corev1.Service{
+	return &corev1.Service{
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      name,
 			Namespace: sc.Namespace,
@@ -127,30 +127,6 @@ func MemberService(sc *scyllav1.ScyllaCluster, rackName, name string, oldService
 			PublishNotReadyAddresses: true,
 		},
 	}
-
-	if sc.Spec.ExposeOptions != nil && sc.Spec.ExposeOptions.NodeService != nil {
-		ns := sc.Spec.ExposeOptions.NodeService
-
-		switch ns.Type {
-		case scyllav1.NodeServiceTypeClusterIP:
-			svc.Spec.Type = corev1.ServiceTypeClusterIP
-		case scyllav1.NodeServiceTypeLoadBalancer:
-			svc.Spec.Type = corev1.ServiceTypeLoadBalancer
-		case scyllav1.NodeServiceTypeHeadless:
-			svc.Spec.Type = corev1.ServiceTypeClusterIP
-			svc.Spec.ClusterIP = corev1.ClusterIPNone
-		default:
-			return nil, fmt.Errorf("unsupported node service type %q", ns.Type)
-		}
-
-		svc.Annotations = helpers.MergeMaps(svcAnnotations, ns.Annotations)
-		svc.Spec.InternalTrafficPolicy = copyReferencedValue(ns.InternalTrafficPolicy)
-		svc.Spec.AllocateLoadBalancerNodePorts = copyReferencedValue(ns.AllocateLoadBalancerNodePorts)
-		svc.Spec.LoadBalancerClass = copyReferencedValue(ns.LoadBalancerClass)
-		svc.Spec.ExternalTrafficPolicy = getValueOrDefault(ns.ExternalTrafficPolicy, "")
-	}
-
-	return svc, nil
 }
 
 func servicePorts(cluster *scyllav1.ScyllaCluster) []corev1.ServicePort {
@@ -219,11 +195,8 @@ func servicePorts(cluster *scyllav1.ScyllaCluster) []corev1.ServicePort {
 // StatefulSetForRack make a StatefulSet for the rack.
 // existingSts may be nil if it doesn't exist yet.
 func StatefulSetForRack(r scyllav1.RackSpec, c *scyllav1.ScyllaCluster, existingSts *appsv1.StatefulSet, sidecarImage string) (*appsv1.StatefulSet, error) {
-	rackLabels, err := naming.RackLabels(r, c)
-	if err != nil {
-		return nil, fmt.Errorf("can't get rack labels: %w", err)
-	}
-	matchLabels := helpers.ShallowCopyMap(rackLabels)
+	matchLabels := naming.RackLabels(r, c)
+	rackLabels := naming.RackLabels(r, c)
 	rackLabels[naming.ScyllaVersionLabel] = c.Spec.Version
 
 	placement := r.Placement
@@ -404,18 +377,6 @@ func StatefulSetForRack(r scyllav1.RackSpec, c *scyllav1.ScyllaCluster, existing
 										sort.Strings(res)
 										return strings.Join(res, ",")
 									}()),
-									fmt.Sprintf("--nodes-broadcast-address-type=%s", func() scyllav1.BroadcastAddressType {
-										if c.Spec.ExposeOptions != nil && c.Spec.ExposeOptions.BroadcastOptions != nil {
-											return c.Spec.ExposeOptions.BroadcastOptions.Nodes.Type
-										}
-										return scyllav1.BroadcastAddressTypeServiceClusterIP
-									}()),
-									fmt.Sprintf("--clients-broadcast-address-type=%s", func() scyllav1.BroadcastAddressType {
-										if c.Spec.ExposeOptions != nil && c.Spec.ExposeOptions.BroadcastOptions != nil {
-											return c.Spec.ExposeOptions.BroadcastOptions.Clients.Type
-										}
-										return scyllav1.BroadcastAddressTypeServiceClusterIP
-									}()),
 									"--service-name=$(SERVICE_NAME)",
 									"--cpu-count=$(CPU_COUNT)",
 									// TODO: make it configurable
@@ -491,6 +452,7 @@ func StatefulSetForRack(r scyllav1.RackSpec, c *scyllav1.ScyllaCluster, existing
 										},
 									}...)
 								}
+
 								return mounts
 							}(),
 							// Add CAP_SYS_NICE as instructed by scylla logs
@@ -920,20 +882,6 @@ func stringOrDefault(str, def string) string {
 	return def
 }
 
-func getValueOrDefault[T any](v *T, def T) T {
-	if v != nil {
-		return *v
-	}
-	return def
-}
-
-func copyReferencedValue[T any](v *T) *T {
-	if v != nil {
-		return pointer.Ptr(*v)
-	}
-	return nil
-}
-
 func MakeServiceAccount(sc *scyllav1.ScyllaCluster) *corev1.ServiceAccount {
 	return &corev1.ServiceAccount{
 		ObjectMeta: metav1.ObjectMeta{
diff --git a/pkg/controller/scyllacluster/sync.go b/pkg/controller/scyllacluster/sync.go
index 9f78899f3..bf809b66f 100644
--- a/pkg/controller/scyllacluster/sync.go
+++ b/pkg/controller/scyllacluster/sync.go
@@ -199,12 +199,6 @@ func (scc *Controller) sync(ctx context.Context, key string) error {
 		return scc.updateStatus(ctx, sc, status)
 	}
 
-	err = runPreRolloutChecks(sc, scc.eventRecorder)
-	if err != nil {
-		statusUpdateErr := scc.updateStatus(ctx, sc, status)
-		return utilerrors.NewAggregate([]error{statusUpdateErr, fmt.Errorf("ScyllaCluster %q did not pass pre-rollout check: %w", naming.ObjRef(sc), err)})
-	}
-
 	var errs []error
 
 	err = controllerhelpers.RunSync(
diff --git a/pkg/controller/scyllacluster/sync_certs.go b/pkg/controller/scyllacluster/sync_certs.go
index 9556e49d6..9e07e063b 100644
--- a/pkg/controller/scyllacluster/sync_certs.go
+++ b/pkg/controller/scyllacluster/sync_certs.go
@@ -20,11 +20,10 @@ import (
 	"github.com/scylladb/scylla-operator/pkg/scheme"
 	cqlclientv1alpha1 "github.com/scylladb/scylla-operator/pkg/scylla/api/cqlclient/v1alpha1"
 	corev1 "k8s.io/api/core/v1"
-	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/runtime/schema"
-	"k8s.io/apimachinery/pkg/util/errors"
+	apierrors "k8s.io/apimachinery/pkg/util/errors"
 	"k8s.io/klog/v2"
 )
 
@@ -129,7 +128,7 @@ func (scc *Controller) syncCerts(
 	// Be careful to always apply signers first to be sure they have been persisted
 	// before applying any child certificate signed by it.
 
-	var errs []error
+	var errors []error
 	var progressingConditions []metav1.Condition
 
 	cm := okubecrypto.NewCertificateManager(
@@ -144,7 +143,7 @@ func (scc *Controller) syncCerts(
 	clusterLabels := naming.ClusterLabels(sc)
 
 	// Manage client certificates.
-	errs = append(errs, cm.ManageCertificates(
+	errors = append(errors, cm.ManageCertificates(
 		ctx,
 		time.Now,
 		&sc.ObjectMeta,
@@ -192,80 +191,23 @@ func (scc *Controller) syncCerts(
 
 	// For the clients not using the proxy we'll sign for IPs that are published by ScyllaDB.
 	var ipAddresses []net.IP
-	var servingDNSNames []string
-
-	var externalAddressRequired bool
-	if sc.Spec.ExposeOptions != nil && sc.Spec.ExposeOptions.BroadcastOptions != nil {
-		bo := sc.Spec.ExposeOptions.BroadcastOptions
-		externalAddressRequired = bo.Clients.Type == scyllav1.BroadcastAddressTypeServiceLoadBalancerIngress ||
-			bo.Nodes.Type == scyllav1.BroadcastAddressTypeServiceLoadBalancerIngress
-	}
-
 	for _, svc := range serviceMap {
 		if svc.Labels[naming.ScyllaServiceTypeLabel] != string(naming.ScyllaServiceTypeMember) {
 			continue
 		}
 
-		if svc.Spec.ClusterIP != corev1.ClusterIPNone {
-			parsedIP, err := helpers.ParseClusterIP(svc.Spec.ClusterIP)
-			if err != nil {
-				return progressingConditions, fmt.Errorf("can't parse Service %q ClusterIP %q: %w", naming.ObjRef(svc), svc.Spec.ClusterIP, err)
-			}
-
-			ipAddresses = append(ipAddresses, parsedIP)
-		}
-
-		externalAddressFound := false
-		for _, ingressStatus := range svc.Status.LoadBalancer.Ingress {
-			if len(ingressStatus.IP) != 0 {
-				parsedIP := net.ParseIP(ingressStatus.IP)
-				if parsedIP == nil {
-					return progressingConditions, fmt.Errorf("can't parse ingress IP %q", ingressStatus.IP)
-				}
-
-				externalAddressFound = true
-				ipAddresses = append(ipAddresses, parsedIP)
-			}
-
-			if len(ingressStatus.Hostname) != 0 {
-				externalAddressFound = true
-				servingDNSNames = append(servingDNSNames, ingressStatus.Hostname)
-			}
-		}
-
-		if externalAddressRequired && !externalAddressFound {
-			progressingConditions = append(progressingConditions, metav1.Condition{
-				Type:               certControllerProgressingCondition,
-				Status:             metav1.ConditionTrue,
-				Reason:             internalapi.ProgressingReason,
-				Message:            fmt.Sprintf("waiting for external address in Service %q to be available", naming.ObjRef(svc)),
-				ObservedGeneration: sc.Generation,
-			})
+		ips := svc.Spec.ClusterIPs
+		if len(ips) == 0 {
+			klog.V(2).InfoS("No IP available for member", "Service", klog.KObj(svc))
+			continue
 		}
-
-		pod, err := scc.podLister.Pods(sc.Namespace).Get(svc.Name)
-		if err != nil && !apierrors.IsNotFound(err) {
-			return progressingConditions, fmt.Errorf("can't get Pod %q: %w", naming.ManualRef(sc.Namespace, svc.Name), err)
+		parsedIPs, err := helpers.ParseClusterIPs(ips)
+		if err != nil {
+			return progressingConditions, err
 		}
 
-		if pod != nil && len(pod.Status.PodIP) != 0 {
-			parsedIP := net.ParseIP(pod.Status.PodIP)
-			if parsedIP == nil {
-				return progressingConditions, fmt.Errorf("can't parse Pod %q IP %q", naming.ObjRef(pod), pod.Status.PodIP)
-			}
-
-			ipAddresses = append(ipAddresses, parsedIP)
-		} else {
-			progressingConditions = append(progressingConditions, metav1.Condition{
-				Type:               certControllerProgressingCondition,
-				Status:             metav1.ConditionTrue,
-				Reason:             internalapi.ProgressingReason,
-				Message:            fmt.Sprintf("waiting for Pod %q to be have IP address", naming.ManualRef(sc.Namespace, svc.Name)),
-				ObservedGeneration: sc.Generation,
-			})
-		}
+		ipAddresses = append(ipAddresses, parsedIPs...)
 	}
-
 	// Make sure ipAddresses are always sorted and can be reconciled in a declarative way.
 	sort.SliceStable(ipAddresses, func(i, j int) bool {
 		return ipAddresses[i].String() < ipAddresses[j].String()
@@ -294,6 +236,7 @@ func (scc *Controller) syncCerts(
 	}
 
 	// For every cluster domain we'll create "cql" subdomain and "UUID.cql" subdomains for every node.
+	var servingDNSNames []string
 	for _, domain := range sc.Spec.DNSDomains {
 		servingDNSNames = append(servingDNSNames, naming.GetCQLProtocolSubDomain(domain))
 
@@ -301,16 +244,6 @@ func (scc *Controller) syncCerts(
 			servingDNSNames = append(servingDNSNames, naming.GetCQLHostIDSubDomain(hostID, domain))
 		}
 	}
-
-	// Sign for every node DNS name and discovery endpoint.
-	for _, svc := range serviceMap {
-		svcType := svc.Labels[naming.ScyllaServiceTypeLabel]
-		if svcType != string(naming.ScyllaServiceTypeIdentity) && svcType != string(naming.ScyllaServiceTypeMember) {
-			return progressingConditions, fmt.Errorf("can't sign certificate for DNS name of unknown service type %q", svcType)
-		}
-		servingDNSNames = append(servingDNSNames, fmt.Sprintf("%s.%s.svc", svc.Name, svc.Namespace))
-	}
-
 	// Make sure servingDNSNames are always sorted and can be reconciled in a declarative way.
 	sort.Strings(servingDNSNames)
 
@@ -324,7 +257,7 @@ func (scc *Controller) syncCerts(
 		})
 	}
 
-	errs = append(errs, cm.ManageCertificates(
+	errors = append(errors, cm.ManageCertificates(
 		ctx,
 		time.Now,
 		&sc.ObjectMeta,
@@ -368,7 +301,7 @@ func (scc *Controller) syncCerts(
 
 	scyllaConnectionConfigSecret, err := makeScyllaConnectionConfig(sc, secrets, configMaps, scc.cqlsIngressPort)
 	if err != nil {
-		errs = append(errs, err)
+		errors = append(errors, err)
 	} else {
 		_, changed, err := resourceapply.ApplySecret(ctx, scc.kubeClient.CoreV1(), scc.secretLister, scc.eventRecorder, scyllaConnectionConfigSecret, resourceapply.ApplyOptions{})
 		if changed {
@@ -379,5 +312,5 @@ func (scc *Controller) syncCerts(
 		}
 	}
 
-	return progressingConditions, errors.NewAggregate(errs)
+	return progressingConditions, apierrors.NewAggregate(errors)
 }
diff --git a/pkg/controller/scyllacluster/sync_services.go b/pkg/controller/scyllacluster/sync_services.go
index 76541a66a..293b2ce41 100644
--- a/pkg/controller/scyllacluster/sync_services.go
+++ b/pkg/controller/scyllacluster/sync_services.go
@@ -24,7 +24,7 @@ import (
 
 var serviceOrdinalRegex = regexp.MustCompile("^.*-([0-9]+)$")
 
-func (scc *Controller) makeServices(sc *scyllav1.ScyllaCluster, oldServices map[string]*corev1.Service, jobs map[string]*batchv1.Job) ([]*corev1.Service, error) {
+func (scc *Controller) makeServices(sc *scyllav1.ScyllaCluster, oldServices map[string]*corev1.Service, jobs map[string]*batchv1.Job) []*corev1.Service {
 	services := []*corev1.Service{
 		IdentityService(sc),
 	}
@@ -35,15 +35,11 @@ func (scc *Controller) makeServices(sc *scyllav1.ScyllaCluster, oldServices map[
 		for ord := int32(0); ord < rack.Members; ord++ {
 			svcName := fmt.Sprintf("%s-%d", stsName, ord)
 			oldSvc := oldServices[svcName]
-			svc, err := MemberService(sc, rack.Name, svcName, oldSvc, jobs)
-			if err != nil {
-				return nil, fmt.Errorf("can't create member service for %d'th node: %w", ord, err)
-			}
-			services = append(services, svc)
+			services = append(services, MemberService(sc, rack.Name, svcName, oldSvc, jobs))
 		}
 	}
 
-	return services, nil
+	return services
 }
 
 func (scc *Controller) pruneServices(
@@ -188,27 +184,9 @@ func (scc *Controller) syncServices(
 	statefulSets map[string]*appsv1.StatefulSet,
 	jobs map[string]*batchv1.Job,
 ) ([]metav1.Condition, error) {
-	if sc.Spec.ExposeOptions != nil && sc.Spec.ExposeOptions.NodeService != nil && sc.Spec.ExposeOptions.NodeService.Type != scyllav1.NodeServiceTypeClusterIP {
-		supportsExposing, err := scyllafeatures.Supports(sc, scyllafeatures.ExposingScyllaClusterViaServiceOtherThanClusterIP)
-		if err != nil {
-			return nil, fmt.Errorf("can't determine if ScyllaDB version %q supports exposing via Service other than ClusterIP: %w", sc.Spec.Version, err)
-		}
-
-		if !supportsExposing {
-			scc.eventRecorder.Eventf(
-				sc,
-				corev1.EventTypeWarning,
-				"InvalidScyllaDBVersion",
-				fmt.Sprintf("Requested ScyllaDB version %q does not support exposing via Service other than ClusterIP, use the latest one", sc.Spec.Version),
-			)
-			return nil, fmt.Errorf("requested ScyllaDB version %q does not support exposing via Service other than ClusterIP, use the latest one", sc.Spec.Version)
-		}
-	}
+	var err error
 
-	requiredServices, err := scc.makeServices(sc, services, jobs)
-	if err != nil {
-		return nil, fmt.Errorf("can't make services: %w", err)
-	}
+	requiredServices := scc.makeServices(sc, services, jobs)
 
 	// Delete any excessive Services.
 	// Delete has to be the fist action to avoid getting stuck on quota.
diff --git a/pkg/controller/scyllacluster/sync_statefulsets.go b/pkg/controller/scyllacluster/sync_statefulsets.go
index 9c14f7205..917a889bb 100644
--- a/pkg/controller/scyllacluster/sync_statefulsets.go
+++ b/pkg/controller/scyllacluster/sync_statefulsets.go
@@ -16,7 +16,6 @@ import (
 	"github.com/scylladb/scylla-operator/pkg/pointer"
 	"github.com/scylladb/scylla-operator/pkg/resourceapply"
 	"github.com/scylladb/scylla-operator/pkg/scyllaclient"
-	"github.com/scylladb/scylla-operator/pkg/scyllafeatures"
 	"github.com/scylladb/scylla-operator/pkg/util/parallel"
 	"github.com/scylladb/scylla-operator/pkg/util/slices"
 	appsv1 "k8s.io/api/apps/v1"
@@ -464,26 +463,6 @@ func (scc *Controller) syncStatefulSets(
 	var err error
 	var progressingConditions []metav1.Condition
 
-	if sc.Spec.ExposeOptions != nil && sc.Spec.ExposeOptions.BroadcastOptions != nil {
-		if sc.Spec.ExposeOptions.BroadcastOptions.Clients.Type != scyllav1.BroadcastAddressTypeServiceClusterIP ||
-			sc.Spec.ExposeOptions.BroadcastOptions.Nodes.Type != scyllav1.BroadcastAddressTypeServiceClusterIP {
-			supportsExposing, err := scyllafeatures.Supports(sc, scyllafeatures.ExposingScyllaClusterViaServiceOtherThanClusterIP)
-			if err != nil {
-				return nil, fmt.Errorf("can't determine if ScyllaDB version %q supports exposing via Service other than ClusterIP: %w", sc.Spec.Version, err)
-			}
-
-			if !supportsExposing {
-				scc.eventRecorder.Eventf(
-					sc,
-					corev1.EventTypeWarning,
-					"InvalidScyllaDBVersion",
-					fmt.Sprintf("Requested ScyllaDB version %q does not support broadcasting other address than ClusterIP, use the latest one", sc.Spec.Version),
-				)
-				return nil, fmt.Errorf("requested ScyllaDB version %q does not support broadcasting other address than ClusterIP, use the latest one", sc.Spec.Version)
-			}
-		}
-	}
-
 	requiredStatefulSets, err := scc.makeRacks(sc, statefulSets)
 	if err != nil {
 		scc.eventRecorder.Eventf(
diff --git a/pkg/controller/scyllacluster/validation.go b/pkg/controller/scyllacluster/validation.go
deleted file mode 100644
index 4f2069a37..000000000
--- a/pkg/controller/scyllacluster/validation.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2023 ScyllaDB.
-
-package scyllacluster
-
-import (
-	"fmt"
-
-	scyllav1 "github.com/scylladb/scylla-operator/pkg/api/scylla/v1"
-	"github.com/scylladb/scylla-operator/pkg/scyllafeatures"
-	corev1 "k8s.io/api/core/v1"
-	"k8s.io/client-go/tools/record"
-)
-
-func runPreRolloutChecks(sc *scyllav1.ScyllaCluster, eventRecorder record.EventRecorder) error {
-	supportsExposing, err := scyllafeatures.Supports(sc, scyllafeatures.ExposingScyllaClusterViaServiceOtherThanClusterIP)
-	if err != nil {
-		return fmt.Errorf("can't determine if ScyllaDB version %q supports exposing via Service other than ClusterIP: %w", sc.Spec.Version, err)
-	}
-
-	exposingSupportRequired := false
-
-	if sc.Spec.ExposeOptions != nil && sc.Spec.ExposeOptions.NodeService != nil && sc.Spec.ExposeOptions.NodeService.Type != scyllav1.NodeServiceTypeClusterIP {
-		exposingSupportRequired = true
-	}
-
-	if sc.Spec.ExposeOptions != nil && sc.Spec.ExposeOptions.BroadcastOptions != nil {
-		bo := sc.Spec.ExposeOptions.BroadcastOptions
-		exposingSupportRequired = bo.Clients.Type != scyllav1.BroadcastAddressTypeServiceClusterIP || bo.Nodes.Type != scyllav1.BroadcastAddressTypeServiceClusterIP
-	}
-
-	if exposingSupportRequired && !supportsExposing {
-		eventRecorder.Eventf(
-			sc,
-			corev1.EventTypeWarning,
-			"InvalidScyllaDBVersion",
-			fmt.Sprintf("Can't proceed with the rollout. Specified ScyllaDB version %q does not support exposing via Service other than ClusterIP. Please use different ScyllaDB version.", sc.Spec.Version),
-		)
-		return fmt.Errorf("can't proceed with the rollout. Specified ScyllaDB version %q does not support exposing via Service other than ClusterIP. Please use different ScyllaDB version", sc.Spec.Version)
-	}
-
-	return nil
-}
diff --git a/pkg/controller/scylladbmonitoring/sync_grafana.go b/pkg/controller/scylladbmonitoring/sync_grafana.go
index 77f870773..1035cd0aa 100644
--- a/pkg/controller/scylladbmonitoring/sync_grafana.go
+++ b/pkg/controller/scylladbmonitoring/sync_grafana.go
@@ -11,7 +11,6 @@ import (
 	"github.com/scylladb/scylla-operator/pkg/controllerhelpers"
 	ocrypto "github.com/scylladb/scylla-operator/pkg/crypto"
 	"github.com/scylladb/scylla-operator/pkg/helpers"
-	"github.com/scylladb/scylla-operator/pkg/helpers/slices"
 	okubecrypto "github.com/scylladb/scylla-operator/pkg/kubecrypto"
 	"github.com/scylladb/scylla-operator/pkg/naming"
 	"github.com/scylladb/scylla-operator/pkg/pointer"
@@ -304,7 +303,7 @@ func (smc *Controller) syncGrafana(
 
 	err = controllerhelpers.Prune(
 		ctx,
-		slices.ToSlice(requiredGrafanaSA),
+		helpers.ToArray(requiredGrafanaSA),
 		serviceAccounts,
 		&controllerhelpers.PruneControlFuncs{
 			DeleteFunc: smc.kubeClient.CoreV1().ServiceAccounts(sm.Namespace).Delete,
@@ -344,7 +343,7 @@ func (smc *Controller) syncGrafana(
 
 	err = controllerhelpers.Prune(
 		ctx,
-		slices.ToSlice(requiredService),
+		helpers.ToArray(requiredService),
 		services,
 		&controllerhelpers.PruneControlFuncs{
 			DeleteFunc: smc.kubeClient.CoreV1().Services(sm.Namespace).Delete,
@@ -355,7 +354,7 @@ func (smc *Controller) syncGrafana(
 
 	err = controllerhelpers.Prune(
 		ctx,
-		slices.ToSlice(requiredDeployment),
+		helpers.ToArray(requiredDeployment),
 		deployments,
 		&controllerhelpers.PruneControlFuncs{
 			DeleteFunc: smc.kubeClient.AppsV1().Deployments(sm.Namespace).Delete,
@@ -366,7 +365,7 @@ func (smc *Controller) syncGrafana(
 
 	err = controllerhelpers.Prune(
 		ctx,
-		slices.FilterOutNil(slices.ToSlice(requiredIngress)),
+		helpers.FilterOutNil(helpers.ToArray(requiredIngress)),
 		ingresses,
 		&controllerhelpers.PruneControlFuncs{
 			DeleteFunc: smc.kubeClient.NetworkingV1().Ingresses(sm.Namespace).Delete,
diff --git a/pkg/controller/scylladbmonitoring/sync_prometheus.go b/pkg/controller/scylladbmonitoring/sync_prometheus.go
index e0f6d75b9..fafe5c192 100644
--- a/pkg/controller/scylladbmonitoring/sync_prometheus.go
+++ b/pkg/controller/scylladbmonitoring/sync_prometheus.go
@@ -12,7 +12,6 @@ import (
 	ocrypto "github.com/scylladb/scylla-operator/pkg/crypto"
 	monitoringv1 "github.com/scylladb/scylla-operator/pkg/externalapi/monitoring/v1"
 	"github.com/scylladb/scylla-operator/pkg/helpers"
-	"github.com/scylladb/scylla-operator/pkg/helpers/slices"
 	okubecrypto "github.com/scylladb/scylla-operator/pkg/kubecrypto"
 	"github.com/scylladb/scylla-operator/pkg/naming"
 	"github.com/scylladb/scylla-operator/pkg/pointer"
@@ -301,7 +300,7 @@ func (smc *Controller) syncPrometheus(
 
 	err = controllerhelpers.Prune(
 		ctx,
-		slices.ToSlice(requiredPrometheusSA),
+		helpers.ToArray(requiredPrometheusSA),
 		serviceAccounts,
 		&controllerhelpers.PruneControlFuncs{
 			DeleteFunc: smc.kubeClient.CoreV1().ServiceAccounts(sm.Namespace).Delete,
@@ -312,7 +311,7 @@ func (smc *Controller) syncPrometheus(
 
 	err = controllerhelpers.Prune(
 		ctx,
-		slices.ToSlice(requiredPrometheusService),
+		helpers.ToArray(requiredPrometheusService),
 		services,
 		&controllerhelpers.PruneControlFuncs{
 			DeleteFunc: smc.kubeClient.CoreV1().Services(sm.Namespace).Delete,
@@ -323,7 +322,7 @@ func (smc *Controller) syncPrometheus(
 
 	err = controllerhelpers.Prune(
 		ctx,
-		slices.ToSlice(requiredPrometheusRoleBinding),
+		helpers.ToArray(requiredPrometheusRoleBinding),
 		roleBindings,
 		&controllerhelpers.PruneControlFuncs{
 			DeleteFunc: smc.kubeClient.RbacV1().RoleBindings(sm.Namespace).Delete,
@@ -334,7 +333,7 @@ func (smc *Controller) syncPrometheus(
 
 	err = controllerhelpers.Prune(
 		ctx,
-		slices.ToSlice(requiredPrometheus),
+		helpers.ToArray(requiredPrometheus),
 		prometheuses,
 		&controllerhelpers.PruneControlFuncs{
 			DeleteFunc: smc.monitoringClient.Prometheuses(sm.Namespace).Delete,
@@ -345,7 +344,7 @@ func (smc *Controller) syncPrometheus(
 
 	err = controllerhelpers.Prune(
 		ctx,
-		slices.FilterOutNil(slices.ToSlice(requiredIngress)),
+		helpers.FilterOutNil(helpers.ToArray(requiredIngress)),
 		ingresses,
 		&controllerhelpers.PruneControlFuncs{
 			DeleteFunc: smc.kubeClient.NetworkingV1().Ingresses(sm.Namespace).Delete,
@@ -356,7 +355,7 @@ func (smc *Controller) syncPrometheus(
 
 	err = controllerhelpers.Prune(
 		ctx,
-		slices.ToSlice(requiredRecodingPrometheusRule, requiredAlertsPrometheusRule),
+		helpers.ToArray(requiredRecodingPrometheusRule, requiredAlertsPrometheusRule),
 		prometheusRules,
 		&controllerhelpers.PruneControlFuncs{
 			DeleteFunc: smc.monitoringClient.PrometheusRules(sm.Namespace).Delete,
@@ -367,7 +366,7 @@ func (smc *Controller) syncPrometheus(
 
 	err = controllerhelpers.Prune(
 		ctx,
-		slices.ToSlice(requiredScyllaDBServiceMonitor),
+		helpers.ToArray(requiredScyllaDBServiceMonitor),
 		serviceMonitors,
 		&controllerhelpers.PruneControlFuncs{
 			DeleteFunc: smc.monitoringClient.ServiceMonitors(sm.Namespace).Delete,
diff --git a/pkg/helpers/slices/slices.go b/pkg/helpers/array.go
similarity index 72%
rename from pkg/helpers/slices/slices.go
rename to pkg/helpers/array.go
index 551ea655b..3b05b480a 100644
--- a/pkg/helpers/slices/slices.go
+++ b/pkg/helpers/array.go
@@ -1,13 +1,11 @@
-// Copyright (c) 2023 ScyllaDB
+package helpers
 
-package slices
-
-func ToSlice[T any](objs ...T) []T {
+func ToArray[T any](objs ...T) []T {
 	res := make([]T, 0, len(objs))
 	return append(res, objs...)
 }
 
-func ConvertToSlice[To, From any](convert func(From) To, objs ...From) []To {
+func ConvertToArray[To, From any](convert func(From) To, objs ...From) []To {
 	res := make([]To, 0, len(objs))
 
 	for i := range objs {
@@ -18,7 +16,7 @@ func ConvertToSlice[To, From any](convert func(From) To, objs ...From) []To {
 }
 
 func ConvertSlice[To, From any](slice []From, convert func(From) To) []To {
-	return ConvertToSlice(convert, slice...)
+	return ConvertToArray(convert, slice...)
 }
 
 func Filter[T any](array []T, filterFunc func(T) bool) []T {
@@ -65,18 +63,14 @@ func ContainsItem[T comparable](slice []T, item T) bool {
 	return Contains(slice, IdentityFunc(item))
 }
 
-func Find[T any](slice []T, filterFunc func(T) bool) (T, int, bool) {
+func Find[T comparable](slice []T, filterFunc func(T) bool) (T, bool) {
 	for i := range slice {
 		if filterFunc(slice[i]) {
-			return slice[i], i, true
+			return slice[i], true
 		}
 	}
 
-	return *new(T), 0, false
-}
-
-func FindItem[T comparable](slice []T, item T) (T, int, bool) {
-	return Find(slice, IdentityFunc(item))
+	return *new(T), false
 }
 
 func Flatten[T any](xs [][]T) []T {
@@ -88,7 +82,3 @@ func Flatten[T any](xs [][]T) []T {
 
 	return res
 }
-
-func ToString[T ~string](v T) string {
-	return string(v)
-}
diff --git a/pkg/helpers/collections.go b/pkg/helpers/collections.go
index 010ae18b9..29ab974ed 100644
--- a/pkg/helpers/collections.go
+++ b/pkg/helpers/collections.go
@@ -18,11 +18,3 @@ func GetMapValues[M ~map[K]V, K comparable, V any](m M) []V {
 	}
 	return res
 }
-
-func ShallowCopyMap[M ~map[K]V, K comparable, V any](m M) M {
-	res := make(M, len(m))
-	for k, v := range m {
-		res[k] = v
-	}
-	return res
-}
diff --git a/pkg/naming/constants.go b/pkg/naming/constants.go
index f6d93c133..beaa6832d 100644
--- a/pkg/naming/constants.go
+++ b/pkg/naming/constants.go
@@ -64,7 +64,6 @@ const (
 	ClusterNameLabel             = "scylla/cluster"
 	DatacenterNameLabel          = "scylla/datacenter"
 	RackNameLabel                = "scylla/rack"
-	RackOrdinalLabel             = "scylla/rack-ordinal"
 	ScyllaVersionLabel           = "scylla/scylla-version"
 	ScyllaServiceTypeLabel       = "scylla-operator.scylladb.com/scylla-service-type"
 	ScyllaIngressTypeLabel       = "scylla-operator.scylladb.com/scylla-ingress-type"
diff --git a/pkg/naming/labels.go b/pkg/naming/labels.go
index ab0aa9beb..4601c4422 100644
--- a/pkg/naming/labels.go
+++ b/pkg/naming/labels.go
@@ -1,11 +1,7 @@
 package naming
 
 import (
-	"fmt"
-	"strconv"
-
 	scyllav1 "github.com/scylladb/scylla-operator/pkg/api/scylla/v1"
-	"github.com/scylladb/scylla-operator/pkg/helpers/slices"
 	appsv1 "k8s.io/api/apps/v1"
 	"k8s.io/apimachinery/pkg/labels"
 )
@@ -30,19 +26,12 @@ func DatacenterLabels(c *scyllav1.ScyllaCluster) map[string]string {
 
 // RackLabels returns a map of label keys and values
 // for the given Rack.
-func RackLabels(r scyllav1.RackSpec, c *scyllav1.ScyllaCluster) (map[string]string, error) {
+func RackLabels(r scyllav1.RackSpec, c *scyllav1.ScyllaCluster) map[string]string {
 	recLabels := ScyllaLabels()
 	rackLabels := DatacenterLabels(c)
 	rackLabels[RackNameLabel] = r.Name
-	_, rackOrdinal, ok := slices.Find(c.Spec.Datacenter.Racks, func(rack scyllav1.RackSpec) bool {
-		return rack.Name == r.Name
-	})
-	if !ok {
-		return nil, fmt.Errorf("can't find ordinal of rack %q in ScyllaCluster %q", r.Name, ObjRef(c))
-	}
-	rackLabels[RackOrdinalLabel] = strconv.Itoa(rackOrdinal)
 
-	return mergeLabels(rackLabels, recLabels), nil
+	return mergeLabels(rackLabels, recLabels)
 }
 
 // StatefulSetPodLabel returns a map of labels to uniquely
@@ -54,16 +43,12 @@ func StatefulSetPodLabel(name string) map[string]string {
 }
 
 // RackSelector returns a LabelSelector for the given rack.
-func RackSelector(r scyllav1.RackSpec, c *scyllav1.ScyllaCluster) (labels.Selector, error) {
-	rackLabels, err := RackLabels(r, c)
-	if err != nil {
-		return nil, fmt.Errorf("can't get rack labels: %w", err)
-	}
+func RackSelector(r scyllav1.RackSpec, c *scyllav1.ScyllaCluster) labels.Selector {
 
-	rackLabelsSet := labels.Set(rackLabels)
+	rackLabelsSet := labels.Set(RackLabels(r, c))
 	sel := labels.SelectorFromSet(rackLabelsSet)
 
-	return sel, nil
+	return sel
 }
 
 func ScyllaLabels() map[string]string {
diff --git a/pkg/scyllaclient/config_client.go b/pkg/scyllaclient/config_client.go
index 205119bc1..dfe454ec0 100644
--- a/pkg/scyllaclient/config_client.go
+++ b/pkg/scyllaclient/config_client.go
@@ -46,14 +46,6 @@ func NewConfigClient(host, authToken string) *ConfigClient {
 	}
 }
 
-func (c *ConfigClient) BroadcastRPCAddress(ctx context.Context) (string, error) {
-	resp, err := c.client.Config.FindConfigBroadcastRPCAddress(config.NewFindConfigBroadcastRPCAddressParamsWithContext(ctx))
-	if err != nil {
-		return "", fmt.Errorf("can't get broadcast_rpc_address: %w", err)
-	}
-	return resp.Payload, nil
-}
-
 func (c *ConfigClient) BroadcastAddress(ctx context.Context) (string, error) {
 	resp, err := c.client.Config.FindConfigBroadcastAddress(config.NewFindConfigBroadcastAddressParamsWithContext(ctx))
 	if err != nil {
diff --git a/pkg/scyllafeatures/scyllafeatures.go b/pkg/scyllafeatures/scyllafeatures.go
index 09f0a9243..a41d511fa 100644
--- a/pkg/scyllafeatures/scyllafeatures.go
+++ b/pkg/scyllafeatures/scyllafeatures.go
@@ -16,8 +16,7 @@ var (
 type ScyllaFeature string
 
 const (
-	ReplacingNodeUsingHostID                          ScyllaFeature = "ReplacingNodeUsingHostID"
-	ExposingScyllaClusterViaServiceOtherThanClusterIP ScyllaFeature = "ExposingScyllaClusterViaServiceOtherThanClusterIP"
+	ReplacingNodeUsingHostID ScyllaFeature = "ReplacingNodeUsingHostID"
 )
 
 type scyllaDBVersionMinimalConstraint struct {
@@ -30,39 +29,30 @@ var featureMinimalVersionConstraints = map[ScyllaFeature]scyllaDBVersionMinimalC
 		openSource: semver.MustParse("5.2.0"),
 		enterprise: semver.MustParse("2023.1.0"),
 	},
-	// Exposing requires ReplacingNodeUsingHostID, so minimal values should be the same.
-	ExposingScyllaClusterViaServiceOtherThanClusterIP: {
-		openSource: semver.MustParse("5.2.0"),
-		enterprise: semver.MustParse("2023.1.0"),
-	},
 }
 
-func VersionSupports(version string, feature ScyllaFeature) (bool, error) {
+func Supports(sc *scyllav1.ScyllaCluster, feature ScyllaFeature) (bool, error) {
 	constraints, ok := featureMinimalVersionConstraints[feature]
 	if !ok {
 		return false, fmt.Errorf("unable to find minimal version constraints, unknown feature %q", feature)
 	}
 
-	parsedVersion, err := semver.Parse(version)
+	version, err := semver.Parse(sc.Spec.Version)
 	if err != nil {
-		return false, fmt.Errorf("can't parse ScyllaCluster version %q: %w", version, err)
+		return false, fmt.Errorf("can't parse ScyllaCluster version %q: %w", sc.Spec.Version, err)
 	}
 
-	if isOpenSource(parsedVersion) && parsedVersion.GTE(constraints.openSource) {
+	if isOpenSource(version) && version.GTE(constraints.openSource) {
 		return true, nil
 	}
 
-	if isEnterprise(parsedVersion) && parsedVersion.GTE(constraints.enterprise) {
+	if isEnterprise(version) && version.GTE(constraints.enterprise) {
 		return true, nil
 	}
 
 	return false, nil
 }
 
-func Supports(sc *scyllav1.ScyllaCluster, feature ScyllaFeature) (bool, error) {
-	return VersionSupports(sc.Spec.Version, feature)
-}
-
 func isEnterprise(v semver.Version) bool {
 	return v.GTE(scyllaEnterpriseMinimalVersion)
 }
diff --git a/pkg/sidecar/config/config.go b/pkg/sidecar/config/config.go
index 496ee4e1c..8b8cd42e8 100644
--- a/pkg/sidecar/config/config.go
+++ b/pkg/sidecar/config/config.go
@@ -231,15 +231,14 @@ func (s *ScyllaConfig) setupEntrypoint(ctx context.Context) (*exec.Cmd, error) {
 	prometheusAddress := "0.0.0.0"
 	args := map[string]*string{
 		"listen-address":        &listenAddress,
+		"broadcast-address":     &m.StaticIP,
+		"broadcast-rpc-address": &m.StaticIP,
 		"seeds":                 pointer.Ptr(strings.Join(seeds, ",")),
 		"developer-mode":        &devMode,
 		"overprovisioned":       &overprovisioned,
 		"smp":                   pointer.Ptr(strconv.Itoa(s.cpuCount)),
 		"prometheus-address":    &prometheusAddress,
-		"broadcast-address":     &m.BroadcastAddress,
-		"broadcast-rpc-address": &m.BroadcastRPCAddress,
 	}
-
 	if cluster.Spec.Alternator.Enabled() {
 		args["alternator-port"] = pointer.Ptr(strconv.Itoa(int(cluster.Spec.Alternator.Port)))
 		if cluster.Spec.Alternator.WriteIsolation != "" {
diff --git a/pkg/sidecar/identity/member.go b/pkg/sidecar/identity/member.go
index a00dae514..c9668d5d4 100644
--- a/pkg/sidecar/identity/member.go
+++ b/pkg/sidecar/identity/member.go
@@ -4,9 +4,7 @@ import (
 	"context"
 	"fmt"
 	"sort"
-	"strconv"
 
-	scyllav1 "github.com/scylladb/scylla-operator/pkg/api/scylla/v1"
 	"github.com/scylladb/scylla-operator/pkg/controllerhelpers"
 	"github.com/scylladb/scylla-operator/pkg/naming"
 	corev1 "k8s.io/api/core/v1"
@@ -22,95 +20,32 @@ type Member struct {
 	Name string
 	// Namespace of the Pod
 	Namespace string
-	// PodIP IP of the Pod
-	PodIP string
-	// ExternalAddress is an external IP or hostname of a LoadBalancer Service
-	ExternalAddress string
+	// IP of the Pod
+	IP string
 	// ClusterIP of the member's Service
-	ClusterIP     string
+	StaticIP      string
 	Rack          string
-	RackOrdinal   int
 	Datacenter    string
 	Cluster       string
 	ServiceLabels map[string]string
 	PodID         string
 
-	Overprovisioned     bool
-	BroadcastRPCAddress string
-	BroadcastAddress    string
-
-	NodesBroadcastAddressType scyllav1.BroadcastAddressType
+	Overprovisioned bool
 }
 
-func NewMember(service *corev1.Service, pod *corev1.Pod, nodesAddressType, clientAddressType scyllav1.BroadcastAddressType) (*Member, error) {
-	rackOrdinalString, ok := pod.Labels[naming.RackOrdinalLabel]
-	if !ok {
-		return nil, fmt.Errorf("pod %q is missing %q label", naming.ObjRef(pod), naming.RackOrdinalLabel)
-	}
-	rackOrdinal, err := strconv.Atoi(rackOrdinalString)
-	if err != nil {
-		return nil, fmt.Errorf("can't get rack ordinal from label %q: %w", rackOrdinalString, err)
-	}
-
-	var externalIP string
-	if service.Spec.Type == corev1.ServiceTypeLoadBalancer {
-		if len(service.Status.LoadBalancer.Ingress) == 0 {
-			return nil, fmt.Errorf("LoadBalancer Service %q is missing endpoints in status", naming.ObjRef(service))
-		}
-
-		firstIngress := service.Status.LoadBalancer.Ingress[0]
-		if len(firstIngress.Hostname) != 0 {
-			externalIP = firstIngress.Hostname
-		}
-
-		if len(firstIngress.IP) != 0 {
-			externalIP = firstIngress.IP
-		}
-
-		if len(externalIP) == 0 {
-			return nil, fmt.Errorf("service first ingress status has empty external address")
-		}
-	}
-
-	m := &Member{
-		Namespace:                 service.Namespace,
-		Name:                      service.Name,
-		PodIP:                     pod.Status.PodIP,
-		ClusterIP:                 service.Spec.ClusterIP,
-		ExternalAddress:           externalIP,
-		Rack:                      pod.Labels[naming.RackNameLabel],
-		RackOrdinal:               rackOrdinal,
-		Datacenter:                pod.Labels[naming.DatacenterNameLabel],
-		Cluster:                   pod.Labels[naming.ClusterNameLabel],
-		ServiceLabels:             service.Labels,
-		PodID:                     string(pod.UID),
-		Overprovisioned:           pod.Status.QOSClass != corev1.PodQOSGuaranteed,
-		NodesBroadcastAddressType: nodesAddressType,
-	}
-
-	switch nodesAddressType {
-	case scyllav1.BroadcastAddressTypePodIP:
-		m.BroadcastAddress = m.PodIP
-	case scyllav1.BroadcastAddressTypeServiceClusterIP:
-		m.BroadcastAddress = m.ClusterIP
-	case scyllav1.BroadcastAddressTypeServiceLoadBalancerIngress:
-		m.BroadcastAddress = m.ExternalAddress
-	default:
-		return nil, fmt.Errorf("unsupported nodes address type: %q", nodesAddressType)
-	}
-
-	switch clientAddressType {
-	case scyllav1.BroadcastAddressTypePodIP:
-		m.BroadcastRPCAddress = m.PodIP
-	case scyllav1.BroadcastAddressTypeServiceClusterIP:
-		m.BroadcastRPCAddress = m.ClusterIP
-	case scyllav1.BroadcastAddressTypeServiceLoadBalancerIngress:
-		m.BroadcastRPCAddress = m.ExternalAddress
-	default:
-		return nil, fmt.Errorf("unsupported clients address type: %q", clientAddressType)
+func NewMemberFromObjects(service *corev1.Service, pod *corev1.Pod) *Member {
+	return &Member{
+		Namespace:       service.Namespace,
+		Name:            service.Name,
+		IP:              pod.Status.PodIP,
+		StaticIP:        service.Spec.ClusterIP,
+		Rack:            pod.Labels[naming.RackNameLabel],
+		Datacenter:      pod.Labels[naming.DatacenterNameLabel],
+		Cluster:         pod.Labels[naming.ClusterNameLabel],
+		ServiceLabels:   service.Labels,
+		PodID:           string(pod.UID),
+		Overprovisioned: pod.Status.QOSClass != corev1.PodQOSGuaranteed,
 	}
-
-	return m, nil
 }
 
 func (m *Member) GetSeeds(ctx context.Context, coreClient v1.CoreV1Interface, externalSeeds []string) ([]string, error) {
@@ -138,21 +73,11 @@ func (m *Member) GetSeeds(ctx context.Context, coreClient v1.CoreV1Interface, ex
 
 	if len(otherPods) == 0 {
 		// We are the only one, assuming first bootstrap.
-
-		podOrdinal, err := naming.IndexFromName(m.Name)
-		if err != nil {
-			return nil, fmt.Errorf("can't get pod index from name: %w", err)
-		}
-
-		if m.RackOrdinal != 0 || podOrdinal != 0 {
-			return nil, fmt.Errorf("pod is not first in the cluster, but there are no other pods")
-		}
-
 		if len(externalSeeds) > 0 {
 			return externalSeeds, nil
 		}
 
-		return []string{m.BroadcastAddress}, nil
+		return []string{m.StaticIP}, nil
 	}
 
 	sort.Slice(otherPods, func(i, j int) bool {
@@ -172,33 +97,7 @@ func (m *Member) GetSeeds(ctx context.Context, coreClient v1.CoreV1Interface, ex
 
 	res := make([]string, 0, len(externalSeeds)+1)
 	res = append(res, externalSeeds...)
-
-	// Assume nodes share broadcast address type, and it's immutable.
-	switch m.NodesBroadcastAddressType {
-	case scyllav1.BroadcastAddressTypeServiceLoadBalancerIngress:
-		if len(svc.Status.LoadBalancer.Ingress) < 1 {
-			return nil, fmt.Errorf("service %q does not have ingress status, despite external address being set as broadcasted", naming.ObjRef(svc))
-		}
-		if len(svc.Status.LoadBalancer.Ingress[0].IP) != 0 {
-			res = append(res, svc.Status.LoadBalancer.Ingress[0].IP)
-		} else if len(svc.Status.LoadBalancer.Ingress[0].Hostname) != 0 {
-			res = append(res, svc.Status.LoadBalancer.Ingress[0].Hostname)
-		} else {
-			return nil, fmt.Errorf("service %q does not have external address, despite being set as broadcasted", naming.ObjRef(svc))
-		}
-	case scyllav1.BroadcastAddressTypeServiceClusterIP:
-		if svc.Spec.ClusterIP == corev1.ClusterIPNone {
-			return nil, fmt.Errorf("service %q does not have ClusterIP address, despite being set as broadcasted", naming.ObjRef(svc))
-		}
-		res = append(res, svc.Spec.ClusterIP)
-	case scyllav1.BroadcastAddressTypePodIP:
-		if len(pod.Status.PodIP) == 0 {
-			return nil, fmt.Errorf("pod %q does not have IP address, despite being set as broadcasted", naming.ObjRef(pod))
-		}
-		res = append(res, pod.Status.PodIP)
-	default:
-		return nil, fmt.Errorf("unsupported node broadcast address type %q", m.NodesBroadcastAddressType)
-	}
+	res = append(res, svc.Spec.ClusterIP)
 
 	return res, nil
 }
diff --git a/pkg/systemd/unit.go b/pkg/systemd/unit.go
index 50998b3d2..4ea48f04f 100644
--- a/pkg/systemd/unit.go
+++ b/pkg/systemd/unit.go
@@ -10,7 +10,7 @@ import (
 	"path/filepath"
 
 	scyllav1alpha1 "github.com/scylladb/scylla-operator/pkg/api/scylla/v1alpha1"
-	"github.com/scylladb/scylla-operator/pkg/helpers/slices"
+	"github.com/scylladb/scylla-operator/pkg/helpers"
 	"gopkg.in/yaml.v2"
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/client-go/tools/record"
@@ -156,7 +156,7 @@ func (m *UnitManager) EnsureUnits(ctx context.Context, nc *scyllav1alpha1.NodeCo
 
 	// First save the updated list of managed units first,
 	// so we can clean up in the next run, if we were interrupted.
-	status.ManagedUnits = slices.ConvertToSlice(func(unit *NamedUnit) string {
+	status.ManagedUnits = helpers.ConvertToArray(func(unit *NamedUnit) string {
 		return unit.FileName
 	}, requiredUnits...)
 


Test patch:
diff --git a/pkg/api/scylla/validation/cluster_validation_test.go b/pkg/api/scylla/validation/cluster_validation_test.go
index 86b5b3c5d..9c1b3ed61 100644
--- a/pkg/api/scylla/validation/cluster_validation_test.go
+++ b/pkg/api/scylla/validation/cluster_validation_test.go
@@ -15,8 +15,6 @@ import (
 )
 
 func TestValidateScyllaCluster(t *testing.T) {
-	t.Parallel()
-
 	validCluster := unit.NewSingleRackCluster(3)
 	validCluster.Spec.Datacenter.Racks[0].Resources = corev1.ResourceRequirements{
 		Limits: map[corev1.ResourceName]resource.Quantity{
@@ -115,177 +113,10 @@ func TestValidateScyllaCluster(t *testing.T) {
 			},
 			expectedErrorString: `spec.dnsDomains[0]: Invalid value: "-hello": a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')`,
 		},
-		{
-			name: "unsupported type of node service",
-			cluster: func() *v1.ScyllaCluster {
-				cluster := validCluster.DeepCopy()
-				cluster.Spec.Version = "5.2.0"
-				cluster.Spec.ExposeOptions = &v1.ExposeOptions{
-					NodeService: &v1.NodeServiceTemplate{
-						Type: "foo",
-					},
-				}
-
-				return cluster
-			}(),
-			expectedErrorList: field.ErrorList{
-				&field.Error{Type: field.ErrorTypeNotSupported, Field: "spec.exposeOptions.nodeService.type", BadValue: v1.NodeServiceType("foo"), Detail: `supported values: "Headless", "ClusterIP", "LoadBalancer"`},
-			},
-			expectedErrorString: `spec.exposeOptions.nodeService.type: Unsupported value: "foo": supported values: "Headless", "ClusterIP", "LoadBalancer"`,
-		},
-		{
-			name: "invalid load balancer class name in node service template",
-			cluster: func() *v1.ScyllaCluster {
-				cluster := validCluster.DeepCopy()
-				cluster.Spec.ExposeOptions = &v1.ExposeOptions{
-					NodeService: &v1.NodeServiceTemplate{
-						Type:              v1.NodeServiceTypeClusterIP,
-						LoadBalancerClass: pointer.Ptr("-hello"),
-					},
-				}
-
-				return cluster
-			}(),
-			expectedErrorList: field.ErrorList{
-				&field.Error{Type: field.ErrorTypeInvalid, Field: "spec.exposeOptions.nodeService.loadBalancerClass", BadValue: "-hello", Detail: `a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')`},
-			},
-			expectedErrorString: `spec.exposeOptions.nodeService.loadBalancerClass: Invalid value: "-hello": a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')`,
-		},
-		{
-			name: "unsupported type of client broadcast address",
-			cluster: func() *v1.ScyllaCluster {
-				cluster := validCluster.DeepCopy()
-				cluster.Spec.Version = "5.2.0"
-				cluster.Spec.ExposeOptions = &v1.ExposeOptions{
-					BroadcastOptions: &v1.NodeBroadcastOptions{
-						Nodes: v1.BroadcastOptions{
-							Type: v1.BroadcastAddressTypeServiceClusterIP,
-						},
-						Clients: v1.BroadcastOptions{
-							Type: "foo",
-						},
-					},
-				}
-
-				return cluster
-			}(),
-			expectedErrorList: field.ErrorList{
-				&field.Error{Type: field.ErrorTypeNotSupported, Field: "spec.exposeOptions.broadcastOptions.clients.type", BadValue: v1.BroadcastAddressType("foo"), Detail: `supported values: "PodIP", "ServiceClusterIP", "ServiceLoadBalancerIngress"`},
-			},
-			expectedErrorString: `spec.exposeOptions.broadcastOptions.clients.type: Unsupported value: "foo": supported values: "PodIP", "ServiceClusterIP", "ServiceLoadBalancerIngress"`,
-		},
-		{
-			name: "unsupported type of node broadcast address",
-			cluster: func() *v1.ScyllaCluster {
-				cluster := validCluster.DeepCopy()
-				cluster.Spec.Version = "5.2.0"
-				cluster.Spec.ExposeOptions = &v1.ExposeOptions{
-					BroadcastOptions: &v1.NodeBroadcastOptions{
-						Nodes: v1.BroadcastOptions{
-							Type: "foo",
-						},
-						Clients: v1.BroadcastOptions{
-							Type: v1.BroadcastAddressTypeServiceClusterIP,
-						},
-					},
-				}
-
-				return cluster
-			}(),
-			expectedErrorList: field.ErrorList{
-				&field.Error{Type: field.ErrorTypeNotSupported, Field: "spec.exposeOptions.broadcastOptions.nodes.type", BadValue: v1.BroadcastAddressType("foo"), Detail: `supported values: "PodIP", "ServiceClusterIP", "ServiceLoadBalancerIngress"`},
-			},
-			expectedErrorString: `spec.exposeOptions.broadcastOptions.nodes.type: Unsupported value: "foo": supported values: "PodIP", "ServiceClusterIP", "ServiceLoadBalancerIngress"`,
-		},
-		{
-			name: "invalid ClusterIP broadcast type when node service is Headless",
-			cluster: func() *v1.ScyllaCluster {
-				cluster := validCluster.DeepCopy()
-				cluster.Spec.Version = "5.2.0"
-				cluster.Spec.ExposeOptions = &v1.ExposeOptions{
-					NodeService: &v1.NodeServiceTemplate{
-						Type: v1.NodeServiceTypeHeadless,
-					},
-					BroadcastOptions: &v1.NodeBroadcastOptions{
-						Clients: v1.BroadcastOptions{
-							Type: v1.BroadcastAddressTypeServiceClusterIP,
-						},
-						Nodes: v1.BroadcastOptions{
-							Type: v1.BroadcastAddressTypeServiceClusterIP,
-						},
-					},
-				}
-
-				return cluster
-			}(),
-			expectedErrorList: field.ErrorList{
-				&field.Error{Type: field.ErrorTypeInvalid, Field: "spec.exposeOptions.broadcastOptions.clients.type", BadValue: v1.BroadcastAddressTypeServiceClusterIP, Detail: `can't broadcast address unavailable within the selected node service type, allowed types for chosen broadcast address type are: [ClusterIP LoadBalancer]`},
-				&field.Error{Type: field.ErrorTypeInvalid, Field: "spec.exposeOptions.broadcastOptions.nodes.type", BadValue: v1.BroadcastAddressTypeServiceClusterIP, Detail: `can't broadcast address unavailable within the selected node service type, allowed types for chosen broadcast address type are: [ClusterIP LoadBalancer]`},
-			},
-			expectedErrorString: `[spec.exposeOptions.broadcastOptions.clients.type: Invalid value: "ServiceClusterIP": can't broadcast address unavailable within the selected node service type, allowed types for chosen broadcast address type are: [ClusterIP LoadBalancer], spec.exposeOptions.broadcastOptions.nodes.type: Invalid value: "ServiceClusterIP": can't broadcast address unavailable within the selected node service type, allowed types for chosen broadcast address type are: [ClusterIP LoadBalancer]]`,
-		},
-		{
-			name: "invalid LoadBalancerIngressIP broadcast type when node service is Headless",
-			cluster: func() *v1.ScyllaCluster {
-				cluster := validCluster.DeepCopy()
-				cluster.Spec.Version = "5.2.0"
-				cluster.Spec.ExposeOptions = &v1.ExposeOptions{
-					NodeService: &v1.NodeServiceTemplate{
-						Type: v1.NodeServiceTypeHeadless,
-					},
-					BroadcastOptions: &v1.NodeBroadcastOptions{
-						Clients: v1.BroadcastOptions{
-							Type: v1.BroadcastAddressTypeServiceLoadBalancerIngress,
-						},
-						Nodes: v1.BroadcastOptions{
-							Type: v1.BroadcastAddressTypeServiceLoadBalancerIngress,
-						},
-					},
-				}
-
-				return cluster
-			}(),
-			expectedErrorList: field.ErrorList{
-				&field.Error{Type: field.ErrorTypeInvalid, Field: "spec.exposeOptions.broadcastOptions.clients.type", BadValue: v1.BroadcastAddressTypeServiceLoadBalancerIngress, Detail: `can't broadcast address unavailable within the selected node service type, allowed types for chosen broadcast address type are: [LoadBalancer]`},
-				&field.Error{Type: field.ErrorTypeInvalid, Field: "spec.exposeOptions.broadcastOptions.nodes.type", BadValue: v1.BroadcastAddressTypeServiceLoadBalancerIngress, Detail: `can't broadcast address unavailable within the selected node service type, allowed types for chosen broadcast address type are: [LoadBalancer]`},
-			},
-			expectedErrorString: `[spec.exposeOptions.broadcastOptions.clients.type: Invalid value: "ServiceLoadBalancerIngress": can't broadcast address unavailable within the selected node service type, allowed types for chosen broadcast address type are: [LoadBalancer], spec.exposeOptions.broadcastOptions.nodes.type: Invalid value: "ServiceLoadBalancerIngress": can't broadcast address unavailable within the selected node service type, allowed types for chosen broadcast address type are: [LoadBalancer]]`,
-		},
-		{
-			name: "invalid LoadBalancerIngressIP broadcast type when node service is ClusterIP",
-			cluster: func() *v1.ScyllaCluster {
-				cluster := validCluster.DeepCopy()
-				cluster.Spec.Version = "5.2.0"
-				cluster.Spec.ExposeOptions = &v1.ExposeOptions{
-					NodeService: &v1.NodeServiceTemplate{
-						Type: v1.NodeServiceTypeClusterIP,
-					},
-					BroadcastOptions: &v1.NodeBroadcastOptions{
-						Clients: v1.BroadcastOptions{
-							Type: v1.BroadcastAddressTypeServiceLoadBalancerIngress,
-						},
-						Nodes: v1.BroadcastOptions{
-							Type: v1.BroadcastAddressTypeServiceLoadBalancerIngress,
-						},
-					},
-				}
-
-				return cluster
-			}(),
-			expectedErrorList: field.ErrorList{
-				&field.Error{Type: field.ErrorTypeInvalid, Field: "spec.exposeOptions.broadcastOptions.clients.type", BadValue: v1.BroadcastAddressTypeServiceLoadBalancerIngress, Detail: `can't broadcast address unavailable within the selected node service type, allowed types for chosen broadcast address type are: [LoadBalancer]`},
-				&field.Error{Type: field.ErrorTypeInvalid, Field: "spec.exposeOptions.broadcastOptions.nodes.type", BadValue: v1.BroadcastAddressTypeServiceLoadBalancerIngress, Detail: `can't broadcast address unavailable within the selected node service type, allowed types for chosen broadcast address type are: [LoadBalancer]`},
-			},
-			expectedErrorString: `[spec.exposeOptions.broadcastOptions.clients.type: Invalid value: "ServiceLoadBalancerIngress": can't broadcast address unavailable within the selected node service type, allowed types for chosen broadcast address type are: [LoadBalancer], spec.exposeOptions.broadcastOptions.nodes.type: Invalid value: "ServiceLoadBalancerIngress": can't broadcast address unavailable within the selected node service type, allowed types for chosen broadcast address type are: [LoadBalancer]]`,
-		},
 	}
 
-	for i := range tests {
-		test := tests[i]
-
+	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
-			t.Parallel()
-
 			errList := validation.ValidateScyllaCluster(test.cluster)
 			if !reflect.DeepEqual(errList, test.expectedErrorList) {
 				t.Errorf("expected and actual error lists differ: %s", cmp.Diff(test.expectedErrorList, errList))
@@ -422,126 +253,6 @@ func TestValidateScyllaClusterUpdate(t *testing.T) {
 			},
 			expectedErrorString: `[spec.datacenter.racks[0]: Forbidden: rack "rack-0" can't be removed because it still has members that have to be scaled down to zero first, spec.datacenter.racks[1]: Forbidden: rack "rack-1" can't be removed because it still has members that have to be scaled down to zero first, spec.datacenter.racks[2]: Forbidden: rack "rack-2" can't be removed because it still has members that have to be scaled down to zero first]`,
 		},
-		{
-			name: "node service type cannot be unset",
-			old: func() *v1.ScyllaCluster {
-				sc := unit.NewSingleRackCluster(3)
-				sc.Spec.ExposeOptions = &v1.ExposeOptions{
-					NodeService: &v1.NodeServiceTemplate{
-						Type: v1.NodeServiceTypeClusterIP,
-					},
-				}
-				return sc
-			}(),
-			new: func() *v1.ScyllaCluster {
-				sc := unit.NewSingleRackCluster(3)
-				sc.Spec.ExposeOptions = nil
-				return sc
-			}(),
-			expectedErrorList: field.ErrorList{
-				&field.Error{Type: field.ErrorTypeInvalid, Field: "spec.exposeOptions.nodeService.type", BadValue: (*v1.NodeServiceType)(nil), Detail: `field is immutable`},
-			},
-			expectedErrorString: `spec.exposeOptions.nodeService.type: Invalid value: "null": field is immutable`,
-		},
-		{
-			name: "node service type cannot be changed",
-			old: func() *v1.ScyllaCluster {
-				sc := unit.NewSingleRackCluster(3)
-				sc.Spec.ExposeOptions = &v1.ExposeOptions{
-					NodeService: &v1.NodeServiceTemplate{
-						Type: v1.NodeServiceTypeHeadless,
-					},
-				}
-				return sc
-			}(),
-			new: func() *v1.ScyllaCluster {
-				sc := unit.NewSingleRackCluster(3)
-				sc.Spec.ExposeOptions = &v1.ExposeOptions{
-					NodeService: &v1.NodeServiceTemplate{
-						Type: v1.NodeServiceTypeClusterIP,
-					},
-				}
-				return sc
-			}(),
-			expectedErrorList: field.ErrorList{
-				&field.Error{Type: field.ErrorTypeInvalid, Field: "spec.exposeOptions.nodeService.type", BadValue: pointer.Ptr(v1.NodeServiceTypeClusterIP), Detail: `field is immutable`},
-			},
-			expectedErrorString: `spec.exposeOptions.nodeService.type: Invalid value: "ClusterIP": field is immutable`,
-		},
-		{
-			name: "clients broadcast address type cannot be changed",
-			old: func() *v1.ScyllaCluster {
-				sc := unit.NewSingleRackCluster(3)
-				sc.Spec.Version = "5.2.0"
-				sc.Spec.ExposeOptions = &v1.ExposeOptions{
-					BroadcastOptions: &v1.NodeBroadcastOptions{
-						Clients: v1.BroadcastOptions{
-							Type: v1.BroadcastAddressTypeServiceClusterIP,
-						},
-						Nodes: v1.BroadcastOptions{
-							Type: v1.BroadcastAddressTypeServiceClusterIP,
-						},
-					},
-				}
-				return sc
-			}(),
-			new: func() *v1.ScyllaCluster {
-				sc := unit.NewSingleRackCluster(3)
-				sc.Spec.Version = "5.2.0"
-				sc.Spec.ExposeOptions = &v1.ExposeOptions{
-					BroadcastOptions: &v1.NodeBroadcastOptions{
-						Clients: v1.BroadcastOptions{
-							Type: v1.BroadcastAddressTypePodIP,
-						},
-						Nodes: v1.BroadcastOptions{
-							Type: v1.BroadcastAddressTypeServiceClusterIP,
-						},
-					},
-				}
-				return sc
-			}(),
-			expectedErrorList: field.ErrorList{
-				&field.Error{Type: field.ErrorTypeInvalid, Field: "spec.exposeOptions.broadcastOptions.clients.type", BadValue: pointer.Ptr(v1.BroadcastAddressTypePodIP), Detail: `field is immutable`},
-			},
-			expectedErrorString: `spec.exposeOptions.broadcastOptions.clients.type: Invalid value: "PodIP": field is immutable`,
-		},
-		{
-			name: "nodes broadcast address type cannot be changed",
-			old: func() *v1.ScyllaCluster {
-				sc := unit.NewSingleRackCluster(3)
-				sc.Spec.Version = "5.2.0"
-				sc.Spec.ExposeOptions = &v1.ExposeOptions{
-					BroadcastOptions: &v1.NodeBroadcastOptions{
-						Nodes: v1.BroadcastOptions{
-							Type: v1.BroadcastAddressTypeServiceClusterIP,
-						},
-						Clients: v1.BroadcastOptions{
-							Type: v1.BroadcastAddressTypeServiceClusterIP,
-						},
-					},
-				}
-				return sc
-			}(),
-			new: func() *v1.ScyllaCluster {
-				sc := unit.NewSingleRackCluster(3)
-				sc.Spec.Version = "5.2.0"
-				sc.Spec.ExposeOptions = &v1.ExposeOptions{
-					BroadcastOptions: &v1.NodeBroadcastOptions{
-						Nodes: v1.BroadcastOptions{
-							Type: v1.BroadcastAddressTypePodIP,
-						},
-						Clients: v1.BroadcastOptions{
-							Type: v1.BroadcastAddressTypeServiceClusterIP,
-						},
-					},
-				}
-				return sc
-			}(),
-			expectedErrorList: field.ErrorList{
-				&field.Error{Type: field.ErrorTypeInvalid, Field: "spec.exposeOptions.broadcastOptions.nodes.type", BadValue: pointer.Ptr(v1.BroadcastAddressTypePodIP), Detail: `field is immutable`},
-			},
-			expectedErrorString: `spec.exposeOptions.broadcastOptions.nodes.type: Invalid value: "PodIP": field is immutable`,
-		},
 	}
 
 	for _, test := range tests {
diff --git a/pkg/cmd/tests/tests_run.go b/pkg/cmd/tests/tests_run.go
index fcffe3423..26b2d18bc 100644
--- a/pkg/cmd/tests/tests_run.go
+++ b/pkg/cmd/tests/tests_run.go
@@ -20,7 +20,7 @@ import (
 	gomegaformat "github.com/onsi/gomega/format"
 	"github.com/scylladb/scylla-operator/pkg/cmdutil"
 	"github.com/scylladb/scylla-operator/pkg/genericclioptions"
-	"github.com/scylladb/scylla-operator/pkg/helpers/slices"
+	"github.com/scylladb/scylla-operator/pkg/helpers"
 	"github.com/scylladb/scylla-operator/pkg/signals"
 	ginkgotest "github.com/scylladb/scylla-operator/pkg/test/ginkgo"
 	"github.com/scylladb/scylla-operator/pkg/thirdparty/github.com/onsi/ginkgo/v2/exposedinternal/parallel_support"
@@ -358,7 +358,7 @@ func (o *RunOptions) run(ctx context.Context, streams genericclioptions.IOStream
 	commonArgs = append(commonArgs, fmt.Sprintf("--%s=%v", cmdutil.FlagLogLevelKey, o.ParallelLogLevel))
 
 	// Propagate random seed to child processes.
-	if !slices.Contains(commonArgs, func(arg string) bool {
+	if !helpers.Contains(commonArgs, func(arg string) bool {
 		return strings.HasPrefix(arg, fmt.Sprintf("--%s", randomSeedFlagKey))
 	}) {
 		commonArgs = append(commonArgs, fmt.Sprintf("--%s=%v", randomSeedFlagKey, suiteConfig.RandomSeed))
diff --git a/pkg/controller/scyllacluster/resource_test.go b/pkg/controller/scyllacluster/resource_test.go
index 77f568149..527ab16d4 100644
--- a/pkg/controller/scyllacluster/resource_test.go
+++ b/pkg/controller/scyllacluster/resource_test.go
@@ -433,149 +433,11 @@ func TestMemberService(t *testing.T) {
 				},
 			},
 		},
-		{
-			name: "Service properties are taken from ExposeOptions.NodeService",
-			scyllaCluster: func() *scyllav1.ScyllaCluster {
-				sc := basicSC.DeepCopy()
-				sc.Spec.ExposeOptions = &scyllav1.ExposeOptions{
-					NodeService: &scyllav1.NodeServiceTemplate{
-						Annotations: map[string]string{
-							"foo": "bar",
-						},
-						Type:                          scyllav1.NodeServiceTypeLoadBalancer,
-						ExternalTrafficPolicy:         pointer.Ptr(corev1.ServiceExternalTrafficPolicyLocal),
-						AllocateLoadBalancerNodePorts: pointer.Ptr(true),
-						LoadBalancerClass:             pointer.Ptr("my-lb-class"),
-						InternalTrafficPolicy:         pointer.Ptr(corev1.ServiceInternalTrafficPolicyCluster),
-					},
-				}
-
-				return sc
-			}(),
-			rackName:   basicRackName,
-			svcName:    basicSVCName,
-			oldService: nil,
-			jobs:       nil,
-			expectedService: &corev1.Service{
-				ObjectMeta: metav1.ObjectMeta{
-					Name:   basicSVCName,
-					Labels: basicSVCLabels(),
-					Annotations: map[string]string{
-						"foo": "bar",
-					},
-					OwnerReferences: basicSCOwnerRefs,
-				},
-				Spec: corev1.ServiceSpec{
-					Type:                          corev1.ServiceTypeLoadBalancer,
-					Selector:                      basicSVCSelector,
-					PublishNotReadyAddresses:      true,
-					Ports:                         basicPorts,
-					ExternalTrafficPolicy:         corev1.ServiceExternalTrafficPolicyLocal,
-					AllocateLoadBalancerNodePorts: pointer.Ptr(true),
-					LoadBalancerClass:             pointer.Ptr("my-lb-class"),
-					InternalTrafficPolicy:         pointer.Ptr(corev1.ServiceInternalTrafficPolicyCluster),
-				},
-			},
-		},
-		{
-			name: "headless service type in node service template",
-			scyllaCluster: func() *scyllav1.ScyllaCluster {
-				sc := basicSC.DeepCopy()
-				sc.Spec.ExposeOptions = &scyllav1.ExposeOptions{
-					NodeService: &scyllav1.NodeServiceTemplate{
-						Type: scyllav1.NodeServiceTypeHeadless,
-					},
-				}
-
-				return sc
-			}(),
-			rackName:   basicRackName,
-			svcName:    basicSVCName,
-			oldService: nil,
-			jobs:       nil,
-			expectedService: &corev1.Service{
-				ObjectMeta: metav1.ObjectMeta{
-					Name:            basicSVCName,
-					Labels:          basicSVCLabels(),
-					OwnerReferences: basicSCOwnerRefs,
-				},
-				Spec: corev1.ServiceSpec{
-					Type:                     corev1.ServiceTypeClusterIP,
-					Selector:                 basicSVCSelector,
-					PublishNotReadyAddresses: true,
-					Ports:                    basicPorts,
-					ClusterIP:                corev1.ClusterIPNone,
-				},
-			},
-		},
-		{
-			name: "ClusterIP service type in node service template",
-			scyllaCluster: func() *scyllav1.ScyllaCluster {
-				sc := basicSC.DeepCopy()
-				sc.Spec.ExposeOptions = &scyllav1.ExposeOptions{
-					NodeService: &scyllav1.NodeServiceTemplate{
-						Type: scyllav1.NodeServiceTypeClusterIP,
-					},
-				}
-
-				return sc
-			}(),
-			rackName:   basicRackName,
-			svcName:    basicSVCName,
-			oldService: nil,
-			jobs:       nil,
-			expectedService: &corev1.Service{
-				ObjectMeta: metav1.ObjectMeta{
-					Name:            basicSVCName,
-					Labels:          basicSVCLabels(),
-					OwnerReferences: basicSCOwnerRefs,
-				},
-				Spec: corev1.ServiceSpec{
-					Type:                     corev1.ServiceTypeClusterIP,
-					Selector:                 basicSVCSelector,
-					PublishNotReadyAddresses: true,
-					Ports:                    basicPorts,
-				},
-			},
-		},
-		{
-			name: "LoadBalancer service type in node service template",
-			scyllaCluster: func() *scyllav1.ScyllaCluster {
-				sc := basicSC.DeepCopy()
-				sc.Spec.ExposeOptions = &scyllav1.ExposeOptions{
-					NodeService: &scyllav1.NodeServiceTemplate{
-						Type: scyllav1.NodeServiceTypeLoadBalancer,
-					},
-				}
-
-				return sc
-			}(),
-			rackName:   basicRackName,
-			svcName:    basicSVCName,
-			oldService: nil,
-			jobs:       nil,
-			expectedService: &corev1.Service{
-				ObjectMeta: metav1.ObjectMeta{
-					Name:            basicSVCName,
-					Labels:          basicSVCLabels(),
-					OwnerReferences: basicSCOwnerRefs,
-				},
-				Spec: corev1.ServiceSpec{
-					Type:                     corev1.ServiceTypeLoadBalancer,
-					Selector:                 basicSVCSelector,
-					PublishNotReadyAddresses: true,
-					Ports:                    basicPorts,
-				},
-			},
-		},
 	}
 
 	for _, tc := range tt {
 		t.Run(tc.name, func(t *testing.T) {
-			got, err := MemberService(tc.scyllaCluster, tc.rackName, tc.svcName, tc.oldService, tc.jobs)
-			if err != nil {
-				t.Fatal(err)
-			}
+			got := MemberService(tc.scyllaCluster, tc.rackName, tc.svcName, tc.oldService, tc.jobs)
 
 			if !apiequality.Semantic.DeepEqual(got, tc.expectedService) {
 				t.Errorf("expected and actual services differ: %s", cmp.Diff(tc.expectedService, got))
@@ -624,7 +486,6 @@ func TestStatefulSetForRack(t *testing.T) {
 			"scylla/cluster":               "basic",
 			"scylla/datacenter":            "dc",
 			"scylla/rack":                  "rack",
-			"scylla/rack-ordinal":          "0",
 		}
 	}
 
@@ -827,8 +688,6 @@ func TestStatefulSetForRack(t *testing.T) {
 										"/mnt/shared/scylla-operator",
 										"sidecar",
 										featureGatesFlagString,
-										"--nodes-broadcast-address-type=ServiceClusterIP",
-										"--clients-broadcast-address-type=ServiceClusterIP",
 										"--service-name=$(SERVICE_NAME)",
 										"--cpu-count=$(CPU_COUNT)",
 										"--loglevel=2",
diff --git a/pkg/sidecar/identity/member_test.go b/pkg/sidecar/identity/member_test.go
index e122c406a..63c604b0f 100644
--- a/pkg/sidecar/identity/member_test.go
+++ b/pkg/sidecar/identity/member_test.go
@@ -9,7 +9,6 @@ import (
 	"testing"
 	"time"
 
-	scyllav1 "github.com/scylladb/scylla-operator/pkg/api/scylla/v1"
 	"github.com/scylladb/scylla-operator/pkg/controllerhelpers"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -30,7 +29,6 @@ func TestMember_GetSeeds(t *testing.T) {
 					"app":                          "scylla",
 					"app.kubernetes.io/name":       "scylla",
 					"app.kubernetes.io/managed-by": "scylla-operator",
-					"scylla/rack-ordinal":          "0",
 				},
 				CreationTimestamp: metav1.NewTime(creationTimestamp),
 			},
@@ -53,287 +51,72 @@ func TestMember_GetSeeds(t *testing.T) {
 	thirdPod, thirdService := createPodAndSvc("pod-2", "3.3.3.3", now.Add(2*time.Second))
 
 	ts := []struct {
-		name                       string
-		memberService              *corev1.Service
-		memberPod                  *corev1.Pod
-		memberClientsBroadcastType scyllav1.BroadcastAddressType
-		memberNodesBroadcastType   scyllav1.BroadcastAddressType
-		externalSeeds              []string
-		objects                    []runtime.Object
-		expectSeeds                []string
-		expectError                error
+		name          string
+		memberName    string
+		memberIP      string
+		objects       []runtime.Object
+		externalSeeds []string
+		expectSeeds   []string
+		expectError   error
 	}{
 		{
-			name:                       "error when no pods are found",
-			memberPod:                  firstPod,
-			memberService:              firstService,
-			memberClientsBroadcastType: scyllav1.BroadcastAddressTypeServiceClusterIP,
-			memberNodesBroadcastType:   scyllav1.BroadcastAddressTypeServiceClusterIP,
-			objects:                    []runtime.Object{},
-			expectError:                fmt.Errorf("internal error: can't find any pod for this cluster, including itself"),
+			name:        "error when no pods are found",
+			memberName:  firstPod.Name,
+			memberIP:    firstService.Spec.ClusterIP,
+			objects:     []runtime.Object{},
+			expectError: fmt.Errorf("internal error: can't find any pod for this cluster, including itself"),
 		},
 		{
-			name:                       "bootstrap with external seeds only when cluster is empty and external seeds are provided",
-			memberPod:                  firstPod,
-			memberService:              firstService,
-			memberClientsBroadcastType: scyllav1.BroadcastAddressTypeServiceClusterIP,
-			memberNodesBroadcastType:   scyllav1.BroadcastAddressTypeServiceClusterIP,
-			objects:                    []runtime.Object{firstPod, firstService},
-			externalSeeds:              []string{"10.0.1.1", "10.0.1.2"},
-			expectSeeds:                []string{"10.0.1.1", "10.0.1.2"},
+			name:        "bootstraps with itself when cluster is empty",
+			memberName:  firstPod.Name,
+			memberIP:    firstService.Spec.ClusterIP,
+			objects:     []runtime.Object{firstPod, firstService},
+			expectSeeds: []string{firstService.Spec.ClusterIP},
 		},
 		{
-			name:                       "bootstrap with external seeds and first created UN node when external seeds are provided",
-			memberPod:                  firstPod,
-			memberService:              firstService,
-			memberClientsBroadcastType: scyllav1.BroadcastAddressTypeServiceClusterIP,
-			memberNodesBroadcastType:   scyllav1.BroadcastAddressTypeServiceClusterIP,
-			objects:                    []runtime.Object{firstPod, firstService, markPodReady(secondPod), secondService, markPodReady(thirdPod), thirdService},
-			externalSeeds:              []string{"10.0.1.1", "10.0.1.2"},
-			expectSeeds:                []string{"10.0.1.1", "10.0.1.2", secondService.Spec.ClusterIP},
+			name:        "bootstrap with first created UN node",
+			memberName:  firstPod.Name,
+			memberIP:    firstService.Spec.ClusterIP,
+			objects:     []runtime.Object{firstPod, firstService, markPodReady(secondPod), secondService, markPodReady(thirdPod), thirdService},
+			expectSeeds: []string{secondService.Spec.ClusterIP},
 		},
 		{
-			name:                       "bootstrap with external seeds and first created Pod when all Pods from DC are down and external seeds are provided",
-			memberPod:                  firstPod,
-			memberService:              firstService,
-			memberClientsBroadcastType: scyllav1.BroadcastAddressTypeServiceClusterIP,
-			memberNodesBroadcastType:   scyllav1.BroadcastAddressTypeServiceClusterIP,
-			objects:                    []runtime.Object{firstPod, firstService, secondPod, secondService, thirdPod, thirdService},
-			externalSeeds:              []string{"10.0.1.1", "10.0.1.2"},
-			expectSeeds:                []string{"10.0.1.1", "10.0.1.2", secondService.Spec.ClusterIP},
+			name:        "bootstrap only with UN node",
+			memberName:  firstPod.Name,
+			memberIP:    firstService.Spec.ClusterIP,
+			objects:     []runtime.Object{firstPod, firstService, secondPod, secondService, markPodReady(thirdPod), thirdService},
+			expectSeeds: []string{thirdService.Spec.ClusterIP},
 		},
 		{
-			name:                       "bootstraps with itself using node-to-node identifier of ClusterIP type when cluster is empty",
-			memberPod:                  firstPod,
-			memberService:              firstService,
-			memberClientsBroadcastType: scyllav1.BroadcastAddressTypeServiceClusterIP,
-			memberNodesBroadcastType:   scyllav1.BroadcastAddressTypeServiceClusterIP,
-			objects:                    []runtime.Object{firstPod, firstService},
-			expectSeeds:                []string{firstService.Spec.ClusterIP},
+			name:        "bootstrap with first created Pod when all are down",
+			memberName:  firstPod.Name,
+			memberIP:    firstService.Spec.ClusterIP,
+			objects:     []runtime.Object{firstPod, firstService, secondPod, secondService, thirdPod, thirdService},
+			expectSeeds: []string{secondService.Spec.ClusterIP},
 		},
 		{
-			name:                       "bootstraps with itself using node-to-node identifier of ClusterIP type when cluster is empty",
-			memberPod:                  firstPod,
-			memberService:              firstService,
-			memberClientsBroadcastType: scyllav1.BroadcastAddressTypeServiceClusterIP,
-			memberNodesBroadcastType:   scyllav1.BroadcastAddressTypeServiceClusterIP,
-			objects:                    []runtime.Object{firstPod, firstService},
-			expectSeeds:                []string{firstService.Spec.ClusterIP},
+			name:          "bootstrap with external seeds only when cluster is empty and external seeds are provided",
+			memberName:    firstPod.Name,
+			memberIP:      firstService.Spec.ClusterIP,
+			objects:       []runtime.Object{firstPod, firstService},
+			externalSeeds: []string{"10.0.1.1", "10.0.1.2"},
+			expectSeeds:   []string{"10.0.1.1", "10.0.1.2"},
 		},
 		{
-			name: "bootstraps with itself using node-to-node identifier of PodIP type when cluster is empty",
-			memberPod: func() *corev1.Pod {
-				pod := firstPod.DeepCopy()
-				pod.Status.PodIP = "1.2.3.4"
-				return pod
-			}(),
-			memberService:              firstService,
-			memberClientsBroadcastType: scyllav1.BroadcastAddressTypeServiceClusterIP,
-			memberNodesBroadcastType:   scyllav1.BroadcastAddressTypePodIP,
-			objects:                    []runtime.Object{firstPod, firstService},
-			expectSeeds:                []string{"1.2.3.4"},
+			name:          "bootstrap with external seeds and first created UN node when external seeds are provided",
+			memberName:    firstPod.Name,
+			memberIP:      firstService.Spec.ClusterIP,
+			objects:       []runtime.Object{firstPod, firstService, markPodReady(secondPod), secondService, markPodReady(thirdPod), thirdService},
+			externalSeeds: []string{"10.0.1.1", "10.0.1.2"},
+			expectSeeds:   []string{"10.0.1.1", "10.0.1.2", secondService.Spec.ClusterIP},
 		},
 		{
-			name:      "bootstraps with itself using node-to-node identifier of LoadBalancer External IP type when cluster is empty",
-			memberPod: firstPod,
-			memberService: func() *corev1.Service {
-				svc := firstService.DeepCopy()
-				svc.Spec.Type = corev1.ServiceTypeLoadBalancer
-				svc.Status.LoadBalancer = corev1.LoadBalancerStatus{
-					Ingress: []corev1.LoadBalancerIngress{
-						{
-							IP: "4.3.2.1",
-						},
-					},
-				}
-				return svc
-			}(),
-			memberClientsBroadcastType: scyllav1.BroadcastAddressTypeServiceClusterIP,
-			memberNodesBroadcastType:   scyllav1.BroadcastAddressTypeServiceLoadBalancerIngress,
-			objects:                    []runtime.Object{firstPod, firstService},
-			expectSeeds:                []string{"4.3.2.1"},
-		},
-		{
-			name:      "bootstraps with itself using node-to-node identifier of LoadBalancer hostname when cluster is empty",
-			memberPod: firstPod,
-			memberService: func() *corev1.Service {
-				svc := firstService.DeepCopy()
-				svc.Spec.Type = corev1.ServiceTypeLoadBalancer
-				svc.Status.LoadBalancer = corev1.LoadBalancerStatus{
-					Ingress: []corev1.LoadBalancerIngress{
-						{
-							Hostname: "node-1-hostname.scylladb.com",
-						},
-					},
-				}
-				return svc
-			}(),
-			memberClientsBroadcastType: scyllav1.BroadcastAddressTypeServiceClusterIP,
-			memberNodesBroadcastType:   scyllav1.BroadcastAddressTypeServiceLoadBalancerIngress,
-			objects:                    []runtime.Object{firstPod, firstService},
-			expectSeeds:                []string{"node-1-hostname.scylladb.com"},
-		},
-		{
-			name:                       "bootstrap with first created UN node",
-			memberPod:                  firstPod,
-			memberService:              firstService,
-			memberClientsBroadcastType: scyllav1.BroadcastAddressTypeServiceClusterIP,
-			memberNodesBroadcastType:   scyllav1.BroadcastAddressTypeServiceClusterIP,
-			objects:                    []runtime.Object{firstPod, firstService, markPodReady(secondPod), secondService, markPodReady(thirdPod), thirdService},
-			expectSeeds:                []string{secondService.Spec.ClusterIP},
-		},
-		{
-			name:                       "bootstrap only with UN node",
-			memberPod:                  firstPod,
-			memberService:              firstService,
-			memberClientsBroadcastType: scyllav1.BroadcastAddressTypeServiceClusterIP,
-			memberNodesBroadcastType:   scyllav1.BroadcastAddressTypeServiceClusterIP,
-			objects:                    []runtime.Object{firstPod, firstService, secondPod, secondService, markPodReady(thirdPod), thirdService},
-			expectSeeds:                []string{thirdService.Spec.ClusterIP},
-		},
-		{
-			name:                       "bootstrap with first created Pod when all are down",
-			memberPod:                  firstPod,
-			memberService:              firstService,
-			memberClientsBroadcastType: scyllav1.BroadcastAddressTypeServiceClusterIP,
-			memberNodesBroadcastType:   scyllav1.BroadcastAddressTypeServiceClusterIP,
-			objects:                    []runtime.Object{firstPod, firstService, secondPod, secondService, thirdPod, thirdService},
-			expectSeeds:                []string{secondService.Spec.ClusterIP},
-		},
-		{
-			name:                       "use PodIP from status when node broadcast address type is PodIP",
-			memberPod:                  firstPod,
-			memberService:              firstService,
-			memberClientsBroadcastType: scyllav1.BroadcastAddressTypeServiceClusterIP,
-			memberNodesBroadcastType:   scyllav1.BroadcastAddressTypePodIP,
-			objects: []runtime.Object{
-				firstPod,
-				firstService,
-				func() runtime.Object {
-					pod := secondPod.DeepCopy()
-					pod.Status.PodIP = "1.2.3.4"
-					pod = markPodReady(pod)
-					return pod
-				}(),
-				func() runtime.Object {
-					svc := secondService.DeepCopy()
-					svc.Spec.ClusterIP = corev1.ClusterIPNone
-					return svc
-				}(),
-				thirdPod,
-				thirdService,
-			},
-			expectSeeds: []string{"1.2.3.4"},
-		},
-		{
-			name:                       "use ClusterIP from Service when node broadcast address type is ClusterIP",
-			memberPod:                  firstPod,
-			memberService:              firstService,
-			memberClientsBroadcastType: scyllav1.BroadcastAddressTypeServiceClusterIP,
-			memberNodesBroadcastType:   scyllav1.BroadcastAddressTypeServiceClusterIP,
-			objects: []runtime.Object{
-				firstPod,
-				firstService,
-				secondPod,
-				func() runtime.Object {
-					svc := secondService.DeepCopy()
-					svc.Spec.ClusterIP = "1.2.3.4"
-					return svc
-				}(),
-				thirdPod,
-				thirdService,
-			},
-			expectSeeds: []string{"1.2.3.4"},
-		},
-		{
-			name:                       "use preferred IP address from first Service ingress status when node broadcast address type is LoadBalancer Ingress",
-			memberPod:                  firstPod,
-			memberService:              firstService,
-			memberClientsBroadcastType: scyllav1.BroadcastAddressTypeServiceClusterIP,
-			memberNodesBroadcastType:   scyllav1.BroadcastAddressTypeServiceLoadBalancerIngress,
-			objects: []runtime.Object{
-				firstPod,
-				firstService,
-				secondPod,
-				func() runtime.Object {
-					svc := secondService.DeepCopy()
-					svc.Status.LoadBalancer = corev1.LoadBalancerStatus{
-						Ingress: []corev1.LoadBalancerIngress{
-							{
-								IP:       "1.2.3.4",
-								Hostname: "second.service.scylladb.com",
-							},
-						},
-					}
-					return svc
-				}(),
-				thirdPod,
-				thirdService,
-			},
-			expectSeeds: []string{"1.2.3.4"},
-		},
-		{
-			name:                       "use hostname from first Service ingress status when node broadcast address type is LoadBalancer Ingress and IP is not available",
-			memberPod:                  firstPod,
-			memberService:              firstService,
-			memberClientsBroadcastType: scyllav1.BroadcastAddressTypeServiceClusterIP,
-			memberNodesBroadcastType:   scyllav1.BroadcastAddressTypeServiceLoadBalancerIngress,
-			objects: []runtime.Object{
-				firstPod,
-				firstService,
-				secondPod,
-				func() runtime.Object {
-					svc := secondService.DeepCopy()
-					svc.Status.LoadBalancer = corev1.LoadBalancerStatus{
-						Ingress: []corev1.LoadBalancerIngress{
-							{
-								Hostname: "second.service.scylladb.com",
-							},
-						},
-					}
-					return svc
-				}(),
-				thirdPod,
-				thirdService,
-			},
-			expectSeeds: []string{"second.service.scylladb.com"},
-		},
-		{
-			name:                       "error when node is not first in rack, but there are no other pods",
-			memberPod:                  secondPod,
-			memberService:              secondService,
-			memberClientsBroadcastType: scyllav1.BroadcastAddressTypeServiceClusterIP,
-			memberNodesBroadcastType:   scyllav1.BroadcastAddressTypeServiceClusterIP,
-			objects:                    []runtime.Object{secondPod, secondService},
-			expectSeeds:                nil,
-			expectError:                fmt.Errorf("pod is not first in the cluster, but there are no other pods"),
-		},
-		{
-			name: "error when node is first in rack of ordinal > 0, but there are no other pods",
-			memberPod: func() *corev1.Pod {
-				pod := firstPod.DeepCopy()
-				pod.Labels["scylla/rack-ordinal"] = "1"
-				return pod
-			}(),
-			memberService:              firstService,
-			memberClientsBroadcastType: scyllav1.BroadcastAddressTypeServiceClusterIP,
-			memberNodesBroadcastType:   scyllav1.BroadcastAddressTypeServiceClusterIP,
-			objects:                    []runtime.Object{firstPod, firstService},
-			expectSeeds:                nil,
-			expectError:                fmt.Errorf("pod is not first in the cluster, but there are no other pods"),
-		},
-		{
-			name: "bootstrap with other pod when node is first in rack of ordinal > 0 and there are other pods",
-			memberPod: func() *corev1.Pod {
-				pod := secondPod.DeepCopy()
-				pod.Labels["scylla/rack-ordinal"] = "1"
-				return pod
-			}(),
-			memberService:              secondService,
-			memberClientsBroadcastType: scyllav1.BroadcastAddressTypeServiceClusterIP,
-			memberNodesBroadcastType:   scyllav1.BroadcastAddressTypeServiceClusterIP,
-			objects:                    []runtime.Object{firstPod, firstService, secondPod, secondService},
-			expectSeeds:                []string{firstService.Spec.ClusterIP},
+			name:          "bootstrap with external seeds and first created Pod when all Pods from DC are down and external seeds are provided",
+			memberName:    firstPod.Name,
+			memberIP:      firstService.Spec.ClusterIP,
+			objects:       []runtime.Object{firstPod, firstService, secondPod, secondService, thirdPod, thirdService},
+			externalSeeds: []string{"10.0.1.1", "10.0.1.2"},
+			expectSeeds:   []string{"10.0.1.1", "10.0.1.2", secondService.Spec.ClusterIP},
 		},
 	}
 
@@ -345,9 +128,11 @@ func TestMember_GetSeeds(t *testing.T) {
 			ctx, cancel := context.WithCancel(context.Background())
 			defer cancel()
 
-			member, err := NewMember(test.memberService, test.memberPod, test.memberNodesBroadcastType, test.memberClientsBroadcastType)
-			if err != nil {
-				t.Fatal(err)
+			member := Member{
+				Cluster:   "my-cluster",
+				Namespace: "namespace",
+				Name:      test.memberName,
+				StaticIP:  test.memberIP,
 			}
 
 			fakeClient := fake.NewSimpleClientset(test.objects...)
diff --git a/pkg/systemd/unit_test.go b/pkg/systemd/unit_test.go
index 951c91281..8ad77a34b 100644
--- a/pkg/systemd/unit_test.go
+++ b/pkg/systemd/unit_test.go
@@ -9,7 +9,7 @@ import (
 
 	"github.com/google/go-cmp/cmp"
 	"github.com/google/go-cmp/cmp/cmpopts"
-	"github.com/scylladb/scylla-operator/pkg/helpers/slices"
+	"github.com/scylladb/scylla-operator/pkg/helpers"
 	"k8s.io/client-go/tools/record"
 )
 
@@ -296,10 +296,10 @@ func Test_unitManager_EnsureUnits(t *testing.T) {
 				t.Fatal(err)
 			}
 
-			unexpectedEntries := slices.Filter(entries, func(entry os.DirEntry) bool {
+			unexpectedEntries := helpers.Filter(entries, func(entry os.DirEntry) bool {
 				return !entry.IsDir() &&
 					entry.Name() != m.getStatusName() &&
-					!slices.Contains(
+					!helpers.Contains(
 						tc.expectedUnits,
 						func(v *NamedUnit) bool {
 							return v.FileName == entry.Name()
@@ -308,7 +308,7 @@ func Test_unitManager_EnsureUnits(t *testing.T) {
 			})
 
 			if len(unexpectedEntries) != 0 {
-				unexpectedEntryNames := slices.ConvertSlice(unexpectedEntries, func(entry os.DirEntry) string {
+				unexpectedEntryNames := helpers.ConvertSlice(unexpectedEntries, func(entry os.DirEntry) string {
 					return entry.Name()
 				})
 				t.Errorf("Unexpected files were created: %q", strings.Join(unexpectedEntryNames, ","))
diff --git a/test/e2e/framework/framework.go b/test/e2e/framework/framework.go
index c0a5526c0..04ae7467a 100644
--- a/test/e2e/framework/framework.go
+++ b/test/e2e/framework/framework.go
@@ -9,6 +9,7 @@ import (
 	"fmt"
 	"os"
 	"path"
+	"strconv"
 	"time"
 
 	g "github.com/onsi/ginkgo/v2"
@@ -148,6 +149,7 @@ func (f *Framework) setupNamespace(ctx context.Context) {
 		return names.SimpleNameGenerator.GenerateName(fmt.Sprintf("e2e-test-%s-", f.name))
 	}
 	name := generateName()
+	sr := g.CurrentSpecReport()
 	err := wait.PollImmediate(2*time.Second, 30*time.Second, func() (bool, error) {
 		var err error
 		// We want to know the name ahead, even if the api call fails.
@@ -157,6 +159,10 @@ func (f *Framework) setupNamespace(ctx context.Context) {
 				ObjectMeta: metav1.ObjectMeta{
 					Name:   name,
 					Labels: f.CommonLabels(),
+					Annotations: map[string]string{
+						"ginkgo-parallel-process": strconv.Itoa(sr.ParallelProcess),
+						"ginkgo-full-text":        sr.FullText(),
+					},
 				},
 			},
 			metav1.CreateOptions{},
diff --git a/test/e2e/set/scyllacluster/scyllacluster_cleanup.go b/test/e2e/set/scyllacluster/scyllacluster_cleanup.go
index 63c4a44ba..055808c5c 100644
--- a/test/e2e/set/scyllacluster/scyllacluster_cleanup.go
+++ b/test/e2e/set/scyllacluster/scyllacluster_cleanup.go
@@ -8,7 +8,6 @@ import (
 	g "github.com/onsi/ginkgo/v2"
 	o "github.com/onsi/gomega"
 	"github.com/scylladb/scylla-operator/pkg/helpers"
-	"github.com/scylladb/scylla-operator/pkg/helpers/slices"
 	"github.com/scylladb/scylla-operator/pkg/naming"
 	scyllafixture "github.com/scylladb/scylla-operator/test/e2e/fixture/scylla"
 	"github.com/scylladb/scylla-operator/test/e2e/framework"
@@ -102,7 +101,7 @@ var _ = g.Describe("ScyllaCluster", func() {
 			}
 		}
 
-		cleanupJobsCreated := slices.Filter(jobEvents, func(e utils.ObserverEvent[*batchv1.Job]) bool {
+		cleanupJobsCreated := helpers.Filter(jobEvents, func(e utils.ObserverEvent[*batchv1.Job]) bool {
 			return e.Action == watch.Added && e.Obj.Labels[naming.NodeJobTypeLabel] == string(naming.JobTypeCleanup)
 		})
 
@@ -143,7 +142,7 @@ var _ = g.Describe("ScyllaCluster", func() {
 
 		o.Expect(jobEvents).NotTo(o.BeEmpty())
 
-		cleanupJobsCreated = slices.Filter(jobEvents, func(e utils.ObserverEvent[*batchv1.Job]) bool {
+		cleanupJobsCreated = helpers.Filter(jobEvents, func(e utils.ObserverEvent[*batchv1.Job]) bool {
 			return e.Action == watch.Added && e.Obj.Labels[naming.NodeJobTypeLabel] == string(naming.JobTypeCleanup)
 		})
 
diff --git a/test/e2e/set/scyllacluster/scyllacluster_expose.go b/test/e2e/set/scyllacluster/scyllacluster_expose.go
index 249c020f8..16a8b2600 100644
--- a/test/e2e/set/scyllacluster/scyllacluster_expose.go
+++ b/test/e2e/set/scyllacluster/scyllacluster_expose.go
@@ -4,277 +4,26 @@ package scyllacluster
 
 import (
 	"context"
-	"crypto/x509"
 	"fmt"
-	"net"
 
 	g "github.com/onsi/ginkgo/v2"
 	o "github.com/onsi/gomega"
 	scyllav1 "github.com/scylladb/scylla-operator/pkg/api/scylla/v1"
-	"github.com/scylladb/scylla-operator/pkg/features"
-	"github.com/scylladb/scylla-operator/pkg/helpers"
 	"github.com/scylladb/scylla-operator/pkg/naming"
-	"github.com/scylladb/scylla-operator/pkg/pointer"
-	"github.com/scylladb/scylla-operator/pkg/scyllaclient"
 	scyllafixture "github.com/scylladb/scylla-operator/test/e2e/fixture/scylla"
 	"github.com/scylladb/scylla-operator/test/e2e/framework"
 	"github.com/scylladb/scylla-operator/test/e2e/utils"
-	"github.com/scylladb/scylla-operator/test/e2e/verification"
 	corev1 "k8s.io/api/core/v1"
 	networkingv1 "k8s.io/api/networking/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/labels"
-	"k8s.io/apimachinery/pkg/types"
-	"k8s.io/apimachinery/pkg/util/rand"
-	utilfeature "k8s.io/apiserver/pkg/util/feature"
-	corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
 )
 
-var _ = g.Describe("ScyllaCluster", func() {
+var _ = g.Describe("ScyllaCluster Ingress", func() {
 	defer g.GinkgoRecover()
 
 	f := framework.NewFramework("scyllacluster")
 
-	type entry struct {
-		exposeOptions                            *scyllav1.ExposeOptions
-		memberServiceCreatedHook                 func(ctx context.Context, client corev1client.CoreV1Interface, svc *corev1.Service)
-		validateService                          func(svc *corev1.Service)
-		validateScyllaConfig                     func(ctx context.Context, configClient *scyllaclient.ConfigClient, svc *corev1.Service, pod *corev1.Pod)
-		expectedNumberOfIPAddressesInServingCert func(nodes int) int
-	}
-
-	g.DescribeTable("should be exposed", func(e *entry) {
-		ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
-		defer cancel()
-
-		sc := scyllafixture.BasicScyllaCluster.ReadOrFail()
-		sc.Spec.Datacenter.Racks[0].Members = 1
-		sc.Spec.ExposeOptions = e.exposeOptions
-
-		framework.By("Creating a ScyllaCluster")
-		sc, err := f.ScyllaClient().ScyllaV1().ScyllaClusters(f.Namespace()).Create(ctx, sc, metav1.CreateOptions{})
-		o.Expect(err).NotTo(o.HaveOccurred())
-
-		framework.By("Waiting for member Service to be created")
-		waitCtx, waitCtxCancel := utils.ContextForRollout(ctx, sc)
-		defer waitCtxCancel()
-
-		svcName := naming.MemberServiceName(sc.Spec.Datacenter.Racks[0], sc, 0)
-		svc, err := utils.WaitForServiceState(waitCtx, f.KubeClient().CoreV1().Services(sc.Namespace), svcName, utils.WaitForStateOptions{}, func(svc *corev1.Service) (bool, error) {
-			return svc != nil, nil
-		})
-		o.Expect(err).NotTo(o.HaveOccurred())
-
-		if e.memberServiceCreatedHook != nil {
-			e.memberServiceCreatedHook(ctx, f.KubeAdminClient().CoreV1(), svc)
-		}
-
-		framework.By("Waiting for ScyllaCluster to deploy")
-
-		sc, err = utils.WaitForScyllaClusterState(waitCtx, f.ScyllaClient().ScyllaV1(), sc.Namespace, sc.Name, utils.WaitForStateOptions{}, utils.IsScyllaClusterRolledOut)
-		o.Expect(err).NotTo(o.HaveOccurred())
-
-		verifyScyllaCluster(ctx, f.KubeClient(), sc)
-
-		svc, err = f.KubeClient().CoreV1().Services(sc.Namespace).Get(ctx, svcName, metav1.GetOptions{})
-		o.Expect(err).NotTo(o.HaveOccurred())
-
-		e.validateService(svc)
-
-		pod, err := f.KubeClient().CoreV1().Pods(sc.Namespace).Get(ctx, svcName, metav1.GetOptions{})
-		o.Expect(err).NotTo(o.HaveOccurred())
-
-		configClient, err := utils.GetScyllaConfigClient(ctx, f.KubeClient().CoreV1(), sc, pod.Status.PodIP)
-		o.Expect(err).NotTo(o.HaveOccurred())
-
-		e.validateScyllaConfig(ctx, configClient, svc, pod)
-
-		if utilfeature.DefaultMutableFeatureGate.Enabled(features.AutomaticTLSCertificates) {
-			serviceAndPodIPs, err := utils.GetNodesServiceAndPodIPs(ctx, f.KubeClient().CoreV1(), sc)
-			o.Expect(err).NotTo(o.HaveOccurred())
-			o.Expect(serviceAndPodIPs).To(o.HaveLen(e.expectedNumberOfIPAddressesInServingCert(int(utils.GetMemberCount(sc)))))
-
-			hostsIPs, err := helpers.ParseClusterIPs(serviceAndPodIPs)
-			o.Expect(err).NotTo(o.HaveOccurred())
-
-			var servingDNSNames []string
-			services, err := f.KubeClient().CoreV1().Services(sc.Namespace).List(ctx, metav1.ListOptions{
-				LabelSelector: labels.SelectorFromSet(naming.ClusterLabels(sc)).String(),
-			})
-			o.Expect(err).NotTo(o.HaveOccurred())
-			o.Expect(services.Items).To(o.HaveLen(int(utils.GetMemberCount(sc)) + 1))
-			for _, svc := range services.Items {
-				servingDNSNames = append(servingDNSNames, fmt.Sprintf("%s.%s.svc", svc.Name, svc.Namespace))
-			}
-
-			servingCertSecret, err := f.KubeClient().CoreV1().Secrets(f.Namespace()).Get(ctx, fmt.Sprintf("%s-local-serving-certs", sc.Name), metav1.GetOptions{})
-			o.Expect(err).NotTo(o.HaveOccurred())
-			servingCerts, _, _, _ := verification.VerifyAndParseTLSCert(servingCertSecret, verification.TLSCertOptions{
-				IsCA:     pointer.Ptr(false),
-				KeyUsage: pointer.Ptr(x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature),
-			})
-			o.Expect(servingCerts).To(o.HaveLen(1))
-			o.Expect(servingCerts[0].Subject.CommonName).To(o.BeEmpty())
-			o.Expect(helpers.NormalizeIPs(servingCerts[0].IPAddresses)).To(o.ConsistOf(hostsIPs))
-			o.Expect(servingCerts[0].DNSNames).To(o.ConsistOf(servingDNSNames))
-		}
-	},
-		g.Entry("using ClusterIP Service, and broadcast it to both client and nodes", &entry{
-			exposeOptions: &scyllav1.ExposeOptions{
-				NodeService: &scyllav1.NodeServiceTemplate{
-					Type: scyllav1.NodeServiceTypeClusterIP,
-				},
-				BroadcastOptions: &scyllav1.NodeBroadcastOptions{
-					Nodes: scyllav1.BroadcastOptions{
-						Type: scyllav1.BroadcastAddressTypeServiceClusterIP,
-					},
-					Clients: scyllav1.BroadcastOptions{
-						Type: scyllav1.BroadcastAddressTypeServiceClusterIP,
-					},
-				},
-			},
-			validateService: func(svc *corev1.Service) {
-				o.Expect(svc.Spec.Type).To(o.Equal(corev1.ServiceTypeClusterIP))
-				o.Expect(svc.Spec.ClusterIP).NotTo(o.BeEmpty())
-				parsedClusterIP := net.ParseIP(svc.Spec.ClusterIP)
-				o.Expect(parsedClusterIP).ToNot(o.BeNil())
-			},
-			validateScyllaConfig: func(ctx context.Context, configClient *scyllaclient.ConfigClient, svc *corev1.Service, pod *corev1.Pod) {
-				broadcastAddress, err := configClient.BroadcastAddress(ctx)
-				o.Expect(err).NotTo(o.HaveOccurred())
-				o.Expect(broadcastAddress).To(o.Equal(svc.Spec.ClusterIP))
-
-				broadcastRPCAddress, err := configClient.BroadcastRPCAddress(ctx)
-				o.Expect(err).NotTo(o.HaveOccurred())
-				o.Expect(broadcastRPCAddress).To(o.Equal(svc.Spec.ClusterIP))
-			},
-			expectedNumberOfIPAddressesInServingCert: func(nodes int) int {
-				// Each node have 1 PodIP and 1 Service ClusterIP
-				return 2 * nodes
-			},
-		}),
-		g.Entry("using ClusterIP Service, and broadcast it to nodes, and PodIP from Pod Status to clients", &entry{
-			exposeOptions: &scyllav1.ExposeOptions{
-				NodeService: &scyllav1.NodeServiceTemplate{
-					Type: scyllav1.NodeServiceTypeClusterIP,
-				},
-				BroadcastOptions: &scyllav1.NodeBroadcastOptions{
-					Nodes: scyllav1.BroadcastOptions{
-						Type: scyllav1.BroadcastAddressTypeServiceClusterIP,
-					},
-					Clients: scyllav1.BroadcastOptions{
-						Type: scyllav1.BroadcastAddressTypePodIP,
-						PodIP: &scyllav1.PodIPAddressOptions{
-							Source: scyllav1.StatusPodIPSource,
-						},
-					},
-				},
-			},
-			validateService: func(svc *corev1.Service) {
-				o.Expect(svc.Spec.Type).To(o.Equal(corev1.ServiceTypeClusterIP))
-				o.Expect(svc.Spec.ClusterIP).NotTo(o.BeEmpty())
-				parsedClusterIP := net.ParseIP(svc.Spec.ClusterIP)
-				o.Expect(parsedClusterIP).ToNot(o.BeNil())
-			},
-			validateScyllaConfig: func(ctx context.Context, configClient *scyllaclient.ConfigClient, svc *corev1.Service, pod *corev1.Pod) {
-				broadcastAddress, err := configClient.BroadcastAddress(ctx)
-				o.Expect(err).NotTo(o.HaveOccurred())
-				o.Expect(broadcastAddress).To(o.Equal(svc.Spec.ClusterIP))
-
-				broadcastRPCAddress, err := configClient.BroadcastRPCAddress(ctx)
-				o.Expect(err).NotTo(o.HaveOccurred())
-				o.Expect(broadcastRPCAddress).To(o.Equal(pod.Status.PodIP))
-			},
-			expectedNumberOfIPAddressesInServingCert: func(nodes int) int {
-				// Each node have 1 PodIP and 1 Service ClusterIP
-				return 2 * nodes
-			},
-		}),
-		g.Entry("using Headless Service, and broadcast PodIP from Pod Status to both client and nodes", &entry{
-			exposeOptions: &scyllav1.ExposeOptions{
-				NodeService: &scyllav1.NodeServiceTemplate{
-					Type: scyllav1.NodeServiceTypeHeadless,
-				},
-				BroadcastOptions: &scyllav1.NodeBroadcastOptions{
-					Nodes: scyllav1.BroadcastOptions{
-						Type: scyllav1.BroadcastAddressTypePodIP,
-						PodIP: &scyllav1.PodIPAddressOptions{
-							Source: scyllav1.StatusPodIPSource,
-						},
-					},
-					Clients: scyllav1.BroadcastOptions{
-						Type: scyllav1.BroadcastAddressTypePodIP,
-						PodIP: &scyllav1.PodIPAddressOptions{
-							Source: scyllav1.StatusPodIPSource,
-						},
-					},
-				},
-			},
-			validateService: func(svc *corev1.Service) {
-				o.Expect(svc.Spec.Type).To(o.Equal(corev1.ServiceTypeClusterIP))
-				o.Expect(svc.Spec.ClusterIP).To(o.Equal(corev1.ClusterIPNone))
-			},
-			validateScyllaConfig: func(ctx context.Context, configClient *scyllaclient.ConfigClient, svc *corev1.Service, pod *corev1.Pod) {
-				broadcastAddress, err := configClient.BroadcastAddress(ctx)
-				o.Expect(err).NotTo(o.HaveOccurred())
-				o.Expect(broadcastAddress).To(o.Equal(pod.Status.PodIP))
-
-				broadcastRPCAddress, err := configClient.BroadcastRPCAddress(ctx)
-				o.Expect(err).NotTo(o.HaveOccurred())
-				o.Expect(broadcastRPCAddress).To(o.Equal(pod.Status.PodIP))
-			},
-			expectedNumberOfIPAddressesInServingCert: func(nodes int) int {
-				// Each node have only PodIP
-				return nodes
-			},
-		}),
-		g.Entry("using LoadBalancer Service, and broadcast external IP to client and PodIP to nodes", &entry{
-			exposeOptions: &scyllav1.ExposeOptions{
-				NodeService: &scyllav1.NodeServiceTemplate{
-					Type: scyllav1.NodeServiceTypeLoadBalancer,
-					// Change to non-default LB class to avoid conflicts on status when running in cloud
-					LoadBalancerClass: pointer.Ptr(fmt.Sprintf("lb-class-%s", rand.String(6))),
-				},
-				BroadcastOptions: &scyllav1.NodeBroadcastOptions{
-					Nodes: scyllav1.BroadcastOptions{
-						Type: scyllav1.BroadcastAddressTypePodIP,
-					},
-					Clients: scyllav1.BroadcastOptions{
-						Type: scyllav1.BroadcastAddressTypeServiceLoadBalancerIngress,
-					},
-				},
-			},
-			memberServiceCreatedHook: func(ctx context.Context, client corev1client.CoreV1Interface, svc *corev1.Service) {
-				framework.By("Patching member Service with dummy external IP")
-				_, err := f.KubeAdminClient().CoreV1().Services(svc.Namespace).Patch(
-					ctx,
-					svc.Name,
-					types.MergePatchType,
-					[]byte(`{"status":{"loadBalancer":{"ingress":[{"ip":"123.123.123.123"}]}}}`),
-					metav1.PatchOptions{},
-					"status",
-				)
-				o.Expect(err).NotTo(o.HaveOccurred())
-			},
-			validateService: func(svc *corev1.Service) {
-				o.Expect(svc.Spec.Type).To(o.Equal(corev1.ServiceTypeLoadBalancer))
-			},
-			validateScyllaConfig: func(ctx context.Context, configClient *scyllaclient.ConfigClient, svc *corev1.Service, pod *corev1.Pod) {
-				broadcastAddress, err := configClient.BroadcastAddress(ctx)
-				o.Expect(err).NotTo(o.HaveOccurred())
-				o.Expect(broadcastAddress).To(o.Equal(pod.Status.PodIP))
-
-				broadcastRPCAddress, err := configClient.BroadcastRPCAddress(ctx)
-				o.Expect(err).NotTo(o.HaveOccurred())
-				o.Expect(broadcastRPCAddress).To(o.Equal("123.123.123.123"))
-			},
-			expectedNumberOfIPAddressesInServingCert: func(nodes int) int {
-				// Each node have 1 PodIP, 1 Service ClusterIP and External IP
-				return 3 * nodes
-			},
-		}),
-	)
-
 	g.It("should create ingress objects when ingress exposeOptions are provided", func() {
 		ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
 		defer cancel()
diff --git a/test/e2e/set/scyllacluster/scyllacluster_tls.go b/test/e2e/set/scyllacluster/scyllacluster_tls.go
index 21d1ecc19..4be53f2bd 100644
--- a/test/e2e/set/scyllacluster/scyllacluster_tls.go
+++ b/test/e2e/set/scyllacluster/scyllacluster_tls.go
@@ -18,7 +18,6 @@ import (
 	"github.com/scylladb/scylla-operator/pkg/features"
 	"github.com/scylladb/scylla-operator/pkg/helpers"
 	"github.com/scylladb/scylla-operator/pkg/kubecrypto"
-	"github.com/scylladb/scylla-operator/pkg/naming"
 	"github.com/scylladb/scylla-operator/pkg/pointer"
 	scyllafixture "github.com/scylladb/scylla-operator/test/e2e/fixture/scylla"
 	"github.com/scylladb/scylla-operator/test/e2e/framework"
@@ -28,7 +27,6 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	apiequality "k8s.io/apimachinery/pkg/api/equality"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/labels"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/types"
 	utilfeature "k8s.io/apiserver/pkg/util/feature"
@@ -174,8 +172,9 @@ var _ = g.Describe("ScyllaCluster", func() {
 
 				framework.By("Verifying certificates")
 
-				_, nodeIDs, err := utils.GetHostsAndUUIDs(ctx, f.KubeClient().CoreV1(), sc)
+				nodeClusterIPs, nodeIDs, err := utils.GetHostsAndUUIDs(ctx, f.KubeClient().CoreV1(), sc)
 				o.Expect(err).NotTo(o.HaveOccurred())
+				o.Expect(nodeClusterIPs).To(o.HaveLen(tc.replicas))
 				o.Expect(nodeIDs).To(o.HaveLen(tc.replicas))
 
 				var sniHosts []string
@@ -188,31 +187,13 @@ var _ = g.Describe("ScyllaCluster", func() {
 				}
 				o.Expect(sniHosts).To(o.HaveLen(len(sc.Spec.DNSDomains) + len(sc.Spec.DNSDomains)*tc.replicas))
 
-				var serviceServingDNSNames []string
-				services, err := f.KubeClient().CoreV1().Services(sc.Namespace).List(ctx, metav1.ListOptions{
-					LabelSelector: labels.SelectorFromSet(naming.ClusterLabels(sc)).String(),
-				})
-				o.Expect(err).NotTo(o.HaveOccurred())
-
-				for _, svc := range services.Items {
-					serviceServingDNSNames = append(serviceServingDNSNames, fmt.Sprintf("%s.%s.svc", svc.Name, svc.Namespace))
-				}
-
-				serviceAndPodIPs, err := utils.GetNodesServiceAndPodIPs(ctx, f.KubeClient().CoreV1(), sc)
-				o.Expect(err).NotTo(o.HaveOccurred())
-				o.Expect(serviceAndPodIPs).To(o.HaveLen(2 * int(utils.GetMemberCount(sc))))
-
-				hostsIPs, err := helpers.ParseClusterIPs(serviceAndPodIPs)
+				nodeIPs, err := helpers.ParseClusterIPs(nodeClusterIPs)
 				o.Expect(err).NotTo(o.HaveOccurred())
 
-				servingDNSNames := make([]string, 0, len(sniHosts)+len(serviceServingDNSNames))
-				servingDNSNames = append(servingDNSNames, sniHosts...)
-				servingDNSNames = append(servingDNSNames, serviceServingDNSNames...)
-
 				// Check the serving cert content first to distinguish whether the cert was correctly reloaded by ScyllaDB or not.
 				o.Expect(servingCerts[0].Subject.CommonName).To(o.BeEmpty())
-				o.Expect(helpers.NormalizeIPs(servingCerts[0].IPAddresses)).To(o.ConsistOf(hostsIPs))
-				o.Expect(servingCerts[0].DNSNames).To(o.ConsistOf(servingDNSNames))
+				o.Expect(helpers.NormalizeIPs(servingCerts[0].IPAddresses)).To(o.ConsistOf(nodeIPs))
+				o.Expect(servingCerts[0].DNSNames).To(o.ConsistOf(sniHosts))
 
 				// Now check the cert used by ScyllaDB.
 				servingCAPool := x509.NewCertPool()
@@ -220,7 +201,7 @@ var _ = g.Describe("ScyllaCluster", func() {
 				adminTLSCert, err := tls.X509KeyPair(adminClientCertBytes, adminClientKeyBytes)
 				o.Expect(err).NotTo(o.HaveOccurred())
 
-				for _, nodeAddress := range hosts {
+				for _, nodeAddress := range nodeClusterIPs {
 					framework.Infof("Starting to probe node %q for correct certs", nodeAddress)
 
 					o.Eventually(func(eo o.Gomega) {
@@ -234,8 +215,8 @@ var _ = g.Describe("ScyllaCluster", func() {
 						eo.Expect(serverCerts).NotTo(o.BeEmpty())
 
 						eo.Expect(serverCerts[0].Subject.CommonName).To(o.BeEmpty())
-						eo.Expect(helpers.NormalizeIPs(serverCerts[0].IPAddresses)).To(o.ConsistOf(hostsIPs))
-						eo.Expect(serverCerts[0].DNSNames).To(o.ConsistOf(servingDNSNames))
+						eo.Expect(helpers.NormalizeIPs(serverCerts[0].IPAddresses)).To(o.ConsistOf(nodeIPs))
+						eo.Expect(serverCerts[0].DNSNames).To(o.ConsistOf(sniHosts))
 					}).WithTimeout(5 * 60 * time.Second).WithPolling(1 * time.Second).Should(o.Succeed())
 
 					framework.Infof("Node %q has correct certs", nodeAddress)
@@ -311,6 +292,7 @@ var _ = g.Describe("ScyllaCluster", func() {
 				o.Expect(initialSecret.Data).To(o.HaveKey("tls.key"))
 				o.Expect(initialSecret.Data["tls.crt"]).NotTo(o.BeEmpty())
 				o.Expect(initialSecret.Data["tls.key"]).NotTo(o.BeEmpty())
+				o.Expect(initialSecret.Annotations).To(o.HaveKeyWithValue("certificates.internal.scylla-operator.scylladb.com/refresh-reason", "needs new cert"))
 
 				var configMap *corev1.ConfigMap
 				var initialBundleCert *x509.Certificate
diff --git a/test/e2e/set/scyllacluster/verify.go b/test/e2e/set/scyllacluster/verify.go
index 41aa860f8..f8bad8c98 100644
--- a/test/e2e/set/scyllacluster/verify.go
+++ b/test/e2e/set/scyllacluster/verify.go
@@ -9,7 +9,6 @@ import (
 	scyllav1 "github.com/scylladb/scylla-operator/pkg/api/scylla/v1"
 	"github.com/scylladb/scylla-operator/pkg/features"
 	"github.com/scylladb/scylla-operator/pkg/helpers"
-	"github.com/scylladb/scylla-operator/pkg/helpers/slices"
 	"github.com/scylladb/scylla-operator/pkg/naming"
 	"github.com/scylladb/scylla-operator/pkg/pointer"
 	cqlclientv1alpha1 "github.com/scylladb/scylla-operator/pkg/scylla/api/cqlclient/v1alpha1"
@@ -265,7 +264,7 @@ func getScyllaHostsAndWaitForFullQuorum(ctx context.Context, client corev1client
 	dcClientMap := make(map[string]corev1client.CoreV1Interface, 1)
 	dcClientMap[sc.Spec.Datacenter.Name] = client
 	hosts := getScyllaHostsByDCAndWaitForFullQuorum(ctx, dcClientMap, []*scyllav1.ScyllaCluster{sc})
-	return slices.Flatten(helpers.GetMapValues(hosts))
+	return helpers.Flatten(helpers.GetMapValues(hosts))
 }
 
 func getScyllaHostsByDCAndWaitForFullQuorum(ctx context.Context, dcClientMap map[string]corev1client.CoreV1Interface, scs []*scyllav1.ScyllaCluster) map[string][]string {
diff --git a/test/e2e/utils/datainserter.go b/test/e2e/utils/datainserter.go
index 851711b92..bca5ba6b1 100644
--- a/test/e2e/utils/datainserter.go
+++ b/test/e2e/utils/datainserter.go
@@ -13,7 +13,6 @@ import (
 	"github.com/scylladb/gocqlx/v2"
 	"github.com/scylladb/gocqlx/v2/table"
 	"github.com/scylladb/scylla-operator/pkg/helpers"
-	"github.com/scylladb/scylla-operator/pkg/helpers/slices"
 	"github.com/scylladb/scylla-operator/test/e2e/framework"
 	utilrand "k8s.io/apimachinery/pkg/util/rand"
 )
@@ -62,7 +61,7 @@ func NewMultiDCDataInserter(dcHosts map[string][]string) (*DataInserter, error)
 		replicationFactor: replicationFactor,
 	}
 
-	err := di.SetClientEndpoints(slices.Flatten(helpers.GetMapValues(dcHosts)))
+	err := di.SetClientEndpoints(helpers.Flatten(helpers.GetMapValues(dcHosts)))
 	if err != nil {
 		return nil, fmt.Errorf("can't set client endpoints: %w", err)
 	}
diff --git a/test/e2e/utils/helpers.go b/test/e2e/utils/helpers.go
index 9106aff0e..50aad6733 100644
--- a/test/e2e/utils/helpers.go
+++ b/test/e2e/utils/helpers.go
@@ -285,10 +285,6 @@ func WaitForSecretState(ctx context.Context, client corev1client.SecretInterface
 	return WaitForObjectState[*corev1.Secret, *corev1.SecretList](ctx, client, name, options, condition, additionalConditions...)
 }
 
-func WaitForServiceState(ctx context.Context, client corev1client.ServiceInterface, name string, options WaitForStateOptions, condition func(*corev1.Service) (bool, error), additionalConditions ...func(*corev1.Service) (bool, error)) (*corev1.Service, error) {
-	return WaitForObjectState[*corev1.Service, *corev1.ServiceList](ctx, client, name, options, condition, additionalConditions...)
-}
-
 func RunEphemeralContainerAndWaitForCompletion(ctx context.Context, client corev1client.PodInterface, podName string, ec *corev1.EphemeralContainer) (*corev1.Pod, error) {
 	ephemeralPod := &corev1.Pod{
 		Spec: corev1.PodSpec{
@@ -449,91 +445,21 @@ func GetHostsAndUUIDs(ctx context.Context, client corev1client.CoreV1Interface,
 	var hosts []string
 	var uuids []string
 	for _, s := range serviceList.Items {
-		host := s.Spec.ClusterIP
-
-		if host == corev1.ClusterIPNone {
-			pod, err := client.Pods(sc.Namespace).Get(ctx, s.Name, metav1.GetOptions{})
-			if err != nil {
-				return nil, nil, fmt.Errorf("can't get pod %q: %w", naming.ManualRef(sc.Namespace, s.Name), err)
-			}
-			host = pod.Status.PodIP
+		if s.Spec.Type != corev1.ServiceTypeClusterIP {
+			return nil, nil, fmt.Errorf("service %s/%s is of type %q instead of %q", s.Namespace, s.Name, s.Spec.Type, corev1.ServiceTypeClusterIP)
 		}
 
-		configClient, err := GetScyllaConfigClient(ctx, client, sc, host)
-		if err != nil {
-			return nil, nil, fmt.Errorf("can't create scylla config client with host %q: %w", host, err)
-		}
-		clientBroadcastedAddress, err := configClient.BroadcastRPCAddress(ctx)
-		if err != nil {
-			return nil, nil, fmt.Errorf("can't get broadcast_rpc_address of host %q: %w", host, err)
+		if s.Spec.ClusterIP == corev1.ClusterIPNone {
+			return nil, nil, fmt.Errorf("service %s/%s doesn't have a ClusterIP", s.Namespace, s.Name)
 		}
 
-		hosts = append(hosts, clientBroadcastedAddress)
+		hosts = append(hosts, s.Spec.ClusterIP)
 		uuids = append(uuids, s.Annotations[naming.HostIDAnnotation])
 	}
 
 	return hosts, uuids, nil
 }
 
-func GetNodesServiceAndPodIPs(ctx context.Context, client corev1client.CoreV1Interface, sc *scyllav1.ScyllaCluster) ([]string, error) {
-	serviceIPs, err := GetNodesServiceIPs(ctx, client, sc)
-	if err != nil {
-		return nil, fmt.Errorf("can't get nodes service IPs: %w", err)
-	}
-
-	podIPs, err := GetNodesPodIPs(ctx, client, sc)
-	if err != nil {
-		return nil, fmt.Errorf("can't get nodes pod IPs: %w", err)
-	}
-
-	ipAddresses := make([]string, 0, len(serviceIPs)+len(podIPs))
-	ipAddresses = append(ipAddresses, serviceIPs...)
-	ipAddresses = append(ipAddresses, podIPs...)
-	return ipAddresses, nil
-}
-
-func GetNodesServiceIPs(ctx context.Context, client corev1client.CoreV1Interface, sc *scyllav1.ScyllaCluster) ([]string, error) {
-	serviceList, err := client.Services(sc.Namespace).List(ctx, metav1.ListOptions{
-		LabelSelector: GetMemberServiceSelector(sc.Name).String(),
-	})
-	if err != nil {
-		return nil, fmt.Errorf("can't get member services: %w", err)
-	}
-
-	var ipAddresses []string
-
-	for _, svc := range serviceList.Items {
-		if svc.Spec.ClusterIP != corev1.ClusterIPNone {
-			ipAddresses = append(ipAddresses, svc.Spec.ClusterIP)
-		}
-
-		for _, ingressStatus := range svc.Status.LoadBalancer.Ingress {
-			ipAddresses = append(ipAddresses, ingressStatus.IP)
-		}
-	}
-
-	return ipAddresses, nil
-}
-
-func GetNodesPodIPs(ctx context.Context, client corev1client.CoreV1Interface, sc *scyllav1.ScyllaCluster) ([]string, error) {
-	clusterPods, err := client.Pods(sc.Namespace).List(ctx, metav1.ListOptions{
-		LabelSelector: labels.SelectorFromSet(map[string]string{
-			naming.ClusterNameLabel: sc.Name,
-		}).String(),
-	})
-	if err != nil {
-		return nil, fmt.Errorf("can't get cluster pods: %w", err)
-	}
-
-	ipAddresses := make([]string, 0, len(clusterPods.Items))
-
-	for _, pod := range clusterPods.Items {
-		ipAddresses = append(ipAddresses, pod.Status.PodIP)
-	}
-
-	return ipAddresses, nil
-}
-
 func GetHosts(ctx context.Context, client corev1client.CoreV1Interface, sc *scyllav1.ScyllaCluster) ([]string, error) {
 	hosts, _, err := GetHostsAndUUIDs(ctx, client, sc)
 	return hosts, err