AWS Lambdaの[Errno 28]を修正する:512MBの/tmp制限への対処法

intermediate☁️ AWS2026-07-09| Amazon Linux 2 / Amazon Linux 2023上で動作するAWS Lambda (Python, Node.js, Go, Java)

Error Message

[Errno 28] No space left on device: '/tmp/large_file.csv'
#aws-lambda#クラウドコンピューティング#python#サーバーレス#トラブルシューティング

問題点

S3バケットから700MBのCSVファイルを処理している場面を想像してください。Lambda関数には2GBのRAMが割り当てられているため、処理はスムーズに進むはずです。しかし、突然ディスクスペースエラーが発生して実行が停止してしまいます。これは、デフォルトでAWS Lambdaが/tmpディレクトリに512 MBのエフェメラルストレージしか提供していないために起こります。

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

コードが512MBを超えるファイルをダウンロードしたり、複数の並列プロセスがその領域を使い果たしたりすると、環境のハードリミットに達します。関数は単に遅くなるだけでなく、即座にクラッシュします。

解決策1:エフェメラルストレージの拡張

最も手っ取り早い修正方法は、割り当てられたディスク容量を増やすことです。AWSでは、/tmpを最大10,240 MB (10 GB) まで拡張できます。最初の512MBは無料ですが、追加のストレージには、ほとんどのリージョンで1GB秒あたり約0.00003090ドルのコストがかかることに注意してください。

AWS コンソールを使用する場合

  • Lambdaコンソールに移動し、対象の関数を開きます。
  • 設定タブを選択します。
  • 左側のメニューから一般設定を選択します。
  • 編集をクリックし、エフェメラルストレージの設定項目を見つけます。
  • 値(例:2048 MB)を更新し、保存をクリックします。

AWS CLI を使用する場合

CI/CDでインフラを自動化している場合は、次のコマンドを使用して設定を即座に更新できます:

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

解決策2:ストリーミングによるディスクの回避

/tmpへの書き込みは不要な場合が多いです。データをメモリに直接ストリーミングすることで、コストを抑え、パフォーマンスを向上させることができます。このアプローチでは、ファイルをチャンクごとに処理するため、ディスクのボトルネックを完全に回避できます。

例:Python (Boto3) でのS3データのストリーミング

download_file()を使用する代わりに、get_object()を使用してストリーミングボディにアクセスします。これにより、ディスク使用量をゼロに抑えられます。

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)
    
    # ストリームを1行ずつ処理
    lines = (line.decode('utf-8') for line in response['Body'].iter_lines())
    reader = csv.DictReader(lines)
    
    for row in reader:
        # ここにロジックを記述
        pass

解決策3:ウォームコンテナのクリーンアップ管理

AWSは、コールドスタートを減らすためにLambdaの実行環境を再利用することがよくあります。コードが200MBのファイルを/tmpに書き込み、削除し忘れた場合、次の実行時にはすでに200MBが消費された状態で始まります。3回実行されると、512MBの制限に達してしまいます。

ファイル操作は常にtry...finallyブロックで囲むようにしてください。これにより、スクリプトの途中でエラーが発生しても、ファイルが確実に削除されるようになります。

import os

file_path = "/tmp/temp_data.tmp"
try:
    # 重い処理を実行
    pass
finally:
    if os.path.exists(file_path):
        os.remove(file_path)

解決策4:大規模なワークロードにAmazon EFSをマウントする

10GBでも足りない場合があります。数テラバイトのデータセットを扱う場合や、複数の関数で共有ワークスペースが必要な場合は、Amazon Elastic File System (EFS) が適しています。これには、LambdaをVPC内で実行する必要があります。

  • EFSファイルシステムとアクセスポイントを作成します。
  • NFSトラフィック(ポート2049)を許可するようにVPCセキュリティグループを更新します。
  • Lambdaの設定で、EFSを/mnt/storageのようなローカルパスにマウントします。

ストレージ制限の確認方法

変更が反映されたかどうかわからない場合は、shutilライブラリを使用して、利用可能な実際のディスク容量をCloudWatchログに出力できます。

`import shutil

def lambda_handler(event, context):
    total, used, free = shutil.disk_usage("/tmp")
    print(f"合計容量: {total // (2**20)} MiB")
    print(f"現在の使用量: {used // (2**20)} MiB")

クイックヒント

  • ディスク vs RAM: /tmpスペースと関数のメモリを混同しないでください。1GBのファイルを変数に読み込む場合は、エフェメラルストレージではなく、メモリ設定を増やす必要があります。
  • 分離: Lambdaの各同時実行には、専用の/tmpが割り当てられます。ある関数が別の関数のディスクを参照したり、容量を圧迫したりすることはありません。
  • コスト: データのストリーミングは、追加のエフェメラルストレージ料金を支払うよりも、ほとんどの場合安価に済みます。

Related Error Notes