This is an automated email from the ASF dual-hosted git repository.

dongjoon-hyun pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/spark-kubernetes-operator.git


The following commit(s) were added to refs/heads/main by this push:
     new 6d079691 [SPARK-59964] Fix workload RBAC to grant `deletecollection` 
to Spark drivers
6d079691 is described below

commit 6d0796914b3014e7c12ef638cddc351ab3b68fd2
Author: Dongjoon Hyun <[email protected]>
AuthorDate: Mon Oct 5 08:16:32 2026 -0700

    [SPARK-59964] Fix workload RBAC to grant `deletecollection` to Spark drivers
    
    ### What changes were proposed in this pull request?
    
    This PR aims to grant `deletecollection` on `pods`, `services`, 
`configmaps` and `persistentvolumeclaims` to the Spark workload ClusterRole and 
Roles of the Helm chart, with Helm test assertions and a migration guide item.
    
    ### Why are the changes needed?
    
    SPARK-57942 replaced the wildcard RBAC verbs with an explicit verb list 
without `deletecollection` in 
[1.0.0](https://github.com/apache/spark-kubernetes-operator/releases/tag/1.0.0) 
(2026-07-23). However, Spark drivers delete the resources of their application 
by label selector, which K8s RBAC authorizes as `deletecollection`. So every 
driver logs errors like the following when it stops, and leaves the resources 
until the driver pod is deleted.
    
    ```
    io.fabric8.kubernetes.client.KubernetesClientException: Failure executing: 
DELETE at: 
https://kubernetes.default.svc/api/v1/namespaces/default/services?labelSelector=spark-app-selector%3Dpi-before-0.
 Message: services is forbidden: User "system:serviceaccount:default:spark" 
cannot deletecollection resource "services" in API group "" in the namespace 
"default". ...
    ```
    
    ### Does this PR introduce _any_ user-facing change?
    
    Yes. This fixes a regression of 1.0.0.
    
    ### How was this patch tested?
    
    Pass the CIs with the new Helm test assertions. I also verified manually on 
Minikube with the operator `1.0.0` and Spark `4.2.0` that the driver logs no 
error and deletes its resources when it stops.
    
    ### Was this patch authored or co-authored using generative AI tooling?
    
    Generated-by: Claude Opus 5.5
    
    This patch had conflicts when merged, resolved by
    Committer: Dongjoon Hyun <[email protected]>
    
    Closes #931 from dongjoon-hyun/SPARK-59964.
    
    Authored-by: Dongjoon Hyun <[email protected]>
    Signed-off-by: Dongjoon Hyun <[email protected]>
---
 .../spark-kubernetes-operator/templates/tests/test-rbac.yaml   |  4 ++++
 .../spark-kubernetes-operator/templates/workload-rbac.yaml     |  1 +
 docs/migration_guide.md                                        | 10 ++++++++++
 3 files changed, 15 insertions(+)

diff --git 
a/build-tools/helm/spark-kubernetes-operator/templates/tests/test-rbac.yaml 
b/build-tools/helm/spark-kubernetes-operator/templates/tests/test-rbac.yaml
index deefe934..74ff44ab 100644
--- a/build-tools/helm/spark-kubernetes-operator/templates/tests/test-rbac.yaml
+++ b/build-tools/helm/spark-kubernetes-operator/templates/tests/test-rbac.yaml
@@ -145,6 +145,10 @@ spec:
           kubectl auth can-i update statefulsets.apps --subresource=scale 
--namespace={{ .Release.Namespace }}
           kubectl auth can-i get    deployments.apps --subresource=scale 
--namespace={{ .Release.Namespace }}
           kubectl auth can-i update deployments.apps --subresource=scale 
--namespace={{ .Release.Namespace }}
+          kubectl auth can-i deletecollection pods --namespace={{ 
.Release.Namespace }}
+          kubectl auth can-i deletecollection services --namespace={{ 
.Release.Namespace }}
+          kubectl auth can-i deletecollection configmaps --namespace={{ 
.Release.Namespace }}
+          kubectl auth can-i deletecollection persistentvolumeclaims 
--namespace={{ .Release.Namespace }}
 
           # Spark workloads must not reach beyond their own namespace. `set -e`
           # ignores a failing `!` pipeline, so assert each denial explicitly.
diff --git 
a/build-tools/helm/spark-kubernetes-operator/templates/workload-rbac.yaml 
b/build-tools/helm/spark-kubernetes-operator/templates/workload-rbac.yaml
index 213a506e..5de37a91 100644
--- a/build-tools/helm/spark-kubernetes-operator/templates/workload-rbac.yaml
+++ b/build-tools/helm/spark-kubernetes-operator/templates/workload-rbac.yaml
@@ -33,6 +33,7 @@ rules:
       - update
       - patch
       - delete
+      - deletecollection
   - apiGroups:
       - "apps"
     resources:
diff --git a/docs/migration_guide.md b/docs/migration_guide.md
index 2b19793c..7370961a 100644
--- a/docs/migration_guide.md
+++ b/docs/migration_guide.md
@@ -73,6 +73,16 @@ affect building the project, CI, tests or examples.
   failed to start, since creating the Deployment or scaling the StatefulSet 
was forbidden. To keep
   the rules of 1.0, set `workloadResources.clusterRole.create` and 
`workloadResources.role.create`
   to `false`, and grant them with your own Role or ClusterRole.
+- Since 1.1.0, the workload ClusterRole and Roles grant `deletecollection` on 
`pods`, `services`,
+  `configmaps` and `persistentvolumeclaims`, which Spark drivers need to 
delete the resources of
+  their application by label selector. 1.0 did not grant it, so drivers logged 
errors like
+  `cannot deletecollection resource "services"` when they stopped, and left 
the driver service,
+  the on-demand PVCs and the executor pods and configmaps until the driver pod 
was deleted, e.g.
+  as long as `resourceRetainPolicy` retained it. With dynamic allocation, they 
could not delete
+  unneeded pending executor pods either. If you manage the workload Role or 
ClusterRole yourself,
+  add `deletecollection` to it as well. To keep the driver service and the 
executor pods and
+  configmaps, set `spark.kubernetes.driver.service.deleteOnTermination` and
+  `spark.kubernetes.executor.deleteOnTermination` to `false`.
 - Since 1.1.0, each option of 
`operatorDeployment.operatorPod.operatorContainer.jvmArgs` is passed
   to the operator JVM as its own argument. 1.0 passed the whole value as one 
argument, which the
   JVM took as a single `-Dfile.encoding` system property, so the other options 
had no effect. The


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to