Files
642f7381b1 feat: add per-application driver PodDisruptionBudget (#2949) (#2954)
* feat: optional PodDisruptionBudget for Spark drivers (#2949)

Refs: https://github.com/kubeflow/spark-operator/issues/2949

Add an opt-in PodDisruptionBudget for the driver pod so a voluntary
eviction (e.g. `kubectl drain`) cannot kill the driver mid-job. The
apiserver's eviction admission handler consults a matching PDB; without
one the eviction is admitted and the operator only learns of it after
the fact via its watch. A PDB is the only lever the operator has here
that does not put it on the eviction hot path.

Gated twice, off by default so upgrades are no-op:
  --enable-driver-pdb              controller flag (default false)
  spec.driverPodDisruptionBudget   per-app *bool (nil/false = no PDB)

A bare *bool suffices: the driver is a singleton, so MinAvailable is
fixed at 1 and a selector struct has nothing to grow into.

Lifecycle (driver_pdb.go):
  - ensureDriverPDB converges PDB existence to spec on every
    Submitted/Running reconcile, so it recovers from operator restart
    with the gate flipped on, live spec edits, and transient API
    failures (retry.RetryOnConflict + controller-runtime backoff).
  - createDriverPDB/deleteDriverPDB read the cache first for
    idempotency; AlreadyExists/NotFound are treated as success.
  - The PDB carries a controller OwnerReference plus
    LabelLaunchedBySparkOperator + LabelSparkAppName, so kube GC reaps
    it on app deletion and the cache informer can filter to owned PDBs.
  - cleanUpOnTermination deletes the PDB on Completed/Failed; the
    terminal-app reconcile re-runs it to reap PDBs orphaned when the
    controller itself was drained mid-transition.
  - deleteSparkResources drops the PDB before the driver pod so an
    in-flight external drain does not block on a stale PDB.

RBAC: the PDB entry in cache.Options.ByObject starts an informer, which
needs list+watch even though the code only Get/Create/Deletes. Granted
get;list;watch;create;delete on poddisruptionbudgets via the kubebuilder
marker (regenerated config/rbac/role.yaml), the Helm chart helper, and
the chart rbac unit test. Missing verbs would loop the informer on
Forbidden and saturate the shared client rate limiter.

Helm: controller.driverPodDisruptionBudget.enable (default false) emits
--enable-driver-pdb=true; ci-values.yaml turns it on for e2e.

Tests: envtest specs cover the gate matrix and the convergence cases
ensureDriverPDB owns (restart-with-gate-on, spec false->true and
true->false on a running app, transient Create failure retried via an
interceptor.Funcs client). E2e submits real apps with the field set and
omitted and asserts PDB creation, GC on deletion, and absence when not
opted in.

Makefile: kind-load-spark-image preloads the Spark runtime image and
e2e-test pins IMAGE_TAG=local with the load targets as prerequisites, so
`make deploy` and `make e2e-test` are self-contained on a local Kind
cluster instead of hitting ImagePullBackOff.

Signed-off-by: Vincent Janelle <[email protected]>

* test: use events.FakeRecorder in driver PDB test

NewReconciler takes an events.EventRecorder, not the legacy
record.EventRecorder. Align driver_pdb_test.go with controller_test.go.

Signed-off-by: Vincent Janelle <[email protected]>

* allow for kustomize to patch pdb value; default to true in ci
Signed-off-by: Vincent Janelle <[email protected]>

---------

Signed-off-by: Vincent Janelle <[email protected]>

Co-authored-by: Hanzo Dev <[email protected]>
2026-06-30 20:28:48 +00:00

22 KiB
Raw Permalink Blame History

spark-operator

Version: 2.5.0-rc.0 AppVersion: 2.5.0-rc.0

A Helm chart for Spark on Kubernetes operator.

Homepage: https://github.com/kubeflow/spark-operator

Introduction

This chart bootstraps a Kubernetes Operator for Apache Spark deployment using the Helm package manager.

Prerequisites

  • Helm >= 3
  • Kubernetes >= 1.16

Previous Helm Chart

The previous spark-operator Helm chart hosted at helm/charts has been moved to this repository in accordance with the Deprecation timeline. Note that a few things have changed between this version and the old version:

  • This repository only supports Helm chart installations using Helm 3+ since the apiVersion on the chart has been marked as v2.
  • Previous versions of the Helm chart have not been migrated, and the version has been set to 1.0.0 at the onset. If you are looking for old versions of the chart, it's best to run helm pull incubator/sparkoperator --version <your-version> until you are ready to move to this repository's version.
  • Several configuration properties have been changed, carefully review the values section below to make sure you're aligned with the new values.

Usage

Add Helm Repo

helm repo add spark-operator https://kubeflow.github.io/spark-operator

helm repo update

See helm repo for command documentation.

Install the chart

helm install [RELEASE_NAME] spark-operator/spark-operator

For example, if you want to create a release with name spark-operator in the spark-operator namespace:

helm install spark-operator spark-operator/spark-operator \
    --namespace spark-operator \
    --create-namespace

Note that by passing the --create-namespace flag to the helm install command, helm will create the release namespace if it does not exist.

See helm install for command documentation.

Upgrade the chart

helm upgrade [RELEASE_NAME] spark-operator/spark-operator [flags]

See helm upgrade for command documentation.

Uninstall the chart

helm uninstall [RELEASE_NAME]

This removes all the Kubernetes resources associated with the chart and deletes the release, except for the crds, those will have to be removed manually.

See helm uninstall for command documentation.

Values

Key Type Default Description
nameOverride string "" String to partially override release name.
fullnameOverride string "" String to fully override release name.
commonLabels object {} Common labels to add to the resources.
image.registry string "ghcr.io" Image registry.
image.repository string "kubeflow/spark-operator/controller" Image repository.
image.tag string If not set, the chart appVersion will be used. Image tag.
image.pullPolicy string "IfNotPresent" Image pull policy.
image.pullSecrets list [] Image pull secrets for private image registry.
hook.upgradeCrd bool false Whether to create a Helm pre-install/pre-upgrade hook Job to update CRDs.
hook.image.registry string "ghcr.io" Image registry.
hook.image.repository string "kubeflow/spark-operator/kubectl" Image repository.
hook.image.tag string If not set, the chart appVersion will be used. Image tag.
hook.resources object {"limits":{"cpu":"100m","memory":"64Mi"},"requests":{"cpu":"100m","memory":"64Mi"}} Pod resource requests and limits for the Helm hook Job container.
hook.nodeSelector object {} Node selector for the Helm hook Job.
hook.affinity object {} Affinity for the Helm hook Job.
hook.tolerations list [] List of node taints to tolerate for the Helm hook Job.
hook.labels object {} Extra labels for the Helm hook Job pod.
hook.annotations object {} Extra annotations for the Helm hook Job pod.
controller.replicas int 1 Number of replicas of controller.
controller.featureGates list [{"enabled":false,"name":"PartialRestart"},{"enabled":false,"name":"LoadSparkDefaults"},{"enabled":false,"name":"RestSubmitter"}] Feature gates to enable or disable specific features.
controller.revisionHistoryLimit int 10 The number of old history to retain to allow rollback.
controller.leaderElection.enable bool true Specifies whether to enable leader election for controller.
controller.leaderElection.leaseDuration string "15s" Leader election lease duration.
controller.leaderElection.renewDeadline string "10s" Leader election renew deadline.
controller.leaderElection.retryPeriod string "2s" Leader election retry period.
controller.workers int 10 Reconcile concurrency, higher values might increase memory usage.
controller.logLevel string "info" Configure the verbosity of logging, can be one of debug, info, error.
controller.logEncoder string "console" Configure the encoder of logging, can be one of console or json.
controller.driverPodCreationGracePeriod string "10s" Grace period after a successful spark-submit when driver pod not found errors will be retried. Useful if the driver pod can take some time to be created.
controller.maxTrackedExecutorPerApp int 1000 Specifies the maximum number of Executor pods that can be tracked by the controller per SparkApplication.
controller.driverPodDisruptionBudget object {"enable":false} Driver PDB feature gate. When true, the controller creates a PodDisruptionBudget for each SparkApplication that sets spec.driverPodDisruptionBudget=true. Default false.
controller.kubeAPIQPS int 20 Maximum QPS to the API server from the controller client.
controller.kubeAPIBurst int 30 Maximum burst for throttle from the controller client.
controller.scheduledSparkApplicationTimestampPrecision string "nanos" Timestamp precision for ScheduledSparkApplication run names. Valid values: nanos (default), micros, millis, seconds, minutes. Shorter precisions produce shorter names which helps with Kubernetes name length limits. NOTE: Using lower precisions such as "seconds" or "minutes" increases the risk of name collisions if multiple runs are created within the same time unit (for example during reconciliation loops or manual re-triggers). A collision will cause run creation to fail. Choose a precision compatible with your scheduling frequency: "minutes" is only suitable for jobs scheduled at most once per minute, "seconds" for jobs scheduled at most once per second.
controller.uiService.enable bool true Specifies whether to create service for Spark web UI.
controller.uiIngress.enable bool false Specifies whether to create ingress for Spark web UI. controller.uiService.enable must be true to enable ingress.
controller.uiIngress.urlFormat string "" Ingress URL format. Required if controller.uiIngress.enable is true.
controller.uiIngress.ingressClassName string "" Optionally set the ingressClassName.
controller.uiIngress.tls list [] Optionally set default TLS configuration for the Spark UI's ingress. ingressTLS in the SparkApplication spec overrides this.
controller.uiIngress.annotations object {} Optionally set default ingress annotations for the Spark UI's ingress. ingressAnnotations in the SparkApplication spec overrides this.
controller.batchScheduler.enable bool false Specifies whether to enable batch scheduler for spark jobs scheduling. If enabled, users can specify batch scheduler name in spark application.
controller.batchScheduler.kubeSchedulerNames list [] Specifies a list of kube-scheduler names for scheduling Spark pods.
controller.batchScheduler.default string "" Default batch scheduler to be used if not specified by the user. If specified, this value must be either "volcano" or "yunikorn". Specifying any other value will cause the controller to error on startup.
controller.serviceAccount.create bool true Specifies whether to create a service account for the controller.
controller.serviceAccount.name string "" Optional name for the controller service account.
controller.serviceAccount.annotations object {} Extra annotations for the controller service account.
controller.serviceAccount.automountServiceAccountToken bool true Auto-mount service account token to the controller pods.
controller.rbac.create bool true Specifies whether to create RBAC resources for the controller.
controller.rbac.annotations object {} Extra annotations for the controller RBAC resources.
controller.labels object {} Extra labels for controller pods.
controller.annotations object {} Extra annotations for controller pods.
controller.deploymentAnnotations object {} Annotations for the controller Deployment resource (metadata.annotations).
controller.volumes list [{"emptyDir":{"sizeLimit":"1Gi"},"name":"tmp"}] Volumes for controller pods.
controller.nodeSelector object {} Node selector for controller pods.
controller.affinity object {} Affinity for controller pods.
controller.tolerations list [] List of node taints to tolerate for controller pods.
controller.priorityClassName string "" Priority class for controller pods.
controller.podSecurityContext object {"fsGroup":185} Security context for controller pods.
controller.topologySpreadConstraints list [] Topology spread constraints rely on node labels to identify the topology domain(s) that each Node is in. Ref: Pod Topology Spread Constraints. The labelSelector field in topology spread constraint will be set to the selector labels for controller pods if not specified.
controller.hostUsers string nil Whether to use user namespace or not Kubernetes version 1.30 for feature beta (1.33 for GA) or higher is required with support from OS and OCI runtime ref: https://kubernetes.io/docs/concepts/workloads/pods/user-namespaces/
controller.env list [] Environment variables for controller containers.
controller.envFrom list [] Environment variable sources for controller containers.
controller.volumeMounts list [{"mountPath":"/tmp","name":"tmp","readOnly":false}] Volume mounts for controller containers.
controller.resources object {} Pod resource requests and limits for controller containers. Note, that each job submission will spawn a JVM within the controller pods using "/usr/local/openjdk-11/bin/java -Xmx128m". Kubernetes may kill these Java processes at will to enforce resource limits. When that happens, you will see the following error: 'failed to run spark-submit for SparkApplication [...]: signal: killed' - when this happens, you may want to increase memory limits.
controller.securityContext object {"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}} Security context for controller containers.
controller.sidecars list [] Sidecar containers for controller pods.
controller.podDisruptionBudget.enable bool false Specifies whether to create pod disruption budget for controller. Ref: Specifying a Disruption Budget for your Application
controller.podDisruptionBudget.minAvailable int 1 The number of pods that must be available. Require controller.replicas to be greater than 1
controller.pprof.enable bool false Specifies whether to enable pprof.
controller.pprof.port int 6060 Specifies pprof port.
controller.pprof.portName string "pprof" Specifies pprof service port name.
controller.workqueueRateLimiter.bucketQPS int 50 Specifies the average rate of items process by the workqueue rate limiter.
controller.workqueueRateLimiter.bucketSize int 500 Specifies the maximum number of items that can be in the workqueue at any given time.
controller.workqueueRateLimiter.maxDelay.enable bool true Specifies whether to enable max delay for the workqueue rate limiter. This is useful to avoid losing events when the workqueue is full.
controller.workqueueRateLimiter.maxDelay.duration string "6h" Specifies the maximum delay duration for the workqueue rate limiter.
submitter.serviceUrl string "http://spark-operator-submitter-svc:8080/api/v1/spark-submit" URL of the REST submitter service endpoint.
submitter.requestTimeout string "2m" HTTP request timeout per spark submission attempt.
submitter.startupTimeout string "5m" How long the controller waits for the submitter service to become reachable at startup.
submitter.maxRetries int 3 Max retry attempts for transient submission failures.
submitter.initialBackoff string "2s" Initial backoff duration before the first retry. Doubles on each subsequent attempt.
submitter.startupProbe.periodSeconds int 5 Seconds between probe attempts.
submitter.startupProbe.failureThreshold int 60 Number of failures before restart. (failureThreshold × periodSeconds) should >= startupTimeout.
webhook.enable bool true Specifies whether to enable webhook.
webhook.replicas int 1 Number of replicas of webhook server.
webhook.revisionHistoryLimit int 10 The number of old history to retain to allow rollback.
webhook.leaderElection.enable bool true Specifies whether to enable leader election for webhook.
webhook.logLevel string "info" Configure the verbosity of logging, can be one of debug, info, error.
webhook.logEncoder string "console" Configure the encoder of logging, can be one of console or json.
webhook.port int 9443 Specifies webhook port.
webhook.portName string "webhook" Specifies webhook service port name.
webhook.failurePolicy string "Fail" Specifies how unrecognized errors are handled. Available options are Ignore or Fail.
webhook.timeoutSeconds int 10 Specifies the timeout seconds of the webhook, the value must be between 1 and 30.
webhook.kubeAPIQPS int 20 Maximum QPS to the API server from the controller client.
webhook.kubeAPIBurst int 30 Maximum burst for throttle from the controller client.
webhook.resourceQuotaEnforcement.enable bool false Specifies whether to enable the ResourceQuota enforcement for SparkApplication resources.
webhook.serviceAccount.create bool true Specifies whether to create a service account for the webhook.
webhook.serviceAccount.name string "" Optional name for the webhook service account.
webhook.serviceAccount.annotations object {} Extra annotations for the webhook service account.
webhook.serviceAccount.automountServiceAccountToken bool true Auto-mount service account token to the webhook pods.
webhook.rbac.create bool true Specifies whether to create RBAC resources for the webhook.
webhook.rbac.annotations object {} Extra annotations for the webhook RBAC resources.
webhook.labels object {} Extra labels for webhook pods.
webhook.annotations object {} Extra annotations for webhook pods.
webhook.deploymentAnnotations object {} Annotations for the webhook Deployment resource (metadata.annotations).
webhook.sidecars list [] Sidecar containers for webhook pods.
webhook.volumes list [{"emptyDir":{"sizeLimit":"500Mi"},"name":"serving-certs"}] Volumes for webhook pods.
webhook.nodeSelector object {} Node selector for webhook pods.
webhook.affinity object {} Affinity for webhook pods.
webhook.tolerations list [] List of node taints to tolerate for webhook pods.
webhook.priorityClassName string "" Priority class for webhook pods.
webhook.podSecurityContext object {"fsGroup":185} Security context for webhook pods.
webhook.topologySpreadConstraints list [] Topology spread constraints rely on node labels to identify the topology domain(s) that each Node is in. Ref: Pod Topology Spread Constraints. The labelSelector field in topology spread constraint will be set to the selector labels for webhook pods if not specified.
webhook.hostUsers string nil Whether to use user namespace or not Kubernetes version 1.30 for feature beta (1.33 for GA) or higher is required with support from OS and OCI runtime ref: https://kubernetes.io/docs/concepts/workloads/pods/user-namespaces/
webhook.env list [] Environment variables for webhook containers.
webhook.envFrom list [] Environment variable sources for webhook containers.
webhook.volumeMounts list [{"mountPath":"/etc/k8s-webhook-server/serving-certs","name":"serving-certs","readOnly":false,"subPath":"serving-certs"}] Volume mounts for webhook containers.
webhook.resources object {} Pod resource requests and limits for webhook pods.
webhook.securityContext object {"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}} Security context for webhook containers.
webhook.podDisruptionBudget.enable bool false Specifies whether to create pod disruption budget for webhook. Ref: Specifying a Disruption Budget for your Application
webhook.podDisruptionBudget.minAvailable int 1 The number of pods that must be available. Require webhook.replicas to be greater than 1
spark.jobNamespaces list ["default"] List of namespaces where to run spark jobs. If empty string is included, all namespaces will be allowed. Namespaces specified here will be watched in addition to those matching jobNamespaceSelector. Make sure the namespaces have already existed.
spark.jobNamespaceSelector string "" Label selector to filter namespaces to watch. Supports standard Kubernetes label selector syntax (e.g., 'spark-operator=enabled,env in (prod,staging)'). Namespaces matching this selector will be watched in addition to those in jobNamespaces. When specified, requires ClusterRole permission to list and watch namespaces. Leave empty to disable namespace selector functionality.
spark.serviceAccount.create bool true Specifies whether to create a service account for spark applications.
spark.serviceAccount.name string "" Optional name for the spark service account.
spark.serviceAccount.annotations object {} Optional annotations for the spark service account.
spark.serviceAccount.automountServiceAccountToken bool true Auto-mount service account token to the spark applications pods.
spark.rbac.create bool true Specifies whether to create RBAC resources for spark applications.
spark.rbac.annotations object {} Optional annotations for the spark application RBAC resources.
prometheus.metrics.enable bool true Specifies whether to enable prometheus metrics scraping.
prometheus.metrics.port int 8080 Metrics port.
prometheus.metrics.portName string "metrics" Metrics port name.
prometheus.metrics.endpoint string "/metrics" Metrics serving endpoint.
prometheus.metrics.prefix string "" Metrics prefix, will be added to all exported metrics.
prometheus.metrics.jobSubmitLatencyBuckets string "0.5,1,2,4,8,16,32,64,128,256" Job Submit Latency histogram buckets. Specified in seconds.
prometheus.metrics.jobStartLatencyBuckets string "30,60,90,120,150,180,210,240,270,300" Job Start Latency histogram buckets. Specified in seconds.
prometheus.metrics.labels string "" Labels to be added to the Spark Operator standard metrics, e.g., "label1Key,label2Key". Defaults to 'app_type' if not set.
prometheus.podMonitor.create bool false Specifies whether to create pod monitor. Note that prometheus metrics should be enabled as well.
prometheus.podMonitor.labels object {} Pod monitor labels
prometheus.podMonitor.jobLabel string "spark-operator-podmonitor" The label to use to retrieve the job name from
prometheus.podMonitor.podMetricsEndpoint object {"interval":"5s","scheme":"http"} Prometheus metrics endpoint properties. metrics.portName will be used as a port
certManager.enable bool false Specifies whether to use cert-manager to generate certificate for webhook. webhook.enable must be set to true to enable cert-manager.
certManager.issuerRef object A self-signed issuer will be created and used if not specified. The reference to the issuer.
certManager.duration string 2160h (90 days) will be used if not specified. The duration of the certificate validity (e.g. 2160h). See cert-manager.io/v1.Certificate.
certManager.renewBefore string 1/3 of issued certificate’s lifetime. The duration before the certificate expiration to renew the certificate (e.g. 720h). See cert-manager.io/v1.Certificate.

Maintainers

Name Email Url
yuchaoran2011 [email protected] https://github.com/yuchaoran2011
ChenYi015 [email protected] https://github.com/ChenYi015