Amazon S3 Files が GA — S3 バケットをファイルシステムとしてマウント、EFS と比較してみた

Amazon S3 Files が GA — S3 バケットをファイルシステムとしてマウント、EFS と比較してみた

2026年4月提供開始のAmazon S3 Filesは、S3バケットをNFS v4.2でマウント可能にする新サービス。EC2/Lambda/EKS/ECSから利用でき、既存レガシーアプリケーションのコード変更なしでS3を活用できます。
2026.04.08

2026/4/7、Amazon S3 Files の一般提供(GA)が発表されました。

https://aws.amazon.com/about-aws/whats-new/2026/04/amazon-s3-files/

S3 バケットをファイルシステムとしてマウントできる新機能です。S3 バケットの作成、IAM ロールの準備、S3 Files ファイルシステムの構築までを AWS CLI で行い、Amazon Linux 2023 上にマウント。
マウント後はファイル操作やロックの動作を検証するとともに、EFS との I/O 性能や同期ラグなどを測定しましたので、その結果を紹介します。

S3 Files とは

S3 Files は、S3 バケットのデータに対してファイルシステムインターフェースを提供するサービスです。Amazon EFS をベースに構築されており、NFS v4.2 プロトコルで EC2 や Lambda、EKS、ECS からマウントできます。

  • S3 バケットの既存データにそのままファイルとしてアクセスできる
  • ファイルシステムへの書き込みは自動的に S3 バケットに同期される
  • アクティブに使用するデータのみが高性能ストレージにキャッシュされる
  • 最大 25,000 のコンピュートリソースから同時アクセス可能

検証環境

項目
OS Amazon Linux 2023 (aarch64)
インスタンスタイプ r7gd.medium
リージョン / AZ us-west-2 / us-west-2a
VPC デフォルト VPC
AWS CLI 2.34.26
amazon-efs-utils 3.0.0

手順 1: AWS CLI の更新

S3 Files の CLI コマンド(aws s3files)を使うには AWS CLI 2.34 以上が必要です。最新バージョンへ更新しました。

curl -s "https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip" -o /tmp/awscliv2.zip
cd /tmp && unzip -qo awscliv2.zip
sudo ./aws/install --update

x86_64 環境の場合は URL を https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip に変更してください。

更新後、aws s3files help でサブコマンド一覧が表示されれば OK です。

$ aws --version
aws-cli/2.34.26 Python/3.14.3 Linux/6.1.161-183.298.amzn2023.aarch64

$ aws s3files help
...
AVAILABLE COMMANDS
       o create-file-system
       o create-mount-target
       o get-file-system
       o list-file-systems
       o list-mount-targets
       ...

手順 2: S3 バケットの作成

S3 Files にはバージョニングが有効な S3 バケットが必要です。バケット作成とバージョニング有効化を行いました。

BUCKET_NAME="s3files-demo-$(date +%Y%m%d)-${RANDOM}"
REGION="us-west-2"

# バケット作成
aws s3api create-bucket \
  --bucket "${BUCKET_NAME}" \
  --region "${REGION}" \
  --create-bucket-configuration LocationConstraint="${REGION}"

# バージョニング有効化
aws s3api put-bucket-versioning \
  --bucket "${BUCKET_NAME}" \
  --versioning-configuration Status=Enabled

手順 3: IAM ロールの作成

S3 Files がバケットにアクセスするための IAM ロールを作成しました。

ポリシー作成

信頼ポリシー

ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)

cat > /tmp/s3files-trust-policy.json << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "elasticfilesystem.amazonaws.com"
            },
            "Action": "sts:AssumeRole",
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": "${ACCOUNT_ID}"
                },
                "ArnLike": {
                    "aws:SourceArn": "arn:aws:s3files:${REGION}:${ACCOUNT_ID}:file-system/*"
                }
            }
        }
    ]
}
EOF

aws iam create-role \
  --role-name S3FilesRole-demo \
  --assume-role-policy-document file:///tmp/s3files-trust-policy.json

インラインポリシー

cat > /tmp/s3files-policy.json << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "S3BucketPermissions",
            "Effect": "Allow",
            "Action": ["s3:ListBucket", "s3:ListBucketVersions"],
            "Resource": "arn:aws:s3:::${BUCKET_NAME}",
            "Condition": {
                "StringEquals": { "aws:ResourceAccount": "${ACCOUNT_ID}" }
            }
        },
        {
            "Sid": "S3ObjectPermissions",
            "Effect": "Allow",
            "Action": [
                "s3:AbortMultipartUpload", "s3:DeleteObject*",
                "s3:GetObject*", "s3:List*", "s3:PutObject*"
            ],
            "Resource": "arn:aws:s3:::${BUCKET_NAME}/*",
            "Condition": {
                "StringEquals": { "aws:ResourceAccount": "${ACCOUNT_ID}" }
            }
        },
        {
            "Sid": "UseKmsKeyWithS3Files",
            "Effect": "Allow",
            "Action": [
                "kms:GenerateDataKey", "kms:Encrypt", "kms:Decrypt",
                "kms:ReEncryptFrom", "kms:ReEncryptTo"
            ],
            "Condition": {
                "StringLike": {
                    "kms:ViaService": "s3.${REGION}.amazonaws.com",
                    "kms:EncryptionContext:aws:s3:arn": [
                        "arn:aws:s3:::${BUCKET_NAME}",
                        "arn:aws:s3:::${BUCKET_NAME}/*"
                    ]
                }
            },
            "Resource": "arn:aws:kms:${REGION}:${ACCOUNT_ID}:*"
        },
        {
            "Sid": "EventBridgeManage",
            "Effect": "Allow",
            "Action": [
                "events:DeleteRule", "events:DisableRule", "events:EnableRule",
                "events:PutRule", "events:PutTargets", "events:RemoveTargets"
            ],
            "Condition": {
                "StringEquals": { "events:ManagedBy": "elasticfilesystem.amazonaws.com" }
            },
            "Resource": ["arn:aws:events:*:*:rule/DO-NOT-DELETE-S3-Files*"]
        },
        {
            "Sid": "EventBridgeRead",
            "Effect": "Allow",
            "Action": [
                "events:DescribeRule", "events:ListRuleNamesByTarget",
                "events:ListRules", "events:ListTargetsByRule"
            ],
            "Resource": ["arn:aws:events:*:*:rule/*"]
        }
    ]
}
EOF

aws iam put-role-policy \
  --role-name S3FilesRole-demo \
  --policy-name S3FilesBucketAccess \
  --policy-document file:///tmp/s3files-policy.json

ポリシーの内容は 公式ドキュメント に準拠しています。

また、EC2 のインスタンスプロファイルには以下の権限も必要です。

  • AmazonS3FilesClientFullAccess(または AmazonS3FilesClientReadOnlyAccess
  • S3 バケットへの直接読み取り権限(読み取りパフォーマンス最適化のため)

手順 4: ファイルシステムの作成

ROLE_ARN="arn:aws:iam::${ACCOUNT_ID}:role/S3FilesRole-demo"

aws s3files create-file-system \
  --region "${REGION}" \
  --bucket "arn:aws:s3:::${BUCKET_NAME}" \
  --role-arn "${ROLE_ARN}"

レスポンスの fileSystemId を控えておきます。

FS_ID="fs-0123456789abcdef0"  # 出力された fileSystemId に置き換え

手順 5: マウントターゲットの作成

EC2 インスタンスと同じサブネットにマウントターゲットを作成しました。

SUBNET_ID="subnet-xxxxxxxx"  # EC2 と同じサブネット

aws s3files create-mount-target \
  --region "${REGION}" \
  --file-system-id "${FS_ID}" \
  --subnet-id "${SUBNET_ID}"

available になるまで数分待ちました。ステータスは以下で確認できます。

aws s3files list-mount-targets \
  --region "${REGION}" \
  --file-system-id "${FS_ID}" \
  --query 'mountTargets[0].{status:status,ip:ipv4Address}'

手順 6: セキュリティグループの設定

マウントターゲットのセキュリティグループに、EC2 からの NFS(TCP 2049)インバウンドを許可する必要がありました。

# マウントターゲットの SG を確認(ENI から取得)
MT_IP="172.31.xx.xx"  # マウントターゲットの IP
aws ec2 describe-network-interfaces \
  --filters "Name=addresses.private-ip-address,Values=${MT_IP}" \
  --query 'NetworkInterfaces[0].Groups[0].GroupId' \
  --output text

# EC2 の SG からマウントターゲットの SG への TCP 2049 を許可
MT_SG="sg-xxxxxxxxx"   # マウントターゲットの SG
EC2_SG="sg-yyyyyyyyy"  # EC2 の SG

aws ec2 authorize-security-group-ingress \
  --group-id "${MT_SG}" \
  --ip-permissions '[{
    "FromPort": 2049,
    "ToPort": 2049,
    "IpProtocol": "tcp",
    "UserIdGroupPairs": [{"GroupId": "'${EC2_SG}'", "Description": "NFS from EC2 for S3 Files"}]
  }]'

手順 7: amazon-efs-utils のインストール

S3 Files のマウントヘルパー(mount.s3files)は amazon-efs-utils 3.0.0 以上 に含まれています。

# efs-utils リポジトリの追加
sudo bash -c 'cat > /etc/yum.repos.d/efs-utils.repo << EOF
[efs-utils]
name=efs-utils repository
baseurl=https://amazon-efs-utils.aws.com/repo/rpm/amazon/2023
priority=1
enabled=1
repo_gpgcheck=1
type=rpm
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-efs-utils.gpg
EOF'

sudo curl -fsSL https://amazon-efs-utils.aws.com/efs-utils-armored.gpg \
  -o /etc/pki/rpm-gpg/RPM-GPG-KEY-efs-utils.gpg
sudo rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-efs-utils.gpg

# インストール
sudo dnf install -y amazon-efs-utils-3.0.0

# botocore も root 向けにインストール(IAM 認証で使用)
sudo python3 -m pip install botocore
$ rpm -q amazon-efs-utils
amazon-efs-utils-3.0.0-1.amzn2023.aarch64

$ which mount.s3files
/sbin/mount.s3files

手順 8: マウントと動作確認

sudo mkdir -p /mnt/s3files
sudo mount -t s3files ${FS_ID}:/ /mnt/s3files
$ df -hT /mnt/s3files
Filesystem   Type  Size  Used Avail Use% Mounted on
127.0.0.1:/  nfs4  8.0E     0  8.0E   0% /mnt/s3files

8.0E(8 エクサバイト)は S3 の実質無制限のストレージ容量を反映しています。

ファイルを作成して S3 側への反映を確認しました。

echo "Hello from S3 Files!" > /mnt/s3files/test.txt
cat /mnt/s3files/test.txt
Hello from S3 Files!
# S3 側で確認(同期に ~1 分かかる場合があります)
sleep 60
aws s3 ls s3://${BUCKET_NAME}/
2026-04-08 07:45:12         21 test.txt

ファイルシステムへの書き込みが S3 バケットに自動同期されていることを確認できました。

EFS との簡易パフォーマンス比較

S3 Files は EFS をベースに構築されています。同一インスタンスに EFS(Elastic スループットモード)もマウントし、簡易的な比較を行いました。

I/O パフォーマンス

各テストは 3 回実行し、中央値を採用しました。読み込みテスト前にはページキャッシュをクリアしています。

テスト S3 Files EFS
1GB 書き込み 4.283s (約 239 MB/s) 4.224s (約 242 MB/s) ほぼ同等
1GB 読み込み 1.601s (約 639 MB/s) 1.474s (約 694 MB/s) S3 Files が約 9% 遅い
1KB×1,000 書き込み 11.265s 9.048s S3 Files が約 24% 遅い
1KB×1,000 読み込み 4.916s 3.665s S3 Files が約 34% 遅い

大容量ファイルの書き込みはほぼ同等でした。S3 Files は 1MB 以上の読み込みを S3 から直接ストリーミングする設計のため、大容量の読み込みでも差は小さくなっています。小容量ファイルの多数操作では EFS が優位でしたが、S3 Files でも 1 ファイルあたり約 11ms で書き込みが完了しており、実用上は十分な性能でした。

同期ラグ

S3 Files と S3 バケット間の同期は双方向で自動的に行われます。公式ドキュメントによると、ファイルシステムへの書き込みは最大 60 秒間の変更を集約して 1 回の S3 PUT で同期し、S3 バケットへの直接変更は S3 Event Notifications で検知してファイルシステムに反映されます。

方向 計測方法 中央値
ファイルシステム → S3 書き込み後、head-object でポーリング 約 63〜66 秒
S3 → ファイルシステム s3 cp 後、ファイル出現をポーリング 約 30 秒

ファイルシステム → S3 方向は公式ドキュメントの「最大 60 秒間の変更を集約」という仕様と一致しました。S3 → ファイルシステム方向は S3 Event Notifications の配信間隔に依存するため、タイミングによってばらつきがありました。

S3 オブジェクトのメタデータ

S3 に同期されたオブジェクトには、POSIX のパーミッション、オーナー、タイムスタンプが S3 オブジェクトメタデータとして保持されていました。

Metadata:
  user-agent: aws-s3-files
  file-permissions: 0100644
  file-owner: 0
  file-group: 0
  file-mtime: 1775634941827000000ns

ファイルロックの動作確認

S3 Files は NFS v4.2 のファイルロックをサポートしています。flock による排他ロックの動作を確認しました。

FILE=/mnt/s3files/locktest.txt
echo "test" > $FILE

# プロセス1: 排他ロックを取得して3秒保持
(
  flock -x 200
  echo "P1 lock acquired at $(date +%T)"
  sleep 3
  echo "P1 lock released at $(date +%T)"
) 200>$FILE &

sleep 0.5

# プロセス2: 排他ロックを要求(P1が解放するまで待機)
(
  echo "P2 waiting at $(date +%T)"
  flock -x 200
  echo "P2 lock acquired at $(date +%T)"
) 200>$FILE &

wait
P1 lock acquired at 08:15:48
P2 waiting at 08:15:48
P1 lock released at 08:15:51
P2 lock acquired at 08:15:51

排他ロック、非ブロッキングモード(flock -n)ともに期待通りに動作しました。

S3 API からの変更はロックをバイパスする

ファイルシステムで排他ロックを保持した状態で、S3 API から同じファイルを上書きする検証を行いました。

タイミング ファイルシステム S3 API
ロック取得前 original content original content
ロック中に S3 API で上書き後 OVERWRITTEN BY S3 API OVERWRITTEN BY S3 API
ロック解放後 OVERWRITTEN BY S3 API OVERWRITTEN BY S3 API

S3 API はファイルシステムのロックを一切認識せず、ロック保持中でも上書きが成功しました。変更内容はロック保持中のプロセスからも即座に見えました。

まとめ

S3 Files を AWS CLI でゼロから構築し、マウント、EFS との比較、ファイルロックの検証まで行いました。

検証結果

I/O 性能は EFS とほぼ同等で、大容量ファイルの書き込みでは差がなく、小容量ファイルの多数操作でも実用上十分な性能でした。S3 への同期は約 1 分、S3 からファイルシステムへの反映は約 30 秒で完了しました。NFS のファイルロックは正常に動作しましたが、S3 API からの操作はロックをバイパスするため、両方の経路からデータを更新するワークロードでは注意が必要です。

S3 Files が効くユースケース

SDK や CLI で S3 をネイティブに利用することが難しいワークロードに対して、最小限の変更で S3 を活用できる点が最大の価値です。NFS v4.2 対応の既存アプリケーションであれば、マウントポイントの変更だけでコード変更なしに S3 上のデータを扱えます。

S3 のバージョニングが必須のため変更履歴が自動保持され、イレブンナインの耐久性もそのまま活きます。アクティブなデータのみが高性能ストレージにキャッシュされるため、S3 と別途ファイルシステムを併用してデータを二重管理する構成と比べてコスト削減も期待できます。

より高い NFS 性能が必要な場合

S3 Files を採用する際は、同期ラグやファイルロックの制約がワークロードの要件に合っているか、事前に十分な検証をおすすめします。特に小容量ファイルを大量に扱うワークロードでは、S3 への同期に伴う API リクエスト費用が積み上がる可能性がある点にも注意が必要です。検証の結果、レイテンシやスループット、コストが要件を満たせない場合は、Amazon FSx for NetApp ONTAP も有力な選択肢です。マルチプロトコル(NFS / SMB / iSCSI)対応に加え、S3 への自動階層化(FabricPool)機能も備えており、高性能なファイルアクセスと S3 のコスト効率を両立できます。

参考リンク

この記事をシェアする

関連記事