Khắc phục lỗi [Errno 28] trên AWS Lambda: Cách xử lý giới hạn 512MB của /tmp

intermediate☁️ AWS2026-07-09| AWS Lambda (Python, Node.js, Go, Java) chạy trên Amazon Linux 2 / Amazon Linux 2023

Error Message

[Errno 28] No space left on device: '/tmp/large_file.csv'
#aws-lambda#cloud-computing#python#serverless#khac-phuc-loi

Vấn đề

Hãy tưởng tượng bạn đang xử lý một tệp CSV dung lượng 700MB từ một S3 bucket. Hàm Lambda của bạn có 2GB RAM, vì vậy bạn hy vọng nó sẽ hoàn thành công việc một cách dễ dàng. Tuy nhiên, quá trình thực thi bị dừng đột ngột với lỗi dung lượng đĩa. Điều này xảy ra do theo mặc định, AWS Lambda chỉ cung cấp 512 MB bộ nhớ tạm (ephemeral storage) trong thư mục /tmp.

[Errno 28] No space left on device: '/tmp/large_file.csv'

Nếu mã nguồn của bạn tải xuống một tệp lớn hơn 512MB, hoặc nếu nhiều tiến trình đồng thời lấp đầy khoảng trống đó, môi trường sẽ chạm giới hạn cứng. Hàm của bạn không chỉ chạy chậm lại—nó sẽ bị sập ngay lập tức.

Giải pháp 1: Mở rộng bộ nhớ tạm (Ephemeral Storage)

Cách khắc phục nhanh nhất là tăng dung lượng đĩa được cấp phát. AWS cho phép bạn mở rộng /tmp lên tới 10.240 MB (10 GB). Mặc dù 512MB đầu tiên là miễn phí, hãy lưu ý rằng dung lượng bổ sung có chi phí khoảng $0,00003090 mỗi GB-giây ở hầu hết các khu vực.

Sử dụng AWS Console

  • Điều hướng đến console Lambda và mở hàm cụ thể của bạn.
  • Chọn tab Configuration.
  • Chọn General configuration từ menu bên trái.
  • Nhấp vào Edit và tìm cài đặt Ephemeral storage.
  • Cập nhật giá trị (ví dụ: 2048 MB) và nhấn Save.

Sử dụng AWS CLI

Đối với những người tự động hóa hạ tầng qua CI/CD, hãy sử dụng lệnh này để cập nhật cài đặt ngay lập tức:

aws lambda update-function-configuration \
    --function-name MyProcessingFunction \
    --ephemeral-storage '{"Size": 2048}'

Giải pháp 2: Stream dữ liệu để không cần dùng đến đĩa

Việc ghi vào /tmp thường không cần thiết. Bạn có thể tiết kiệm chi phí và cải thiện hiệu suất bằng cách stream dữ liệu trực tiếp vào bộ nhớ (memory). Cách tiếp cận này tránh hoàn toàn nghẽn cổ chai ở đĩa bằng cách xử lý tệp theo từng phần (chunks).

Ví dụ: Streaming dữ liệu S3 trong Python (Boto3)

Thay vì sử dụng download_file(), hãy sử dụng get_object() để truy cập một streaming body. Điều này giúp mức sử dụng đĩa của bạn luôn ở mức 0.

import boto3
import csv

s3 = boto3.client('s3')

def lambda_handler(event, context):
    bucket = "my-data-bucket"
    key = "large_file.csv"
    
    response = s3.get_object(Bucket=bucket, Key=key)
    
    # Xử lý stream theo từng dòng
    lines = (line.decode('utf-8') for line in response['Body'].iter_lines())
    reader = csv.DictReader(lines)
    
    for row in reader:
        # Logic của bạn ở đây
        pass

Giải pháp 3: Quản lý việc dọn dẹp Container ấm (Warm Container)

AWS thường tái sử dụng môi trường thực thi Lambda để giảm tình trạng khởi động lạnh (cold start). Nếu mã của bạn ghi một tệp 200MB vào /tmp và không xóa nó, lần thực thi tiếp theo sẽ bắt đầu với 200MB đó đã bị chiếm dụng. Sau ba lần chạy, bạn sẽ chạm giới hạn 512MB.

Luôn bao bọc các thao tác tệp trong khối try...finally. Điều này đảm bảo rằng các tệp được xóa ngay cả khi script gặp lỗi giữa chừng.

import os

file_path = "/tmp/temp_data.tmp"
try:
    # Thực hiện các tác vụ nặng
    pass
finally:
    if os.path.exists(file_path):
        os.remove(file_path)

Giải pháp 4: Gắn Amazon EFS cho các tác vụ khối lượng lớn

Đôi khi 10GB là không đủ. Nếu bạn đang xử lý các tập dữ liệu hàng Terabyte hoặc cần một không gian làm việc chung cho nhiều hàm, Amazon Elastic File System (EFS) là công cụ phù hợp. Điều này yêu cầu Lambda của bạn phải chạy trong một VPC.

  • Tạo một EFS File System và một Access Point.
  • Cập nhật security groups của VPC để cho phép lưu lượng NFS (Cổng 2049).
  • Gắn EFS vào một đường dẫn cục bộ như /mnt/storage trong cấu hình Lambda.

Cách kiểm tra giới hạn bộ nhớ của bạn

Bạn không chắc liệu các thay đổi của mình đã có hiệu lực chưa? Bạn có thể in dung lượng đĩa thực tế còn trống ra CloudWatch logs bằng thư viện shutil.

import shutil

def lambda_handler(event, context):
    total, used, free = shutil.disk_usage("/tmp")
    print(f"Tổng dung lượng: {total // (2**20)} MiB")
    print(f"Dung lượng đang dùng: {used // (2**20)} MiB")

Mẹo nhanh

  • Đĩa và RAM: Đừng nhầm lẫn không gian /tmp với bộ nhớ của hàm (memory). Nếu bạn tải một tệp 1GB vào một biến, bạn cần tăng cài đặt Memory, chứ không phải bộ nhớ tạm.
  • Sự cô lập: Mỗi lần thực thi Lambda đồng thời sẽ có bộ nhớ /tmp chuyên dụng riêng. Một hàm không thể nhìn thấy hoặc làm đầy đĩa của hàm khác.
  • Chi phí: Stream dữ liệu hầu như luôn rẻ hơn so với việc trả tiền cho bộ nhớ tạm bổ sung.

Related Error Notes