在 DAY12 雲端基礎章-S3 Data Lakehouse 儲存結構設計 中我們介紹了本次將要建立的 S3 Data Lake 儲存架構,並於 DAY13 雲端基礎章-Lambda、EventBridge 概念篇 中,接續了解 Lambda 與 EventBridge 如何協同運作,今天我們就來動手實作:
當檔案上傳到 S3 Bucket 時,由 EventBridge 偵測事件並觸發 Lambda,自動在 S3 建立資料夾並重新命名檔案後存放。
這樣的設計可以讓我們:
首先先來看看我們 Day12 的設計,在 S3 的設計上,我們需要建立:
anime-lake
的 S3 BucketBronze
Folderanimes
、ratings
等兩個子資料夾Step1:首先我們先登入 DE 權限的帳號 (Andy),接著進入到 S3 的儲存佇體頁面點選「建立儲存佇體」
Step2:接著我們先確認:
Step3:接著往下設定,首先我們要設定封鎖公開存取的權限,基本上由於安全的考量,都會選擇預設「封鎖所有公開存取權」來避免 S3 Bucket 被其他外人瀏覽。再來我們先將「儲存佇體版本控制」做關閉,因為目前開起後就會開始針對資料的異動做版控,等於每次有檔案更新時,S3 會直接儲存一個新檔案,這個版控是需要額外收費的
Step4:最後是要設定 S3 Bucket 的加密類型,這邊我們直接選擇預設的 SSE-S3 加密即可,並「啟用」儲存佇體金鑰(預設),然後點選「建立儲存佇體」
Step5:然後會預設跳轉回 S3 Bucket 的頁面,等待約 30 ~ 60 秒的建立時間後,會自動跳出剛剛建立的 S3 Bucket,即完成建立
Step6:接著我們要來建立 Bronze
Folder,我們先進入 anime-lake
中,並點選「建立資料夾」
Step7:首先輸入資料夾名稱 Bronze
,接著伺服器端加密我們直接使用預設「不要指定加密金鑰」即可,最後點選「建立資料夾」
Step8:建立後會一樣會自動跳轉回剛剛的 anime-lake
Bucket,可以看到成功建立的 Bronze
資料夾,接著我們直接進入該資料夾,接續建立子資料夾
Step9:透過一樣的資料夾建立流程,分別建立 animes
與 ratings
等兩個子資料夾,即完成我們本次的 S3 的相關資料夾建立
在使用 Lambda 之前,我們要建立一個 Lambda 的執行 Role
Step1:首先我們要切換使用者 Joe,才有權限建立新的 Role,並登入 IAM 服務選擇「建立角色」
Step2:選擇 「AWS 服務」,使用案例選擇 「Lambda」,然後點選「下一步」
Step3:接著搜尋並選擇 「AWSLambda_FullAccess」、「AmazonS3FullAccess」、「AWSLambdaBasicExecutionRole」等政策,並於右下角點選下一步
Step4:接著我們要針對此 Role 做角色命名,我這邊先命名 Full_Lambda_Role
方便管理即可
Step5:確認政策是否選擇正確,就可以點選「建立角色」
Step6:跳轉頁面後,確認 Full_Lambda_Role
有正常建立,我們就可以回到 Andy 的使用者開始建立 Lambda Function
建立完 S3 Bucket 和所需 Folder 後,我們要來撰寫 Python 的 Lambda Function 來針對每次上傳的新 CSV 檔案做一個年月日 Partition 的處理
Step1:接著我們一樣於左上方的搜尋功能尋找到 Lambda 的 Service
Step2:於 Lambda 的頁面右上角選擇「建立函數」
Step3:首先我們選擇 「從頭開始撰寫」,接著輸入
anime-lake-bronze-partition
Step4:在使用 Lambda Function 時,會需要一個擁有使用 Lambda 權限的 Role,我們這邊選擇剛剛建立好的Full_Lambda_Role
後點選「建立函數」
Step5:跳轉到 anime-lake-bronze-partition
頁面後,我們將於下方程式碼頁面開始編輯 Python 腳本
Step6:於程式編輯區塊撰寫 Python 腳本,撰寫好後,點選左邊的 「Deploy」按鈕,即完成 Lambda Function 的建立
為本次所需之 Python Code,使用 boto3 lib 來控制 S3
import boto3
import os
import re
s3 = boto3.client("s3")
def lambda_handler(event, context):
record = event["Records"][0]
bucket = record["s3"]["bucket"]["name"]
key = record["s3"]["object"]["key"]
# 檔名 (不含路徑)
filename = os.path.basename(key) # e.g. animes_20250928.csv
# 正則解析 dataset 與日期 (YYYYMMDD)
match = re.match(r"^(animes|ratings)_(\d{8})\.csv$", filename)
if not match:
return {
"statusCode": 400,
"body": f"Unsupported file format: {filename}"
}
dataset, file_date_raw = match.groups() # dataset=animes, file_date_raw=20250928
# 轉換日期格式 YYYYMMDD → YYYY-MM-DD
file_date = f"{file_date_raw[0:4]}-{file_date_raw[4:6]}-{file_date_raw[6:8]}"
# 生成新 S3 路徑
new_key = f"Bronze/{dataset}/{file_date}/{dataset}.csv"
# 複製到新位置
s3.copy_object(
Bucket=bucket,
CopySource={"Bucket": bucket, "Key": key},
Key=new_key
)
# 刪除原始檔案(可選)
s3.delete_object(Bucket=bucket, Key=key)
return {
"statusCode": 200,
"body": f"File {filename} moved to {new_key}"
}
建立完 S3 Bucket 和所需 Folder 後,我們要來建立監聽 S3 PutObject 的 Event
Step1:首先先回到 anime-lake 的頁面,然後點選下方 Menu 的 「屬性」頁籤
Step2:接著找到事件通知的區塊,點選「建立事件通知」
Step3:接著做設定:
bronze-file-upload-animes
我們這邊這些可以按照你好讀懂的命名方式,方面後續的管控Bronze/animes
作為偵測 animes 子資料夾的路徑設定Step4:接著我們將頁面往下拉,找到目的地的設定
anime-lake-bronze-partition
後,點選「儲存變更」Step5:完成後,我們回到 Lambda Function anime-lake-bronze-partition
的頁面,可以看到上方的函示概觀的區塊下方多了一個 S3 的 Pipeline,即完成了 EventBridge 觸發 Lambda 的設定
Step6:最後由於 EventBridge 是預設不啟動的,我們需要把調整成「啟動」,才可以正常的開始做 S3 Bucket 的 Event 偵測
接著我們還需要建立另一個資料夾
ratings
的 EventBridge,這邊我們做個小挑戰,想請讀者自己建立看看,並實際查閱是否正常運作
將 S3 Bucket 、Lambda、EventBridge 都建立完成後,接著我們來實測看看上傳檔案到 S3 Folder 內是否真的會自動建立新的 Partition Folder
Step1:回到 anime-lake/Bronze/animes 的頁面,並點選上傳檔案
Step2:選擇要上傳的 animes.csv 檔案後點選「上傳」
Step3:接著到 anime-lake/Bronze/animes/
查看剛剛設計好的 EventBridge 是否有正常運作,可以看到剛剛的 animes_20250928.csv 檔案變成一個 2025-09-28
的資料夾,且裡面存放了去掉日期的 animes.csv
檔案,代表我們的 EventBridge 和 Lambda 是有正常運作的,即完成了整個 S3 Event 觸發 Lambda 的設定
透過 S3 + EventBridge + Lambda,我們建立了一個自動檔案歸檔流程。
這種設計在資料湖專案中非常常見,例如:
可需根據不同的場景依照需求設定相關的 Pipeline,才能最佳的解決自己的需求
下篇我們將進入下一個章節 「Day15 淬鍊之章-Glue 概念篇」,一起來了解一下 AWS 的 ETL 服務 Glue。
Amazon S3
AWS Lambda
Amazon EventBridge
AWS IAM