Skip to content
Merged
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file.
config property `requestedSecretLifetime`. This helps reducing frequent Pod restarts ([#501]).
- Run a `containerdebug` process in the background of each Spark container to collect debugging information ([#508]).
- Aggregate emitted Kubernetes events on the CustomResources ([#515]).
- Support configuring JVM arguments ([#532]).

### Changed

Expand All @@ -19,6 +20,7 @@ All notable changes to this project will be documented in this file.
[#508]: https://github.com/stackabletech/spark-k8s-operator/pull/508
[#514]: https://github.com/stackabletech/spark-k8s-operator/pull/514
[#515]: https://github.com/stackabletech/spark-k8s-operator/pull/515
[#532]: https://github.com/stackabletech/spark-k8s-operator/pull/532

## [24.11.1] - 2025-01-10

Expand Down
130 changes: 130 additions & 0 deletions deploy/helm/spark-k8s-operator/crds/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,32 @@ spec:
default: {}
description: '`envOverrides` configure environment variables to be set in the Pods. It is a map from strings to strings - environment variables and the value to set. Read the [environment variable overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#env-overrides) for more information and consult the operator specific usage guide to find out about the product specific environment variables that are available.'
type: object
jvmArgumentOverrides:
default:
add: []
remove: []
removeRegex: []
description: Allows overriding JVM arguments. Please read on the [JVM argument overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#jvm-argument-overrides) for details on the usage.
properties:
add:
default: []
description: JVM arguments to be added
items:
type: string
type: array
remove:
default: []
description: JVM arguments to be removed by exact match
items:
type: string
type: array
removeRegex:
default: []
description: JVM arguments matching any of this regexes will be removed
items:
type: string
type: array
type: object
podOverrides:
default: {}
description: In the `podOverrides` property you can define a [PodTemplateSpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#podtemplatespec-v1-core) to override any property that can be set on a Kubernetes Pod. Read the [Pod overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#pod-overrides) for more information.
Expand Down Expand Up @@ -530,6 +556,32 @@ spec:
default: {}
description: '`envOverrides` configure environment variables to be set in the Pods. It is a map from strings to strings - environment variables and the value to set. Read the [environment variable overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#env-overrides) for more information and consult the operator specific usage guide to find out about the product specific environment variables that are available.'
type: object
jvmArgumentOverrides:
default:
add: []
remove: []
removeRegex: []
description: Allows overriding JVM arguments. Please read on the [JVM argument overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#jvm-argument-overrides) for details on the usage.
properties:
add:
default: []
description: JVM arguments to be added
items:
type: string
type: array
remove:
default: []
description: JVM arguments to be removed by exact match
items:
type: string
type: array
removeRegex:
default: []
description: JVM arguments matching any of this regexes will be removed
items:
type: string
type: array
type: object
podOverrides:
default: {}
description: In the `podOverrides` property you can define a [PodTemplateSpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#podtemplatespec-v1-core) to override any property that can be set on a Kubernetes Pod. Read the [Pod overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#pod-overrides) for more information.
Expand Down Expand Up @@ -620,6 +672,32 @@ spec:
default: {}
description: '`envOverrides` configure environment variables to be set in the Pods. It is a map from strings to strings - environment variables and the value to set. Read the [environment variable overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#env-overrides) for more information and consult the operator specific usage guide to find out about the product specific environment variables that are available.'
type: object
jvmArgumentOverrides:
default:
add: []
remove: []
removeRegex: []
description: Allows overriding JVM arguments. Please read on the [JVM argument overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#jvm-argument-overrides) for details on the usage.
properties:
add:
default: []
description: JVM arguments to be added
items:
type: string
type: array
remove:
default: []
description: JVM arguments to be removed by exact match
items:
type: string
type: array
removeRegex:
default: []
description: JVM arguments matching any of this regexes will be removed
items:
type: string
type: array
type: object
podOverrides:
default: {}
description: In the `podOverrides` property you can define a [PodTemplateSpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#podtemplatespec-v1-core) to override any property that can be set on a Kubernetes Pod. Read the [Pod overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#pod-overrides) for more information.
Expand Down Expand Up @@ -1416,6 +1494,32 @@ spec:
default: {}
description: '`envOverrides` configure environment variables to be set in the Pods. It is a map from strings to strings - environment variables and the value to set. Read the [environment variable overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#env-overrides) for more information and consult the operator specific usage guide to find out about the product specific environment variables that are available.'
type: object
jvmArgumentOverrides:
default:
add: []
remove: []
removeRegex: []
description: Allows overriding JVM arguments. Please read on the [JVM argument overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#jvm-argument-overrides) for details on the usage.
properties:
add:
default: []
description: JVM arguments to be added
items:
type: string
type: array
remove:
default: []
description: JVM arguments to be removed by exact match
items:
type: string
type: array
removeRegex:
default: []
description: JVM arguments matching any of this regexes will be removed
items:
type: string
type: array
type: object
podOverrides:
default: {}
description: In the `podOverrides` property you can define a [PodTemplateSpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#podtemplatespec-v1-core) to override any property that can be set on a Kubernetes Pod. Read the [Pod overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#pod-overrides) for more information.
Expand Down Expand Up @@ -1636,6 +1740,32 @@ spec:
default: {}
description: '`envOverrides` configure environment variables to be set in the Pods. It is a map from strings to strings - environment variables and the value to set. Read the [environment variable overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#env-overrides) for more information and consult the operator specific usage guide to find out about the product specific environment variables that are available.'
type: object
jvmArgumentOverrides:
default:
add: []
remove: []
removeRegex: []
description: Allows overriding JVM arguments. Please read on the [JVM argument overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#jvm-argument-overrides) for details on the usage.
properties:
add:
default: []
description: JVM arguments to be added
items:
type: string
type: array
remove:
default: []
description: JVM arguments to be removed by exact match
items:
type: string
type: array
removeRegex:
default: []
description: JVM arguments matching any of this regexes will be removed
items:
type: string
type: array
type: object
podOverrides:
default: {}
description: In the `podOverrides` property you can define a [PodTemplateSpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#podtemplatespec-v1-core) to override any property that can be set on a Kubernetes Pod. Read the [Pod overrides documentation](https://docs.stackable.tech/home/nightly/concepts/overrides#pod-overrides) for more information.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,10 @@ spec:

The Spark operator also supports Pod overrides, allowing you to override any property that you can set on a Kubernetes Pod.
Read the xref:concepts:overrides.adoc#pod-overrides[Pod overrides documentation] to learn more about this feature.

== JVM argument overrides

Stackable operators automatically determine the set of needed JVM arguments, such as memory settings or trust- and keystores.
Using JVM argument overrides you can configure the JVM arguments xref:concepts:overrides.adoc#jvm-argument-overrides[according to the concepts page].

TODO more docs
2 changes: 1 addition & 1 deletion docs/modules/spark-k8s/partials/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
** xref:spark-k8s:usage-guide/logging.adoc[]
** xref:spark-k8s:usage-guide/history-server.adoc[]
** xref:spark-k8s:usage-guide/examples.adoc[]
** xref:spark-k8s:usage-guide/configuration-environment-overrides.adoc[]
** xref:spark-k8s:usage-guide/overrides.adoc[]
** xref:spark-k8s:usage-guide/operations/index.adoc[]
*** xref:spark-k8s:usage-guide/operations/applications.adoc[]
*** xref:spark-k8s:usage-guide/operations/pod-placement.adoc[]
Expand Down
151 changes: 151 additions & 0 deletions rust/operator-binary/src/config/jvm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
use snafu::{ResultExt, Snafu};
use stackable_operator::{
commons::s3::S3ConnectionSpec,
role_utils::{self, JvmArgumentOverrides},
};

use crate::crd::{
constants::{
JVM_SECURITY_PROPERTIES_FILE, STACKABLE_TLS_STORE_PASSWORD, STACKABLE_TRUST_STORE,
VOLUME_MOUNT_PATH_LOG_CONFIG,
},
logdir::ResolvedLogDir,
tlscerts::tls_secret_names,
v1alpha1::SparkApplication,
};

#[derive(Snafu, Debug)]
pub enum Error {
#[snafu(display("failed to merge jvm argument overrides"))]
MergeJvmArgumentOverrides { source: role_utils::Error },
}

/// JVM arguments that go into
/// 1.`spark.driver.extraJavaOptions`
/// 2. `spark.executor.extraJavaOptions`
pub fn construct_extra_java_options(
spark_application: &SparkApplication,
s3_conn: &Option<S3ConnectionSpec>,
log_dir: &Option<ResolvedLogDir>,
) -> Result<(String, String), Error> {
// Note (@sbernauer): As of 2025-03-04, we did not set any heap related JVM arguments, so I
// kept the implementation as is. We can always re-visit this as needed.

let mut jvm_args = vec![format!(
"-Djava.security.properties={VOLUME_MOUNT_PATH_LOG_CONFIG}/{JVM_SECURITY_PROPERTIES_FILE}"
)];

if tls_secret_names(s3_conn, log_dir).is_some() {
jvm_args.extend([
format!("-Djavax.net.ssl.trustStore={STACKABLE_TRUST_STORE}/truststore.p12"),
format!("-Djavax.net.ssl.trustStorePassword={STACKABLE_TLS_STORE_PASSWORD}"),
"-Djavax.net.ssl.trustStoreType=pkcs12".to_string(),
]);
}

let operator_generated = JvmArgumentOverrides::new_with_only_additions(jvm_args);
let from_driver = match &spark_application.spec.driver {
Some(driver) => &driver.product_specific_common_config.jvm_argument_overrides,
None => &JvmArgumentOverrides::default(),
};
let from_executor = match &spark_application.spec.executor {
Some(executor) => {
&executor
.config
.product_specific_common_config
.jvm_argument_overrides
}
None => &JvmArgumentOverrides::default(),
};

// Please note that the merge order is different than we normally do!
// This is not trivial, as the merge operation is not purely additive (as it is with e.g. `PodTemplateSpec).
let mut from_driver = from_driver.clone();
let mut from_executor = from_executor.clone();
from_driver
.try_merge(&operator_generated)
.context(MergeJvmArgumentOverridesSnafu)?;
from_executor
.try_merge(&operator_generated)
.context(MergeJvmArgumentOverridesSnafu)?;

Ok((
from_driver.effective_jvm_config_after_merging().join(" "),
from_executor.effective_jvm_config_after_merging().join(" "),
))
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_construct_jvm_arguments_defaults() {
let input = r#"
apiVersion: spark.stackable.tech/v1alpha1
kind: SparkApplication
metadata:
name: spark-example
spec:
mode: cluster
mainApplicationFile: test.py
sparkImage:
productVersion: 1.2.3
"#;

let deserializer = serde_yaml::Deserializer::from_str(input);
let spark_app: SparkApplication =
serde_yaml::with::singleton_map_recursive::deserialize(deserializer).unwrap();
let (driver_extra_java_options, executor_extra_java_options) =
construct_extra_java_options(&spark_app, &None, &None).unwrap();

assert_eq!(
driver_extra_java_options,
"-Djava.security.properties=/stackable/log_config/security.properties"
);
assert_eq!(
executor_extra_java_options,
"-Djava.security.properties=/stackable/log_config/security.properties"
);
}

#[test]
fn test_construct_jvm_argument_overrides() {
let input = r#"
apiVersion: spark.stackable.tech/v1alpha1
kind: SparkApplication
metadata:
name: spark-example
spec:
mode: cluster
mainApplicationFile: test.py
sparkImage:
productVersion: 1.2.3
driver:
jvmArgumentOverrides:
add:
- -Dhttps.proxyHost=from-driver
executor:
jvmArgumentOverrides:
add:
- -Dhttps.proxyHost=from-executor
removeRegex:
- -Djava.security.properties=.*
"#;

let deserializer = serde_yaml::Deserializer::from_str(input);
let spark_app: SparkApplication =
serde_yaml::with::singleton_map_recursive::deserialize(deserializer).unwrap();
let (driver_extra_java_options, executor_extra_java_options) =
construct_extra_java_options(&spark_app, &None, &None).unwrap();

assert_eq!(
driver_extra_java_options,
"-Djava.security.properties=/stackable/log_config/security.properties -Dhttps.proxyHost=from-driver"
);
assert_eq!(
executor_extra_java_options,
"-Dhttps.proxyHost=from-executor"
);
}
}
1 change: 1 addition & 0 deletions rust/operator-binary/src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod jvm;
Loading