Building a Governed Iceberg Lakehouse with BigLake and Dataplex

1. מבוא

בסביבת Data Cloud ארגונית מודרנית, שבה הנתונים מאוחסנים במערכות אחסון פיזיות שונות, יש אתגר ארכיטקטוני עצום של אבטחה מפוצלת.

איך אפשר לוודא שנתונים רגישים (כמו סכומי עסקאות פיננסיות) מוגנים באופן עקבי כשהנתונים מאוחסנים פיזית בפורמטים של קוד פתוח כמו Parquet ב-Google Cloud Storage ונשלפים באמצעות מנועים שונים, כמו BigQuery SQL או Apache Spark?

בשיעור Codelab הזה, תיצרו ארכיטקטורה של lakehouse מנוהל שפותרת את הבעיות האלה באמצעות טבלאות Apache Iceberg,‏ BigQuery ו-Dataplex Universal Catalog. תשתמשו בתשתית כקוד (IaC) כדי להגדיר מדיניות אבטחה של אפס אמון, ואיך היא נאכפת באופן דינמי במנועי מחשוב שונים.

דרישות מוקדמות

  • פרויקט ב-Google Cloud שהחיוב בו מופעל.
  • הבנה בסיסית של מושגי SQL,‏ IAM ו-Cloud Storage.

מה תלמדו

סקירה כללית של הארכיטקטורה: ניהול אוניברסלי ב-Iceberg

6f05a096ec94f996.png

כדי להשיג בקרת גישה ברמת גרנולריות גבוהה (כמו אבטחה ברמת העמודה והסתרת נתונים) בפורמטים של נתונים בקוד פתוח, צריך ליצור ארכיטקטורת אבטחה מחמירה ומאוחדת.

כפי שמוצג בתרשים, התבנית הזו של lakehouse מבוססת על שני עקרונות מרכזיים כדי לפתור את אתגר האבטחה המפוצל:

‫🛡️ השכבות הארכיטקטוניות המאובטחות (מימין)

במקום לאפשר למשתמשים או למנועים חיצוניים לגשת ישירות ל-Cloud Storage – שמאפשר רק אבטחה רחבה ברמת הקטגוריה – אתם בונים בסיס מאובטח.

  • פורמט פתוח, מטא-נתונים מנוהלים: הנתונים נשארים פיזית ב-Cloud Storage בפורמט הפתוח Apache Iceberg ‏ (Parquet), בזמן ש-BigLake מנהל בצורה חלקה את המטא-נתונים השולטים.
  • גבול אבטחה לוגי: אתם מפרידים בין הגישה לאחסון הפיזי לבין הגישה הלוגית לנתונים באמצעות קישור מאובטח למשאבים ב-Cloud. למשתמשי קצה אף פעם לא מוענקת גישה פיזית ישירה ל-IAM לקבצים הגולמיים ב-GCS.
  • העברת הרשאות מחשוב לפי עקרונות של אפס אמון: כדי לוודא שאף מנוע ביצוע לא יכול לעקוף את כללי הממשל, כל בקשות הקריאה של הנתונים מנותבות באופן קפדני דרך BigQuery Storage API. זה נכון גם אם השאילתה מגיעה מ-BigQuery SQL מקורי או מ-Apache Spark בקוד פתוח.

🎯 אכיפת מדיניות מרכזית (מימין)

אחרי שמקימים את הבסיס המאובטח, Dataplex משמש כמרכז בקרה מאוחד לניהול:

  • הגדרה פעם אחת, אכיפה בכל מקום: מגדירים את תגי המדיניות ב-Dataplex רק פעם אחת, והארכיטקטורה מחילה כללי מיסוך עקביים באופן אוניברסלי בכל סביבות זמן הריצה הנתמכות.
  • הסתרת נתונים דינמית: כשמתבצעת שאילתה על נתונים, המערכת מעריכה את זהות המשתמש באופן דינמי. משתמשים מורשים יראו את הערכים הגולמיים שלא הוסתרו (למשל, 100.0) גם ב-SQL וגם ב-Spark, אבל משתמשים עם הרשאות מוגבלות יקבלו באופן אוטומטי ערכי NULL מוסתרים בעמודות מוגבלות בשני המנועים.
  • שקיפות אוטומטית של מקורות הנתונים: כשהנתונים זורמים ועוברים שינויים, Dataplex מתעד באופן אוטומטי את המטא-נתונים של השינויים, ומספק יכולות מובנות של ביקורת ומעקב מקצה לקצה, בלי שנדרש קוד רישום מותאם אישית.

2. הגדרה ודרישות

מפעילים את Cloud Shell

אפשר להפעיל את Google Cloud מרחוק מהמחשב הנייד, אבל ב-codelab הזה תשתמשו ב-Google Cloud Shell, סביבת שורת פקודה שפועלת בענן.

ב-מסוף Google Cloud, לוחצים על סמל Cloud Shell בסרגל הכלים שבפינה הימנית העליונה:

הפעלת Cloud Shell

יחלפו כמה רגעים עד שההקצאה והחיבור לסביבת העבודה יושלמו. בסיום התהליך, אמור להופיע משהו כזה:

צילום מסך של טרמינל Google Cloud Shell שבו מוצג שהסביבה מחוברת

המכונה הווירטואלית הזו כוללת את כל הכלים שדרושים למפתחים. יש בה ספריית בית בנפח מתמיד של 5GB והיא פועלת ב-Google Cloud, מה שמשפר מאוד את הביצועים והאימות ברשת. אפשר לבצע את כל העבודה ב-codelab הזה בדפדפן. לא צריך להתקין שום דבר.

אתחול הסביבה

פותחים את Cloud Shell ומגדירים את משתני הפרויקט כדי לוודא שכל הפקודות מכוונות לתשתית הנכונה.

export PROJECT_ID=$(gcloud config get-value project)
export REGION="us-central1"
export ICEBERG_BUCKET="iceberg-retail-demo-${PROJECT_ID}"
export DATASET_ID="lakehouse_retail_demo"
export CONN_NAME="iceberg-bq-conn-demo"

לאחר מכן מגדירים את שתי דמויות הקונים.

export USER_ANALYST="retail-analyst-demo"
export EMAIL_ANALYST="${USER_ANALYST}@${PROJECT_ID}.iam.gserviceaccount.com"

export USER_MANAGER="retail-manager-demo"
export EMAIL_MANAGER="${USER_MANAGER}@${PROJECT_ID}.iam.gserviceaccount.com"
export CURRENT_USER=$(gcloud config get-value account)

הפעלת ממשקי API

מפעילים את שירותי Google Cloud הנדרשים.

gcloud services enable \
  bigquery.googleapis.com \
  bigqueryconnection.googleapis.com \
  datacatalog.googleapis.com \
  bigquerydatapolicy.googleapis.com \
  datalineage.googleapis.com \
  dataplex.googleapis.com \
  dataproc.googleapis.com \
  storage-component.googleapis.com

הורדת קוד המקור של ה-Codelab

כדי להימנע מבלגן ב-Cloud Shell, תבצעו sparse checkout כדי להוריד רק את סקריפטים Python הנדרשים ל-codelab הזה ממאגר DevRel של Google Cloud.

# Shallow clone without full history
git clone --depth 1 --filter=blob:none --sparse https://github.com/GoogleCloudPlatform/devrel-demos.git
cd devrel-demos

# Download only the specific folder
git sparse-checkout set data-analytics/governed-lakehouse
cd data-analytics/governed-lakehouse

יצירת אחסון

יוצרים את הקטגוריה לאחסון נתוני Iceberg מאובטחים ומפוקחים.

gcloud storage buckets create gs://${ICEBERG_BUCKET} --location=${REGION}

הכנת זהויות ואבטחה

הגדרת הקישור למשאבים ב-Cloud. זוהי הישות היחידה שמחזיקה במפתחות ה-IAM הפיזיים הקבועים לקריאת קובצי Iceberg הגולמיים.

# Create the BigQuery connection
bq mk --connection \
    --connection_type=CLOUD_RESOURCE \
    --location=${REGION} \
    ${CONN_NAME}

# Retrieve the connection's automatically generated Service Account
export BQ_CONN_SVC_ACCT=$(bq show --format=json --connection ${REGION}.${CONN_NAME} \
    | jq -r '.cloudResource.serviceAccountId')

# Grant Storage Object Admin to the connection for the Iceberg bucket
gcloud storage buckets add-iam-policy-binding gs://${ICEBERG_BUCKET} \
    --member="serviceAccount:${BQ_CONN_SVC_ACCT}" \
    --role="roles/storage.objectAdmin" \
    --quiet

לאחר מכן מגדירים את פרסונות המשתמשים. למשתמשים ניתנת גישה לוגית, ולא גישה לאחסון פיזי. כדי למנוע שגיאות שנגרמות בגלל עיכובים בהפצת IAM, קודם יוצרים את החשבונות, מחכים כמה שניות ואז מקצים להם את התפקידים.

echo "Creating Service Accounts..."
for USER in "${USER_ANALYST}" "${USER_MANAGER}"; do
    gcloud iam service-accounts create ${USER} --display-name="Lakehouse ${USER}"
done

echo "⏳ Waiting 15 seconds for IAM propagation..."
sleep 15

echo "Granting IAM Roles to Service Accounts..."
for USER in "${USER_ANALYST}" "${USER_MANAGER}"; do
    EMAIL="${USER}@${PROJECT_ID}.iam.gserviceaccount.com"
    
    # Allow Cloud Shell to impersonate them for testing
    gcloud iam service-accounts add-iam-policy-binding ${EMAIL} \
        --member="user:${CURRENT_USER}" \
        --role="roles/iam.serviceAccountTokenCreator" \
        --quiet

    # Allow logical viewing of the catalog, querying, and running Dataproc jobs
    for ROLE in "roles/datacatalog.viewer" "roles/bigquery.dataViewer" "roles/bigquery.user" "roles/bigquery.connectionUser" "roles/serviceusage.serviceUsageConsumer" "roles/dataproc.worker"; do
        gcloud projects add-iam-policy-binding ${PROJECT_ID} \
            --member="serviceAccount:${EMAIL}" \
            --role="${ROLE}" \
            --quiet
    done
done

# Grant the Manager data creation rights
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
    --member="serviceAccount:${EMAIL_MANAGER}" \
    --role="roles/bigquery.dataEditor" \
    --quiet

echo "✅ Identity and Security setup completed!"

3. יצירת טבלאות Iceberg מקוריות באמצעות BigLake

תשתמשו ביכולות המובנות של BigLake כדי ליצור את טבלאות Iceberg המנוהלות.

יצירת מערך נתונים ב-BigQuery

קודם צריך ליצור מערך נתונים ב-BigQuery כדי לקבץ באופן לוגי את טבלאות Iceberg.

echo "Creating BigQuery Dataset..."
bq mk --location=${REGION} --dataset ${PROJECT_ID}:${DATASET_ID}

יצירת טבלאות Iceberg

לאחר מכן, מריצים את הפקודות הבאות כדי ליצור את הטבלאות. שימו לב לבלוק OPTIONS שבו אנחנו מציינים את table_format = 'ICEBERG' וממפים אותו ישירות לקטגוריה של Cloud Storage ולחיבור שלנו.

echo "Creating Iceberg tables..."

# Inventory table
bq query --use_legacy_sql=false \
"CREATE OR REPLACE TABLE \`${PROJECT_ID}.${DATASET_ID}.inventory\` (
    product_id INT64, 
    product_name STRING, 
    stock_count INT64
) 
WITH CONNECTION \`${REGION}.${CONN_NAME}\` 
OPTIONS (
    file_format = 'PARQUET',
    table_format = 'ICEBERG',
    storage_uri = 'gs://${ICEBERG_BUCKET}/inventory/'
);"

# Transactions table
bq query --use_legacy_sql=false \
"CREATE OR REPLACE TABLE \`${PROJECT_ID}.${DATASET_ID}.transactions\` (
    id INT64, 
    item STRING, 
    amount FLOAT64, 
    transaction_date DATE
) 
WITH CONNECTION \`${REGION}.${CONN_NAME}\` 
OPTIONS (
    file_format = 'PARQUET',
    table_format = 'ICEBERG',
    storage_uri = 'gs://${ICEBERG_BUCKET}/transactions/'
);"

איך מאכלסים את הטבלאות בנתונים

לבסוף, מוסיפים נתונים לדוגמה לטבלאות Iceberg החדשות שנוצרו.

echo "Inserting data into Iceberg tables..."

# Insert into Inventory table
bq query --use_legacy_sql=false \
"INSERT INTO \`${PROJECT_ID}.${DATASET_ID}.inventory\` (product_id, product_name, stock_count)
VALUES (101, 'Widget A', 500), (102, 'Widget B', 250), (103, 'Widget C', 800);"

# Insert into Transactions table
bq query --use_legacy_sql=false \
"INSERT INTO \`${PROJECT_ID}.${DATASET_ID}.transactions\` (id, item, amount, transaction_date)
VALUES 
    (1, 'Widget A', 100.0, DATE '2024-01-01'), 
    (2, 'Widget B', 150.0, DATE '2024-01-02'), 
    (3, 'Widget C', 50.0, DATE '2024-01-03');"

עכשיו יש לכם שתי טבלאות Iceberg שמתפקדות באופן מלא. ‫BigLake מנהל את המטא-נתונים, אבל קובצי ה-Parquet הפיזיים נמצאים באופן מאובטח בדלי GCS שלכם.

סימולציה של פייפליין ETL

בתרחיש מהעולם האמיתי, נתונים גולמיים לרוב נצברים בטבלאות סיכום לצורך דיווח עסקי. בואו נתנהג כמו מהנדסי נתונים וניצור טבלת סיכום מכירות יומית מנתוני העסקאות הגולמיים שלנו.

(הערה: חשוב להריץ את השלב הזה עכשיו כדי של-Google Cloud יהיה מספיק זמן לעבד את המטא-נתונים ברקע. תגלו למה זה חשוב בהמשך ה-codelab!)

echo "Creating transactions summary table..."
bq query --use_legacy_sql=false \
"CREATE TABLE \`${PROJECT_ID}.${DATASET_ID}.transactions_summary\` AS 
 SELECT transaction_date, SUM(amount) as total_sales, COUNT(id) as transaction_count 
 FROM \`${PROJECT_ID}.${DATASET_ID}.transactions\` 
 GROUP BY transaction_date;"

4. ניהול מרכזי: הגדרת מדיניות באמצעות Python

בסביבת ייצור, קשה להרחיב ולתחזק את ההגדרות של מדיניות ניהול הגישה דרך ממשק המשתמש. במקום זאת, מומלץ מאוד להשתמש בתשתית כקוד (IaC).

בקטע הזה תשתמשו ב-Google Cloud Python SDK כדי ליצור ולאכוף באופן פרוגרמטי את כללי הממשל שלכם לפי גישת אפס אמון, שלב אחר שלב.

הגדרת סביבת Python

קודם כל, נגדיר סביבת Python מבודדת (venv) כדי למנוע התנגשויות בין ספריות, ונתקין את ערכות ה-SDK הנדרשות של Google Cloud.

מריצים את הפקודות הבאות ב-Cloud Shell:

# Create and activate a virtual environment
python3 -m venv lakehouse_env
source lakehouse_env/bin/activate

# Install required Dataplex and BigQuery governance libraries
pip install google-cloud-datacatalog google-cloud-bigquery-datapolicies google-cloud-bigquery --quiet

echo "✅ Python environment is ready!"

יצירת הטקסונומיה ותג המדיניות

טקסונומיה היא מאגר לוגי, ותג מדיניות הוא התווית הספציפית שתצרפו לעמודה הרגישה שלנו. כדי לאכוף אבטחה ברמת העמודה, קודם צריך מאגר נתונים לוגי (טקסונומיה) ותווית ספציפית (תג מדיניות).

אם תבדקו את הקוד של 1_create_taxonomy.py, תראו את הלוגיקה הבסיסית הבאה:

# Create Taxonomy with Fine-Grained Access Control enabled
taxonomy = datacatalog_v1.Taxonomy(
    display_name="BusinessCritical",
    activated_policy_types=[datacatalog_v1.Taxonomy.PolicyType.FINE_GRAINED_ACCESS_CONTROL]
)
created_taxonomy = client.create_taxonomy(parent=parent, taxonomy=taxonomy)

# Create Policy Tag inside the Taxonomy
policy_tag = datacatalog_v1.PolicyTag(display_name="RestrictedFinancial")
created_policy_tag = client.create_policy_tag(parent=created_taxonomy.name, policy_tag=policy_tag)

הגדרה מפורשת של FINE_GRAINED_ACCESS_CONTROL סוג המדיניות הופכת תג מטא-נתונים רגיל לגבול אבטחה מחמיר של אפס אמון. כברירת מחדל, הגישה לכל עמודה עם התג הזה תיחסם לכל המשתמשים.

מריצים את הסקריפט כדי ליצור את המשאבים:

python 1_create_taxonomy.py

הגדרת כלל המיסוך (מדיניות נתונים)

עכשיו מגדירים מה קורה כשמישהו בלי הרשאות שולח שאילתה לעמודה עם התיוג. תצרו מדיניות נתונים שתחייב את החזרת הערך NULL, ותצרפו את הכלל הזה לפרסונה של אנליסט.

בתוך 2_create_masking.py, הסקריפט מחפש באופן דינמי את מזהה תג המדיניות שיצרתם ומחיל מדיניות נתונים:

# Define a Masking Policy that always returns NULL
data_policy = bigquery_datapolicies_v1.DataPolicy(
    data_policy_id="mask_financial_null",
    policy_tag=policy_tag_id,
    data_policy_type=bigquery_datapolicies_v1.DataPolicy.DataPolicyType.DATA_MASKING_POLICY,
    data_masking_policy=bigquery_datapolicies_v1.DataMaskingPolicy(
        predefined_expression=bigquery_datapolicies_v1.DataMaskingPolicy.PredefinedExpression.ALWAYS_NULL
    )
)

# ... (Policy creation code) ...

# Bind the Masked Reader role to the Analyst
iam_policy.bindings.add(
    role="roles/bigquerydatapolicy.maskedReader", 
    members=[f"serviceAccount:{analyst_email}"]
)

הקוד הזה יוצר באופן פרוגרמטי כלל שמאלץ את הערכים הבסיסיים לחזור כ-NULL. לאחר מכן, המערכת מקצה את תפקיד IAM ‏maskedReader באופן ספציפי לדמות האנליסט, כדי להבטיח שהאנליסט יראה רק את הגרסה המוסתרת של הנתונים.

מריצים את הסקריפט כדי להגדיר את כלל המיסוך:

python 2_create_masking.py

הענקת גישה עם הרשאות מפורטות

בגלל הגדרת אפס אמון, אף אחד לא יכול לקרוא את העמודה שתויגה כרגע. אתם צריכים להעניק במפורש גישה לחשבון הניהול ולחשבון לשימוש אישי שלכם.

בתוך 3_grant_access.py, משנים את מדיניות ה-IAM של תג המדיניות עצמו:

# Grant original data read access
iam_policy.bindings.add(
    role="roles/datacatalog.categoryFineGrainedReader",
    members=[f"serviceAccount:{manager_email}", f"user:{current_user}"]
)
client.set_iam_policy(request=iam_policy_pb2.SetIamPolicyRequest(resource=policy_tag_id, policy=iam_policy))

הוספת התפקיד categoryFineGrainedReader מאפשרת לישויות המורשות הספציפיות האלה לעקוף את כללי ההסתרה ולקרוא את הנתונים הגולמיים שלא הוסתרו.

מריצים את הסקריפט כדי להעניק גישה:

python 3_grant_access.py

צירוף תג המדיניות לטבלת BigQuery

לבסוף, צריך לצרף את תג המדיניות הלוגי הזה לסכימת הטבלה הפיזית של Iceberg.

כדאי לעיין ב4_attach_tag.py. הסקריפט מאחזר את סכימת הטבלה ב-BigQuery, מבצע איטרציה בשדות ומצרף את התג באופן ספציפי לעמודה amount:

new_schema =[]
for field in table.schema:
    if field.name == 'amount':
        # Wrap the Policy Tag ID and attach it to the column
        policy_tags_list = bigquery.PolicyTagList(names=[policy_tag_id])
        new_field = bigquery.SchemaField(
            name=field.name, field_type=field.field_type, mode=field.mode,
            description=field.description, policy_tags=policy_tags_list
        )
        new_schema.append(new_field)
    else:
        new_schema.append(field)

# Update the table schema in BigQuery
table.schema = new_schema
client.update_table(table, ["schema"])

כשעדכון הסכימה הזה מוחל, BigLake מגשר באופן מיידי בין התגים הלוגיים של Dataplex לבין קובצי Parquet הפיזיים שמאוחסנים בקטגוריה של Cloud Storage.

מריצים את הסקריפט כדי לעדכן את סכימת הטבלה:

python 4_attach_tag.py

5. אימות מדיניות Dataplex

הגיע הזמן לבדוק אם הממשל המרכזי שלנו פועל. תבדקו את זה בשני מנועים שונים כדי להוכיח שהמדיניות של Dataplex נאכפת באופן אוניברסלי.

אימות באמצעות SQL מקורי של BigQuery

קודם כל, תשתמשו ב-Cloud Shell כדי להניח את הזהות של שתי הדמויות שלנו ולשאול שאילתה בטבלה באמצעות מנוע ה-SQL המקורי של BigQuery.

בדיקה בתור המנהל (משתמש עם הרשאות מיוחדות):

# Impersonate the manager
gcloud config set auth/impersonate_service_account ${EMAIL_MANAGER}

# Query the transactions table
bq query --use_legacy_sql=false "SELECT * FROM \`${PROJECT_ID}.${DATASET_ID}.transactions\`"

מכיוון שלחשבון הניהול יש את התפקיד 'קורא עם הרשאות גישה מפורטות', יוצגו בו ערכי הסכומים הגולמיים

+----+----------+--------+------------------+
| id |   item   | amount | transaction_date |
+----+----------+--------+------------------+
|  1 | Widget A |  100.0 |       2024-01-01 |
|  3 | Widget C |   50.0 |       2024-01-03 |
|  2 | Widget B |  150.0 |       2024-01-02 |
+----+----------+--------+------------------+

בדיקה בתור אנליסט (משתמש עם הרשאה מוגבלת):

gcloud config set auth/impersonate_service_account ${EMAIL_ANALYST}

bq query --use_legacy_sql=false "SELECT * FROM \`${PROJECT_ID}.${DATASET_ID}.transactions\`"

בגלל כלל המיסוך של Dataplex, העמודה amount מחזירה NULL לכל שורה.

+----+----------+--------+------------------+
| id |   item   | amount | transaction_date |
+----+----------+--------+------------------+
|  1 | Widget A |   NULL |       2024-01-01 |
|  3 | Widget C |   NULL |       2024-01-03 |
|  2 | Widget B |   NULL |       2024-01-02 |
+----+----------+--------+------------------+

שחזור הזהות

כדי לחזור למשתמש האדמין, צריך לנקות את מצב האימות של Cloud Shell.

# Unset impersonation
gcloud config unset auth/impersonate_service_account

אימות באמצעות Apache Spark (הענקת הרשאות ל-Compute)

מה קורה אם מדען נתונים משתמש ב-Apache Spark כדי לקרוא את הטבלה הזו? אם Spark קורא ישירות את קובצי ה-Parquet הפיזיים ב-GCS, כללי המיסוך של Dataplex לא חלים כי Cloud Storage מבין רק הרשאות ברמת הקטגוריה.

כדי למנוע את זה, אפשר לאכוף העברת סמכויות מחשוב באמצעות המחבר של Spark-BigQuery. המחבר הזה פועל כגשר מאובטח, ומנתב את בקשות הקריאה של Spark דרך BigQuery Storage API, כך שכללי ניהול הגישה של Dataplex מוערכים באופן דינמי לפני שנתונים נשלחים לאשכול Spark.

כדאי לעיין בלוגיקה המרכזית בסקריפט read_transactions.py שהורדתם:

# Reading data via Compute Delegation (Dataplex policies are applied dynamically here)
df = spark.read \
    .format("bigquery") \
    .option("table", f"{project_id}.{dataset_id}.{table_name}") \
    .load()

print("\n=== 📊 Data Preview ===")
df.show(truncate=False)

שימו לב שלא מציינים ב-Spark את הנתיב gs:// של קובצי Iceberg. אם מציינים .format("bigquery"), BigQuery Storage API מיירט את בקשת הקריאה, בודק את הזהות של המשתמש שמריץ את משימת Spark, מחיל את כללי המיסוך של Dataplex ומחזיר רק את הנתונים המורשים ל-DataFrame של Spark.

מעלים את סקריפט PySpark הזה לקטגוריה של Cloud Storage כדי ש-Dataproc יוכל לגשת אליו:

# Upload script to GCS
gsutil cp read_transactions.py gs://${ICEBERG_BUCKET}/scripts/read_transactions.py

מריצים את Spark כמנהל:

תשתמשו ב-Google Cloud Serverless ל-Apache Spark. השירות המנוהל הזה מאפשר להריץ עומסי עבודה של Spark ישירות, בלי צורך להקצות, להגדיר או לנהל אשכולות ייעודיים.

echo "🚀 Submitting Dataproc Serverless Job as [MANAGER]..."
gcloud dataproc batches submit pyspark gs://${ICEBERG_BUCKET}/scripts/read_transactions.py \
    --project=${PROJECT_ID} \
    --region=${REGION} \
    --service-account=${EMAIL_MANAGER} \
    --version=2.3 \
    -- ${PROJECT_ID} ${DATASET_ID} \
    --format="value(name)"

בודקים את יומני הפלט של המשימה במסוף. מכיוון שלמנהל יש את התפקיד 'קורא עם גישה מפורטת',‏ Spark מאחזר בהצלחה את הסכומים הגולמיים שלא הוסתרו.

=== 📊 Data Preview ===
+---+--------+------+-------------------+
|id |item    |amount|transaction_date   |
+---+--------+------+-------------------+
|1  |Widget A|100.0 |2024-01-01         |
|2  |Widget B|150.0 |2024-01-02         |
|3  |Widget C|50.0  |2024-01-03         |
+---+--------+------+-------------------+

הפעלת Spark כמנתח:

עכשיו, שולחים את אותה משימת Spark, אבל הפעם מתחזים לדמות של האנליסט.

echo "🚀 Submitting Dataproc Serverless Job as [ANALYST]..."
gcloud dataproc batches submit pyspark gs://${ICEBERG_BUCKET}/scripts/read_transactions.py \
    --project=${PROJECT_ID} \
    --region=${REGION} \
    --service-account=${EMAIL_ANALYST} \
    --version=2.3 \
    -- ${PROJECT_ID} ${DATASET_ID} \
    --format="value(name)"

בודקים שוב את היומנים. למרות שהאנליסט הפעיל את אותו קוד Spark, ממשק BigQuery Storage API יירוט את הבקשה ואכף את מדיניות Dataplex. ב-DataFrame של Spark של האנליסט מוצג null עבור הסכומים!

=== 📊 Data Preview ===
+---+--------+------+-------------------+
|id |item    |amount|transaction_date   |
+---+--------+------+-------------------+
|1  |Widget A|null  |2024-01-01         |
|2  |Widget B|null  |2024-01-02         |
|3  |Widget C|null  |2024-01-03         |
+---+--------+------+-------------------+

התפשרויות ארכיטקטוניות: BigQuery SQL לעומת Spark

הוכחת שהתוצאה זהה לא משנה באיזה מנוע משתמשים. אכיפת המדיניות של Dataplex הושלמה בהצלחה. אבל באיזו שיטה כדאי להשתמש בסביבת ייצור?

  • BigQuery SQL: מתאים מאוד לתהליכי עבודה שבהם SQL הוא המנוע הרצוי, והחישובים מבוצעים ישירות במקום. הוא אידיאלי לניתוח מהיר ולבינה עסקית.
  • Apache Spark: מאפשר עומסי עבודה מורכבים יותר באמצעות Python, ולכן מתאים מאוד לצינורות מתקדמים של למידת מכונה או לקוד Hadoop מדור קודם.

המסר העיקרי: לא משנה באיזה מנוע משתמשים, אי אפשר לעקוף את שכבת השליטה המרכזית של אפס אמון על ידי אכיפת הקצאת הרשאות לחישוב.

6. שושלת נתונים אוטומטית

בכל ארכיטקטורת נתונים של ארגון, חשוב לדעת בדיוק מאיפה הנתונים מגיעים ואיך הם השתנו כדי לעמוד בדרישות התאימות, לבצע ניפוי באגים ולבסס אמון. הקונספט הזה נקרא מקורות נתונים. הוא עונה על שאלות בסיסיות כמו: "אם מנהל בוחן דוח מכירות יומי, באילו טבלאות גולמיות נעשה שימוש כדי לחשב את המספרים האלה?"

באופן מסורתי, כדי לעקוב אחרי מחזור החיים הזה, מהנדסי נתונים צריכים לכתוב באופן ידני קוד מותאם אישית לרישום ביומן או להשתמש בכלים מורכבים של צד שלישי כדי לנתח סקריפטים של SQL. אבל ב-Lakehouse מנוהל ב-Google Cloud, המעקב הזה מובנה ומתבצע באופן אוטומטי לחלוטין.

זוכרים את טבלת transactions_summary שיצרתם מטבלת העסקאות הגולמיות קודם ב-codelab? כש-BigQuery מריץ את ההצהרה CREATE TABLE AS SELECT, ‏ Compute Engine מתעד באופן אוטומטי את המטא-נתונים של הטרנספורמציה ושולח אותם ל-Dataplex. בואו נראה את התוצאה.

הצגה חזותית של שרשרת המקור

  1. במסוף Google Cloud, עוברים אל Dataplex universal catalog > Search.
  2. מקלידים lakehouse_retail_demo.transactions בסרגל החיפוש ולוחצים על הטבלה.
  3. לוחצים על הכרטיסייה Lineage.

c890a11d6ea1cca4.png

יוצג לכם גרף אינטראקטיבי שנוצר על ידי מנוע הידע של Dataplex, שמוכיח שהטבלה של היעד (transactions_summary) נגזרה מטבלת Iceberg הגולמית המנוהלת (transactions). השגתם יכולת מעקב מקצה לקצה, שחיונית לביקורת נתונים.

7. הסרת המשאבים

כדי לא לצבור חיובים לחשבון Google Cloud על המשאבים שבהם השתמשתם ב-Codelab הזה:

הסרת משאבי ניהול גישה ב-Dataplex

לפני שמוחקים את מערך הנתונים ב-BigQuery או את הקטגוריה של Cloud Storage, צריך להסיר את כללי ניהול הנתונים הלוגיים. אם תבדקו את הסקריפט cleanup_governance.py מהמאגר, תראו את רצף הפירוק הבא:

# 1. Delete Data Policy
data_policy_name = f"{parent_loc}/dataPolicies/mask_financial_null"
dp_client.delete_data_policy(name=data_policy_name)

# 2. Find and Delete Taxonomy (This auto-deletes child Policy Tags)
taxonomies = catalog_client.list_taxonomies(parent=parent_loc)
taxonomy_id = next((t.name for t in taxonomies if t.display_name == "BusinessCritical"), None)
catalog_client.delete_taxonomy(name=taxonomy_id)

הסדר כאן הוא קריטי. הסקריפט מוחק קודם את מדיניות הנתונים (כלל המיסוך) כי הוא מסתמך על תג המדיניות. אחרי שמסירים את המדיניות, מחיקה של הטקסונומיה הראשית תגרום אוטומטית למחיקה של כל תגי המדיניות הבסיסיים, בלי להפעיל שגיאות של תלות במשאבים.

מריצים את סקריפט הניקוי של Python:

python cleanup_governance.py

הסרה של זהויות, אחסון ונכסי מחשוב

עכשיו, אחרי שהשכבה של ניהול הגישה מנותקת, אפשר למחוק בבטחה את הטבלאות ב-BigQuery, את הקטגוריות ב-Cloud Storage, את חשבונות השירות ואת סביבת Python המקומית.

מעתיקים ומריצים את בלוק הניקוי המקיף הבא ב-Cloud Shell:

echo "Deleting Service Accounts and Impersonation Bindings..."
export CURRENT_USER=$(gcloud config get-value account)

for USER in "${USER_ANALYST}" "${USER_MANAGER}"; do
    EMAIL="${USER}@${PROJECT_ID}.iam.gserviceaccount.com"
    
    # Remove impersonation binding
    gcloud iam service-accounts remove-iam-policy-binding ${EMAIL} \
        --member="user:${CURRENT_USER}" \
        --role="roles/iam.serviceAccountTokenCreator" \
        --quiet > /dev/null 2>&1
        
    # Delete the Service Account
    gcloud iam service-accounts delete ${EMAIL} --quiet
done

echo "Removing BigQuery Dataset and Tables..."
bq rm -f ${DATASET_ID}.transactions_summary
bq rm -f ${DATASET_ID}.transactions
bq rm -f ${DATASET_ID}.inventory
bq rm -f -d ${DATASET_ID}

echo "Removing BigQuery Cloud Resource Connection..."
bq rm --connection --location=${REGION} ${CONN_NAME}

echo "Removing Iceberg Cloud Storage Bucket..."
gcloud storage rm --recursive gs://${ICEBERG_BUCKET} --quiet

echo "Removing Auto-generated Dataproc Staging & Temp Buckets..."
for BUCKET in $(gcloud storage ls | grep -E "gs://dataproc-(staging|temp)-${REGION}"); do
    gcloud storage rm --recursive $BUCKET --quiet
done

echo "Deactivating and removing the local Python environment..."
deactivate
cd ../..
rm -rf devrel-demos

echo "✅ Clean up completed successfully!"

השלמת השלבים האלה מבטיחה שלא יישארו בפרויקט משאבים יתומים או כללי מדיניות מוסתרים.

8. מעולה!

הטמעתם בהצלחה Data Lakehouse שניתן לניהול, לגילוי ולחיפוש.

למדנו ש:

  • שילוב מקורי של Iceberg:‏ BigLake יכול לנהל באופן מקורי טבלאות Iceberg בקוד פתוח, תוך אחסון הקבצים הפיזיים בצורה מאובטחת ב-Cloud Storage.
  • העברת חישובים לצורך אבטחה: על ידי ניתוב שאילתות דרך BigQuery Storage API, אכפתם מסכות דינמיות מדויקות על קבצים פיזיים שלא יכולים להגביל גישה חלקית באופן מקורי.
  • ניהול ללא תלות במנוע: תגי מדיניות מאפשרים להגדיר כללים פעם אחת ולאכוף אותם באופן אוניברסלי, בין אם השאילתה מתבצעת באמצעות SQL מקורי או באמצעות סביבות ריצה של Apache Spark.
  • גילוי נתונים: מנוע הידע של Dataplex עוקב באופן אוטומטי אחר שרשרת המקור של הנתונים, ומספק יכולת ביקורת חיונית לארגונים.

מה השלב הבא?

  • כדאי לעיין במידע על בקרת גישה מתקדמת: כדי ליישם תרחישי אבטחה מורכבים יותר, מומלץ לעיין במסמכים הרשמיים בנושא התאמה אישית של BigLake עם תכונות נוספות.
  • שליטה בנתונים לא מובנים ל-AI גנרטיבי: מידע על טבלאות אובייקטים של BigLake. אפשר להרחיב את דפוס הגשר המאובטח הזה לקבצים לא מובנים (קובצי PDF, תמונות) ב-Cloud Storage, וכך ליצור בסיס נתונים מאובטח ומנוהל לצינורות של Vertex AI ו-RAG.