|
| 1 | += OpenLineage |
| 2 | + |
| 3 | +https://openlineage.io/[OpenLineage] is an open standard for data lineage collection. |
| 4 | +The Spark operator can automatically emit lineage events for a `SparkApplication` to an OpenLineage-compatible backend such as https://marquezproject.github.io/marquez/[Marquez], without any manual `sparkConf` wiring. |
| 5 | + |
| 6 | +When enabled, the operator injects everything required to make the https://openlineage.io/docs/integrations/spark/[OpenLineage Spark listener] work: |
| 7 | + |
| 8 | +* the OpenLineage Spark listener (appended to `spark.extraListeners`, so any listener you configure yourself is preserved), |
| 9 | +* the OpenLineage jar baked into the Spark image, referenced via `spark.jars` so it shares the same classloader as connectors pulled in through xref:usage-guide/job-dependencies.adoc[`deps.packages`] (for example Apache Iceberg), |
| 10 | +* an HTTP transport pointing at the backend endpoint, |
| 11 | +* a stable lineage namespace and job name (see <<job-name>>), and |
| 12 | +* the `--add-opens java.base/java.security=ALL-UNNAMED` JVM flag the listener requires on the driver and executors. |
| 13 | +
|
| 14 | +== Enabling OpenLineage |
| 15 | + |
| 16 | +The backend endpoint is not configured on the `SparkApplication` directly. |
| 17 | +Instead, mirroring the xref:usage-guide/logging.adoc[vector aggregator discovery], the operator reads it from a discovery ConfigMap referenced by `configMapName`: |
| 18 | + |
| 19 | +[source,yaml] |
| 20 | +---- |
| 21 | +apiVersion: spark.stackable.tech/v1alpha1 |
| 22 | +kind: SparkApplication |
| 23 | +metadata: |
| 24 | + name: orders-by-nation |
| 25 | +spec: |
| 26 | + openLineage: |
| 27 | + enabled: true # <1> |
| 28 | + configMapName: marquez-discovery # <2> |
| 29 | + # namespace: orders-lineage # <3> |
| 30 | + # appName: orders-by-nation # <4> |
| 31 | + ... |
| 32 | +---- |
| 33 | +<1> Enable OpenLineage event emission. Defaults to `false`, in which case the operator emits nothing OpenLineage-related and behaviour is unchanged. |
| 34 | +<2> Name of a discovery ConfigMap holding the backend endpoint (see below). |
| 35 | + Must be in the same namespace as the `SparkApplication`. |
| 36 | +<3> Optional. The OpenLineage namespace events are reported under. |
| 37 | + Defaults to the application's Kubernetes namespace. |
| 38 | +<4> Optional. The stable OpenLineage job name (see <<job-name>>). |
| 39 | + |
| 40 | +The discovery ConfigMap holds the backend base URL under the `ADDRESS` key: |
| 41 | + |
| 42 | +.Example discovery ConfigMap |
| 43 | +[source,yaml] |
| 44 | +---- |
| 45 | +apiVersion: v1 |
| 46 | +kind: ConfigMap |
| 47 | +metadata: |
| 48 | + name: marquez-discovery |
| 49 | +data: |
| 50 | + ADDRESS: http://marquez:5000 # <1> |
| 51 | +---- |
| 52 | +<1> Base URL of the OpenLineage backend, for example the Marquez API service. |
| 53 | + |
| 54 | +Alternatively, you can set the endpoint directly through `sparkConf` (`spark.openlineage.transport.url`). |
| 55 | +If `enabled: true` and no endpoint can be resolved from either the discovery ConfigMap or `sparkConf`, reconciliation fails with a clear error rather than emitting a config that silently drops events. |
| 56 | + |
| 57 | +[#job-name] |
| 58 | +== Job name |
| 59 | + |
| 60 | +The OpenLineage job name is resolved in the following order: |
| 61 | + |
| 62 | +. `spec.openLineage.appName`, if set. |
| 63 | +. `spark.app.name` from `sparkConf`, if set. |
| 64 | +. `metadata.name` as a last resort. |
| 65 | + |
| 66 | +The last case additionally emits a Kubernetes warning event. |
| 67 | +Falling back to `metadata.name` is discouraged: if that name carries a timestamp or other run-specific suffix (as generated names often do), every run becomes a separate job in the backend and the run history fragments. |
| 68 | +Set `spec.openLineage.appName` (or `spark.app.name`) to a stable value to keep all runs of the same logical job together. |
| 69 | + |
| 70 | +== Overriding injected configuration |
| 71 | + |
| 72 | +Every injected value is a default that goes into the submit configuration *before* your xref:usage-guide/overrides.adoc[`sparkConf`] is merged, so any key you set yourself wins. |
| 73 | +`spark.extraListeners` and `spark.jars` are the exception: the operator *appends* to any value you provide (comma-merged) rather than overwriting it, so your own listeners and jars are kept alongside OpenLineage's. |
0 commit comments