Spark in JupyterLab verwenden
Zuletzt aktualisiert am
Einführung
Abschnitt betitelt „Einführung“STACKIT Notebooks werden vorkonfiguriert mit Spark-Unterstützung ausgeliefert. Je nachdem, ob Ihr Code interaktiv in JupyterLab oder automatisiert über einen Airflow/Papermill-Job ausgeführt wird, unterscheidet sich jedoch die Initialisierung der Spark-Sitzung.
Diese Anleitung erklärt, wie Sie eine Spark-Sitzung erstellen, die eine Verbindung zu Ihrem Data Lakehouse (STACKIT Dremio/Iceberg) herstellt.
Arten der Interaktion
Abschnitt betitelt „Arten der Interaktion“Es gibt zwei Hauptarten, wie Ihr Notebook ausgeführt werden kann:
- Interaktiver Modus: Sie führen die Zellen manuell in der JupyterLab-Benutzeroberfläche aus. Sie müssen Anmeldedaten (wie ein Personal Access Token) bereitstellen, um sich am Katalog zu authentifizieren.
- Papermill-/Produktionsmodus: Das Notebook wird über STACKIT Workflows (Apache Airflow) ausgeführt. Die Umgebung ist bereits mit den erforderlichen Tokens und der Katalog-URI vorkonfiguriert.
Implementierung
Abschnitt betitelt „Implementierung“Das folgende Code-Beispiel zeigt, wie beide Umgebungen gehandhabt werden. Es prüft das Vorhandensein der Umgebungsvariablen STACKIT__PAPERMILL, um zu entscheiden, ob die automatische Konfiguration oder die manuelle Credential-Injektion verwendet werden soll.
import osimport stackit_spark
# 1. Prüfen, ob der Code über Airflow/Papermill ausgeführt wirdif "STACKIT__PAPERMILL" in os.environ: # Im Papermill-Modus bezieht get_spark() die Konfiguration # automatisch aus der Umgebung / dem Operator. CATALOG_NAME = "catalog" spark = get_spark()else: # 2. Interaktiver Modus: Manuelle Konfiguration erforderlich # Diese Variablen sollten im JupyterLab-Terminal oder über Umgebungseinstellungen gesetzt sein DREMIO_PAT = os.environ["DREMIO_PAT"] DREMIO_ADDRESS = os.environ["DREMIO_ADDRESS"] CATALOG_URI = os.environ["CATALOG_URI"] CATALOG_NAME = "stackit" ICEBERG_VERSION = "1.9.1"
JAR_PATH = os.path.abspath("./authmgr-oauth2-runtime-0.1.2.jar")
packages = ( f"org.apache.iceberg:iceberg-spark-runtime-3.5_2.12:{ICEBERG_VERSION}," f"org.apache.iceberg:iceberg-azure-bundle:{ICEBERG_VERSION}," f"org.apache.iceberg:iceberg-aws-bundle:{ICEBERG_VERSION}," f"org.apache.iceberg:iceberg-gcp-bundle:{ICEBERG_VERSION}" )
spark = stackit_spark.get_spark( additional_config={ "spark.jars.packages": packages, "spark.jars": JAR_PATH, "spark.sql.extensions": "org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions", "spark.driver.userClassPathFirst": "true",
# --- Iceberg Katalog-Konfiguration --- f"spark.sql.catalog.{CATALOG_NAME}": "org.apache.iceberg.spark.SparkCatalog", f"spark.sql.catalog.{CATALOG_NAME}.type": "rest", f"spark.sql.catalog.{CATALOG_NAME}.warehouse": "default", f"spark.sql.catalog.{CATALOG_NAME}.uri": CATALOG_URI,
# Konfigurationen zur Bypassung von Validierungsprüfungen f"spark.sql.catalog.{CATALOG_NAME}.check-location": "false", f"spark.sql.catalog.{CATALOG_NAME}.validation.check-location-exists": "false", f"spark.sql.catalog.{CATALOG_NAME}.metadata.check-location-exists": "false",
# --- OAuth2 Authentifizierung --- f"spark.sql.catalog.{CATALOG_NAME}.rest.auth.type": "com.dremio.iceberg.authmgr.oauth2.OAuth2Manager", f"spark.sql.catalog.{CATALOG_NAME}.rest.auth.oauth2.client-auth": "none", f"spark.sql.catalog.{CATALOG_NAME}.rest.auth.oauth2.token-endpoint": f"https://{DREMIO_ADDRESS}/oauth/token", f"spark.sql.catalog.{CATALOG_NAME}.rest.auth.oauth2.grant-type": "urn:ietf:params:oauth:grant-type:token-exchange", f"spark.sql.catalog.{CATALOG_NAME}.rest.auth.oauth2.client-id": "dremio", f"spark.sql.catalog.{CATALOG_NAME}.rest.auth.oauth2.scope": "dremio.all", f"spark.sql.catalog.{CATALOG_NAME}.rest.auth.oauth2.token-exchange.subject-token": DREMIO_PAT, f"spark.sql.catalog.{CATALOG_NAME}.rest.auth.oauth2.token-exchange.subject-token-type": "urn:ietf:params:oauth:token-type:dremio:personal-access-token",
# --- STS/Vended Credentials Konfiguration --- f"spark.sql.catalog.{CATALOG_NAME}.header.X-Iceberg-Access-Delegation": "vended-credentials", f"spark.sql.catalog.{CATALOG_NAME}.io-impl": "org.apache.iceberg.aws.s3.S3FileIO", f"spark.sql.catalog.{CATALOG_NAME}.s3.vended-credentials-enabled": "true" } )
spark.sql(f"USE {CATALOG_NAME}").show(truncate=False)spark.sql("SHOW NAMESPACES").show()
spark.sql(f"CREATE TABLE IF NOT EXISTS {CATALOG_NAME}.test.customer (id INT, name STRING, age INT) USING iceberg")spark.sql(f"SELECT * FROM {CATALOG_NAME}.test.customer ORDER BY id").show()spark.sql(f"INSERT INTO {CATALOG_NAME}.test.customer VALUES (1, 'Daniel', 30), (2, 'Jane', 25)")spark.sql(f"SELECT * FROM {CATALOG_NAME}.test.customer ORDER BY id").show()Spark interaktiv nutzen
Abschnitt betitelt „Spark interaktiv nutzen“-
Umgebungsvariablen setzen
Öffnen Sie ein Terminal in JupyterLab und exportieren Sie Ihr Dremio Personal Access Token (PAT):
Terminal-Fenster export DREMIO_PAT="ihr-token-hier"export DREMIO_ADDRESS=ihre-dremio-urlexport CATALOG_URI=ihre-katalog-uriAlternativ können Sie diese Umgebungsvariablen direkt in einer Code-Zelle durch
%env DREMIO_PAT="ihr-token-hier"setzen. -
Bibliotheken importieren Die Bibliothek
stackit_sparkist ein STACKIT-spezifischer Wrapper umpyspark. Sie übernimmt die zugrunde liegende Konfiguration, die für die Kommunikation mit dem Spark-Cluster erforderlich ist. -
Katalog definieren Im obigen Code definieren wir den
CATALOGalsstackit. Dieser dient als Namespace innerhalb Ihrer Spark SQL-Abfragen (zum BeispielSELECT * FROM stackit.DB.TABLE). -
SQL-Abfragen ausführen Sobald das
spark-Objekt initialisiert ist, können Siespark.sql()verwenden, um mit Ihren Iceberg-Tabellen wie mit einer gewöhnlichen SQL-Datenbank zu interagieren.
Integration mit Dremio
Abschnitt betitelt „Integration mit Dremio“Die Konfiguration nutzt den REST-Katalog-Typ von Iceberg. Dies stellt sicher, dass jede über Spark erstellte oder geänderte Tabelle sofort in Dremio sichtbar und lesbar ist. Voraussetzung dafür ist, dass Sie dieselbe Warehouse-URI verwenden.