Đọc hóa đơn S3: khi tiền request lớn hơn tiền lưu trữ
Phân tích chi phí S3 theo từng bucket và từng loại phí, cùng những cái bẫy thường gặp khi áp dụng lifecycle hay Intelligent-Tiering cho hàng triệu object nhỏ.
Khi nhắc tới chi phí S3, phần lớn đội kỹ thuật nghĩ tới dung lượng lưu trữ và giá theo GB của từng storage class. Trong thực tế, với những hệ thống lưu nhiều object nhỏ hoặc truy cập dữ liệu với tần suất cao, tiền request có thể lớn hơn cả tiền lưu trữ. Bài viết này đi qua cách đọc hóa đơn S3 theo từng bucket, những khoản phí ít được để ý, và những cái bẫy thường gặp khi áp dụng lifecycle hay Intelligent-Tiering.
Hóa đơn S3 gồm những gì
Một dòng S3 trên hóa đơn AWS thực ra gộp nhiều loại phí khác nhau:
- Storage: tính theo GB-tháng, khác nhau theo storage class.
- Requests: tính theo số request, chia thành nhóm PUT, COPY, POST, LIST và nhóm GET, SELECT. Tại us-east-1, tại thời điểm viết bài, S3 Standard tính khoảng $0.005 cho mỗi 1.000 request PUT hoặc LIST, và khoảng $0.0004 cho mỗi 1.000 request GET. Request LIST luôn được tính theo giá PUT của S3 Standard, bất kể object nằm ở storage class nào.
- Retrieval: các class như Standard-IA hay Glacier tính thêm phí theo GB mỗi khi dữ liệu được đọc ra.
- Lifecycle transition: mỗi object được chuyển sang class khác bị tính như một request, với giá theo class đích.
- Data transfer: dữ liệu đi ra internet hoặc sang region khác.
Giá khác nhau giữa các region, nên bạn nên kiểm tra lại trang S3 pricing của region mình đang dùng trước khi tính toán.
Bước 1: chia hóa đơn theo từng bucket
Cost Explorer chỉ cho biết tổng chi phí S3 theo usage type. Để biết bucket nào đang tốn tiền và tốn vào loại phí nào, chúng tôi thường dùng:
- Cost and Usage Report: cột
line_item_resource_idchứa tên bucket. Nhóm theo bucket vàline_item_usage_typesẽ cho thấy bucket nào tốn chủ yếu vào storage, bucket nào tốn vào request. - S3 Storage Lens: cho biết số object, kích thước trung bình của object, và tỉ lệ dữ liệu ở từng storage class theo bucket và prefix.
- S3 Inventory: xuất danh sách object kèm kích thước và storage class ra file CSV hoặc Parquet, có thể truy vấn bằng Athena để phân tích chi tiết theo prefix.
SELECT line_item_resource_id AS bucket,
line_item_usage_type AS usage_type,
sum(line_item_unblended_cost) AS cost
FROM cur
WHERE line_item_product_code = 'AmazonS3'
AND month = '10'
GROUP BY 1, 2
ORDER BY cost DESC
LIMIT 30;Nếu các usage type có chứa Requests-Tier1 (nhóm PUT, LIST) hoặc Requests-Tier2 (nhóm GET) đứng gần đầu danh sách, hệ thống của bạn thuộc nhóm mà tiền request đáng được chú ý hơn tiền lưu trữ.
Khi tiền request lớn hơn tiền lưu trữ
Tình huống này thường xuất hiện ở những hệ thống ghi nhiều object nhỏ: log, event, ảnh thumbnail, hoặc dữ liệu từ thiết bị IoT được ghi thành từng file riêng lẻ.
Giả sử một pipeline ghi mỗi event thành một object khoảng 2 KB, với 100 triệu event mỗi tháng, tại us-east-1:
Lưu trữ: 100.000.000 × 2 KB ≈ 200 GB × $0.023 ≈ $4.6 / tháng
PUT: 100.000.000 / 1.000 × $0.005 ≈ $500 / thángTiền ghi dữ liệu lớn gấp hơn trăm lần tiền lưu trữ. Nếu pipeline phía sau còn LIST và GET từng object để xử lý, khoản phí request còn lớn hơn nữa.
Cách xử lý hiệu quả nhất thường nằm ở phía ứng dụng: gom nhiều event thành một file lớn hơn trước khi ghi, ví dụ dùng Kinesis Data Firehose với buffer theo thời gian và kích thước, hoặc ghi theo batch ở định dạng Parquet. Với các pipeline phải tìm object mới, thay vì LIST cả bucket theo chu kỳ, bạn có thể dùng S3 Event Notifications để nhận thông báo mỗi khi có object được ghi.
Những cái bẫy của lifecycle
Lifecycle rule chuyển dữ liệu cũ sang class rẻ hơn là gợi ý quen thuộc nhất khi nói về tối ưu S3. Tuy vậy, có ba điểm cần tính trước khi áp dụng:
- Phí transition theo object: mỗi object được chuyển class bị tính như một request. Với hàng trăm triệu object nhỏ, chi phí transition một lần có thể lớn hơn số tiền tiết kiệm được trong nhiều tháng.
- Kích thước tối thiểu được tính phí: Standard-IA, One Zone-IA và Glacier Instant Retrieval tính mỗi object tối thiểu 128 KB. Một object 2 KB chuyển sang Standard-IA vẫn bị tính như 128 KB, nên chi phí lưu trữ thực tế có thể tăng lên. Glacier Flexible Retrieval và Deep Archive tính thêm 40 KB metadata cho mỗi object, gồm 8 KB theo giá S3 Standard và 32 KB theo giá Glacier.
- Thời gian lưu trữ tối thiểu: Standard-IA tính tối thiểu 30 ngày, Glacier Instant Retrieval và Glacier Flexible Retrieval tính tối thiểu 90 ngày, Deep Archive tính tối thiểu 180 ngày. Object bị xóa hoặc ghi đè trước thời hạn vẫn bị tính đủ số ngày còn lại.
Gần đây, lifecycle rule mặc định không chuyển các object nhỏ hơn 128 KB sang class khác, chính vì lý do trên. Nếu bạn có rule được tạo từ trước, hoặc đã tự đặt bộ lọc kích thước, hãy kiểm tra lại cấu hình ObjectSizeGreaterThan của rule đó.
resource "aws_s3_bucket_lifecycle_configuration" "logs" {
bucket = aws_s3_bucket.logs.id
rule {
id = "archive-large-objects"
status = "Enabled"
filter {
and {
prefix = "exports/"
object_size_greater_than = 131072 # 128 KB
}
}
transition {
days = 90
storage_class = "GLACIER_IR"
}
}
}Intelligent-Tiering không phải lúc nào cũng rẻ hơn
S3 Intelligent-Tiering tự chuyển object giữa các tầng dựa trên tần suất truy cập, không tính phí retrieval, và thường là lựa chọn an toàn cho dữ liệu có cách truy cập khó dự đoán. Đổi lại, mỗi object được theo dõi bị tính phí monitoring, khoảng $0.0025 cho mỗi 1.000 object mỗi tháng tại thời điểm viết bài.
Object nhỏ hơn 128 KB không bị tính phí monitoring, nhưng cũng không bao giờ được chuyển xuống tầng rẻ hơn mà luôn được tính theo giá của tầng Frequent Access. Vì vậy, với bucket chứa chủ yếu object nhỏ, Intelligent-Tiering gần như không mang lại lợi ích gì. Với bucket có hàng tỉ object cỡ vừa, phí monitoring cộng dồn cũng cần được so với số tiền tiết kiệm dự kiến.
- Object phần lớn lớn hơn vài MB
- Không biết trước dữ liệu nào sẽ được đọc lại
- Dữ liệu được lưu nhiều tháng trở lên
- Muốn tránh phí retrieval bất ngờ
- Phần lớn object nhỏ hơn 128 KB
- Biết chắc dữ liệu sau một thời gian sẽ không được đọc
- Dữ liệu bị xóa hoặc ghi đè sau vài tuần
- Số lượng object rất lớn nhưng tổng dung lượng nhỏ
Tóm lại
Trước khi đổi storage class, hãy chia hóa đơn theo bucket và theo loại phí để biết bạn đang trả tiền cho dung lượng hay cho request. Với những bucket mà request chiếm phần lớn, thay đổi hiệu quả nhất thường nằm ở cách ứng dụng ghi và đọc dữ liệu. Với những bucket mà dung lượng chiếm phần lớn, lifecycle và Intelligent-Tiering mới thực sự có tác dụng, miễn là kích thước object và thời gian lưu trữ phù hợp với điều kiện tính phí của class đích.
Trong một số trường hợp, khi dữ liệu chỉ được ghi một lần và đọc rất ít, câu hỏi đáng đặt ra còn là liệu dữ liệu đó có cần nằm trên S3 hay không. Đó là chủ đề chúng tôi sẽ viết trong một bài khác.