iT邦幫忙

2025 iThome 鐵人賽

DAY 16
0

簡介

我們通過上篇 DAY15 淬鍊之章-Glue 概念篇 了解到了 Glue 的概念與核心功能。

本篇我們要來實際使用 Glue 建立 Silver PySpark Job,來針對數據做一個簡單的清理。

建立 Glue Role

在使用 Glue 之前,我們一樣需要先建立一個 Glue 專用的 Role,並賦予 Role 所需的 Policy。

Step1:登入 Joe 使用者,進入 IAM 建立 Role 頁面

  • 選擇 AWS 相關服務
  • 選擇 Glue
  • 並按下一步
    https://ithelp.ithome.com.tw/upload/images/20250930/20163443E8yug4cW1c.png

Step2:選擇 AWSGlueConsoleFullAccessAmazonS3FullAccess 的 Policy
https://ithelp.ithome.com.tw/upload/images/20250930/20163443fh9q9FEQYw.png

Step3:Role Name 命名為Full_Glue_Role
https://ithelp.ithome.com.tw/upload/images/20250930/201634432szzWLUHxZ.png

Step4:確認 Policy 後,按「建立角色」
https://ithelp.ithome.com.tw/upload/images/20250930/20163443wTkuuIipXM.png

Step5:回到 Role 頁面,看到 Full_Glue_Role 即完成建立 Glue Role
https://ithelp.ithome.com.tw/upload/images/20250930/2016344355dXrdlfKe.png

將 Role 指派給 DE Group

Step1:進入 DE Group 的頁面,點選「建立內嵌政策」
https://ithelp.ithome.com.tw/upload/images/20250930/20163443apozygjPqI.png

Step2:點選 Json 並將 Json Policy 語法貼上
https://ithelp.ithome.com.tw/upload/images/20250930/20163443RkZ1BiPCQ7.png

下方 Resource 請填寫自己的 accoint_id

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iam:PassRole",
      "Resource": "arn:aws:iam::account_id:role/Full_Glue_Role"
    },
    {
      "Effect": "Allow",
      "Action": [
        "glue:*",
        "s3:*",
        "logs:*"
      ],
      "Resource": "*"
    }
  ]
}

Step3:接著針對此 Policy 命名 Glue_DE_Group 可自行命名,完成後按建立即可
https://ithelp.ithome.com.tw/upload/images/20250930/20163443o2otwiLOwS.png

Step4:最後回到 DE Group 的頁面確認是否有一個新的內嵌政策Glue_DE_Group,即完成建立,這樣以後 Group 內的 User 都可以使用此政策了
https://ithelp.ithome.com.tw/upload/images/20250930/20163443FnNjrzNztq.png

Silver Glue Job 建置

Step1:首先登入 DE 的 Andy 使用者,接著選擇台北區域,一樣於左上角搜尋 Glue,並點選 Glue 進入頁面
https://ithelp.ithome.com.tw/upload/images/20250930/201634435NK2WzMx30.png

Step2:接著於 Glue 的頁面點選左邊 Menu 的「 Visual ETL 」,進入編寫 ETL Job 的頁面
https://ithelp.ithome.com.tw/upload/images/20250930/20163443vWJYk74Bc2.png

Step3:接著我們要撰寫 Spark 所以點選右上角的 「Script editor」按鈕
https://ithelp.ithome.com.tw/upload/images/20250930/20163443MohoXRCST2.png

Step4:然後選擇「Spark」並選擇 Start fresh,然後點選「Create Script」
https://ithelp.ithome.com.tw/upload/images/20250930/20163443pPUL6IceL1.png

Step5:接著我們要來編寫 Spark Script

  • 首先我們先幫第一支 Glue Job 命名 sliver_animes
  • 接著把邊寫好的 PySpark Code 貼入下方的程式區塊內
    https://ithelp.ithome.com.tw/upload/images/20250930/20163443IG56A9AJUO.png
from awsglue.context import GlueContext
from pyspark.context import SparkContext
from pyspark.sql import functions as F
from awsglue.job import Job

# 初始化 Glue Job
sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session
job = Job(glueContext)

spark.conf.set("spark.sql.catalog.glue_catalog", "org.apache.iceberg.spark.SparkCatalog")
spark.conf.set("spark.sql.catalog.glue_catalog.warehouse", "s3://anime-lake/")
spark.conf.set("spark.sql.catalog.glue_catalog.catalog-impl", "org.apache.iceberg.aws.glue.GlueCatalog")
spark.conf.set("spark.sql.catalog.glue_catalog.io-impl", "org.apache.iceberg.aws.s3.S3FileIO")

# 建立 Silver Database
spark.sql("CREATE DATABASE IF NOT EXISTS silver LOCATION 's3://anime-lake/silver.db/'")

# 讀取 Bronze (原始 CSV) - 確保 s3://anime-lake/bronze/animes/ 底下有檔案
df_bronze_animes = spark.read.option("header", "true").csv(
    "s3://anime-lake/Bronze/animes/*/"
)

# 清理 & 型別轉換 (完整 12 欄位)
silver_animes = (
    df_bronze_animes.dropDuplicates(["animeID"])
                 .filter(df_bronze_animes["score"].isNotNull())
                 .withColumn("animeID", F.col("animeID").cast("int"))
                 .withColumn("year",F.when(F.col("year").rlike("^[0-9]{4}$"), F.col("year").cast("int")).otherwise(None))
                 .withColumn("score", F.col("score").cast("double"))
                 .withColumn("episodes", F.col("episodes").cast("int"))
                 .withColumn("title", F.trim(F.col("title")))
                 .withColumn("alternative_title", F.trim(F.col("alternative_title")))
                 .withColumn("type", F.trim(F.col("type")))
                 .withColumn("mal_url", F.trim(F.col("mal_url")))
                 .withColumn("sequel", F.trim(F.col("sequel")))
                 .withColumn("image_url", F.trim(F.col("image_url")))
                 .withColumn("genres", F.trim(F.col("genres")))
                 .withColumn("genres_detailed", F.trim(F.col("genres_detailed")))
)

# 寫入 Silver (Iceberg Table)
silver_animes.write \
    .format("iceberg") \
    .mode("overwrite") \
    .saveAsTable("glue_catalog.silver.animes")

job.commit()

Step6:接著我們點選頁籤上的「 Job Details 」來查看此 Script 的設定

  • 確認命名是否正確
  • 選擇剛剛建立好的 IAM Role Full_Glue_Role
  • 確認 type 為 Spark
    https://ithelp.ithome.com.tw/upload/images/20250930/20163443RdoS8oKJ1Q.png

Step7:接續設定

  • Glue Version:Glue 4.0

  • Language:Python 3

  • Worker type:G 1X

  • Requested number of workers:2

  • 最後點選右上角的「Save」按鈕完成 Glue Job 設定
    https://ithelp.ithome.com.tw/upload/images/20250930/20163443zrJA83uOK2.png

  • 點選下方 Advanced properties

  • 於 Job parameters 位置建立一個 Key=--datalake-formats value = iceberg 的參數,才能正常使用 iceberg
    https://ithelp.ithome.com.tw/upload/images/20250930/20163443eedNLmoDqe.png

Step8:建立好 Glue Job 後,我們接續來做執行

  • 先進入 Runs 的頁籤,並進入 Run 的區塊
  • 接著點選「Run」按鈕執行 Glue Job
    https://ithelp.ithome.com.tw/upload/images/20250930/20163443WRj4JupSWi.png

Step9:執行後我們可以看到一筆 Job 正在運行中,然後下方 Detail 會出現該 Job 的運作細節
https://ithelp.ithome.com.tw/upload/images/20250930/201634438b6GHTgiij.png

Step10:待 Job 完成後,即可於 Catalog 的 Database 確認有實際建立 silver db 和 table
https://ithelp.ithome.com.tw/upload/images/20250930/20163443NgtYp1wnQn.png

https://ithelp.ithome.com.tw/upload/images/20250930/20163443p8v4rwnLY1.png

接著請大家自行完成 sliver_animes 的 Glue Job 建立,並於後續確認是否有正常建立 DB 和 Table

總結與建議

在本篇中,我們實際撰寫了 AWS Glue Job (PySpark),並將 原始 CSV(Bronze 層存放於 S3)轉換為 Iceberg Table(Silver 層)。這個過程中有幾個關鍵重點:

  1. Bronze 層

    • 僅作為「落地區 (Landing Zone)」,直接存放原始 CSV,不做任何轉換。
    • 檔案結構規劃清楚,未來維護才容易。
  2. Silver 層

    • 是真正的「資料清理層」,負責:
      • 去重、移除缺失值
      • 欄位型別轉換
      • 修正欄位值(例如 trim() 去掉多餘空白)
    • 輸出為 Iceberg 表,底層仍是 Parquet,但多了 Metadata 管理、版本控制、Partition Pruning 的好處。
  3. 建議做法

    • 如果 Bronze 只會存單一檔案 → 直接指定檔案路徑讀取即可。
    • 如果 Bronze 會有多批資料(每日/每月) → 保持資料夾結構,讓 Spark 讀取整個目錄,自動合併。
    • Glue Job Role 必須有 S3 + Glue + Logs + iam:PassRole 權限,否則會遇到 AccessDenied。

下篇預告

在下一篇 「Day17 淬鍊之章-Glue 實作篇-2」 中,我們將:

  • Silver JobGold Job 串成一條完整的 Glue Workflow
  • 展示如何透過 Workflow 建立 事件驅動的數據管道

參考資料


上一篇
DAY15 淬鍊之章-Glue 概念篇
下一篇
Day17 淬鍊之章-Glue 實作篇-2
系列文
動漫宅的 30 天 AWS Lakehouse 修行日誌19
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言