Skip to content

Commit

Permalink
AIOPS-3232:As a data engineer, I want the default memory for Spark ap…
Browse files Browse the repository at this point in the history
…plications to be increased so it works out of the box for more than just toy examples
  • Loading branch information
tianliang0038 committed May 1, 2024
1 parent b63c0f7 commit b483ed2
Show file tree
Hide file tree
Showing 10 changed files with 383 additions and 35 deletions.
67 changes: 34 additions & 33 deletions DRAFT_RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
# Major Additions

* Python modules were renamed to reflect aiSSEMBLE. These include the following.
| Old Python Module | New Python Module |
|--------------------------------------------|----------------------------------------------------------------|
| foundation-core-python | aissemble-core-python |
| foundation-model-training-api | aissemble-foundation-model-training-api |
| foundation-versioning-service | aissemble-foundation-versioning-service |
| foundation-drift-detection-client | aissemble-foundation-drift-detection-client |
| foundation-encryption-policy-python | aissemble-foundation-encryption-policy-python |
| foundation-model-lineage | aissemble-foundation-model-lineage |
| foundation-data-lineage-python | aissemble-foundation-data-lineage-python |
| foundation-messaging-python-client | aissemble-foundation-messaging-python-client |
| foundation-pdp-client-python | aissemble-foundation-pdp-client-python |
| foundation-transform-core-python | aissemble-Foundation-transform-core-python |
| extensions-model-training-api-sagemaker | aissemble-extensions-model-training-api-sagemaker |
| extensions-data-delivery-spark-py | aissemble-extensions-data-delivery-spark-py |
| extensions-encryption-valut-python | aissemble-extensions-encryption-valut-python |
| extensions-transform-spark-python | aissemble-extensions-transform-spark-python |
| test-data-delivery-pyspark-model | aissemble-test-data-delivery-pyspark-model |
| test-data-delivery-pyspark-model-basic | aissemble-test-data-delivery-pyspark-model-basic |
| machine-learning-inference | aissemble-machine-learning-inference |
| machine-learning-training | aissemble-machine-learning-training |
| machine-learning-training-base | aissemble-machine-learning-training-base |
| machine-learning-sagemaker-training | aissemble-machine-learning-sagemaker-training |
| Old Python Module | New Python Module |
| --------------------------------------- | ------------------------------------------------- |
| foundation-core-python | aissemble-core-python |
| foundation-model-training-api | aissemble-foundation-model-training-api |
| foundation-versioning-service | aissemble-foundation-versioning-service |
| foundation-drift-detection-client | aissemble-foundation-drift-detection-client |
| foundation-encryption-policy-python | aissemble-foundation-encryption-policy-python |
| foundation-model-lineage | aissemble-foundation-model-lineage |
| foundation-data-lineage-python | aissemble-foundation-data-lineage-python |
| foundation-messaging-python-client | aissemble-foundation-messaging-python-client |
| foundation-pdp-client-python | aissemble-foundation-pdp-client-python |
| foundation-transform-core-python | aissemble-Foundation-transform-core-python |
| extensions-model-training-api-sagemaker | aissemble-extensions-model-training-api-sagemaker |
| extensions-data-delivery-spark-py | aissemble-extensions-data-delivery-spark-py |
| extensions-encryption-valut-python | aissemble-extensions-encryption-valut-python |
| extensions-transform-spark-python | aissemble-extensions-transform-spark-python |
| test-data-delivery-pyspark-model | aissemble-test-data-delivery-pyspark-model |
| test-data-delivery-pyspark-model-basic | aissemble-test-data-delivery-pyspark-model-basic |
| machine-learning-inference | aissemble-machine-learning-inference |
| machine-learning-training | aissemble-machine-learning-training |
| machine-learning-training-base | aissemble-machine-learning-training-base |
| machine-learning-sagemaker-training | aissemble-machine-learning-sagemaker-training |


## OpenLineage Namespace Conventions
Expand All @@ -38,8 +38,8 @@ for each pipeline step's lineage event to be associated with the pipeline's line
We have also made adjustments regarding customizing the lineage event so that we can customize the lineage event
based on the event type. The below functions have been removed, and replaced by event type-specific functions:

| Python Method Signature | Java Method Signature |
|--------------------------------------------------------------------|----------------------------------------------------------|
| Python Method Signature | Java Method Signature |
| ------------------------------------------------------------------ | -------------------------------------------------------- |
| create_run(self) → Run | Run createRun() |
| create_job(self) → Job | Job createJob() |
| create_run_event(self, run: Run, job: Job, status: str) → RunEvent | RunEvent createRunEvent(Run run, Job job, String status) |
Expand All @@ -53,8 +53,8 @@ root pom.xml file.
There are no known issues with the 1.7.0 release.

# Known Vulnerabilities
| Date<br/>identified | Vulnerability | Severity | Package | Affected <br/>versions | CVE | Fixed <br/>in |
|---------------------|-----------------------------------------|------------|------------|------------------------|-----|---------------|
| Date<br/>identified | Vulnerability | Severity | Package | Affected <br/>versions | CVE | Fixed <br/>in |
| ------------------- | ------------- | -------- | ------- | ---------------------- | --- | ------------- |

# How to Upgrade
The following steps will upgrade your project to 1.7. These instructions consist of multiple phases:
Expand All @@ -66,13 +66,14 @@ The following steps will upgrade your project to 1.7. These instructions consist
## Automatic Upgrades
To reduce burden of upgrading aiSSEMBLE, the Baton project is used to automate the migration of some files to the new version. These migrations run automatically when you build your project, and are included by default when you update the `build-parent` version in your root POM. Below is a description of all of the Baton migrations that are included with this version of aiSSEMBLE.

| Migration Name | Description |
|------------------------------------------------------|--------------------------------------------------------------|
| upgrade-tiltfile-aissemble-version-migration | Updates the aiSSEMBLE version within your project's Tiltfile |
| upgrade-v2-chart-files-aissemble-version-migration | Updates the helm chart dependencies within your project's deployment resources (<YOUR_PROJECT>-deploy/src/main/resources/apps/) to use the latest version of the aiSSEMBLE |
| upgrade-v1-chart-files-aissemble-version-migration | Updates the docker image tags within your project's deployment resources (<YOUR_PROJECT>-deploy/src/main/resources/apps/) to use the latest version of the aiSSEMBLE |
| upgrade-mlflow-v2-external-s3-migration | Update the mlflow V2 deployment (if present) in your project to utilize Localstack for local development and SealedSecrets for remote deployments |
| <pyproject-migration> | Will need to migrate pyproject.toml files to reflect newly named Python modules |
| Migration Name | Description |
| -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| upgrade-tiltfile-aissemble-version-migration | Updates the aiSSEMBLE version within your project's Tiltfile |
| upgrade-v2-chart-files-aissemble-version-migration | Updates the helm chart dependencies within your project's deployment resources (<YOUR_PROJECT>-deploy/src/main/resources/apps/) to use the latest version of the aiSSEMBLE |
| upgrade-v1-chart-files-aissemble-version-migration | Updates the docker image tags within your project's deployment resources (<YOUR_PROJECT>-deploy/src/main/resources/apps/) to use the latest version of the aiSSEMBLE |
| upgrade-mlflow-v2-external-s3-migration | Update the mlflow V2 deployment (if present) in your project to utilize Localstack for local development and SealedSecrets for remote deployments |
| upgrade-spark-pipeline-values-memory | Update the memory allocation within your projects's pipeline Spark Application (if present) to use the latest default value. |
| <pyproject-migration> | Will need to migrate pyproject.toml files to reflect newly named Python modules |

To deactivate any of these migrations, add the following configuration to the `baton-maven-plugin` within your root `pom.xml`:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ sparkApp:
driver:
cores: 1
coreLimit: "1200m"
memory: "512m"
memory: "4096m"
env:
- name: KRAUSENING_BASE
value: /opt/spark/krausening/base
Expand All @@ -90,7 +90,7 @@ sparkApp:
#end
executor:
cores: 1
memory: "512m"
memory: "4096m"
env:
- name: KRAUSENING_BASE
value: /opt/spark/krausening/base
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,9 @@ sparkApp:
spark.kryo.registrator: "org.apache.sedona.viz.core.Serde.SedonaVizKryoRegistrator"
#end
#end
driver:
cores: 1
memory: "2048m"
executor:
cores: 1
memory: "2048m"
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.boozallen.aissemble.upgrade.migration.v1_7_0;
/*-
* #%L
* aiSSEMBLE::Foundation::Upgrade
* %%
* Copyright (C) 2021 Booz Allen
* %%
* This software package is licensed under the Booz Allen Public License. All Rights Reserved.
* #L%
*/
import com.boozallen.aissemble.upgrade.util.YamlUtils;
import com.boozallen.aissemble.upgrade.util.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.boozallen.aissemble.upgrade.migration.AbstractAissembleMigration;
import com.boozallen.aissemble.upgrade.pojo.AbstractYamlObject;

import java.io.File;
import java.io.IOException;
import java.util.List;

public class SparkMemoryUpgradeMigration extends AbstractAissembleMigration {
private static final Logger logger = LoggerFactory.getLogger(SparkMemoryUpgradeMigration.class);
@Override
protected boolean shouldExecuteOnFile(File file) {
try {
YamlUtils.YamlObject yamlObject = YamlUtils.loadYaml(file);
YamlUtils.YamlObject specSection = yamlObject.getObject("sparkApp").getObject("spec");
// Navigate through the YAML structure to access, driver memory, and executor memory
String driverMemory = null;
String executorMemory = null;
if (specSection.getObject("driver") != null) {
driverMemory = specSection.getObject("driver").getString("memory");
}
if (specSection.getObject("executor") != null) {
executorMemory = specSection.getObject("executor").getString("memory");
}

// Check if any of the memory values are not as expected
if ("512m".equals(driverMemory) && "512m".equals(executorMemory)) {
logger.info("Performing migration for file: {}", file.getName());
return true;
} else {
return false;
}
} catch (IOException e) {
logger.error("Error reading file or parsing YAML: {}", e.getMessage());
return false; // Exit if unable to read file or parse YAML
}
}

@Override
protected boolean performMigration(File file) {
return migrateValuesFile(file);
}

private boolean migrateValuesFile(File file) {
try {
List<String> lines = FileUtils.readAllFileLines(file);

// Define the old default values to replace
String oldDefaultValue = "512m";
// Define the new value to replace with
String newValue = "4096m";

// Replace old default values with new value
for (int i = 0; i < lines.size(); i++) {
String line = lines.get(i);
if (line.stripLeading().startsWith("memory:") && line.contains(oldDefaultValue)) {
String updatedLine = line.replace(oldDefaultValue, newValue);
lines.set(i, updatedLine);
}
}

// Write the updated lines back to the file
FileUtils.writeFile(file, lines);
logger.info("Memory values updated successfully in file: {}", file.getName());
return true; // Indicate successful migration
} catch (IOException e) {
logger.error("Error updating memory values in file {}: {}", file.getName(), e.getMessage());
return false; // Indicate migration failure
}
}
}
12 changes: 12 additions & 0 deletions foundation/foundation-upgrade/src/main/resources/migrations.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,17 @@
"excludes": ["**/target/**/Chart.yaml"]
}
]
},
{
"name": "upgrade-spark-pipeline-values-memory",
"implementation": "com.boozallen.aissemble.upgrade.migration.v1_7_0.SparkMemoryUpgradeMigration",
"fileSets": [
{
"includes": [
"*-pipelines/*/src/*/resources/apps/*-base-values.yaml",
"*-pipelines/*/src/main/resources/apps/*-base-values.yaml"
]
}
]
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.boozallen.aissemble.upgrade.migration.v1_7_0;
/*-
* #%L
* aiSSEMBLE::Foundation::Upgrade
* %%
* Copyright (C) 2021 Booz Allen
* %%
* This software package is licensed under the Booz Allen Public License. All Rights Reserved.
* #L%
*/


import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.IOException;

import org.apache.commons.io.FileUtils;
import com.boozallen.aissemble.upgrade.migration.AbstractMigrationTest;

import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;

public class SparkMemoryUpgradeMigrationSteps extends AbstractMigrationTest {

private SparkMemoryUpgradeMigration sparkmigration;
@Given("a project that has a spark application")
public void a_project_that_has_spark_application() {
assertTrue("The project has a Spark application", true);
}

@Given("the base value contains the old memory value")
public void the_values_yaml_has_old_memory_value() throws IOException {
testFile = getTestFile("v1_7_0/SparkUpgradeMigration/migration/base-values.yaml");
}

@When("the 1.7.0 spark application memory migration executes")
public void the_value_yaml_migration_executes() {
performMigration(new SparkMemoryUpgradeMigration());
}

@Then("the memory is updated to new value")
public void the_values_dev_yaml_get_updated() throws IOException {
File validationFile = getTestFile("v1_7_0/SparkUpgradeMigration/validation/base-values.yaml");
File migratedFile = getTestFile("v1_7_0/SparkUpgradeMigration/migration/base-values.yaml");
assertTrue("The content of the migrated file does not match the validation file",
FileUtils.contentEqualsIgnoreEOL(migratedFile, validationFile, null));
assertTrue("Migration did not complete successfully", successful);
}

@Given("the base values.yaml does not have default memory values")
public void the_values_yaml_has_non_default_memory_value() throws IOException {
testFile = getTestFile("v1_7_0/SparkUpgradeMigration/skip-migration/base-values.yaml");
}
@Then("the spark application memory migration is skipped")
public void the_values_dev_yaml_unchanged() throws IOException {
assertFalse("The migration should be skipped", shouldExecute);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@spark-memory-migration
Feature: Migrate a spark application to use the new memory value
Scenario Outline: Migrate a spark application with new memory value in the base values
Given a project that has a spark application
And the base value contains the old memory value
When the 1.7.0 spark application memory migration executes
Then the memory is updated to new value

Scenario: Skip spark application memory migration with non-default values in the base values
Given a project that has a spark application
And the base values.yaml does not have default memory values
When the 1.7.0 spark application memory migration executes
Then the spark application memory migration is skipped
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
metadata:
name: pyspark-pipeline
sparkApp:
spec:
type: Python
image: "boozallen/aiops-2977-spark-worker-docker:latest"
mainApplicationFile: "local:///opt/spark/jobs/pipelines/pyspark-pipeline/pyspark_pipeline_driver.py"
deps:
packages:
- mysql:mysql-connector-java:8.0.30
- org.apache.hadoop:hadoop-aws:3.3.4
- com.amazonaws:aws-java-sdk-bundle:1.12.262
excludePackages: []
hadoopConf:
fs.s3a.fast.upload: "true"
fs.s3a.path.style: "true"
driver:
cores: 1
coreLimit: "1200m"
memory: "512m"
env:
- name: KRAUSENING_BASE
value: /opt/spark/krausening/base
- name: AWS_ACCESS_KEY_ID
value: "123"
- name: AWS_SECRET_ACCESS_KEY
value: "456"
- name: STORAGE_ENDPOINT
value: "http://s3-local:4566"
- name: MyFileStore_FS_PROVIDER
value: "s3"
- name: MyFileStore_FS_ACCESS_KEY_ID
value: ""
- name: MyFileStore_FS_SECRET_ACCESS_KEY
value: ""
- name: MyFileStore_FS_SECURE
value: "false"
- name: MyFileStoreAsync_FS_PROVIDER
value: "s3"
- name: MyFileStoreAsync_FS_ACCESS_KEY_ID
value: ""
- name: MyFileStoreAsync_FS_SECRET_ACCESS_KEY
value: ""
- name: MyFileStoreAsync_FS_SECURE
value: "false"
executor:
cores: 1
memory: "512m"
env:
- name: KRAUSENING_BASE
value: /opt/spark/krausening/base
- name: AWS_ACCESS_KEY_ID
value: "123"
- name: AWS_SECRET_ACCESS_KEY
value: "456"
- name: STORAGE_ENDPOINT
value: "http://s3-local:4566"
Loading

0 comments on commit b483ed2

Please sign in to comment.