diff --git a/Makefile b/Makefile
index 3c0fc2a8..8dcf2268 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@ PROJECT_NAME ?= piraeus-operator
 # To re-generate a bundle for another specific version without changing the standard setup, you can:
 # - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2)
 # - use environment variables to overwrite this value (e.g export VERSION=0.0.2)
-VERSION ?= 2.7.1
+VERSION ?= 2.8.0
 
 # CHANNELS define the bundle channels used in the bundle.
 # Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable")
diff --git a/README.md b/README.md
index 28ac0d3c..84b1cd2a 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@ to fix issues or new software versions until a stable upgrade path to v2 is avai
 To deploy Piraeus Operator v2 from this repository, simply run:
 
 ```
-$ kubectl apply --server-side -k "https://github.com/piraeusdatastore/piraeus-operator//config/default?ref=v2.7.1"
+$ kubectl apply --server-side -k "https://github.com/piraeusdatastore/piraeus-operator//config/default?ref=v2.8.0"
 # Verify the operator is running:
 $ kubectl wait pod --for=condition=Ready -n piraeus-datastore -l app.kubernetes.io/component=piraeus-operator
 pod/piraeus-operator-controller-manager-dd898f48c-bhbtv condition met
diff --git a/charts/piraeus/Chart.yaml b/charts/piraeus/Chart.yaml
index 0a2b853d..f43d3e05 100644
--- a/charts/piraeus/Chart.yaml
+++ b/charts/piraeus/Chart.yaml
@@ -3,8 +3,8 @@ name: piraeus
 description: |
   The Piraeus Operator manages software defined storage clusters using LINSTOR in Kubernetes.
 type: application
-version: 2.7.1
-appVersion: "v2.7.1"
+version: 2.8.0
+appVersion: "v2.8.0"
 maintainers:
   - name: Piraeus Datastore
     url: https://piraeus.io
diff --git a/charts/piraeus/templates/config.yaml b/charts/piraeus/templates/config.yaml
index 14b8b9be..6252976c 100644
--- a/charts/piraeus/templates/config.yaml
+++ b/charts/piraeus/templates/config.yaml
@@ -17,20 +17,19 @@ data:
     #   quay.io/piraeusdatastore/piraeus-server:v1.24.2
     components:
       linstor-controller:
-        tag: v1.29.2
+        tag: v1.30.4
         image: piraeus-server
       linstor-satellite:
-        # Pin with digest to ensure we pull the version with downgraded thin-send-recv
-        tag: v1.29.2
+        tag: v1.30.4
         image: piraeus-server
       linstor-csi:
-        tag: v1.6.4
+        tag: v1.7.0
         image: piraeus-csi
       drbd-reactor:
-        tag: v1.6.0
+        tag: v1.8.0
         image: drbd-reactor
       ha-controller:
-        tag: v1.2.2
+        tag: v1.3.0
         image: piraeus-ha-controller
       drbd-shutdown-guard:
         tag: v1.0.0
@@ -90,25 +89,25 @@ data:
     base: registry.k8s.io/sig-storage
     components:
       csi-attacher:
-        tag: v4.7.0
+        tag: v4.8.0
         image: csi-attacher
       csi-livenessprobe:
-        tag: v2.14.0
+        tag: v2.15.0
         image: livenessprobe
       csi-provisioner:
-        tag: v5.1.0
+        tag: v5.2.0
         image: csi-provisioner
       csi-snapshotter:
-        tag: v8.1.0
+        tag: v8.2.0
         image: csi-snapshotter
       csi-resizer:
-        tag: v1.12.0
+        tag: v1.13.1
         image: csi-resizer
       csi-external-health-monitor-controller:
-        tag: v0.13.0
+        tag: v0.14.0
         image: csi-external-health-monitor-controller
       csi-node-driver-registrar:
-        tag: v2.12.0
+        tag: v2.13.0
         image: csi-node-driver-registrar
   {{- range $idx, $value := .Values.imageConfigOverride }}
   {{ add $idx 1 }}_helm_override.yaml: |
diff --git a/config/manager/0_piraeus_datastore_images.yaml b/config/manager/0_piraeus_datastore_images.yaml
index 9d7c379f..1365a630 100644
--- a/config/manager/0_piraeus_datastore_images.yaml
+++ b/config/manager/0_piraeus_datastore_images.yaml
@@ -8,20 +8,19 @@ base: quay.io/piraeusdatastore
 #   quay.io/piraeusdatastore/piraeus-server:v1.24.2
 components:
   linstor-controller:
-    tag: v1.29.2
+    tag: v1.30.4
     image: piraeus-server
   linstor-satellite:
-    # Pin with digest to ensure we pull the version with downgraded thin-send-recv
-    tag: v1.29.2
+    tag: v1.30.4
     image: piraeus-server
   linstor-csi:
-    tag: v1.6.4
+    tag: v1.7.0
     image: piraeus-csi
   drbd-reactor:
-    tag: v1.6.0
+    tag: v1.8.0
     image: drbd-reactor
   ha-controller:
-    tag: v1.2.2
+    tag: v1.3.0
     image: piraeus-ha-controller
   drbd-shutdown-guard:
     tag: v1.0.0
diff --git a/config/manager/0_sig_storage_images.yaml b/config/manager/0_sig_storage_images.yaml
index 189f492d..9ccc0bf6 100644
--- a/config/manager/0_sig_storage_images.yaml
+++ b/config/manager/0_sig_storage_images.yaml
@@ -2,23 +2,23 @@
 base: registry.k8s.io/sig-storage
 components:
   csi-attacher:
-    tag: v4.7.0
+    tag: v4.8.0
     image: csi-attacher
   csi-livenessprobe:
-    tag: v2.14.0
+    tag: v2.15.0
     image: livenessprobe
   csi-provisioner:
-    tag: v5.1.0
+    tag: v5.2.0
     image: csi-provisioner
   csi-snapshotter:
-    tag: v8.1.0
+    tag: v8.2.0
     image: csi-snapshotter
   csi-resizer:
-    tag: v1.12.0
+    tag: v1.13.1
     image: csi-resizer
   csi-external-health-monitor-controller:
-    tag: v0.13.0
+    tag: v0.14.0
     image: csi-external-health-monitor-controller
   csi-node-driver-registrar:
-    tag: v2.12.0
+    tag: v2.13.0
     image: csi-node-driver-registrar
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 65282aef..6959850e 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [Unreleased]
 
+## [v2.8.0] - 2025-02-13
+
 ### Added
 
 - Automatically set the LINSTOR Satellite image version when using an external LINSTOR Controller.
@@ -15,6 +17,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 - Disable debug logging by default for the Operator.
 - Allow specifying multiple controller URLs for external LINSTOR clusters.
+- Updated images:
+    * LINSTOR 1.30.4
+    * LINSTOR CSI 1.7.0
+    * DRBD Reactor 1.8.0
+    * LINSTOR HA Controller 1.3.0
+    * Latest CSI sidecars
 
 ## [v2.7.1] - 2024-11-25
 
@@ -987,4 +995,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 [v2.7.1]: https://github.com/piraeusdatastore/piraeus-operator/compare/v2.7.0...v2.7.1
 
-[Unreleased]: https://github.com/piraeusdatastore/piraeus-operator/compare/v2.7.1...HEAD
+[v2.8.0]: https://github.com/piraeusdatastore/piraeus-operator/compare/v2.7.1...v2.8.0
+[Unreleased]: https://github.com/piraeusdatastore/piraeus-operator/compare/v2.8.0...HEAD
diff --git a/docs/tutorial/get-started.md b/docs/tutorial/get-started.md
index d3b73663..b2cd71db 100644
--- a/docs/tutorial/get-started.md
+++ b/docs/tutorial/get-started.md
@@ -15,7 +15,7 @@ All resources needed to run Piraeus Operator are included in a single Kustomizat
 Install Piraeus Operator by running:
 
 ```bash
-$ kubectl apply --server-side -k "https://github.com/piraeusdatastore/piraeus-operator//config/default?ref=v2.7.1"
+$ kubectl apply --server-side -k "https://github.com/piraeusdatastore/piraeus-operator//config/default?ref=v2.8.0"
 namespace/piraeus-datastore configured
 ...
 ```
diff --git a/docs/upgrade/README.md b/docs/upgrade/README.md
index 243cdcb1..fee7412d 100644
--- a/docs/upgrade/README.md
+++ b/docs/upgrade/README.md
@@ -10,7 +10,7 @@ To upgrade, apply the resource of the latest release. Use the same method that w
 To upgrade to the latest release using `kubectl`, run the following commands:
 
 ```
-$ kubectl apply --server-side -k "https://github.com/piraeusdatastore/piraeus-operator//config/default?ref=v2.7.1"
+$ kubectl apply --server-side -k "https://github.com/piraeusdatastore/piraeus-operator//config/default?ref=v2.8.0"
 $ kubectl wait pod --for=condition=Ready -n piraeus-datastore --all
 ```
 
diff --git a/go.mod b/go.mod
index ebbf4541..18760571 100644
--- a/go.mod
+++ b/go.mod
@@ -5,14 +5,14 @@ go 1.23.0
 toolchain go1.23.4
 
 require (
-	github.com/LINBIT/golinstor v0.53.0
+	github.com/LINBIT/golinstor v0.54.0
 	github.com/cert-manager/cert-manager v1.17.0
 	github.com/evanphx/json-patch v5.9.11+incompatible
 	github.com/go-logr/logr v1.4.2
 	github.com/google/go-cmp v0.6.0
 	github.com/onsi/ginkgo/v2 v2.22.2
 	github.com/onsi/gomega v1.36.2
-	github.com/piraeusdatastore/linstor-csi v1.6.5
+	github.com/piraeusdatastore/linstor-csi v1.7.0
 	github.com/stretchr/testify v1.10.0
 	golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67
 	golang.org/x/time v0.10.0
diff --git a/go.sum b/go.sum
index c0fc83c7..aab64281 100644
--- a/go.sum
+++ b/go.sum
@@ -1,5 +1,5 @@
-github.com/LINBIT/golinstor v0.53.0 h1:bm5Uso+hYiYldFrje0RilRZpXjrLG8u94dshJR0fEUc=
-github.com/LINBIT/golinstor v0.53.0/go.mod h1:45re6T0ds+G7JCaCnxsigncnlDUs8GwULjYrdunYkE4=
+github.com/LINBIT/golinstor v0.54.0 h1:SEXv+QIM41VXOeXOfxvJBHHq1TrF0Z+5WD/UCxT7ux0=
+github.com/LINBIT/golinstor v0.54.0/go.mod h1:CWTGY62Y14gHKXBmI3g8qUL15La5Og2o/g6mSxbugwo=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
 github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
@@ -97,8 +97,8 @@ github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
 github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
 github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw=
 github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
-github.com/piraeusdatastore/linstor-csi v1.6.5 h1:ZvUrziav0+J2gzJgaYCBtOgeLibe1esRKNkekttCUq4=
-github.com/piraeusdatastore/linstor-csi v1.6.5/go.mod h1:Sv5nfZs1/iixSQMe0B/PrNc1wvz5dwstBwHLub3VcV4=
+github.com/piraeusdatastore/linstor-csi v1.7.0 h1:52YbasWuQwW78c2Ro+tnEcE/0Ke7Rx5qiJvpIo38pDU=
+github.com/piraeusdatastore/linstor-csi v1.7.0/go.mod h1:Y4BVTPU7cO2b4SHHf1a8EAi9aKp0vT/+Rdk1LNJAI/4=
 github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
diff --git a/hack/make-release.sh b/hack/make-release.sh
index 2a3bd798..6a888456 100755
--- a/hack/make-release.sh
+++ b/hack/make-release.sh
@@ -40,7 +40,7 @@ $KUSTOMIZE edit set image controller="$IMG:v$VERSION"
 popd
 
 # replace deployment instructions in docs
-for FILE in ./README.md ./docs/tutorial/get-started.md ./docs/how-to/upgrade/UPGRADE.md ; do
+for FILE in ./README.md ./docs/tutorial/get-started.md ./docs/upgrade/README.md ; do
 	sed -e "s/ref=v[0-9\.]\+/ref=v$VERSION/" -i "$FILE"
 done
 
diff --git a/pkg/imageversions/dynamic.go b/pkg/imageversions/dynamic.go
index 5c8e5df7..5581fb4a 100644
--- a/pkg/imageversions/dynamic.go
+++ b/pkg/imageversions/dynamic.go
@@ -38,7 +38,7 @@ func FromConfigMap(ctx context.Context, client client.Client, name types.Namespa
 //
 // The Configs will be updated so that the first entry containing a LINSTOR Satellite image is updated.
 // Returns an error is the LINSTOR Controller could not be reached, or no LINSTOR Satellite image was found.
-func SetFromExternalCluster(ctx context.Context, client lclient.Client, configs Configs) error {
+func SetFromExternalCluster(ctx context.Context, client *lclient.Client, configs Configs) error {
 	version, err := client.Controller.GetVersion(ctx)
 	if err != nil {
 		return fmt.Errorf("failed to fetch controller version: %w", err)
diff --git a/pkg/imageversions/dynamic_test.go b/pkg/imageversions/dynamic_test.go
index 5354fc94..83836ef2 100644
--- a/pkg/imageversions/dynamic_test.go
+++ b/pkg/imageversions/dynamic_test.go
@@ -126,14 +126,14 @@ func TestSetFromExternalCluster(t *testing.T) {
 		},
 	}
 
-	err := imageversions.SetFromExternalCluster(context.Background(), lclient.Client{
+	err := imageversions.SetFromExternalCluster(context.Background(), &lclient.Client{
 		Controller: &FakeVersionReporter{
 			Error: fmt.Errorf("error"),
 		},
 	}, configs)
 	assert.Error(t, err)
 
-	err = imageversions.SetFromExternalCluster(context.Background(), lclient.Client{
+	err = imageversions.SetFromExternalCluster(context.Background(), &lclient.Client{
 		Controller: &FakeVersionReporter{
 			ControllerVersion: lclient.ControllerVersion{Version: "10.11.12"},
 		},
diff --git a/pkg/linstorhelper/client.go b/pkg/linstorhelper/client.go
index fd9a342b..0e6ed77e 100644
--- a/pkg/linstorhelper/client.go
+++ b/pkg/linstorhelper/client.go
@@ -29,7 +29,7 @@ import (
 
 // Client is a LINSTOR client with convenience functions.
 type Client struct {
-	lapi.Client
+	*lapi.Client
 }
 
 var (
@@ -61,14 +61,10 @@ func PerClusterRateLimiter(r rate.Limit, b int) lapi.Option {
 
 // NewClientForCluster returns a LINSTOR client for a LINSTOR Controller managed by the operator.
 func NewClientForCluster(ctx context.Context, cl client.Client, namespace string, ref *piraeusv1.ClusterReference, options ...lapi.Option) (*Client, error) {
-	// Defensive copy: there might be multiple goroutines calling this in parallel, using the same "options" slice.
-	// In theory this could lead to one goroutine overwriting the append()-ed options of another because they point
-	// at the same "base" slice. To prevent this, make a copy of options so we do not trample over appended elements
-	// of other goroutines.
-	options = slices.Clone(options)
+	var opts []lapi.Option
 
 	if ref.ExternalController != nil {
-		options = append(options, lapi.Controllers(strings.Split(ref.ExternalController.URL, ",")))
+		opts = append(opts, lapi.Controllers(strings.Split(ref.ExternalController.URL, ",")))
 	} else {
 		services := corev1.ServiceList{}
 		err := cl.List(ctx, &services, client.InNamespace(namespace), client.MatchingLabels{
@@ -90,7 +86,7 @@ func NewClientForCluster(ctx context.Context, cl client.Client, namespace string
 			return nil, nil
 		}
 
-		options = append(options, lapi.BaseURL(&url.URL{
+		opts = append(opts, lapi.BaseURL(&url.URL{
 			Scheme: scheme,
 			Host:   fmt.Sprintf("%s.%s.svc:%d", s.Name, s.Namespace, port),
 		}))
@@ -113,24 +109,24 @@ func NewClientForCluster(ctx context.Context, cl client.Client, namespace string
 			return nil, err
 		}
 
-		options = append(options, lapi.HTTPClient(&http.Client{
+		opts = append(opts, lapi.HTTPClient(&http.Client{
 			Transport: &http.Transport{
 				TLSClientConfig: tlsConfig,
 			},
 		}))
 	}
 
-	options = append(options,
+	opts = append(opts,
 		lapi.UserAgent(vars.OperatorName+"/"+vars.Version),
 		lapi.Log(&logrAdapter{log.FromContext(ctx)}),
 	)
 
-	c, err := lapi.NewClient(options...)
+	c, err := lapi.NewClient(append(opts, options...)...)
 	if err != nil {
 		return nil, err
 	}
 
-	return &Client{*c}, nil
+	return &Client{c}, nil
 }
 
 // extractSchemeAndPort returns the preferred connection scheme and port from the service.
diff --git a/pkg/linstorhelper/client_test.go b/pkg/linstorhelper/client_test.go
index 21a2ed73..f15b8fb8 100644
--- a/pkg/linstorhelper/client_test.go
+++ b/pkg/linstorhelper/client_test.go
@@ -215,7 +215,7 @@ func TestNewClientForCluster(t *testing.T) {
 				require.NoError(t, err)
 
 				// need to use go-cmp here, as that can handle the embedded x509.CertPool comparison.
-				diff := cmp.Diff(*expected, actual.Client,
+				diff := cmp.Diff(expected, actual.Client,
 					// Compare all unexported fields, too
 					cmp.Exporter(func(r reflect.Type) bool {
 						return true
@@ -390,7 +390,7 @@ func TestCreateOrUpdateNode(t *testing.T) {
 		t.Run(test.name, func(t *testing.T) {
 			t.Parallel()
 
-			lc := linstorhelper.Client{Client: lapi.Client{
+			lc := linstorhelper.Client{Client: &lapi.Client{
 				Nodes: test.setupCalls(t),
 			}}