diff --git a/.github/workflows/test_e2e.yml b/.github/workflows/test_e2e.yml
index c3e507927fa78f35008505f02b80989604c044ff..d0d2f655399f2a06356fe234003d03faac638b03 100644
--- a/.github/workflows/test_e2e.yml
+++ b/.github/workflows/test_e2e.yml
@@ -16,14 +16,14 @@ jobs:
       fail-fast: false
       matrix:
         include:
-          - k3s: v1.24
-            k8s-test: v1.24.13
           - k3s: v1.25
-            k8s-test: v1.25.9
+            k8s-test: v1.25.13
           - k3s: v1.26
-            k8s-test: v1.26.4
+            k8s-test: v1.26.8
           - k3s: v1.27
-            k8s-test: v1.27.1
+            k8s-test: v1.27.5
+          - k3s: v1.28
+            k8s-test: v1.28.1
     steps:
     - uses: actions/setup-go@v4
       with:
@@ -44,7 +44,7 @@ jobs:
           kubectl
           skaffold
         helm: v3.11.2
-        kubectl: v1.26.3
+        kubectl: v1.28.1
         skaffold: v2.3.0
 
     - name: Run tests
diff --git a/docs/kubernetes/README.md b/docs/kubernetes/README.md
index 46e49a77bf8f822e2662711a578f23022fd16e92..66b4f41f632e7901a67787c9c34aaf5eedf16848 100644
--- a/docs/kubernetes/README.md
+++ b/docs/kubernetes/README.md
@@ -165,7 +165,7 @@ $ kubectl apply -f https://raw.githubusercontent.com/hetznercloud/csi-driver/v2.
 
 ## Integration with Root Servers
 
-Root servers can be part of the cluster, but the CSI plugin doesn't work there. Taint the root server as follows to skip that node for the daemonset.
+Root servers can be part of the cluster, but the CSI plugin doesn't work there. Taint the root server as follows to skip that node for the DaemonSet.
 
 ```bash
 kubectl label nodes <node name> instance.hetzner.cloud/is-root-server=true
@@ -182,10 +182,11 @@ related only to an unsupported version.
 
 | Kubernetes | CSI Driver |                                                                                   Deployment File |
 |------------|-----------:|--------------------------------------------------------------------------------------------------:|
-| 1.27       |      2.3.2 | https://raw.githubusercontent.com/hetznercloud/csi-driver/v2.3.2/deploy/kubernetes/hcloud-csi.yml |
-| 1.26       |      2.3.2 | https://raw.githubusercontent.com/hetznercloud/csi-driver/v2.3.2/deploy/kubernetes/hcloud-csi.yml |
-| 1.25       |      2.3.2 | https://raw.githubusercontent.com/hetznercloud/csi-driver/v2.3.2/deploy/kubernetes/hcloud-csi.yml |
-| 1.24       |      2.3.2 | https://raw.githubusercontent.com/hetznercloud/csi-driver/v2.3.2/deploy/kubernetes/hcloud-csi.yml |
+| 1.28       |     2.4.0+ | https://raw.githubusercontent.com/hetznercloud/csi-driver/v2.4.0/deploy/kubernetes/hcloud-csi.yml |
+| 1.27       |     2.4.0+ | https://raw.githubusercontent.com/hetznercloud/csi-driver/v2.4.0/deploy/kubernetes/hcloud-csi.yml |
+| 1.26       |     2.4.0+ | https://raw.githubusercontent.com/hetznercloud/csi-driver/v2.4.0/deploy/kubernetes/hcloud-csi.yml |
+| 1.25       |     2.4.0+ | https://raw.githubusercontent.com/hetznercloud/csi-driver/v2.4.0/deploy/kubernetes/hcloud-csi.yml |
+| 1.24       |      2.4.0 | https://raw.githubusercontent.com/hetznercloud/csi-driver/v2.4.0/deploy/kubernetes/hcloud-csi.yml |
 | 1.23       |      2.2.0 | https://raw.githubusercontent.com/hetznercloud/csi-driver/v2.2.0/deploy/kubernetes/hcloud-csi.yml |
 | 1.22       |      1.6.0 | https://raw.githubusercontent.com/hetznercloud/csi-driver/v1.6.0/deploy/kubernetes/hcloud-csi.yml |
 | 1.21       |      1.6.0 | https://raw.githubusercontent.com/hetznercloud/csi-driver/v1.6.0/deploy/kubernetes/hcloud-csi.yml |
diff --git a/test/e2e/kubernetes/run-e2e-tests.sh b/test/e2e/kubernetes/run-e2e-tests.sh
index ff4f66a8c7975007f09064d4dc875dbb07a72d94..ab5bac1b887953d0c2a08fa775c340453b469007 100755
--- a/test/e2e/kubernetes/run-e2e-tests.sh
+++ b/test/e2e/kubernetes/run-e2e-tests.sh
@@ -2,7 +2,7 @@
 set -uex -o pipefail
 SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
 
-k8s_test_version="${K8S_TEST_VERSION:-v1.26.3}"
+k8s_test_version="${K8S_TEST_VERSION:-v1.28.1}"
 
 mkdir -p "${SCRIPT_DIR}/test-binaries"
 # TODO: Read linux-amd64 from env
@@ -13,7 +13,7 @@ ginkgo="${SCRIPT_DIR}/test-binaries/ginkgo"
 ginkgo_flags="-v --flakeAttempts=2"
 
 e2e="${SCRIPT_DIR}/test-binaries/e2e.test"
-e2e_flags="-storage.testdriver=${SCRIPT_DIR}/testdriver-1.23.yaml"
+e2e_flags="-storage.testdriver=${SCRIPT_DIR}/testdriver-1.25.yaml"
 
 echo "Executing parallel tests"
 ${ginkgo} ${ginkgo_flags} \
diff --git a/test/e2e/kubernetes/testdriver-1.23.yaml b/test/e2e/kubernetes/testdriver-1.25.yaml
similarity index 88%
rename from test/e2e/kubernetes/testdriver-1.23.yaml
rename to test/e2e/kubernetes/testdriver-1.25.yaml
index 7e608358da4f570a3c2e3f95f858062c30a80251..19d8d19d3420ede6b66b2bec858afda795d689cd 100644
--- a/test/e2e/kubernetes/testdriver-1.23.yaml
+++ b/test/e2e/kubernetes/testdriver-1.25.yaml
@@ -8,7 +8,7 @@ DriverInfo:
   Capabilities:
     # Available capabilities are defined in the kubernetes repositories, make
     # sure to select the corresponding k8s version:
-    # https://github.com/kubernetes/kubernetes/blob/release-1.23/test/e2e/storage/framework/testdriver.go#L150
+    # https://github.com/kubernetes/kubernetes/blob/release-1.25/test/e2e/storage/framework/testdriver.go#L150
     persistence: true
     block: true
     fsGroup: true
@@ -21,6 +21,7 @@ DriverInfo:
     controllerExpansion: true
     nodeExpansion: true
     onlineExpansion: false
+    offlineExpansion: true
     volumeLimits: false
     singleNodeVolume: true
     topology: true