Mit Spark auf Workday-Daten zugreifen

Mit Managed Service for Apache Spark können Sie externe Geschäftsdaten direkt aus Ihren Spark-Arbeitslasten abfragen und analysieren. Mit dem JDBC-Treiber für Workday Live Data Query können Sie eine Verbindung zu Ihrem Workday-Mandanten herstellen, Workday-Live-Datasets in Spark-DataFrames laden und diese Daten in Ihre Analysepipeline in Google Cloudeinbinden.

In dieser Anleitung konfigurieren Sie Workday Live Data Query, speichern Ihren privaten Schlüssel sicher in Secret Manager und verwenden die Google Cloud Data Agent Kit-Erweiterung, um ein PySpark-Notebook in Visual Studio Code oder Cloud Shell-Editor für Managed Service for Apache Spark auszuführen.

Kosten

Die Data Agent Kit-Erweiterung ist ohne zusätzliche Kosten verfügbar. In dieser Anleitung werden jedoch die folgenden kostenpflichtigen Komponenten von Google Cloudverwendet:

Mit dem Preisrechner können Sie eine Kostenschätzung Ihrer voraussichtlichen Nutzung vornehmen.

Hinweis

  1. Melden Sie sich in Ihrem Google Cloud -Konto an. Wenn Sie mit Google Cloudnoch nicht vertraut sind, erstellen Sie einfach ein Konto, um die Leistungsfähigkeit unserer Produkte in der Praxis sehen und bewerten zu können. Neukunden erhalten außerdem ein Guthaben von 300 $, um Arbeitslasten auszuführen, zu testen und bereitzustellen.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that you have the permissions required to complete this guide.

  4. Verify that billing is enabled for your Google Cloud project.

  5. Enable the Dataproc, Dataplex, Cloud Storage, and Secret Manager APIs, if any are not already enabled.

    Roles required to enable APIs

    To enable APIs, you need the serviceusage.services.enable permission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.

    Enable the APIs

  6. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  7. Verify that you have the permissions required to complete this guide.

  8. Verify that billing is enabled for your Google Cloud project.

  9. Enable the Dataproc, Dataplex, Cloud Storage, and Secret Manager APIs, if any are not already enabled.

    Roles required to enable APIs

    To enable APIs, you need the serviceusage.services.enable permission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.

    Enable the APIs

Erforderliche IAM-Rollen (Identity and Access Management)

Zum Ausführen der Beispiele auf dieser Seite sind bestimmte IAM-Rollen erforderlich. Je nach Organisationsrichtlinien wurden diese Rollen möglicherweise bereits gewährt. Informationen zum Prüfen von Rollenzuweisungen finden Sie unter Müssen Sie Rollen zuweisen?. Weitere Informationen zum Zuweisen von Rollen finden Sie unter Zugriff auf Projekte, Ordner und Organisationen verwalten.

Welche Rollen Sie benötigen, hängt davon ab, wie Ihre Arbeitslast ausgeführt wird. In Managed Service for Apache Spark Serverless 2.3 und früheren serverlosen Laufzeiten werden Arbeitslasten als Dienstkonto ausgeführt. In Managed Service for Apache Spark-Serverless-Laufzeiten ab Version 3.0 werden Arbeitslasten standardmäßig mit Ihren Endnutzer-Anmeldedaten (EUC) ausgeführt. Daher weisen Sie Ihrem Nutzerkonto anstelle eines Dienstkontos Rollen für den Datenzugriff zu. Wenn Sie ein benutzerdefiniertes Dienstkonto für eine Laufzeit der Version 3.0 oder höher angeben, wird die Arbeitslast mit den Anmeldedaten des Dienstkontos ausgeführt. Weitere Informationen finden Sie unter Rollen für serverlose Bereitstellungen.

Nutzerrollen

Bitten Sie Ihren Administrator, Ihnen die folgenden IAM-Rollen zuzuweisen, um die Berechtigungen zu erhalten, die Sie zum Erstellen einer interaktiven Notebook-Sitzung für Managed Service for Apache Spark und zum Zugriff auf Ressourcen benötigen:

  • Verwenden Sie die serverlose Laufzeit 2.3 oder eine frühere Version:
    • Dataproc-Bearbeiter (roles/dataproc.editor) für das Projekt
    • Dienstkontonutzer (roles/iam.serviceAccountUser) für das Compute Engine-Standarddienstkonto oder ein benutzerdefiniertes Dienstkonto
  • Serverlose Laufzeit 3.0 oder höher verwenden: Dataproc Serverless-Bearbeiter (roles/dataproc.serverlessEditor) für das Projekt
  • JDBC-Treiber mit Endnutzer-Anmeldedaten aus Cloud Storage lesen: Storage-Objekt-Betrachter (roles/storage.objectViewer) für den Bucket, der den Treiber enthält
  • Lesen Sie das Secret für den privaten Schlüssel aus Secret Manager mit Endnutzer-Anmeldedaten: Secret Manager Secret Accessor (roles/secretmanager.secretAccessor) für das Secret oder Projekt

Dienstkontorollen

Weisen Sie dem Dienstkonto, das Ihre Arbeitslast ausführt, die folgenden Rollen zu. Für serverlose Laufzeiten von Managed Service for Apache Spark ab Version 3.0 sind diese Rollen nur erforderlich, wenn die Arbeitslast mit Dienstkonto-Anmeldedaten anstelle der standardmäßigen Endnutzer-Anmeldedaten (EUC) ausgeführt wird.

Damit das Compute Engine-Standarddienstkonto oder ein benutzerdefiniertes Dienstkonto die erforderlichen Berechtigungen zum Ausführen von Managed Service for Apache Spark-Arbeitslasten, zum Lesen des Treibers und zum Zugriff auf Secrets hat, bitten Sie Ihren Administrator, dem Compute Engine-Standarddienstkonto oder einem benutzerdefinierten Dienstkonto die folgenden IAM-Rollen zu gewähren:

  • Verwenden Sie die serverlose Laufzeit 2.3 oder früher: Dataproc-Worker (roles/dataproc.worker) für das Projekt
  • Verwenden Sie die serverlose Laufzeit 3.0 oder höher mit Dienstkonto-Anmeldedaten anstelle der standardmäßigen EUC (End User Credentials):
  • JDBC-Treiber aus Cloud Storage lesen: Storage-Objekt-Betrachter (roles/storage.objectViewer) für den Bucket, der den Treiber enthält
  • Lesen des Secrets für den privaten Schlüssel aus Secret Manager: Secret Manager Secret Accessor (roles/secretmanager.secretAccessor) für das Secret oder Projekt

Voraussetzungen für Workday

Führen Sie die folgende Einrichtung durch, bevor Sie über Live Data Query eine Verbindung zu Workday herstellen:

  1. Laden Sie den JDBC-Treiber für Workday Live Data Query von Workday herunter.

  2. Laden Sie die heruntergeladene JDBC-Treiber-JAR-Datei in einen Cloud Storage-Bucket in Ihrem Projekt hoch.

  3. Führen Sie die Konfigurationsschritte zum Einrichten von Live Data Query in Ihrem Workday-Mandanten aus, wie in der Dokumentation zu Workday Live Data Query beschrieben.

    Erstellen Sie während der Konfiguration in Workday einen Integrationssystemnutzer (Integration System User, ISU), registrieren Sie einen API-Client und generieren Sie ein privates Schlüsselpaar.

  4. Beachten Sie die folgenden Workday-Konfigurationswerte:

    • Workday-Host: Ihr Workday-Mandantenhost, z. B. services1.workday.com.

    • Mandantenname: Ihr Workday-Mandantenname.

    • Client-ID: Die registrierte API-Client-ID Ihres Workday-Mandanten.

    • ISU-Nutzername: der Nutzername des Integrationssystemnutzers.

Privaten Schlüssel in Secret Manager speichern

Speichern Sie die private Schlüsseldatei, die während der Konfiguration von Workday Live Data Query generiert wurde, sicher in Secret Manager:

  1. Führen Sie in Cloud Shell den folgenden Befehl aus, um ein x509-Schlüsselpaar zu generieren:

    openssl req -x509 -newkey rsa:2048 -keyout private-key.pem -out public-key.cert -sha256 -days 365 -nodes
    
  2. Führen Sie den folgenden Befehl aus, um den privaten Schlüssel aufzurufen:

    cat private-key.pem
    
  3. Speichern Sie den privaten Schlüssel in Secret Manager:

    1. Rufen Sie in der Google Cloud Console die Seite Secret Manager auf:

      Zu Secret Manager

    2. Klicken Sie auf Secret erstellen.

    3. Geben Sie im Feld Name einen Namen für das Secret ein, z. B. workday-private-key.

    4. Laden Sie unter Secret-Wert die Datei private-key.pem hoch oder fügen Sie den Inhalt des privaten Schlüssels ein, einschließlich der Kopf- und Fußzeilen -----BEGIN PRIVATE KEY----- und -----END PRIVATE KEY-----.

    5. Klicken Sie auf Secret erstellen.

  4. Führen Sie den folgenden Befehl aus, um den öffentlichen Schlüssel aufzurufen:

    cat public-key.cert
    
  5. Suchen Sie in Workday nach Create x509 Public Key (Öffentlichen x509-Schlüssel erstellen), fügen Sie den öffentlichen Schlüssel aus public-key.cert ein und klicken Sie auf OK.

  6. Aktualisieren Sie im zuvor erstellten Workday API-Client das X.509-Zertifikat auf den neuen X.509-Schlüssel.

Data Agent Kit in Ihrer IDE einrichten

Sie können das Data Agent Kit entweder einrichten, indem Sie die Erweiterung in Visual Studio Code oder einer anderen unterstützten IDE installieren, oder indem Sie die vorinstallierte Erweiterung im Cloud Shell-Editor verwenden.

So konfigurieren Sie das Data Agent Kit in Ihrer IDE oder im Cloud Shell-Editor:

  1. Richten Sie das Data Agent Kit ein und konfigurieren Sie es:

    1. Installieren Sie die Data Agent Kit-Erweiterung.

    2. Data Agent Kit konfigurieren

Notebook erstellen

Erstellen Sie mit dem Data Agent Kit ein interaktives PySpark-Notebook:

  1. Öffnen Sie in Ihrer IDE oder im Cloud Shell-Editor den Bereich Data Agent Kit.

  2. Wählen Sie unter Apache Spark die Option Neues Notebook und dann Lokaler Kernel aus.

  3. Wählen Sie eine Laufzeit aus der Liste der verfügbaren Laufzeiten (auch Sitzungsvorlagen genannt) aus.

  4. Wählen Sie Mit einem neuen Notebook beginnen aus.

    Ein neues Notebook wird geöffnet. Die erste Zelle enthält den Code zur Initialisierung der Spark Connect-Sitzung.

  5. Klicken Sie oben im Notebook-Editor auf Kernel auswählen und wählen Sie dann einen lokalen Python-Kernel für Ihr Notebook aus.

Workday-Daten in PySpark abfragen

  1. Installieren Sie in der ersten Notebook-Zelle die erforderlichen Clientbibliotheken und richten Sie Umgebungsvariablen ein:

    %pip install dataproc-spark-connect google-cloud-dataproc google-cloud-secret-manager google-cloud-storage
    
    #@title Set up all environment variables
    
    # Replace with your Project ID
    %env PROJECT_ID=PROJECT_ID
    
    # Replace with the name of the Secret Manager global secret in the project
    %env SECRET_NAME=workday-private-key
    # Replace with the version of the secret to use
    %env SECRET_VERSION=latest
    
    # Replace with the Cloud Storage bucket where you have the Workday Data Cloud JDBC Driver file stored
    %env JDBC_DRIVER_GCS_BUCKET=BUCKET_NAME
    # Replace with the name of the Workday Data Cloud JDBC Driver file in the Cloud Storage bucket
    %env JDBC_DRIVER_FILE_NAME=ldq-jdbc-driver-1.1.0-all.jar
    # Replace with the local directory of the notebook to copy the JDBC Driver File to
    %env JDBC_DRIVER_LOCAL_DIRECTORY=/tmp
    # Replace with the Driver Class for the Workday Data Cloud JDBC Driver
    %env WORKDAY_DRIVER_CLASS=com.workday.ldq.jdbc.Driver
    
    # ------------------------------------------------------------------------------
    
    # Replace with the Workday URL of your tenant
    %env WORKDAY_HOST=WORKDAY_HOST
    # Replace with your Workday tenant name
    %env TENANT_NAME=TENANT_NAME
    # Replace with the Client ID of the "API Client"
    %env CLIENT_ID=CLIENT_ID
    # Replace with the Integration System User username
    %env ISU_USERNAME=ISU_USERNAME
    
  2. Weisen Sie dem Compute Engine-Standarddienstkonto in einer neuen Zelle die Rolle „Secret Manager Secret Accessor“ (roles/secretmanager.secretAccessor) zu:

    %%bash
    COMPUTE_ENGINE_DEFAULT_SERVICE_ACCOUNT=$(gcloud iam service-accounts list --project="${PROJECT_ID}" \
      --filter="email ~ -compute@developer.gserviceaccount.com" \
      --format="value(email)")
    
    echo "COMPUTE_ENGINE_DEFAULT_SERVICE_ACCOUNT: ${COMPUTE_ENGINE_DEFAULT_SERVICE_ACCOUNT}"
    
    gcloud secrets add-iam-policy-binding ${SECRET_NAME} \
      --project="${PROJECT_ID}" \
      --member="serviceAccount:${COMPUTE_ENGINE_DEFAULT_SERVICE_ACCOUNT}" \
      --role="roles/secretmanager.secretAccessor"
    
  3. Kopieren Sie den JDBC-Treiber aus Cloud Storage in einer neuen Zelle in das lokale Verzeichnis:

    gsutil cp gs://$JDBC_DRIVER_GCS_BUCKET/$JDBC_DRIVER_FILE_NAME $JDBC_DRIVER_LOCAL_DIRECTORY
    
  4. Installieren Sie in einer neuen Zelle die Secret Manager-Clientbibliothek:

    %%bash
    pip install google-cloud-secret-manager
    
  5. Prüfen Sie in einer neuen Zelle, ob die JAR-Datei des Treibers lokal heruntergeladen wurde:

    !gsutil cp gs://$JDBC_DRIVER_GCS_BUCKET/$JDBC_DRIVER_FILE_NAME /tmp/
    !ls -lh /tmp/ldq-jdbc-driver-1.1.0-all.jar
    
  6. Fügen Sie in einer neuen Zelle die JAR-Datei des Workday-Treibers in das PySpark-JAR-Verzeichnis ein:

    %%bash
    
    echo "Downloading Workday JAR from Cloud Storage..."
    # Downloads your specific 1.1.0 driver JAR into the notebook's /tmp folder
    gcloud storage cp gs://$JDBC_DRIVER_GCS_BUCKET/$JDBC_DRIVER_FILE_NAME /tmp/
    
    echo "Dynamically finding the PySpark jars directory..."
    PYSPARK_JARS=$(python -c "import os, pyspark; print(os.path.join(os.path.dirname(pyspark.__file__), 'jars'))")
    echo "Found PySpark jars at: $PYSPARK_JARS"
    
    echo "Injecting Workday driver into PySpark core..."
    cp /tmp/$JDBC_DRIVER_FILE_NAME "$PYSPARK_JARS/"
    
    echo "Success! The driver is now a native part of PySpark."
    
  7. Konfigurieren Sie in einer neuen Zelle die Spark-Umgebung und rufen Sie den privaten x509-Schlüssel aus Secret Manager ab:

    #@title Configure the Spark environment and retrieve the x509 private key from Secret Manager
    
    import os
    import pyspark
    from pyspark.sql import SparkSession
    from google.cloud import secretmanager
    
    PROJECT_ID = os.environ["PROJECT_ID"]
    SECRET_NAME = os.environ["SECRET_NAME"]
    SECRET_VERSION = os.environ["SECRET_VERSION"]
    JDBC_DRIVER_LOCAL_DIRECTORY = os.environ["JDBC_DRIVER_LOCAL_DIRECTORY"]
    JDBC_DRIVER_FILE_NAME = os.environ["JDBC_DRIVER_FILE_NAME"]
    LOCAL_JAR_PATH = JDBC_DRIVER_LOCAL_DIRECTORY + "/" + JDBC_DRIVER_FILE_NAME
    WORKDAY_HOST = os.environ["WORKDAY_HOST"]
    TENANT_NAME = os.environ["TENANT_NAME"]
    CLIENT_ID = os.environ["CLIENT_ID"]
    ISU_USERNAME = os.environ["ISU_USERNAME"]
    WORKDAY_DRIVER_CLASS = os.environ["WORKDAY_DRIVER_CLASS"]
    
    jdbc_url = f"jdbc:workday://{WORKDAY_HOST}:443/system/information_schema?SSLVerification=CA"
    
    def access_private_key_secret():
        print(f"Fetching secret contents from Secret Manager: {SECRET_NAME}...")
        client = secretmanager.SecretManagerServiceClient()
        secret_name = f"projects/{PROJECT_ID}/secrets/{SECRET_NAME}/versions/{SECRET_VERSION}"
        response = client.access_secret_version(request={"name": secret_name})
        print(f"Fetched secret contents from Secret Manager: {SECRET_NAME}")
        return response.payload.data.decode("UTF-8")
    
    private_key_content = access_private_key_secret()
    
  8. Initialisieren Sie die Spark-Sitzung in einer neuen Zelle mit der Klassenpfadkonfiguration:

    # Stop the old cached Spark session so your newly downloaded JAR is not ignored!
    try:
        spark.stop()
        print("Stopped existing Spark session.")
    except Exception:
        pass
    
    print("Initializing fresh Spark session with Classpath configuration...")
    print(f"Loading JAR from: {LOCAL_JAR_PATH}")
    
    # Rebuild Spark session with explicit Driver & Executor classpaths
    spark = SparkSession.builder \
        .appName("WorkdayJDBC Connection Example") \
        .config("spark.jars", LOCAL_JAR_PATH) \
        .config("spark.driver.extraClassPath", LOCAL_JAR_PATH) \
        .config("spark.executor.extraClassPath", LOCAL_JAR_PATH) \
        .getOrCreate()
    print("Spark Session successfully booted with JAR!")
    
  9. Initiieren Sie in einer letzten Zelle die Verbindung und fragen Sie Workday ab:

    import os
    import subprocess
    import zipfile
    from pyspark.sql import SparkSession
    
    LOCAL_JAR_PATH = "/tmp/ldq-jdbc-driver-1.1.0-all.jar"
    
    # Load bucket and file name from your Cell 1 environment variables
    GCS_BUCKET = os.environ.get("JDBC_DRIVER_GCS_BUCKET", "BUCKET_NAME")
    GCS_FILE = os.environ.get("JDBC_DRIVER_FILE_NAME", "ldq-jdbc-driver-1.1.0-all.jar")
    GCS_URI = f"gs://{GCS_BUCKET}/{GCS_FILE}"
    
    # 1. Ensure the JAR file is in the notebook's /tmp directory
    if not os.path.exists(LOCAL_JAR_PATH):
        print(f"Downloading {GCS_URI} to {LOCAL_JAR_PATH}...")
        subprocess.run(["gsutil", "cp", GCS_URI, LOCAL_JAR_PATH], check=True)
    print(f"JAR verified on disk: {LOCAL_JAR_PATH} ({os.path.getsize(LOCAL_JAR_PATH):,} bytes)")
    
    # 2. Read the real JDBC driver class name (skipping any '#' comment lines!)
    with zipfile.ZipFile(LOCAL_JAR_PATH, "r") as z:
        raw_lines = (
            z.read("META-INF/services/java.sql.Driver")
            .decode("utf-8")
            .splitlines()
        )
        # Filter out empty lines and '#' comment lines
        valid_classes = [
            line.strip()
            for line in raw_lines
            if line.strip() and not line.strip().startswith("#")
        ]
        driver_class = valid_classes[0]
    
    print(f"Real Driver Class inside JAR: {driver_class}")
    
    # 3. Get or create the Spark session
    spark = SparkSession.builder.appName("WorkdayJDBC Connection Example").getOrCreate()
    
    # 4. Inject the JAR directly into the running Java URLClassLoader (and Scala SparkContext)
    jvm = spark.sparkContext._jvm
    jar_url = jvm.java.io.File(LOCAL_JAR_PATH).toURI().toURL()
    
    # Add to both the Spark classloader and the current thread's context classloader
    jvm.org.apache.spark.util.Utils.getContextOrSparkClassLoader().addURL(jar_url)
    jvm.java.lang.Thread.currentThread().getContextClassLoader().addURL(jar_url)
    spark.sparkContext._jsc.sc().addJar(LOCAL_JAR_PATH)
    
    # Register the driver class with Spark's JDBC DriverRegistry
    jvm.org.apache.spark.sql.execution.datasources.jdbc.DriverRegistry.register(driver_class)
    print(f"Successfully registered {driver_class} in Spark's live JVM!")
    
    # 5. Query Workday
    print("Querying Workday...")
    df_data = (
        spark.read.format("jdbc")
        .option("driver", driver_class)
        .option("url", jdbc_url)
        .option("wd.authn.clientId", CLIENT_ID)
        .option("wd.authn.isu", ISU_USERNAME)
        .option(
            "wd.authn.accessTokenEndpoint",
            f"https://{WORKDAY_HOST}/ccx/oauth2/{TENANT_NAME}/token",
        )
        .option("wd.authn.privateKey", private_key_content)
        .option("query", "SELECT * FROM system.jdbc.catalogs")
        .load()
    )
    
    print("Connection Successful! Data Retrieved:")
    df_data.show(50, truncate=False)
    

    Ersetzen Sie Folgendes:

    • PROJECT_ID: Projekt-ID in Google Cloud .
    • LOCATION: die Google Cloud -Region Ihrer Managed Service for Apache Spark-Sitzungsvorlage, z. B. us-central1.
    • RUNTIME_ID: die ID Ihrer Sitzungsvorlage für Managed Service for Apache Spark.
    • BUCKET_NAME: der Name des Cloud Storage-Bucket, der den Workday-JDBC-Treiber enthält.
    • PATH/workday-live-data-query-jdbc-driver.jar: der Objektpfad zur JAR-Datei des Workday-JDBC-Treibers in Ihrem Cloud Storage-Bucket.
    • WORKDAY_HOST: Ihr Workday-Mandantenhost, z. B. services1.workday.com.
    • TENANT_NAME: der Name Ihres Workday-Mandanten.
    • CLIENT_ID: die registrierte API-Client-ID Ihres Workday-Mandanten.
    • ISU_USERNAME: der Nutzername des Integrationssystemnutzers aus Ihrem Workday-Mandanten.
  10. Klicken Sie neben der Zelle auf Zelle ausführen (das Wiedergabesymbol) oder drücken Sie Umschalttaste + Eingabetaste.

    Managed Service for Apache Spark führt die Abfrage aus und zeigt die Workday-DataFrame-Ausgabe unter der Zelle an.

Bereinigen

Damit Ihrem Google Cloud Konto die in dieser Anleitung verwendeten Ressourcen nicht in Rechnung gestellt werden, beenden Sie aktive interaktive Sitzungen oder löschen Sie die erstellten Ressourcen.

Interaktive Sitzung beenden

  1. Beenden Sie in Ihrer IDE oder im Cloud Shell-Editor die aktive Notebook-Sitzung, wenn Ihre Arbeitslast abgeschlossen ist.

  2. Optional: Löschen Sie den Cloud Storage-Bucket oder die JAR-Datei des JDBC-Treibers, wenn Sie sie nicht mehr benötigen.

  3. Optional: Löschen Sie das Secret aus Secret Manager, wenn es nicht mehr benötigt wird:

    gcloud secrets delete workday-private-key
    

Nächste Schritte