Repository: kubernetes-sigs/aws-ebs-csi-driver (go)

Issue:
karpenter disruption taint isn't correct for karpenter v1
/kind bug

**What happened?**

EBS CSI driver does not clean up after itself when node is terminating due to karpenter disruption after v1.0.1 karpenter upgrade

**What you expected to happen?**

EBS CSI driver removes all volume attachments when terminating due to node termination

**How to reproduce it (as minimally and precisely as possible)?**

Have an EBS volume attached, and don't configure any tolerations on the EBS CSI driver (so it gets terminated before the node terminates)

**Anything else we need to know?**:

The taint during karpenter disruption is:
```
  taints:
  - effect: NoSchedule
    key: karpenter.sh/disrupted
 ```
 
 But the `IsDisruptedTaint` looks for `disrupting` rather than `disrupted` because it's using the v1beta1 API rather than the v1 API.

https://github.com/kubernetes-sigs/karpenter/blob/b69e975128ac9a511542f9f1d245a6d4c3f91112/pkg/apis/v1beta1/taints.go#L28

vs

https://github.com/kubernetes-sigs/karpenter/blob/b69e975128ac9a511542f9f1d245a6d4c3f91112/pkg/apis/v1/taints.go#L28



**Environment**
- Kubernetes version (use `kubectl version`):
```
Client Version: v1.31.1
Kustomize Version: v5.4.2
Server Version: v1.30.3-eks-a18cd3a
```
- Driver version: v1.35.0


Pull request:
Add v1 Karpenter disrupted taint to pre-stop hook
**Is this a bug fix or adding new feature?**
Bug fix

**What is this PR about? / Why do we need it?**
Fixes #2158 

Our pre-stop hook attempts to keep the EBS CSI Driver node plugin alive while node is being drained so that it can Unstage/Unpublish all volumes and report that to Kubelet before node termination. Karpenter v1 changed their disruption taint, so we need to update our pre-stop hook to check for it. 

We also remove the dependency on Karpenter because we are compatible with multiple versions of it, and switch to just checking taint key instead of taint key and effect in case these auto-scalars switch to a `NoExecute` effect.

**What testing is done?** 
New unit tests. 

TODO test with karpenter v1. 

Patch:
diff --git a/OWNERS b/OWNERS
index 2dec5e76..ee6785b3 100644
--- a/OWNERS
+++ b/OWNERS
@@ -2,7 +2,6 @@ approvers:
 - AndrewSirenko
 - bertinatto
 - ConnorJC3
-- ElijahQuinones
 - gnufied
 - jsafrane
 - leakingtapan
@@ -16,5 +15,4 @@ emiritus_approvers:
 reviewers:
 - AndrewSirenko
 - ConnorJC3
-- ElijahQuinones
 - torredil
diff --git a/charts/aws-ebs-csi-driver/templates/poddisruptionbudget-controller.yaml b/charts/aws-ebs-csi-driver/templates/poddisruptionbudget-controller.yaml
index 8f1659db..979a18a1 100644
--- a/charts/aws-ebs-csi-driver/templates/poddisruptionbudget-controller.yaml
+++ b/charts/aws-ebs-csi-driver/templates/poddisruptionbudget-controller.yaml
@@ -11,9 +11,6 @@ spec:
     matchLabels:
       app: ebs-csi-controller
       {{- include "aws-ebs-csi-driver.selectorLabels" . | nindent 6 }}
-  {{- if .Values.controller.podDisruptionBudget.unhealthyPodEvictionPolicy }}
-  unhealthyPodEvictionPolicy: {{ .Values.controller.podDisruptionBudget.unhealthyPodEvictionPolicy }}
-  {{- end }}
   {{- if le (.Values.controller.replicaCount | int) 2 }}
   maxUnavailable: 1
   {{- else }}
diff --git a/charts/aws-ebs-csi-driver/values.yaml b/charts/aws-ebs-csi-driver/values.yaml
index 64740254..8a4e5c26 100644
--- a/charts/aws-ebs-csi-driver/values.yaml
+++ b/charts/aws-ebs-csi-driver/values.yaml
@@ -249,7 +249,6 @@ controller:
     # Warning: Disabling PodDisruptionBudget may lead to delays in stateful workloads starting due to controller
     # pod restarts or evictions.
     enabled: true
-    # unhealthyPodEvictionPolicy:
   priorityClassName: system-cluster-critical
   # AWS region to use. If not specified then the region will be looked up via the AWS EC2 metadata
   # service.
diff --git a/cmd/hooks/prestop.go b/cmd/hooks/prestop.go
index eee179b0..2f844248 100644
--- a/cmd/hooks/prestop.go
+++ b/cmd/hooks/prestop.go
@@ -27,7 +27,6 @@ import (
 	"k8s.io/client-go/kubernetes"
 	"k8s.io/client-go/tools/cache"
 	"k8s.io/klog/v2"
-	corev1beta1 "sigs.k8s.io/karpenter/pkg/apis/v1beta1"
 )
 
 /*
@@ -44,6 +43,16 @@ If the PreStop hook hangs during its execution, the driver node pod will be forc
 */
 
 const clusterAutoscalerTaint = "ToBeDeletedByClusterAutoscaler"
+const v1KarpenterTaint = "karpenter.sh/disrupted"
+const v1beta1KarpenterTaint = "karpenter.sh/disruption"
+
+// drainTaints includes taints used by K8s or autoscalers that signify node draining or pod eviction
+var drainTaints = map[string]struct{}{
+	v1.TaintNodeUnschedulable: {}, // Kubernetes common eviction taint (kubectl drain)
+	clusterAutoscalerTaint:    {},
+	v1KarpenterTaint:          {},
+	v1beta1KarpenterTaint:     {},
+}
 
 func PreStop(clientset kubernetes.Interface) error {
 	klog.InfoS("PreStop: executing PreStop lifecycle hook")
@@ -76,20 +85,10 @@ func fetchNode(clientset kubernetes.Interface, nodeName string) (*v1.Node, error
 	return node, nil
 }
 
+// isNodeBeingDrained returns true if node resource has a known drain/eviction taint.
 func isNodeBeingDrained(node *v1.Node) bool {
 	for _, taint := range node.Spec.Taints {
-		// Kubernetes common eviction taint (kubectl drain)
-		if taint.Key == v1.TaintNodeUnschedulable && taint.Effect == v1.TaintEffectNoSchedule {
-			return true
-		}
-
-		// Karpenter eviction taint
-		if corev1beta1.IsDisruptingTaint(taint) {
-			return true
-		}
-
-		// cluster-autoscaler eviction taint
-		if taint.Key == clusterAutoscalerTaint {
+		if _, isDrainTaint := drainTaints[taint.Key]; isDrainTaint {
 			return true
 		}
 	}
diff --git a/docs/example-iam-policy.json b/docs/example-iam-policy.json
index 0ab57904..a85b7b29 100644
--- a/docs/example-iam-policy.json
+++ b/docs/example-iam-policy.json
@@ -13,8 +13,7 @@
         "ec2:DescribeSnapshots",
         "ec2:DescribeTags",
         "ec2:DescribeVolumes",
-        "ec2:DescribeVolumesModifications",
-        "ec2:EnableFastSnapshotRestores"
+        "ec2:DescribeVolumesModifications"
       ],
       "Resource": "*"
     },
@@ -43,7 +42,7 @@
       "Action": [
         "ec2:CreateVolume"
       ],
-      "Resource": "arn:aws:ec2:*:*:volume/*",
+      "Resource": "*",
       "Condition": {
         "StringLike": {
           "aws:RequestTag/ebs.csi.aws.com/cluster": "true"
@@ -55,20 +54,13 @@
       "Action": [
         "ec2:CreateVolume"
       ],
-      "Resource": "arn:aws:ec2:*:*:volume/*",
+      "Resource": "*",
       "Condition": {
         "StringLike": {
           "aws:RequestTag/CSIVolumeName": "*"
         }
       }
     },
-    {
-      "Effect": "Allow",
-      "Action": [
-        "ec2:CreateVolume"
-      ],
-      "Resource": "arn:aws:ec2:*:*:snapshot/*"
-    },
     {
       "Effect": "Allow",
       "Action": [
diff --git a/docs/faq.md b/docs/faq.md
index 129ed087..88c6059f 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -1,23 +1,5 @@
 # Frequently Asked Questions
 
-## Volume Attachment Capacity Issues
-
-There's a known issue where a mismatch between the reported and actual attachment capacity on nodes can result in scheduling errors and stuck workloads. This commonly occurs when volume slots are consumed after the driver starts up, which results in `kube-scheduler` assigning stateful pods to nodes lacking the necessary capacity to support attachments. As a consequence, volumes can become stuck in the attaching state until a slot is freed up, leading to prolonged delays in pod startup.
-
-### What causes this misalignment?
-
-Today, CSI plugins report node attachment capacity only once, at startup, via the `NodeGetInfo` RPC. This static reporting fails to reflect any subsequent changes in capacity (which may occur when dynamically allocated ENIs or non-CSI devices consume attachment slots).
-
-### What steps can be taken to mitigate this issue?
-
-While a long-term fix is worked on (see [kubernetes/enhancements#4875](https://github.com/kubernetes/enhancements/pull/4875)), you can adopt one or more of the following solutions to mitigate this issue:
-
-1. **Use Dedicated EBS Instance Types**: Gen7 and later EC2 instance types have dedicated EBS volume limits and are not affected by dynamic ENI attachments taking up volume slots.
-2. **Enable VPC CNI's Prefix Delegation Feature**: This can reduce the number of ENIs needed in your cluster. See the [aws-eks-best-practices/networking docs](https://aws.github.io/aws-eks-best-practices/networking/prefix-mode/index_linux/) for recommendations and further instructions.
-3. **Use the `--volume-attach-limit` CLI Option**: Configure the driver with this option to explicitly specify the limit for volumes to be reported to Kubernetes. This is useful when you have a known safe limit.
-4. **Use the `--reserved-volume-attachments` CLI Option**: Configure the driver with this option to reserve a number of slots for non-CSI volumes. These reserved slots will be subtracted from the total slots reported to Kubernetes.
-5. **Use Multiple DaemonSets**: For clusters that need a mix of the above solutions across different groups of nodes, the Helm chart can construct multiple `DaemonSets` via the `additionalDaemonSets` parameter. See [Additional DaemonSets](additional-daemonsets.md) for more information.
-
 ## 6-Minute Delays in Attaching Volumes
 
 ### What causes 6-minute delays in attaching volumes?
diff --git a/docs/parameters.md b/docs/parameters.md
index b03afef2..a992ebfd 100644
--- a/docs/parameters.md
+++ b/docs/parameters.md
@@ -53,7 +53,7 @@ allowedTopologies:
 - matchLabelExpressions:
   - key: topology.kubernetes.io/zone
     values:
-    - us-east-1a
+    - us-east-1
 ```
 
 Additionally, statically provisioned volumes can be restricted to pods in the appropriate Availability Zone, see the [static provisioning example](../examples/kubernetes/static-provisioning/).
diff --git a/go.mod b/go.mod
index f23db819..d0b52e08 100644
--- a/go.mod
+++ b/go.mod
@@ -35,7 +35,6 @@ require (
 	k8s.io/mount-utils v0.31.0
 	k8s.io/pod-security-admission v0.31.0
 	k8s.io/utils v0.0.0-20240902221715-702e33fdd3c3
-	sigs.k8s.io/karpenter v1.0.1
 )
 
 require (
@@ -52,7 +51,6 @@ require (
 	github.com/aws/aws-sdk-go-v2/service/sso v1.22.7 // indirect
 	github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.7 // indirect
 	github.com/aws/aws-sdk-go-v2/service/sts v1.30.7 // indirect
-	github.com/awslabs/operatorpkg v0.0.0-20240911161415-53716ab6d860 // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/blang/semver/v4 v4.0.0 // indirect
 	github.com/cenkalti/backoff/v4 v4.3.0 // indirect
@@ -62,7 +60,6 @@ require (
 	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
 	github.com/distribution/reference v0.6.0 // indirect
 	github.com/emicklei/go-restful/v3 v3.12.1 // indirect
-	github.com/evanphx/json-patch/v5 v5.9.0 // indirect
 	github.com/felixge/httpsnoop v1.0.4 // indirect
 	github.com/fsnotify/fsnotify v1.7.0 // indirect
 	github.com/fxamacker/cbor/v2 v2.7.0 // indirect
@@ -91,7 +88,6 @@ require (
 	github.com/klauspost/compress v1.17.9 // indirect
 	github.com/kylelemons/godebug v1.1.0 // indirect
 	github.com/mailru/easyjson v0.7.7 // indirect
-	github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
 	github.com/moby/spdystream v0.5.0 // indirect
 	github.com/moby/sys/mountinfo v0.7.2 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
@@ -108,8 +104,6 @@ require (
 	github.com/prometheus/client_model v0.6.1 // indirect
 	github.com/prometheus/common v0.59.1 // indirect
 	github.com/prometheus/procfs v0.15.1 // indirect
-	github.com/robfig/cron/v3 v3.0.1 // indirect
-	github.com/samber/lo v1.47.0 // indirect
 	github.com/sirupsen/logrus v1.9.3 // indirect
 	github.com/spf13/cobra v1.8.1 // indirect
 	github.com/stoewer/go-strcase v1.3.0 // indirect
@@ -132,7 +126,6 @@ require (
 	golang.org/x/text v0.18.0 // indirect
 	golang.org/x/time v0.6.0 // indirect
 	golang.org/x/tools v0.25.0 // indirect
-	gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
 	google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect
 	google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
 	gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
@@ -149,9 +142,7 @@ require (
 	k8s.io/kube-openapi v0.0.0-20240903163716-9e1beecbcb38 // indirect
 	k8s.io/kubectl v0.31.0 // indirect
 	k8s.io/kubelet v0.31.0 // indirect
-	knative.dev/pkg v0.0.0-20240910170930-fdbc0b5adde7 // indirect
 	sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 // indirect
-	sigs.k8s.io/controller-runtime v0.19.0 // indirect
 	sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
 	sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
 	sigs.k8s.io/yaml v1.4.0 // indirect
diff --git a/go.sum b/go.sum
index dc43f749..43f57737 100644
--- a/go.sum
+++ b/go.sum
@@ -8,8 +8,6 @@ github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA
 github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
 github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
 github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
-github.com/Pallinder/go-randomdata v1.2.0 h1:DZ41wBchNRb/0GfsePLiSwb0PHZmT67XY00lCDlaYPg=
-github.com/Pallinder/go-randomdata v1.2.0/go.mod h1:yHmJgulpD2Nfrm0cR9tI/+oAgRqCQQixsA8HyRZfV9Y=
 github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
 github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
@@ -17,8 +15,6 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY
 github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
 github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
 github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
-github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0=
-github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
 github.com/aws/aws-sdk-go-v2 v1.30.5 h1:mWSRTwQAb0aLE17dSzztCVJWI9+cRMgqebndjwDyK0g=
 github.com/aws/aws-sdk-go-v2 v1.30.5/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0=
 github.com/aws/aws-sdk-go-v2/config v1.27.33 h1:Nof9o/MsmH4oa0s2q9a0k7tMz5x/Yj5k06lDODWz3BU=
@@ -47,8 +43,6 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.30.7 h1:NKTa1eqZYw8tiHSRGpP0VtTdub/8
 github.com/aws/aws-sdk-go-v2/service/sts v1.30.7/go.mod h1:NXi1dIAGteSaRLqYgarlhP/Ij0cFT+qmCwiJqWh/U5o=
 github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4=
 github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
-github.com/awslabs/operatorpkg v0.0.0-20240911161415-53716ab6d860 h1:BxeuQ/k+J7UOOMbBzUzSQuMpamvnFWCmO9yQixgzUoo=
-github.com/awslabs/operatorpkg v0.0.0-20240911161415-53716ab6d860/go.mod h1:WnRtbjt0U71m4PqDBLybOcY5KkbeGh9FIsJGohVFUo4=
 github.com/awslabs/volume-modifier-for-k8s v0.3.1 h1:KwtubVY3eu3QbCZy5QUz0Ei5kDg5MojyT4onHk58WZA=
 github.com/awslabs/volume-modifier-for-k8s v0.3.1/go.mod h1:QtQqOwJWwfUJRxm8sc/ivBlM9MvqgF+SCujecdROejk=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -95,10 +89,6 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
 github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
-github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls=
-github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
-github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg=
-github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
 github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
@@ -244,8 +234,6 @@ github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+
 github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
 github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
-github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
-github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
 github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
 github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU=
 github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
@@ -317,8 +305,6 @@ github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/
 github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
 github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
 github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
-github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
-github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
 github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
 github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -335,14 +321,10 @@ github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJ
 github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0=
 github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
 github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
-github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
-github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
 github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
 github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
 github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
-github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
 github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
 github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
 github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
@@ -459,8 +441,6 @@ golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
 golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
 golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
-golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -647,8 +627,6 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
-gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
-gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
@@ -754,16 +732,10 @@ k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt
 k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
 k8s.io/utils v0.0.0-20240902221715-702e33fdd3c3 h1:b2FmK8YH+QEwq/Sy2uAEhmqL5nPfGYbJOcaqjeYYZoA=
 k8s.io/utils v0.0.0-20240902221715-702e33fdd3c3/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
-knative.dev/pkg v0.0.0-20240910170930-fdbc0b5adde7 h1:ClGJ7Q7iQC9qxov1lNys7xC0MqDGaw/ysGEuyqdIwAM=
-knative.dev/pkg v0.0.0-20240910170930-fdbc0b5adde7/go.mod h1:fL50zroI/eGDwkkWTJsOpto46G8T/xmTjBzkwnh/S48=
 sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 h1:2770sDpzrjjsAtVhSeUFseziht227YAWYHLGNM8QPwY=
 sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
-sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q=
-sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4=
 sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
 sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
-sigs.k8s.io/karpenter v1.0.1 h1:IUx0DJ+NcdHyDnGhgbHtIlEzMIb38ElJOKmZ/oUpuqA=
-sigs.k8s.io/karpenter v1.0.1/go.mod h1:3NLmsnHHw8p4VutpjTOPUZyhE3qH6yGTs8O94Lsu8uw=
 sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
 sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
 sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=


Test patch:
diff --git a/cmd/hooks/prestop_test.go b/cmd/hooks/prestop_test.go
index d91a25b7..9b72ee1b 100644
--- a/cmd/hooks/prestop_test.go
+++ b/cmd/hooks/prestop_test.go
@@ -25,7 +25,6 @@ import (
 	v1 "k8s.io/api/core/v1"
 	storagev1 "k8s.io/api/storage/v1"
 	"k8s.io/apimachinery/pkg/watch"
-	corev1beta1 "sigs.k8s.io/karpenter/pkg/apis/v1beta1"
 )
 
 func TestPreStopHook(t *testing.T) {
@@ -73,29 +72,6 @@ func TestPreStopHook(t *testing.T) {
 				return nil
 			},
 		},
-		{
-			name:     "TestPreStopHook: node is not being drained, skipping VolumeAttachments check - missing TaintEffectNoSchedule",
-			nodeName: "test-node",
-			expErr:   nil,
-			mockFunc: func(nodeName string, mockClient *driver.MockKubernetesClient, mockCoreV1 *driver.MockCoreV1Interface, mockNode *driver.MockNodeInterface, mockStorageV1 *driver.MockVolumeAttachmentInterface, mockStorageV1Interface *driver.MockStorageV1Interface) error {
-				mockNodeObj := &v1.Node{
-					Spec: v1.NodeSpec{
-						Taints: []v1.Taint{
-							{
-								Key:    v1.TaintNodeUnschedulable,
-								Effect: "",
-							},
-						},
-					},
-				}
-
-				mockClient.EXPECT().CoreV1().Return(mockCoreV1).Times(1)
-				mockCoreV1.EXPECT().Nodes().Return(mockNode).Times(1)
-				mockNode.EXPECT().Get(gomock.Any(), gomock.Eq(nodeName), gomock.Any()).Return(mockNodeObj, nil).Times(1)
-
-				return nil
-			},
-		},
 		{
 			name:     "TestPreStopHook: node is being drained, no volume attachments remain",
 			nodeName: "test-node",
@@ -225,29 +201,6 @@ func TestPreStopHook(t *testing.T) {
 				return nil
 			},
 		},
-		{
-			name:     "TestPreStopHook: Karpenter node is not being drained, skipping VolumeAttachments check - missing TaintEffectNoSchedule",
-			nodeName: "test-karpenter-node",
-			expErr:   nil,
-			mockFunc: func(nodeName string, mockClient *driver.MockKubernetesClient, mockCoreV1 *driver.MockCoreV1Interface, mockNode *driver.MockNodeInterface, mockStorageV1 *driver.MockVolumeAttachmentInterface, mockStorageV1Interface *driver.MockStorageV1Interface) error {
-				mockNodeObj := &v1.Node{
-					Spec: v1.NodeSpec{
-						Taints: []v1.Taint{
-							{
-								Key:    corev1beta1.DisruptionNoScheduleTaint.Key,
-								Effect: "",
-							},
-						},
-					},
-				}
-
-				mockClient.EXPECT().CoreV1().Return(mockCoreV1).Times(1)
-				mockCoreV1.EXPECT().Nodes().Return(mockNode).Times(1)
-				mockNode.EXPECT().Get(gomock.Any(), gomock.Eq(nodeName), gomock.Any()).Return(mockNodeObj, nil).Times(1)
-
-				return nil
-			},
-		},
 		{
 			name:     "TestPreStopHook: Karpenter node is being drained, no volume attachments remain",
 			nodeName: "test-karpenter-node",
@@ -258,7 +211,7 @@ func TestPreStopHook(t *testing.T) {
 					Spec: v1.NodeSpec{
 						Taints: []v1.Taint{
 							{
-								Key:    corev1beta1.DisruptionNoScheduleTaint.Key,
+								Key:    v1beta1KarpenterTaint,
 								Effect: v1.TaintEffectNoSchedule,
 							},
 						},
@@ -290,7 +243,7 @@ func TestPreStopHook(t *testing.T) {
 					Spec: v1.NodeSpec{
 						Taints: []v1.Taint{
 							{
-								Key:    corev1beta1.DisruptionNoScheduleTaint.Key,
+								Key:    v1beta1KarpenterTaint,
 								Effect: v1.TaintEffectNoSchedule,
 							},
 						},
@@ -330,7 +283,7 @@ func TestPreStopHook(t *testing.T) {
 					Spec: v1.NodeSpec{
 						Taints: []v1.Taint{
 							{
-								Key:    corev1beta1.DisruptionNoScheduleTaint.Key,
+								Key:    v1beta1KarpenterTaint,
 								Effect: v1.TaintEffectNoSchedule,
 							},
 						},
@@ -412,3 +365,45 @@ func TestPreStopHook(t *testing.T) {
 		})
 	}
 }
+
+func TestIsNodeBeingDrained(t *testing.T) {
+	testCases := []struct {
+		name         string
+		nodeTaintKey string
+		want         bool
+	}{
+		{"Should recognize common eviction taint", v1.TaintNodeUnschedulable, true},
+		{"Should recognize cluster autoscaler taint", clusterAutoscalerTaint, true},
+		{"Should recognize Karpenter v1beta1 taint", v1beta1KarpenterTaint, true},
+		{"Should recognize Karpenter v1 taint", v1KarpenterTaint, true},
+		{"Should not block on generic taint", "ebs/fake-taint", false},
+		{"Should not block on no taint", "", false},
+	}
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			var taints []v1.Taint
+
+			if tc.nodeTaintKey != "" {
+				taint := v1.Taint{
+					Key:    tc.nodeTaintKey,
+					Value:  "",
+					Effect: v1.TaintEffectNoSchedule,
+				}
+
+				taints = append(taints, taint)
+			}
+
+			testNode := &v1.Node{
+				Spec: v1.NodeSpec{
+					Taints: taints,
+				},
+			}
+
+			got := isNodeBeingDrained(testNode)
+
+			if tc.want != got {
+				t.Fatalf("isNodeBeingDrained returned wrong answer when node contained taint with key: %s; got: %t, want: %t", tc.nodeTaintKey, got, tc.want)
+			}
+		})
+	}
+}
diff --git a/hack/e2e/kops/patch-cluster.yaml b/hack/e2e/kops/patch-cluster.yaml
index e3c0db21..d441869e 100644
--- a/hack/e2e/kops/patch-cluster.yaml
+++ b/hack/e2e/kops/patch-cluster.yaml
@@ -66,7 +66,7 @@ spec:
           "Action": [
             "ec2:CreateVolume"
           ],
-          "Resource": "arn:aws:ec2:*:*:volume/*",
+          "Resource": "*",
           "Condition": {
             "StringLike": {
               "aws:RequestTag/ebs.csi.aws.com/cluster": "true"
@@ -78,7 +78,7 @@ spec:
           "Action": [
             "ec2:CreateVolume"
           ],
-          "Resource": "arn:aws:ec2:*:*:volume/*",
+          "Resource": "*",
           "Condition": {
             "StringLike": {
               "aws:RequestTag/CSIVolumeName": "*"
@@ -90,7 +90,12 @@ spec:
           "Action": [
             "ec2:CreateVolume"
           ],
-          "Resource": "arn:aws:ec2:*:*:snapshot/*"
+          "Resource": "*",
+          "Condition": {
+            "StringLike": {
+              "aws:RequestTag/kubernetes.io/cluster/*": "owned"
+            }
+          }
         },
         {
           "Effect": "Allow",
@@ -124,7 +129,7 @@ spec:
           "Resource": "*",
           "Condition": {
             "StringLike": {
-              "ec2:ResourceTag/kubernetes.io/created-for/pvc/name": "*"
+              "ec2:ResourceTag/kubernetes.io/cluster/*": "owned"
             }
           }
         },