Nỗi ám ảnh mang tên ‘Click chuột’ trên AWS Console
Bạn đã bao giờ mất cả buổi chiều chỉ để tìm và tải hàng nghìn file ảnh từ AWS S3 về máy chưa? Hồi mới làm dự án, mình từng quản lý hệ thống lưu trữ ảnh người dùng trên S3. Lúc đầu chỉ có vài chục tấm, mình cứ thong thả lên Console click chuột. Nhưng khi hệ thống chạm mốc 500.000 file, mọi thứ bắt đầu vượt tầm kiểm soát.
Việc thao tác thủ công không chỉ tốn thời gian mà còn cực kỳ dễ sai sót. Chỉ cần quên set quyền (ACL) hay chọn nhầm thư mục là hệ thống ‘đi’ ngay. Chưa kể, mỗi lần cần migrate khoảng 200GB dữ liệu giữa các môi trường, mình phải thức đến 2 giờ sáng để canh tiến trình copy. Đó là lúc mình nhận ra: Nếu không tự động hóa, mình sẽ sớm bị đống file này đè bẹp.
Tại sao Bash script không còn là lựa chọn số một?
Nhiều anh em thường dùng AWS CLI kết hợp với Bash script vì tính tiện lợi. Bản thân mình cũng từng trung thành với aws s3 sync. Tuy nhiên, khi logic xử lý phức tạp hơn, Bash bắt đầu bộc lộ những điểm yếu chí mạng:
- Logic điều kiện quá phức tạp: Hãy thử viết script: “Chỉ upload file > 5MB, được tạo trong 12h qua và gửi báo cáo qua Slack”. Với Bash, đây là một bài toán đau đầu.
- Khả năng xử lý lỗi kém: Bash rất khó bắt được các exception cụ thể từ AWS API để thực hiện retry (thử lại) thông minh.
- Hiệu suất xử lý song song: Khi cần đẩy 10.000 file thumbnail (mỗi file ~20KB) lên S3, Python xử lý đa luồng (multi-threading) nhanh hơn Bash gấp nhiều lần.
Khi chuyển sang dùng Boto3 cho một dự án xử lý hơn 1 triệu bản ghi, mình thấy code gọn gàng hẳn. Việc bảo trì cũng dễ dàng hơn nhiều so với việc gọi lệnh hệ thống từ Bash.
Boto3 – Trợ thủ đắc lực cho dân DevOps
Boto3 là AWS SDK chính thức cho Python, cho phép bạn điều khiển mọi dịch vụ AWS bằng code thuần túy. Dưới đây là cách mình triển khai để giải quyết bài toán quản lý file thực tế.
1. Thiết lập môi trường trong 30 giây
Cài đặt thư viện cực kỳ đơn giản qua pip:
pip install boto3
Thay vì dán trực tiếp Access Key vào code (rất dễ bị lộ trên GitHub), bạn hãy dùng AWS CLI để cấu hình. Chạy lệnh sau và điền thông tin bảo mật của bạn:
aws configure
2. Khởi tạo kết nối: Resource hay Client?
Boto3 cung cấp resource (hướng đối tượng) và client (gần với API gốc). Mình thường ưu tiên dùng client vì nó hỗ trợ đầy đủ các tính năng mới nhất của AWS.
import boto3
from botocore.exceptions import ClientError
s3_client = boto3.client('s3')
def create_my_bucket(bucket_name, region=None):
try:
if region is None:
s3_client.create_bucket(Bucket=bucket_name)
else:
location = {'LocationConstraint': region}
s3_client.create_bucket(Bucket=bucket_name, CreateBucketConfiguration=location)
print(f"Đã tạo bucket {bucket_name}!")
except ClientError as e:
print(f"Lỗi: {e}")
return False
return True
3. Upload và Download: Đừng quên Metadata
Kinh nghiệm xương máu của mình là luôn set ContentType khi upload. Nếu không, khi người dùng mở link ảnh trên trình duyệt, nó sẽ bị tải về thay vì hiển thị trực tiếp.
def upload_file(file_name, bucket, object_name=None):
object_name = object_name or file_name
try:
# Set ContentType là image/jpeg để hiển thị tốt trên web
s3_client.upload_file(file_name, bucket, object_name, ExtraArgs={'ContentType': 'image/jpeg'})
print(f"Upload {file_name} thành công.")
except Exception as e:
print(f"Lỗi upload: {e}")
4. Xử lý hàng triệu file với Paginator
Một sai lầm phổ biến là dùng list_objects_v2 và nghĩ nó sẽ trả về mọi file. Thực tế, AWS chỉ trả về tối đa 1.000 objects mỗi lần gọi. Nếu bucket của bạn có 1 triệu file, bạn bắt buộc phải dùng Paginator.
def list_all_files(bucket_name):
paginator = s3_client.get_paginator('list_objects_v2')
pages = paginator.paginate(Bucket=bucket_name)
for page in pages:
if 'Contents' in page:
for obj in page['Contents']:
print(f"- {obj['Key']} ({obj['Size']} bytes)")
Kỹ thuật nâng cao: Xử lý file lớn và Bảo mật
Trong môi trường Production, việc upload một file ISO 10GB rất dễ gặp lỗi timeout. Đừng dùng cách upload thông thường nếu bạn không muốn script bị ‘treo’ giữa chừng.
Tăng tốc với Multipart Upload
Boto3 có module s3transfer giúp chia nhỏ file và upload song song. Nếu một phần bị lỗi, nó sẽ tự động retry phần đó mà không cần upload lại từ đầu. Tốc độ sẽ cải thiện rõ rệt.
from boto3.s3.transfer import TransferConfig
# Nếu file > 50MB, chia nhỏ mỗi phần 10MB, chạy 15 luồng song song
config = TransferConfig(multipart_threshold=1024 * 50,
max_concurrency=15,
multipart_chunksize=1024 * 10)
s3_client.upload_file('large_backup.zip', 'my-bucket', 'backups/file.zip', Config=config)
Tuyệt đối không ‘hardcode’ thông tin bảo mật
Nếu bạn commit Access Key lên Git, chỉ sau 5 phút, hacker có thể quét thấy và dùng tài khoản của bạn để đào coin. Hãy dùng Environment Variables hoặc IAM Roles. Trong Python, hãy tận dụng thư viện python-dotenv:
import os
from dotenv import load_dotenv
load_dotenv()
s3 = boto3.client('s3') # Boto3 sẽ tự tìm key trong biến môi trường
Đúc kết kinh nghiệm
Sau nhiều năm làm việc với AWS S3, mình rút ra 3 quy tắc vàng cho anh em:
- Luôn dùng Paginator: Đừng bao giờ tin vào danh sách 1.000 file đầu tiên.
- Tận dụng Prefix: Lọc file theo ‘thư mục ảo’ để tiết kiệm chi phí API và tăng tốc độ tìm kiếm.
- Bắt lỗi chặt chẽ: Luôn dùng
try...exceptvớiClientErrorđể xử lý các trường hợp mất quyền truy cập hoặc sai tên bucket.
Tự động hóa với Boto3 không chỉ giúp bạn nhàn hơn mà còn giảm thiểu rủi ro vận hành. Hy vọng những chia sẻ này giúp ích cho dự án của bạn!

