[筆記] Amazon S3 Batch Operations & Tag-Based Lifecycle Configuration

使用 Amazon S3 Batch Operations 與 Object Tagging 管理 S3 上檔案的生命週期

Jalex Chang
Jalex’s Murmur
14 min readSep 18, 2019

--

Source: https://www.needpix.com/photo/86734/gun-weapon-machine-gun-pilot-target-science-fiction

前言

本篇文章是用來記錄最近自己因應公司 (Umbo Computer Vision) 的商業邏輯,學習與使用 Amazon S3 新功能 — Batch Operations 的心得。主要的應用場景是使用批次物件標記(batch object tagging),並搭配object tagging 與 lifecycle configuration 來管理 S3 bucket 上的檔案。而在示範程式碼的部分,則是會使用 Golang 搭配 AWS 官方的 SDK — aws-go-sdk

Terminology

在開始正文之前,幫大家複習一下 Amazon S3上的專有名詞:

  • Object: 上傳到 Amazon S3 的檔案,也是最基本的儲存與操作單元。
  • Bucket: 儲存 object 的容器。每個 object 都會被儲存於一個 bucket 內。
  • Key: 即是 object 在 bucket 的檔案路徑。像是 https://a_bucket.s3.amazonaws.com/a_path_to_an_object/object_name 中,a_path_to_an_object/object_name 即是 key。
  • Region: AWS Region。每一個 bucket 都被設置在一個 region 內。
  • Lifecycle Configuration: 一個包含各種規則與行動的集合,用來管理bucket 內 object 的生命週期。
  • Job: Amazon S3 上執行 batch operation 的 worker,也是可以操作的最小單元。
  • Operation: Job 所預計執行的指令,可以對應到一個既有 Amazon S3 API。
  • Manifest: 一個 Amazon S3 上的object,裡面包含 bucket 與 key 組成清單。
  • Task: job 內的實際執行 operation 的單位。

S3 Object Lifecycle Management

通常為了成本或是商業邏輯上的考量,我們不會無止盡地在 Amazon S3 保留上傳的 object,相反地,我們必須有計畫地將過時的 object 移除或是將其儲存類型從 Standard 轉成成本較低的 STANDARD_IA GLACIER。而除了透過 S3 API 自行管理外,也可以使用 Amazon S3 內建的 lifecycle configuration 來達到相同的目的。

Lifecycle configuration 是屬於 bucket-level 的設定,因此我們可以在不同的 bucket 中設定不同的 lifecycle rule,管理 bucket 內部 object 的生命週期。而 Lifecycle rule 的設定基本上可以分成兩種類別:適用的 object 範圍(object filtering),及採取的行動 (action)。

Object Filtering

Lifecycle configuration 提供兩種過濾適用 object 的方式:

  • Filter by a key prefix
  • Filter by object tags

Filter by a key prefix 有點像是檔案路徑的概念,你可以指定一個目錄,而在這個目錄及子目錄下的所有檔案都會被涵括在內。Filter by object tags 則是指定適用的 object tag (key-value 的形式),所有在 bucket 內符合條件的 object 都會被涵括在內。

舉個簡單的例子:

如果是用 key prefix,然後下 2019/09 ,可以找到四個 object。如果下 2019/09/18 則只有 doc1 與 doc2。相反地,如果是透過 object tag 找 type=A ,則可以找到 doc1 與 doc3。

值得注意的是,一個 lifecycle rule 只能選擇用key prefix 或 object tag 其中之一。Key prefix 只能設定一個 ,但 object tag 可以設定複數個 (所以可以下 type=A| type=B | type=C,找到所有的 object)。

Actions

Lifecycle configuration 提供了兩種可採取的行動:

  • 轉移儲存類型 (transition actions)
  • 過期 (expiration actions)

前者可以設定 object 上傳後多久 (days after creation) 要轉換它的儲存類型,以減省儲存成本,後者可以設定 object 物件上傳後多久應該刪除。

Limitations

雖然使用 Amazon S3 所提供的 Lifecycle configuration 來管理 object 的生命週期非常的方便,但它還是有些使用上的限制:

  • 一個 bucket 內只能有 1000 個 lifecycle rule。
  • 無法透過 API 去新增/修改/刪除 Lifecycle configuration 裡單一的 lifecycle rule。如果要更動,需要整包拉下來,改完再整包上傳覆蓋舊的。
  • Lifecycle rule 只認 key prefix 或 object tag。所以如果要把 object 從適用 rule A 改成適用 rule B,要嘛需要移動物件位置,要嘛需要更改 object tag。

多變的客戶資料生命週期

在 Umbo ,我們會面臨一些客製化的需求,而其中一項是客戶對於儲存在我們 Amazon S3 上的資料,可以自行選擇儲存的時間長度,從數月到數年不等。此外,客戶也可以在中途修改時間長度。因此,我們面臨了非常複雜的生命週期管理需求。

在過去的兩三年裡,我們採用了基於 key prefix 的 lifecycle rule 管理可戶的資料。基本上可以想像成一個客戶有一個他專屬的 key prefix,因此一個客戶就會需要一個 lifecycle rule 來管理他的資料。這樣的好處是當客戶要修改資料的儲存長度時,只需要更新對應 lifecycle rule 內的設定。但壞處則是一個 bucket 只能處理 1000 個客戶,所以我們得開大量的 bucket ,並且在內部的管理服務中處理客戶與 bucket 間的對應關係與衍生的處理邏輯。

而之所以不採用 filter by object tags 的原因,在於過去想大規模地操作 S3 bucket 內的 object 是非常困難的一件事。需要透過 S3 inventorygetObjectListAPI 或是自己維護的 object 清單,找到所有想修改的 object key 與對應的 bucket, 然後透過 API 逐一去修改。這個過程非常麻煩且費時。可以說,對於生命長度會不定期更改的商業情境來說,object tagging 在過去並不是可行的方案。但這件事在今年迎來了轉機......

S3 Batch Operations

在今年 4月底時, AWS 正式 GA (general availability)了 Amazon S3 的批次修改功能 — Batch Operations 。透過 batch operation,可以簡單地對同一個 bucket 內大量的 object 進行操作。

Basic Concept

Batch operations 的基本概念是,你可以透過 createJobAPI 或是 Amazone S3 console 來啟動一個 Amazon S3 管理的 batch operation job。這個 job 會負責把指定的 object 清單內的 object 用指定 operation API 個別執行,並在整個任務結束後產生執行結果報吿

值得注意的是,job 本質上是個管理者的角色,它負責監控執行狀態並產生事後報表,而實際上執行任務的底層的 task。Task 是個被隱藏在 job 下面的執行單元,它的任務是針對一個object 進行單一 operation。因此 job 的本質上是 concurrent multi-task ,且不保證執行順序

Create A Job

而想要啟動一個 job,需要提供下列的參數設定

  • Operation: Job 預計執行的 S3 API。
  • Manifest: 要操作的 object 清單。目前接受兩種類型的 manifest — S3 inventory 與自行上傳的CSV。如果是 CSV,裡面必須包含 object 的 key 及 bucket
  • Priority: 這個 Job 的優先程度(必須是正整數)。在有複數 job 的情況下,優先程度高的 job 會有較高的機率先被執行 (但不保證一定優先)。
  • RoleArn: Job 所使用的 IAM role。必須給 job 權限對指定 bucket 與 object 進行 API 操作。
  • Report: 決定是否需要產生 job 完成後的報表。值得注意的是,只有透過 report 才能得知個別 object 操作結果為何。
  • Description (optional): 這個 job 的描述。

Permissions

這個章節會介紹使用 batch operation job 所需要的權限,而可以分成兩種 IAM role 來說明: create-batch-operation-job-roleexecute-batch-operation-job-role

The Role for Creating Batch Operation Jobs

如果預計要透過 service (像是 AWS Lamdba)來管理 batch operation job,則需要給此 service 權限:

  1. Permissions:

2. Trust relationship:

需要注意的是,由於 job 相關的權限目前沒有對應的 resource ,因此 resource 必須要設成 wildcard *。另外由於此 service 在新增 job 時需要給予 RoleARN,因此必須給予可以給它人 IAM role 的權限 iam:PassRole

The Role for Executing Batch Operation Jobs

至於執行 job 所用的 IAM role ,可以設定成:

  1. Permissions:

2. Trust relationship:

Notes

在使用 batch operation 時,有些細節需要注意:

  • Job 與要操作 object 必須在同一個 region,但 manifest 與 report 沒有限制。然後 manifest 內的 object 必須在同一個 bucket 內
  • 儘管Amazon S3 將批次操作抽象化成單一的 job,job 的底層實際上還是透過 API 個別更改 object,所以它非常耗時。以筆者的經驗,批次對百萬個 object 做 object tagging 大概需要 20 分鐘。因此在相關管理服務的設計上,必須把 job 當作 asynchronous task 來處理。
  • 執行 job 其實並不便宜。光是新增一個 job 就需要 $0.25,然後透過 job 操作 object ,每一百萬個 object 需要 $1。此外還要加上原本 operation API 的費用。如果你所面對的商業邏輯會非常頻繁地執行 job,那你可能得評估使用 batch operations 是否划算。

透過 Object Tagging 管理客戶資料的生命週期

如上所述,敝公司今年下半年開始採用了新的客戶資料管理方案:

  • 透過 object tagging 與基於 tag 的 lifecycle rule 來管理客戶在 Amazon S3 上的資料。透過特定的 tag key 搭配預先設定好的 tag value (像是expired_days=2month),可以用非常少的 lifecycle rule 來管理數量龐大的客戶資料。
  • 在面對客戶要求更改資料生命週期時,透過 batch operation 來進行修改,而這樣的需求一個月不超過十次,頻率非常低。
  • 對應用服務而言,不再需要維護複雜的客戶與 bucket 間的對應關係與相關邏輯功能,實際減少系統複雜度。

結論

整體而言,使用 batch operations 與 object tagging 管理 Amazon S3 上檔案的生命週期是一件非常舒服的事情。雖然它的軟體維運成本會稍微增加,但可以減少 Dev 與 Ops 非常多的心智負擔,對像我們這種小新創來說十分有幫助。

除此之外,也很感謝主管給了我幾天空閒,來研究這些未知玩意,學習到不少有趣的新知XD

附件:簡單的 Golang 範例

下面附一個簡單的範例,說明如何使用 aws-go-sdk 新增 Batch Operation Job ,以更改 object tag:

Sample code for creating batch object tagging job.

詳細的使用說明可以參考 Go API doc,這邊只提醒文件上沒有說明清楚的部分:

  • (L57) ObjectArn 是 manifest 在 S3 上的 resource name。可以表示成 arn:aws:s3:::the_bucket/the_key
  • 不管 manifest 是用要 S3 inventory 還是要自己兜 CSV,最後都要在 S3 上,Go SDK 不支援 in-memory 或 local file 形式的 manifest。
  • (L65–68) 如果 manifest 選擇用 CSV ,要明確在 s3Control.JobManifest.Spec.Fields 中定義每一個欄位的意義。你必須明確告知哪一個欄位是 bucket ,哪一個欄位是 key,哪一些必須忽視。
  • (L61–62) 如果 manifest 選擇用 S3 inventory,絕對不可以初始化 s3Control.JobManifest.Spec.Fields ,不然你會收到毫無頭緒的 invalid job creation request 。超鳥的,爬 source code 都看不出個所以然。

--

--