Managed Service for Apache Spark 可讓您直接從 Spark 工作負載查詢及分析外部業務資料。您可以使用 Workday Live Data Query JDBC 驅動程式連結至 Workday 租戶、將即時 Workday 資料集載入 Spark DataFrame,並將該資料整合至 Google Cloud的數據分析管道。
在本指南中,您將設定 Workday Live Data Query、將私密金鑰安全地儲存在 Secret Manager,並使用 Google Cloud Data Agent Kit 擴充功能,在 Visual Studio Code 或 Cloud Shell 編輯器中,針對 Managed Service for Apache Spark 執行 PySpark 筆記本。
費用
Data Agent Kit 擴充功能無須額外付費。不過,本指南會使用下列 Google Cloud計費元件:
您可以使用 Pricing Calculator 根據預測用量估算費用。
事前準備
- 登入 Google Cloud 帳戶。如果您未曾使用過 Google Cloud,歡迎 建立帳戶,親自體驗實際使用我們產品的成效。新客戶還能獲得價值 $300 美元的免費抵免額,用於執行、測試及部署工作負載。
-
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 theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that you have the permissions required to complete this guide.
-
Verify that billing is enabled for your Google Cloud project.
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.enablepermission. 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.-
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 theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that you have the permissions required to complete this guide.
-
Verify that billing is enabled for your Google Cloud project.
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.enablepermission. 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.
必要的 Identity and Access Management (IAM) 角色
您必須具備特定 IAM 角色,才能執行本頁範例。視組織政策而定,這些角色可能已授予。如要查看角色授予,請參閱「是否需要授予角色?」一節。如要進一步瞭解如何授予角色,請參閱「管理專案、資料夾和組織的存取權」。
所需角色取決於工作負載的執行方式。Managed Service for Apache Spark 無伺服器 2.3 和更早版本的無伺服器執行階段,會以服務帳戶身分執行工作負載。根據預設,Managed Service for Apache Spark 無伺服器執行階段 3.0 以上版本會使用使用者憑證 (EUC) 執行工作負載,因此您必須將資料存取權角色授予使用者帳戶,而非服務帳戶。如果您為 3.0 以上版本的執行階段指定自訂服務帳戶,工作負載會使用服務帳戶憑證執行。詳情請參閱「無伺服器部署作業角色」。
使用者角色
如要取得建立 Managed Service for Apache Spark 互動式筆記本工作階段及存取資源所需的權限,請要求管理員授予您下列 IAM 角色:
-
使用無伺服器執行階段 2.3 以下版本:
- 專案的 Dataproc 編輯者 (
roles/dataproc.editor) - Compute Engine 預設服務帳戶或自訂服務帳戶的服務帳戶使用者 (
roles/iam.serviceAccountUser)
- 專案的 Dataproc 編輯者 (
-
使用無伺服器執行階段 3.0 以上版本:專案的 Dataproc Serverless 編輯者 (
roles/dataproc.serverlessEditor) -
使用使用者憑證從 Cloud Storage 讀取 JDBC 驅動程式:在包含驅動程式的 bucket 上,具備Storage 物件檢視者 (
roles/storage.objectViewer) 角色 -
使用使用者憑證,從 Secret Manager 讀取私密金鑰密鑰:密鑰或專案的 Secret Manager 密鑰存取者 (
roles/secretmanager.secretAccessor)
服務帳戶角色
將下列角色授予執行工作負載的服務帳戶。只有在工作負載使用服務帳戶憑證 (而非預設使用者憑證 (EUC)) 執行時,Managed Service for Apache Spark 無伺服器執行階段 3.0 以上版本才需要這些角色。
為確保 Compute Engine 預設服務帳戶或自訂服務帳戶具備必要權限,可執行 Managed Service for Apache Spark 工作負載、讀取驅動程式及存取密鑰,請要求管理員將下列 IAM 角色授予 Compute Engine 預設服務帳戶或自訂服務帳戶:
-
使用無伺服器執行階段 2.3 以下版本:專案的 Dataproc 工作者 (
roles/dataproc.worker) -
使用無伺服器執行階段 3.0 以上版本,並搭配服務帳戶憑證,而非預設使用者憑證 (EUC):
- 專案的 Dataproc Serverless 節點 (
roles/dataproc.serverlessNode) - 專案的 Dataproc Resource Manager 節點服務代理 (
roles/dataprocrm.nodeServiceAgent)
- 專案的 Dataproc Serverless 節點 (
-
從 Cloud Storage 讀取 JDBC 驅動程式:在含有驅動程式的 bucket 上,具備 Storage 物件檢視者 (
roles/storage.objectViewer) 角色 -
從 Secret Manager 讀取私密金鑰密鑰:密鑰或專案的 Secret Manager 密鑰存取者 (
roles/secretmanager.secretAccessor)
Workday 必要條件
使用即時資料查詢功能連線至 Workday 前,請先完成下列設定:
從 Workday 下載 Workday Live Data Query JDBC 驅動程式。
將下載的 JDBC 驅動程式 JAR 檔案上傳至專案中的 Cloud Storage bucket。
按照 Workday Live Data Query 說明文件中的說明,完成 Workday 租戶的 Live Data Query 設定步驟。
在 Workday 設定期間,請建立整合系統使用者 (ISU)、註冊 API 用戶端,並產生私密金鑰組。
請記下下列 Workday 設定值:
Workday 主機:Workday 租戶主機,例如
services1.workday.com。租戶名稱:Workday 租戶名稱。
用戶端 ID:Workday 租戶中已註冊的 API 用戶端 ID。
ISU username:整合系統使用者名稱。
將私密金鑰儲存在 Secret Manager
將設定 Workday Live Data Query 時產生的私密金鑰檔案,安全地儲存在 Secret Manager:
在 Cloud Shell 執行下列指令,產生 x509 金鑰組:
openssl req -x509 -newkey rsa:2048 -keyout private-key.pem -out public-key.cert -sha256 -days 365 -nodes執行下列指令,查看私密金鑰:
cat private-key.pem將私密金鑰儲存在 Secret Manager:
前往 Google Cloud 控制台的「Secret Manager」頁面:
點選建立 Secret。
在「Name」(名稱) 欄位中輸入 Secret 名稱,例如
workday-private-key。在「密鑰值」下方,上傳
private-key.pem或貼上私密金鑰內容,包括-----BEGIN PRIVATE KEY-----和-----END PRIVATE KEY-----標頭和頁尾行。點選建立 Secret。
執行下列指令,查看公開金鑰:
cat public-key.cert在 Workday 中搜尋「Create x509 Public Key」,貼上
public-key.cert的公開金鑰,然後按一下「OK」。在先前建立的 Workday API 用戶端中,將「x509 Certificate」更新為新的 x509 金鑰。
在 IDE 中設定 Data Agent Kit
如要設定 Data Agent Kit,您可以在 Visual Studio Code 或其他支援的 IDE 中安裝擴充功能,也可以使用 Cloud Shell 編輯器中預先安裝的擴充功能。
如要在 IDE 或 Cloud Shell 編輯器中設定 Data Agent Kit,請完成下列步驟:
設定 Data Agent Kit:
-
如果沒有 Managed Service for Apache Spark 無伺服器執行階段,請建立一個。
建立筆記本
使用 Data Agent Kit 建立互動式 PySpark 筆記本:
在 IDE 或 Cloud Shell 編輯器中,開啟「Data Agent Kit」面板。
在「Apache Spark」下方,依序選取「新增筆記本」和「本機核心」。
從可用執行階段 (也稱為工作階段範本) 清單中選取執行階段。
選取「從新筆記本開始」。
系統會開啟新的筆記本,並在初始儲存格中填入 Spark Connect 工作階段初始化程式碼。
在筆記本編輯器頂端,按一下「Select Kernel」,然後選取筆記本的本機 Python 核心。
在 PySpark 中查詢 Workday 資料
在第一個筆記本儲存格中,安裝必要的用戶端程式庫並設定環境變數:
%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在新的儲存格中,將 Secret Manager 密鑰存取者角色 (
roles/secretmanager.secretAccessor) 授予 Compute Engine 預設服務帳戶:%%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"在新的儲存格中,將 JDBC 驅動程式從 Cloud Storage 複製到本機目錄:
gsutil cp gs://$JDBC_DRIVER_GCS_BUCKET/$JDBC_DRIVER_FILE_NAME $JDBC_DRIVER_LOCAL_DIRECTORY在新的儲存格中,安裝 Secret Manager 用戶端程式庫:
%%bash pip install google-cloud-secret-manager在新的儲存格中,確認驅動程式 JAR 檔案已下載至本機:
!gsutil cp gs://$JDBC_DRIVER_GCS_BUCKET/$JDBC_DRIVER_FILE_NAME /tmp/ !ls -lh /tmp/ldq-jdbc-driver-1.1.0-all.jar在新的儲存格中,將 Workday 驅動程式 JAR 插入 PySpark JAR 目錄:
%%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."在新的儲存格中,設定 Spark 環境,並從 Secret Manager 擷取 x509 私密金鑰:
#@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()在新的儲存格中,使用 classpath 設定初始化 Spark 工作階段:
# 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!")在最後一個儲存格中,啟動連線並查詢 Workday:
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)更改下列內容:
PROJECT_ID:您的 Google Cloud 專案 ID。LOCATION:Managed Service for Apache Spark 工作階段範本的 Google Cloud 區域,例如us-central1。RUNTIME_ID:Managed Service for Apache Spark 工作階段範本的 ID。BUCKET_NAME:含有 Workday JDBC 驅動程式的 Cloud Storage bucket 名稱。PATH/workday-live-data-query-jdbc-driver.jar:Cloud Storage bucket 中 Workday JDBC 驅動程式 JAR 的物件路徑。WORKDAY_HOST:Workday 租戶主機,例如services1.workday.com。TENANT_NAME:Workday 租用戶名稱。CLIENT_ID:Workday 租戶中已註冊的 API 用戶端 ID。ISU_USERNAME:Workday 租戶的整合系統使用者名稱。
點選儲存格旁的「執行儲存格」(播放圖示),或按下 Shift+Enter 鍵。
Managed Service for Apache Spark 會執行查詢,並在儲存格下方顯示 Workday DataFrame 輸出內容。
清除所用資源
為避免系統向您的 Google Cloud 帳戶收取本指南所用資源的費用,請終止執行中的互動式工作階段,或刪除建立的資源。
終止互動式工作階段
在 IDE 或 Cloud Shell 編輯器中,當工作負載完成時,終止執行中的筆記本工作階段。
選用:如果不再需要 Cloud Storage bucket 或 JDBC 驅動程式 JAR 檔案,請刪除這些檔案。
選用:如果不再需要 Secret Manager 中的密鑰,請將其刪除:
gcloud secrets delete workday-private-key
後續步驟
進一步瞭解 Workday Live Data Query。
進一步瞭解 Data Agent Kit。
瞭解 Spark JDBC 連線選項。