Skip to content

Commit a93e949

Browse files
committed
Claude done the thing
1 parent 85e3b24 commit a93e949

25 files changed

Lines changed: 7032 additions & 2782 deletions

File tree

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file.
77
### Added
88

99
- BREAKING: Add required CLI argument and env var to set the image repository used to construct final product image names: `IMAGE_REPOSITORY` (`--image-repository`), eg. `oci.example.org/my/namespace` ([#684]).
10+
- Add CRD version `v1alpha2` for `SparkApplication` and `SparkApplicationTemplate`. The conversion webhook converts `v1alpha1` objects to `v1alpha2` ([#711]).
1011

1112
### Fixed
1213

@@ -15,6 +16,8 @@ All notable changes to this project will be documented in this file.
1516

1617
### Changed
1718

19+
- BREAKING: The operator no longer runs a separate `spark-submit` process for `SparkApplication`s. The driver is launched directly as a Kubernetes `Job` (built from `spec.driver`) running `spark-submit` in client mode; executors are still created by the driver via Spark's Kubernetes backend. A headless driver `Service` is created so executors can reach the driver. This affects both `v1alpha1` (after conversion) and `v1alpha2` objects ([#711]).
20+
- The driver `Job` is no longer retried on failure (`backoffLimit` is `0`); the previous `spec.job.retryOnFailureCount` is deprecated and ignored ([#711]).
1821
- Document Helm deployed RBAC permissions and remove unnecessary permissions ([#674]).
1922
- BREAKING: Each custom resource accepts now only the known config files in `configOverrides`:
2023
- `SparkApplication`: `spark-env.sh` and `security.properties`
@@ -27,6 +30,11 @@ All notable changes to this project will be documented in this file.
2730
- Fix the `SparkApplication` CRD description, which incorrectly described it as a "Spark cluster stacklet" rather than a Spark application ([#705]).
2831
- BREAKING: make application templates namespaced instead of cluster wide objects ([#694]).
2932

33+
### Deprecated
34+
35+
- `SparkApplication`/`SparkApplicationTemplate` `spec.job` is deprecated and ignored since `v1alpha2` (renamed to `deprecatedJob` in that version). The driver `Job` is now built from `spec.driver` ([#711]).
36+
- `SparkApplication`/`SparkApplicationTemplate` `spec.mode` is deprecated and ignored: the operator always runs the driver in client mode internally ([#711]).
37+
3038
[#674]: https://github.com/stackabletech/spark-k8s-operator/pull/674
3139
[#679]: https://github.com/stackabletech/spark-k8s-operator/pull/679
3240
[#680]: https://github.com/stackabletech/spark-k8s-operator/pull/680
@@ -36,6 +44,7 @@ All notable changes to this project will be documented in this file.
3644
[#694]: https://github.com/stackabletech/spark-k8s-operator/pull/694
3745
[#696]: https://github.com/stackabletech/spark-k8s-operator/pull/696
3846
[#705]: https://github.com/stackabletech/spark-k8s-operator/pull/705
47+
[#711]: https://github.com/stackabletech/spark-k8s-operator/pull/711
3948

4049
## [26.3.0] - 2026-03-16
4150

deploy/helm/spark-k8s-operator/templates/roles.yaml

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,14 @@ rules:
1313
- nodes/proxy
1414
verbs:
1515
- get
16-
# The pod-driver controller watches Spark driver pods
17-
# (labelled spark-role=driver) to track SparkApplication completion. It also
18-
# deletes driver pods once the application reaches a terminal phase (Succeeded
19-
# or Failed).
16+
# The pod-driver controller watches Spark driver pods (labelled spark-role=driver) to track
17+
# SparkApplication completion. Driver pods are owned by the driver Job and cleaned up via the
18+
# Job's ttlSecondsAfterFinished, so the operator no longer deletes them.
2019
- apiGroups:
2120
- ""
2221
resources:
2322
- pods
2423
verbs:
25-
- delete
2624
- get
2725
- list
2826
- watch
@@ -43,9 +41,10 @@ rules:
4341
- patch
4442
- watch
4543
# Services expose Spark History Server and Spark Connect Server for metrics and
46-
# inter-component communication. Applied via Server-Side Apply and tracked for orphan
47-
# cleanup by the history and connect controllers. The history and connect controllers
48-
# watch Services via .owns(Service) to trigger re-reconciliation on change.
44+
# inter-component communication, and the app controller creates a headless driver Service per
45+
# SparkApplication so executors can reach the driver in client mode. Applied via Server-Side
46+
# Apply and tracked for orphan cleanup by the history and connect controllers. The app, history
47+
# and connect controllers watch Services via .owns(Service) to trigger re-reconciliation on change.
4948
# get is required for the ReconciliationPaused strategy in cluster_resources.add().
5049
- apiGroups:
5150
- ""
@@ -115,17 +114,20 @@ rules:
115114
- list
116115
- patch
117116
- watch
118-
# A Kubernetes Job is created per SparkApplication via Server-Side Apply to run
119-
# spark-submit. The app controller applies Jobs directly (not via cluster_resources),
120-
# so only create + patch (SSA) are needed. Jobs are not watched and not tracked for
121-
# orphan cleanup by any controller.
117+
# The driver Job is created per SparkApplication via Server-Side Apply. The app controller
118+
# applies Jobs directly (create + patch via SSA) and watches them via .owns(Job) to track
119+
# SparkApplication progress, so get + list + watch are also required. Jobs are garbage collected
120+
# via their owner reference and ttlSecondsAfterFinished, so no explicit delete is needed.
122121
- apiGroups:
123122
- batch
124123
resources:
125124
- jobs
126125
verbs:
127126
- create
127+
- get
128+
- list
128129
- patch
130+
- watch
129131
# PodDisruptionBudgets limit voluntary disruptions to Spark History Server pods.
130132
# Applied via Server-Side Apply and tracked for orphan cleanup by the history
131133
# controller. No controller watches PDBs via .owns().

docs/modules/spark-k8s/pages/getting_started/first_steps.adoc

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ Afterwards you can <<_verify_that_it_works, verify that it works>> by looking at
66

77
== Starting a Spark job
88

9-
A Spark application is made of up three components:
9+
A Spark application is made up of two components:
1010

11-
* Job: this builds a `spark-submit` command from the resource, passing this to internal spark code together with templates for building the driver and executor pods
12-
* Driver: the driver starts the designated number of executors and removes them when the job is completed.
13-
* Executor(s): responsible for executing the job itself
11+
* Driver: the operator creates a Kubernetes `Job` (built from `spec.driver`) whose pod runs `spark-submit` in client mode and therefore _is_ the Spark driver.
12+
The driver starts the designated number of executors and removes them when the job is completed.
13+
* Executor(s): responsible for executing the job itself. They are created by the driver via Spark's Kubernetes backend and connect back to the driver through a headless `Service` created by the operator.
14+
15+
NOTE: Previous versions ran an additional `spark-submit` process in a dedicated pod that then created the driver pod. This is no longer the case; `spec.job` and `spec.mode` are deprecated and ignored.
1416

1517
Create a Spark application by running:
1618

@@ -27,22 +29,21 @@ include::example$getting_started/application.yaml[Create a Spark application]
2729
----
2830
<1> `metadata.name` contains the name of the SparkApplication
2931
<2> `spec.sparkImage`: the image used by the job, driver and executor pods. This can be a custom image built by the user or an official Stackable image. Available official images are stored in the Stackable https://oci.stackable.tech/[image registry,window=_blank]. Information on how to browse the registry can be found xref:contributor:project-overview.adoc#docker-images[here,window=_blank].
30-
<3> `spec.mode`: only `cluster` is currently supported
32+
<3> `spec.mode`: deprecated and ignored; the driver always runs in client mode internally.
3133
<4> `spec.mainApplicationFile`: the artifact (Java, Scala or Python) that forms the basis of the Spark job.
3234
This path is relative to the image, so in this case an example python script (that calculates the value of pi) is running: it is bundled with the Spark code and therefore already present in the job image
33-
<5> `spec.job`: submit command specific settings.
34-
<6> `spec.driver`: driver-specific settings.
35+
<5> `spec.job`: deprecated and ignored. In previous versions this configured the dedicated `spark-submit` job.
36+
<6> `spec.driver`: driver-specific settings. Used to build the driver `Job` pod.
3537
<7> `spec.executor`: executor-specific settings.
3638

3739
== Verify that it works
3840

39-
As mentioned above, the SparkApplication that has just been created builds a `spark-submit` command and pass it to the driver Pod, which in turn creates executor Pods that run for the duration of the job before being clean up.
41+
As mentioned above, the operator creates a driver `Job` whose pod runs `spark-submit` in client mode and thus acts as the Spark driver, which in turn creates executor Pods that run for the duration of the job before being cleaned up.
4042
A running process looks like this:
4143

4244
image::getting_started/spark_running.png[Spark job]
4345

44-
* `pyspark-pi-xxxx`: this is the initializing job that creates the spark-submit command (named as `metadata.name` with a unique suffix)
45-
* `pyspark-pi-xxxxxxx-driver`: the driver pod that drives the execution
46+
* `pyspark-pi-xxxxxxx-driver`: the driver pod (created by the driver `Job`) that drives the execution
4647
* `pythonpi-xxxxxxxxx-exec-x`: the set of executors started by the driver (in the example `spec.executor.instances` was set to 3 which is why 3 executors are running)
4748

4849
Job progress can be followed by issuing this command:

docs/modules/spark-k8s/pages/usage-guide/examples.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ The following examples have the following `spec` fields in common:
66
* `version`: the current version is "1.0"
77
* `sparkImage`: the docker image that is used by job, driver and executor pods.
88
This can be provided by the user.
9-
* `mode`: only `cluster` is currently supported
9+
* `mode`: deprecated and ignored; the driver always runs in client mode internally
1010
* `mainApplicationFile`: the artifact (Java, Scala or Python) that forms the basis of the Spark job.
1111
* `args`: these are the arguments passed directly to the application. In the examples below it is e.g. the input path for part of the public New York taxi dataset.
1212
* `sparkConf`: these list spark configuration settings that are passed directly to `spark-submit` and which are best defined explicitly by the user. Since the `SparkApplication` "knows" that there is an external dependency (the s3 bucket where the data and/or the application is located) and how that dependency should be treated (i.e. what type of credential checks are required, if any), it is better to have these things declared together.

0 commit comments

Comments
 (0)