Mountpoint for Amazon S3でS3バケットをマウントした領域をログ出力にしてみた
お手軽にS3バケットにログを保存したい
こんにちは、のんピ(@non____97)です。
皆さんはお手軽にS3バケットにEC2インスタンスが出力するログを保存したいなと思ったことはありますか? 私はあります。
CloudWatch Logsへ大量のログを出力する場合はコストが気になります。
コストのウェイトが高い要素はログ取り込み料金であるため、CloudWatch LogsからS3バケットへData Firehoseを介して転送をしても大きなコスト削減効果は得られづらいです。詳細は以下記事をご覧ください。
そのため、コスト削減のためのアプローチとしてS3バケットへ直接書き込む手法が考えられます。具体的な手段としてFluent Bitなどがあります。
ここでもしかすると、MountPoint for Amazon S3でもできるのでは? と思われた方もいるかもしれません。
以下記事にてマウント時のオプションとして--allow-overwrite
とそれらしいものが紹介されています。
ということで、ログの出力先としてMountPoint for Amazon S3でマウントした領域に
いきなりまとめ
- 以下理由からMountpoint for Amazon S3でS3バケットをマウントした領域をログ出力先として指定するのは難しい
- 2025/10/15時点では追記をサポートしているのはS3 Express One Zoneのみ
- 複数AZへのデータの保存は行われないため、データの耐久性を重要視する場合は不向き
- ストレージクラスの変更はできないため、長期間のログ保存には不向き
- 追記の上限9,999回というハードリミットがある
- 直接オブジェクトに追記をする場合、S3のAPIにかかるコストも気になる
- 常時ファイルをオープンするようなプロセスを起動しようとすると失敗する
- 2025/10/15時点では追記をサポートしているのはS3 Express One Zoneのみ
やってみた
検証環境
検証環境は以下のとおりです。
Mountpoint for Amazon S3を用いてS3バケットをEC2インスタンス上のマウントポイントへマウントします。
Mountpoint for Amazon S3を用いた追記確認
まずはMountpoint for Amazon S3を用いた追記ができるか確認をします。
Mountpoint for Amazon S3wおインストールします。
$ wget https://s3.amazonaws.com/mountpoint-s3-release/latest/x86_64/mount-s3.rpm
--2025-10-11 07:11:57-- https://s3.amazonaws.com/mountpoint-s3-release/latest/x86_64/mount-s3.rpm
Resolving s3.amazonaws.com (s3.amazonaws.com)... 52.217.119.88, 16.15.202.114, 16.182.36.48, ...
Connecting to s3.amazonaws.com (s3.amazonaws.com)|52.217.119.88|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 11086952 (11M) [binary/octet-stream]
Saving to: ‘mount-s3.rpm’
mount-s3.rpm 100%[========================================================================================>] 10.57M --.-KB/s in 0.09s
2025-10-11 07:11:58 (121 MB/s) - ‘mount-s3.rpm’ saved [11086952/11086952]
$ sudo dnf install -y ./mount-s3.rpm
Last metadata expiration check: 0:02:42 ago on Sat Oct 11 07:09:30 2025.
Dependencies resolved.
.
.
(中略)
.
.
Installed:
fuse-2.9.9-13.amzn2023.0.2.x86_64 fuse-common-3.10.4-1.amzn2023.0.2.x86_64 mount-s3-1.20.0-1.x86_64
Complete!
インストールされたMountpoint for Amazon S3のバージョンやオプションを確認します。
$ mount-s3 --version
mount-s3 1.20.0
$ mount-s3 --help
Mountpoint for Amazon S3
Usage: mount-s3 [OPTIONS] <BUCKET_NAME> <DIRECTORY>
Arguments:
<BUCKET_NAME>
Name of bucket, or an S3 URI, to mount
<DIRECTORY>
Directory or FUSE file descriptor to mount the bucket at.
For directory mount points, the passed path must be an existing directory.
For FUSE file descriptors (Linux-only), it should be of the format `/dev/fd/N`.
Learn more in Mountpoint's configuration documentation (CONFIGURATION.md).
Options:
-f, --foreground
Run as foreground process
-h, --help
Print help (see a summary with '-h')
-V, --version
Print version
Bucket options:
--prefix <PREFIX>
Prefix inside the bucket to mount, ending in '/' [default: mount the entire bucket]
--region <REGION>
AWS region of the bucket [default: auto-detect region]
--endpoint-url <ENDPOINT_URL>
S3 endpoint URL [default: auto-detect endpoint]
--force-path-style
Force path-style addressing
--transfer-acceleration
Use S3 Transfer Acceleration when accessing S3. This must be enabled on the bucket.
--dual-stack
Use dual-stack endpoints when accessing S3
--requester-pays
Set the 'x-amz-request-payer' to 'requester' on S3 requests
--bucket-type <BUCKET_TYPE>
Type of S3 bucket to use [default: inferred from bucket name]
[possible values: general-purpose, directory]
--storage-class <STORAGE_CLASS>
Set the storage class for new objects
--expected-bucket-owner <AWS_ACCOUNT_ID>
Account ID of the expected bucket owner. If the bucket is owned by a different account, S3 requests fail with an access denied error.
--sse <SSE>
Server-side encryption algorithm to use when uploading new objects
[possible values: aws:kms, aws:kms:dsse, AES256]
--sse-kms-key-id <AWS_KMS_KEY_ARN>
AWS Key Management Service (KMS) key ARN to use with KMS server-side encryption when uploading new objects. Key ID, Alias and Alias ARN are all not supported.
--upload-checksums <ALGORITHM>
Checksum algorithm to use for S3 uploads [default: crc32c]
[possible values: crc32c, off]
AWS credentials options:
--no-sign-request
Do not sign requests. Credentials will not be loaded if this argument is provided.
--profile <PROFILE>
Use a specific profile from your credential file.
Mount options:
--read-only
Mount file system in read-only mode
--allow-delete
Allow delete operations on file system
--allow-overwrite
Allow overwrite operations on file system
--incremental-upload
Enable incremental uploads and support for appending to existing objects
--auto-unmount
Automatically unmount on exit
--allow-root
Allow root user to access file system
--allow-other
Allow other users, including root, to access file system
--uid <UID>
Owner UID [default: current user's UID]
--gid <GID>
Owner GID [default: current user's GID]
--dir-mode <DIR_MODE>
Directory permissions [default: 0755]
--file-mode <FILE_MODE>
File permissions [default: 0644]
Client options:
--maximum-throughput-gbps <N>
Maximum throughput in Gbps [default: auto-detected on EC2 instances, 10 Gbps elsewhere]
--max-threads <N>
Maximum number of FUSE daemon threads
[default: 16]
--part-size <SIZE>
Part size for multi-part GET and PUT in bytes
[default: 8388608]
--read-part-size <SIZE>
Part size for GET in bytes [default: 8388608]
--write-part-size <SIZE>
Part size for multi-part PUT in bytes [default: 8388608]
--bind <NETWORK_INTERFACE>
One or more network interfaces for Mountpoint to use when accessing S3. Requires Linux 5.7+ or running as root. This feature is a work-in-progress.
Logging options:
-l, --log-directory <DIRECTORY>
Write log files to a directory [default: logs written to syslog]
--log-metrics
Enable logging of summarized performance metrics
-d, --debug
Enable debug logging for Mountpoint
--debug-crt
Enable debug logging for AWS Common Runtime
--no-log
Disable all logging. You will still see stdout messages.
Caching options:
--cache <DIRECTORY>
Enable caching of object content to the given directory and set metadata TTL to 60 seconds
--metadata-ttl <SECONDS|indefinite|minimal>
Time-to-live (TTL) for cached metadata in seconds [default: minimal, or 60 seconds if --cache is set]
--negative-metadata-ttl <SECONDS|indefinite|minimal>
Time-to-live (TTL) for cached negative entries in seconds [default: same as metadata TTL]
--max-cache-size <MiB>
Maximum size of the cache directory in MiB [default: preserve 5% of available space]
--cache-xz <BUCKET>
Enable caching of object content to the specified bucket on S3 Express One Zone (same region only)
Advanced options:
--user-agent-prefix <PREFIX>
Configure a string to be prepended to the 'User-Agent' HTTP request header for all S3 requests
Alternative fstab style:
mount-s3 <BUCKET> <DIRECTORY> -o <OPTIONS>
Arguments:
<BUCKET_NAME>
Name of bucket, or an S3 URI, to mount
<DIRECTORY>
Location to mount bucket at
<OPTIONS>
fstab style options. Comma separated list of CLI options, with backslash escapes for commas, backslashes, and double quotes.
Use of `--` to prefix arguments is not allowed.
事前に用意していたS3バケットをMountpoint for Amazon S3でマウントします。
$ sudo mkdir -p /mnt/s3
$ sudo mount-s3 non-97-mountpoint-s3 /mnt/s3 \
--allow-delete \
--allow-overwrite \
--allow-other \
--dir-mode 0775 \
--file-mode 0664
bucket non-97-mountpoint-s3 is mounted at /mnt/s3
この状態でファイルを新規作成します。
$ echo test1 > /mnt/s3/test.txt
bash: /mnt/s3/test.txt: Permission denied
$ whoami
ec2-user
$ echo test1 | sudo tee -a /mnt/s3/test.txt > /dev/null
$ ls -l /mnt/s3/test.txt
-rw-rw-r--. 1 root root 6 Oct 11 07:34 /mnt/s3/test.txt
$ cat /mnt/s3/test.txt
test1
$ aws s3 cp s3://non-97-mountpoint-s3/test.txt -
test1
正常に書き込みできましたね。
では、追記をします。
$ echo test2 | sudo tee -a /mnt/s3/test.txt > /dev/null
tee: /mnt/s3/test.txt: Operation not permitted
はい、できませんでした。
では、viでtest2
を末尾に追加する場合はどうでしょうか。
$ vi /mnt/s3/test.txt
$ cat /mnt/s3/test.txt
test1
test2
$ aws s3 cp s3://non-97-mountpoint-s3/test.txt -
test1
test2
こちらは正常に行えました。
続いて、teeで追記ではなく上書きをできるかどうか確認します。
$ echo test3 | sudo tee /mnt/s3/test.txt > /dev/null
$ cat /mnt/s3/test.txt
test3
$ aws s3 cp s3://non-97-mountpoint-s3/test.txt -
test3
ということで、上書きはできるが、追記はできないことを確認しました。
これは--allow-overwrite
オプションで上書きが可能となっているが、その裏側でO_TRUNC
を使用しているためです。
If the --allow-overwrite flag is set at startup time, Mountpoint also supports replacing existing objects by allowing writes to existing files, but only when the O_TRUNC flag is used at open time to truncate the existing file. In both cases, writes must always start from the beginning of the file and must be made sequentially. Mountpoint uploads new files to S3 asynchronously, and optimizes for high write throughput using multiple concurrent upload requests.
mountpoint-s3/doc/SEMANTICS.md at main · awslabs/mountpoint-s3
O_TRUNC
は既に存在しているファイルがある場合、長さ0で切り詰められます。
$ man open
.
.
(中略)
.
.
O_TRUNC
If the file already exists and is a regular file and the access mode allows writing (i.e., is O_RDWR or O_WRONLY) it will be truncated to length 0. If the file is a FIFO or terminal device file, the O_TRUNC flag is ignored. Otherwise, the effect of O_TRUNC is unspecified.
要するに--allow-overwrite
の上書きの意味合いはファイル全体の置換がイメージとしては近いでしょう。
この時のMountpoint for Amazon S3が出力したログは以下のとおりです。
$ sudo journalctl --since "2025-10-11 07:11:57" | grep mount-s3
Oct 11 07:12:11 ip-10-10-0-11.ec2.internal sudo[1897]: ec2-user : TTY=pts/0 ; PWD=/home/ec2-user ; USER=root ; COMMAND=/usr/bin/dnf install -y ./mount-s3.rpm
Oct 11 07:33:14 ip-10-10-0-11.ec2.internal sudo[2759]: ec2-user : TTY=pts/0 ; PWD=/home/ec2-user ; USER=root ; COMMAND=/usr/bin/mount-s3 non-97-mountpoint-s3 /mnt/s3 --allow-delete --allow-overwrite --allow-other --dir-mode 0775 --file-mode 0664
Oct 11 07:34:12 ip-10-10-0-11.ec2.internal mount-s3[2829]: [WARN] ThreadId(08) getxattr{req=20 ino=2 name="security.capability"}: mountpoint_s3_fs::fuse: getxattr failed: operation not supported by Mountpoint
Oct 11 07:36:38 ip-10-10-0-11.ec2.internal mount-s3[2829]: [WARN] ThreadId(09) open{req=44 ino=2 pid=2990 name=test.txt}: mountpoint_s3_fs::metablock: modifying an existing file is disabled by default, you need to remount with the --allow-overwrite or the --incremental-upload flag to enable it
Oct 11 07:36:38 ip-10-10-0-11.ec2.internal mount-s3[2829]: [WARN] ThreadId(09) open{req=44 ino=2 pid=2990 name=test.txt}: mountpoint_s3_fs::fuse: open failed with errno 1: inode error: inode 2 (partial key "test.txt") is not writable
Oct 11 07:37:53 ip-10-10-0-11.ec2.internal mount-s3[2829]: [WARN] ThreadId(09) unlink{req=80 parent=1 name=".test.txt.swx"}: mountpoint_s3_fs::superblock: unlink on local file not allowed until write is complete parent=1 name=".test.txt.swx"
Oct 11 07:37:53 ip-10-10-0-11.ec2.internal mount-s3[2829]: [WARN] ThreadId(09) unlink{req=80 parent=1 name=".test.txt.swx"}: mountpoint_s3_fs::fuse: unlink failed with errno 1:inode error: inode 4 (partial key ".test.txt.swx") cannot be unlinked while being written
Oct 11 07:37:53 ip-10-10-0-11.ec2.internal mount-s3[2829]: [WARN] ThreadId(10) unlink{req=88 parent=1 name=".test.txt.swp"}: mountpoint_s3_fs::superblock: unlink on local file not allowed until write is complete parent=1 name=".test.txt.swp"
Oct 11 07:37:53 ip-10-10-0-11.ec2.internal mount-s3[2829]: [WARN] ThreadId(10) unlink{req=88 parent=1 name=".test.txt.swp"}: mountpoint_s3_fs::fuse: unlink failed with errno 1:inode error: inode 3 (partial key ".test.txt.swp") cannot be unlinked while being written
Oct 11 07:37:56 ip-10-10-0-11.ec2.internal mount-s3[2829]: [WARN] ThreadId(09) write{req=128 ino=5 fh=6 offset=0 length=4096 pid=3007 name=test_txt.swp}: mountpoint_s3_fs::fuse: write failed with errno 22: upload error: out-of-order write is NOT supported by Mountpoint, aborting the upload; expected offset 4096 but got 0
Oct 11 07:37:56 ip-10-10-0-11.ec2.internal mount-s3[2829]: [WARN] ThreadId(10) flush{req=130 ino=5 fh=6 pid=3007 name=test_txt.swp}: mountpoint_s3_fs::fuse: flush failed with errno 22: upload already aborted for key ValidKey { key: "test_txt.swp", name_offset: 0 }
Oct 11 07:38:03 ip-10-10-0-11.ec2.internal mount-s3[2829]: [WARN] ThreadId(06) unlink{req=168 parent=1 name="4913"}: mountpoint_s3_fs::superblock: unlink on local file not allowed until write is complete parent=1 name="4913"
Oct 11 07:38:03 ip-10-10-0-11.ec2.internal mount-s3[2829]: [WARN] ThreadId(06) unlink{req=168 parent=1 name="4913"}: mountpoint_s3_fs::fuse: unlink failed with errno 1: inode error: inode 7 (partial key "4913") cannot be unlinked while being written
Oct 11 07:38:03 ip-10-10-0-11.ec2.internal mount-s3[2829]: [WARN] ThreadId(13) rename{req=180 parent=1 name="test.txt" newparent=1 newname="test.txt~"}:rename_object_request{id=113 bucket=non-97-mountpoint-s3}: mountpoint_s3_client::s3_crt_client: duration=5.026946ms request_id=3NDKSGDMYQGYHSF0 error=ServiceError(NotImplementedError)meta request failed
Oct 11 07:38:03 ip-10-10-0-11.ec2.internal mount-s3[2829]: [WARN] ThreadId(10) rename{req=180 parent=1 name="test.txt" newparent=1 newname="test.txt~"}: mountpoint_s3_fs::fuse:rename failed with errno 38: inode error: rename is not supported on this bucket
Oct 11 07:38:04 ip-10-10-0-11.ec2.internal mount-s3[2829]: [WARN] ThreadId(08) listxattr{req=236 ino=8}: mountpoint_s3_fs::fuse: listxattr failed: operation not supported by Mountpoint
Oct 11 07:38:04 ip-10-10-0-11.ec2.internal mount-s3[2829]: [WARN] ThreadId(06) setattr{req=238 ino=9 name=test.txt}: mountpoint_s3_fs::fuse: setattr failed with errno 1: inode error: inode 9 (partial key "test.txt") is a remote inode and its attributes cannot be modified
Oct 11 07:38:04 ip-10-10-0-11.ec2.internal mount-s3[2829]: [WARN] ThreadId(09) write{req=244 ino=6 fh=8 offset=0 length=4096 pid=3007 name=test_txt.swp}: mountpoint_s3_fs::fuse: write failed with errno 22: upload error: out-of-order write is NOT supported by Mountpoint, aborting the upload; expected offset 4096 but got 0
Oct 11 07:38:04 ip-10-10-0-11.ec2.internal mount-s3[2829]: [WARN] ThreadId(12) flush{req=246 ino=6 fh=8 pid=3007 name=test_txt.swp}: mountpoint_s3_fs::fuse: flush failed with errno 22: upload already aborted for key ValidKey { key: "test_txt.swp", name_offset: 0 }
少し分かりづらいので再度追記をしてみます。
$ echo test4 | sudo tee -a /mnt/s3/test.txt > /dev/null
tee: /mnt/s3/test.txt: Operation not permitted
$ sudo journalctl --since "2025-10-11 07:11:57" | grep mount-s3 | tail
.
.
(中略)
.
.
Oct 15 05:17:49 ip-10-10-0-11.ec2.internal mount-s3[2431]: [WARN] ThreadId(08) open{req=14 ino=2 pid=2530 name=test.txt}: mountpoint_s3_fs::metablock: modifying an existing file is disabled by default, you need to remount with the --allow-overwrite or the --incremental-upload flag to enable it
Oct 15 05:17:49 ip-10-10-0-11.ec2.internal mount-s3[2431]: [WARN] ThreadId(08) open{req=14 ino=2 pid=2530 name=test.txt}: mountpoint_s3_fs::fuse: open failed with errno 1: inode error: inode 2 (partial key "test.txt") is not writable
ファイルの変更はできないとエラーになっていますね。
こちらの回避策として別の領域にログ出力をしておいて、一定の量もしくは間隔でS3バケットをMountpoint for Amazon S3をマウントしているmvする方式が考えられます。
ただし、そのような対応をするのであれば最初からFluent Bitなどログルーティングをするサービスを導入した方が手っ取り早いと思います。
Express One Zoneをマウント先S3バケットにして Mountpoint for S3を用いた追記確認
では、Mountpoint for Amazon S3ではもうどうしようもないのか... というと、そうではありません。
S3 Express One Zoneを使う場合、--incremental-upload
でマウントすることで追記を行うことが可能です。
For objects stored in S3 Express One Zone, Mountpoint supports appending to files. If the --incremental-upload flag is set at startup time, Mountpoint allows opening existing files without specifying the O_TRUNC flag. All writes must still be sequential and start from the end of the file. In this mode, Mountpoint will always upload data to S3 in sequential increments and offer the same throughput of a single PUT API call on S3. Moreover, partial writes will be visible to other S3 clients before the file is closed. Applications can call fsync to guarantee that the data written so far is uploaded to S3 and are then allowed to continue writing to the file.
mountpoint-s3/doc/SEMANTICS.md at main · awslabs/mountpoint-s3
実際に試してみましょう。
適当にS3 Express One Zoneのバケットの作成をします。
S3 Express One ZoneもカバーするようなIAMポリシーをEC2インスタンスアタッチしてあげます。詳細は以下記事をご覧ください。
作成したディレクトリバケットをマウントします。
$ sudo mount-s3 non-97-mountpoint-s3--use1-az6--x-s3 /mnt/express-s3 \
--allow-delete \
--allow-overwrite \
--incremental-upload \
--allow-other \
--dir-mode 0775 \
--file-mode 0664
bucket non-97-mountpoint-s3--use1-az6--x-s3 is mounted at /mnt/express-s3
書き込みできることを確認しましょう。
$ date
Wed Oct 15 05:28:12 UTC 2025
$ echo test1 | sudo tee -a /mnt/express-s3/test.txt > /dev/null
$ ls -l /mnt/express-s3/
total 1
-rw-rw-r--. 1 root root 6 Oct 15 05:28 test.txt
$ cat /mnt/express-s3/test.txt
test1
$ date
Wed Oct 15 05:30:10 UTC 2025
$ aws s3 cp s3://non-97-mountpoint-s3--use1-az6--x-s3/test.txt -
test1
正常に書き込みできました。
追記の確認もしましょう。
$ echo test2 | sudo tee -a /mnt/express-s3/test.txt > /dev/null
$ ls -l /mnt/express-s3/
total 1
-rw-rw-r--. 1 root root 12 Oct 15 05:30 test.txt
$ cat /mnt/express-s3/test.txt
test1
test2
$ aws s3 cp s3://non-97-mountpoint-s3--use1-az6--x-s3/test.txt -
test1
test2
$ date
Wed Oct 15 05:31:21 UTC 2025
問題なく追記できましたね。
S3 Express One Zoneで追記をする場合の注意点として、オブジェクトの追記可能上限が最大9,999回までというものがあります。
実際に体感をしてみましょう。
ひたすらに追記をします。
$ date
Wed Oct 15 05:37:09 UTC 2025
$ for i in {3..9999}; do
echo "test${i}" | sudo tee -a /mnt/express-s3/test.txt > /dev/null
done
追記をしている間、別セッションで追記の様子を確認します。
$ tail /mnt/express-s3/test.txt
test2225
test2226
test2227
test2228
test2229
test2230
test2231
test2232
test2233
test2234
$ tail /mnt/express-s3/test.txt
tail: cannot open '/mnt/express-s3/test.txt' for reading: Operation not permitted
$ tail /mnt/express-s3/test.txt
test2812
test2813
test2814
test2815
test2816
test2817
test2818
test2819
test2820
test2821
順調に追記されているようですね。一方で権限不足でエラーを吐くこともありました。
また、追記をしているセッションを確認すると、別セッションでtailをした際にOperation not permitted
とエラーを吐いていました。
$ date
Wed Oct 15 05:37:09 UTC 2025
$ for i in {3..9999}; do
echo "test${i}" | sudo tee -a /mnt/express-s3/test.txt > /dev/null
done
tee: /mnt/express-s3/test.txt: Operation not permitted
tee: /mnt/express-s3/test.txt: Operation not permitted
tee: /mnt/express-s3/test.txt: Operation not permitted
tee: /mnt/express-s3/test.txt: Operation not permitted
tee: /mnt/express-s3/test.txt: Operation not permitted
tee: /mnt/express-s3/test.txt: Operation not permitted
tee: /mnt/express-s3/test.txt: Operation not permitted
tee: /mnt/express-s3/test.txt: Operation not permitted
tee: /mnt/express-s3/test.txt: Operation not permitted
tee: /mnt/express-s3/test.txt: Operation not permitted
tee: /mnt/express-s3/test.txt: Operation not permitted
ドキュメントを確認すると、以下が紹介されていました。
- ファイルの書き込みは一人のユーザーのでのみ順次行われる
- 書き込み中はファイルが閉じられ、アップロードが完了するまで読み取りができない
Mountpoint allows multiple readers to access the same object at the same time. However, files can only be written to sequentially and by one writer at a time. Files that are being written to are not available for reading until the writing application closes the file and Mountpoint finishes uploading it to S3, regardless of upload mode.
mountpoint-s3/doc/SEMANTICS.md at main · awslabs/mountpoint-s3
実際に書き込み中に読み込みをしようとした訳なので、ドキュメントに記載のとおりの挙動をしていますね。
しばらくすると書き込みが完了していました。
$ date
Wed Oct 15 05:37:09 UTC 2025
$ for i in {3..9999}; do
echo "test${i}" | sudo tee -a /mnt/express-s3/test.txt > /dev/null
done
tee: /mnt/express-s3/test.txt: Operation not permitted
tee: /mnt/express-s3/test.txt: Operation not permitted
tee: /mnt/express-s3/test.txt: Operation not permitted
tee: /mnt/express-s3/test.txt: Operation not permitted
tee: /mnt/express-s3/test.txt: Operation not permitted
tee: /mnt/express-s3/test.txt: Operation not permitted
tee: /mnt/express-s3/test.txt: Operation not permitted
tee: /mnt/express-s3/test.txt: Operation not permitted
tee: /mnt/express-s3/test.txt: Operation not permitted
tee: /mnt/express-s3/test.txt: Operation not permitted
tee: /mnt/express-s3/test.txt: Operation not permitted
$ date
Wed Oct 15 05:59:07 UTC 2025
$ ls -l /mnt/express-s3/
total 87
-rw-rw-r--. 1 root root 88785 Oct 15 05:56 test.txt
約10,000回追記するのに約22分ほどかかりました。
以下でベンチマーク結果が公開されていますが、今回はより細かいファイルIO かつ インスタンスサイズもt3.microと小さいものであるため、公開されているものよりもパフォーマンスが出なかったのだと推測します。
ファイルの中身を確認します。
$ head /mnt/express-s3/test.txt
test1
test2
test3
test4
test5
test6
test7
test8
test9
test10
$ time tail /mnt/express-s3/test.txt
test9990
test9991
test9992
test9993
test9994
test9995
test9996
test9997
test9998
test9999
real 0m0.730s
user 0m0.002s
sys 0m0.000s
$ time aws s3 cp s3://non-97-mountpoint-s3--use1-az6--x-s3/test.txt - | tail
test9990
test9991
test9992
test9993
test9994
test9995
test9996
test9997
test9998
test9999
real 0m10.092s
user 0m0.876s
sys 0m0.220s
確かに追記されていますね。
それではさらに追記をします。
$ echo "test10000" | sudo tee -a /mnt/express-s3/test.txt > /dev/null
$ ls -l /mnt/express-s3/
total 87
-rw-rw-r--. 1 root root 88795 Oct 15 06:02 test.txt
$ time tail /mnt/express-s3/test.txt
test9991
test9992
test9993
test9994
test9995
test9996
test9997
test9998
test9999
test10000
real 0m0.708s
user 0m0.002s
sys 0m0.000s
$ echo "test10001" | sudo tee -a /mnt/express-s3/test.txt > /dev/null
$ ls -l /mnt/express-s3/
total 87
-rw-rw-r--. 1 root root 88805 Oct 15 06:03 test.txt
$ time tail /mnt/express-s3/test.txt
test9992
test9993
test9994
test9995
test9996
test9997
test9998
test9999
test10000
test10001
real 0m0.664s
user 0m0.002s
sys 0m0.000s
おや、9,999回以上の追記にも関わらず問題なく追記が完了しています。
何かログが出ていないか確認します。
$ sudo journalctl --since "2025-10-11 07:11:57" | grep mount-s3
.
.
(中略)
.
.
Oct 15 05:28:14 ip-10-10-0-11.ec2.internal mount-s3[2934]: [WARN] ThreadId(06) getxattr{req=14 ino=2 name="security.capability"}: mountpoint_s3_fs::fuse: getxattr failed: operation not supported by Mountpoint
Oct 15 05:41:39 ip-10-10-0-11.ec2.internal mount-s3[2934]: [WARN] ThreadId(06) open{req=22408 ino=2 pid=14919 name=test.txt}: mountpoint_s3_fs::fuse: open failed with errno 1: inode error: inode 2 (partial key "test.txt") is not writable while being read
Oct 15 05:41:39 ip-10-10-0-11.ec2.internal mount-s3[2934]: [WARN] ThreadId(09) open{req=22410 ino=2 pid=14925 name=test.txt}: mountpoint_s3_fs::fuse: open failed with errno 1: inode error: inode 2 (partial key "test.txt") is not writable while being read
Oct 15 05:41:39 ip-10-10-0-11.ec2.internal mount-s3[2934]: [WARN] ThreadId(09) open{req=22414 ino=2 pid=14930 name=test.txt}: mountpoint_s3_fs::fuse: open failed with errno 1: inode error: inode 2 (partial key "test.txt") is not writable while being read
Oct 15 05:42:19 ip-10-10-0-11.ec2.internal mount-s3[2934]: [WARN] ThreadId(06) open{req=25808 ino=2 pid=16642 name=test.txt}: mountpoint_s3_fs::fuse: open failed with errno 1: inode error: inode 2 (partial key "test.txt") is not readable while being written
Oct 15 05:42:48 ip-10-10-0-11.ec2.internal mount-s3[2934]: [WARN] ThreadId(06) open{req=28274 ino=2 pid=17940 name=test.txt}: mountpoint_s3_fs::fuse: open failed with errno 1: inode error: inode 2 (partial key "test.txt") is not writable while being read
Oct 15 05:42:48 ip-10-10-0-11.ec2.internal mount-s3[2934]: [WARN] ThreadId(09) open{req=28278 ino=2 pid=17945 name=test.txt}: mountpoint_s3_fs::fuse: open failed with errno 1: inode error: inode 2 (partial key "test.txt") is not writable while being read
Oct 15 05:42:48 ip-10-10-0-11.ec2.internal mount-s3[2934]: [WARN] ThreadId(08) open{req=28282 ino=2 pid=17950 name=test.txt}: mountpoint_s3_fs::fuse: open failed with errno 1: inode error: inode 2 (partial key "test.txt") is not writable while being read
Oct 15 05:42:48 ip-10-10-0-11.ec2.internal mount-s3[2934]: [WARN] ThreadId(09) open{req=28284 ino=2 pid=17955 name=test.txt}: mountpoint_s3_fs::fuse: open failed with errno 1: inode error: inode 2 (partial key "test.txt") is not writable while being read
Oct 15 05:42:48 ip-10-10-0-11.ec2.internal mount-s3[2934]: [WARN] ThreadId(08) open{req=28288 ino=2 pid=17962 name=test.txt}: mountpoint_s3_fs::fuse: open failed with errno 1: inode error: inode 2 (partial key "test.txt") is not writable while being read
Oct 15 05:42:48 ip-10-10-0-11.ec2.internal mount-s3[2934]: [WARN] ThreadId(09) open{req=28290 ino=2 pid=17967 name=test.txt}: mountpoint_s3_fs::fuse: open failed with errno 1: inode error: inode 2 (partial key "test.txt") is not writable while being read
Oct 15 05:42:48 ip-10-10-0-11.ec2.internal mount-s3[2934]: [WARN] ThreadId(08) open{req=28294 ino=2 pid=17972 name=test.txt}: mountpoint_s3_fs::fuse: open failed with errno 1: inode error: inode 2 (partial key "test.txt") is not writable while being read
Oct 15 05:42:49 ip-10-10-0-11.ec2.internal mount-s3[2934]: [WARN] ThreadId(09) open{req=28296 ino=2 pid=17977 name=test.txt}: mountpoint_s3_fs::fuse: open failed with errno 1: inode error: inode 2 (partial key "test.txt") is not writable while being read
いくつかエラーは出ていますが、時間帯的にいずれも書き込み中に読み込もうとした際のログです。
さらに追記をします。
$ echo "test10002" | sudo tee -a /mnt/express-s3/test.txt > /dev/null
$ echo "test10003" | sudo tee -a /mnt/express-s3/test.txt > /dev/null
$ echo "test10004" | sudo tee -a /mnt/express-s3/test.txt > /dev/null
$ echo "test10005" | sudo tee -a /mnt/express-s3/test.txt > /dev/null
$ time tail /mnt/express-s3/test.txt
test9996
test9997
test9998
test9999
test10000
test10001
test10002
test10003
test10004
test10005
real 0m0.697s
user 0m0.002s
sys 0m0.000s
まだエラーになりません。
実際に追記が行われているのか確認をしましょう。
$ wc -l /mnt/express-s3/test.txt
9994 /mnt/express-s3/test.txt
9,994回しか書き込めていないようです。エラーになったタイミングで欠損が発生したようですね。
さらに追記をします。
$ echo "test10006" | sudo tee -a /mnt/express-s3/test.txt > /dev/null
$ echo "test10007" | sudo tee -a /mnt/express-s3/test.txt > /dev/null
$ echo "test10008" | sudo tee -a /mnt/express-s3/test.txt > /dev/null
$ echo "test10009" | sudo tee -a /mnt/express-s3/test.txt > /dev/null
$ echo "test10010" | sudo tee -a /mnt/express-s3/test.txt > /dev/null
$ echo "test10011" | sudo tee -a /mnt/express-s3/test.txt > /dev/null
$ wc -l /mnt/express-s3/test.txt
10000 /mnt/express-s3/test.txt
$ echo "test10012" | sudo tee -a /mnt/express-s3/test.txt > /dev/null
tee: /mnt/express-s3/test.txt: Input/output error
$ wc -l /mnt/express-s3/test.txt
10000 /mnt/express-s3/test.txt
$ tail /mnt/express-s3/test.txt
test10002
test10003
test10004
test10005
test10006
test10007
test10008
test10009
test10010
test10011
10,001回目の書き込みからエラーになるようになりました。
この時のjournalを確認します。
$ aws s3api get-object-attributes \
--bucket non-97-mountpoint-s3--use1-az6--x-s3 \
--key test.txt \
--object-attributes "ObjectParts" \
--region us-east-1
{
"LastModified": "2025-10-15T06:20:55+00:00"
}
$ sudo journalctl --since "2025-10-15 06:20:00" | grep mount-s3
Oct 15 06:21:23 ip-10-10-0-11.ec2.internal mount-s3[2934]: [WARN] ThreadId(11) put_object_single{id=53583 bucket=non-97-mountpoint-s3--use1-az6--x-s3 key=test.txt}: mountpoint_s3_client::s3_crt_client: duration=4.107373ms request_id=01f02b4dfa000199e687cb69040873c16d6e2070 request_result=MetaRequestResult { response_status: 400, crt_error: Error(14343, "aws-c-s3: AWS_ERROR_S3_INVALID_RESPONSE_STATUS, Invalid response status from request"), error_response_headers: Some(Headers { inner: 0x7f2b040533d0 }), error_response_body:Some("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Error><Code>TooManyParts</Code><Message>You have attempted to add more parts than the maximum of 10000 that are allowed for this object. You can use the CopyObject operation to copy this object to another and then add more data to the newly copied object.</Message><RequestId>01f02b4dfa000199e687cb69040873c16d6e2070</RequestId><HostId>mmmVSQ7CID</HostId></Error>") }meta request failed
Oct 15 06:21:23 ip-10-10-0-11.ec2.internal mount-s3[2934]: [WARN] ThreadId(10) flush{req=100264 ino=2 fh=10012 pid=55743 name=test.txt}: mountpoint_s3_fs::fuse: flush failed with errno 5: put failed: put request failed: Client error: Unknown response error: MetaRequestResult { response_status: 400, crt_error: Error(14343, "aws-c-s3: AWS_ERROR_S3_INVALID_RESPONSE_STATUS, Invalid response status from request"), error_response_headers: Some(Headers { inner: 0x7f2b040533d0 }), error_response_body: Some("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Error><Code>TooManyParts</Code><Message>You have attempted to add more parts than the maximum of 10000 that are allowed for this object. You can use the CopyObject operation to copy this object to another and then add more data to the newly copied object.</Message><RequestId>01f02b4dfa000199e687cb69040873c16d6e2070</RequestId><HostId>mmmVSQ7CID</HostId></Error>") }
TooManyParts
と10,000回の書き込み上限に抵触したことが分かりますね。
ログの流量が多い場合、10,000レコードは割と到達しやすいかと思います。
また、S3バケットに期待していることが複数AZにデータを配置することによる耐久性なのであれば、S3 Express One Zoneを使わなければならない以上、採用は難しいように感じます。
Nginxのログ出力先にMountpoint for S3でマウントした領域を指定
続いて、Nginxのログ出力先にMountpoint for S3でマウントした領域を指定します。
Nginxをインストールします。
$ sudo dnf install nginx
.
.
(中略)
.
.
Installed:
generic-logos-httpd-18.0.0-12.amzn2023.0.3.noarch gperftools-libs-2.9.1-1.amzn2023.0.3.x86_64 libunwind-1.4.0-5.amzn2023.0.3.x86_64
nginx-1:1.28.0-1.amzn2023.0.2.x86_64 nginx-core-1:1.28.0-1.amzn2023.0.2.x86_64 nginx-filesystem-1:1.28.0-1.amzn2023.0.2.noarch
nginx-mimetypes-2.1.49-3.amzn2023.0.3.noarch
Complete!
$ ls -l /var/log/ | grep nginx
drwx--x--x. 2 root root 6 Aug 12 21:19 nginx
/var/log/nginx
にディレクトリバケットをマウントします。
$ sudo mount-s3 non-97-mountpoint-s3--use1-az6--x-s3 /var/log/nginx \
--allow-delete \
--allow-overwrite \
--incremental-upload \
--allow-other \
--dir-mode 0775 \
--file-mode 0664
bucket non-97-mountpoint-s3--use1-az6--x-s3 is mounted at /var/log/nginx
$ df -hT
Filesystem Type Size Used Avail Use% Mounted on
devtmpfs devtmpfs 4.0M 0 4.0M 0% /dev
tmpfs tmpfs 453M 0 453M 0% /dev/shm
tmpfs tmpfs 181M 432K 181M 1% /run
/dev/nvme0n1p1 xfs 8.0G 1.8G 6.2G 22% /
tmpfs tmpfs 453M 0 453M 0% /tmp
/dev/nvme0n1p128 vfat 10M 1.3M 8.7M 13% /boot/efi
tmpfs tmpfs 91M 0 91M 0% /run/user/0
mountpoint-s3 fuse 8.0E 0 8.0E 0% /var/log/nginx
Nginxを起動しようとしてみます。
$ sudo systemctl start nginx
Job for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xeu nginx.service" for details.
$ journalctl -xeu nginx.service
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
Oct 15 06:46:33 ip-10-10-0-14.ec2.internal systemd[1]: Starting nginx.service - The nginx HTTP and reverse proxy server...
░░ Subject: A start job for unit nginx.service has begun execution
░░ Defined-By: systemd
░░ Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel
░░
░░ A start job for unit nginx.service has begun execution.
░░
░░ The job identifier is 1725.
Oct 15 06:46:33 ip-10-10-0-14.ec2.internal nginx[25857]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
Oct 15 06:46:33 ip-10-10-0-14.ec2.internal nginx[25857]: nginx: [emerg] open() "/var/log/nginx/error.log" failed (1: Operation not permitted)
Oct 15 06:46:33 ip-10-10-0-14.ec2.internal nginx[25857]: nginx: configuration file /etc/nginx/nginx.conf test failed
Oct 15 06:46:33 ip-10-10-0-14.ec2.internal systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
░░ Subject: Unit process exited
░░ Defined-By: systemd
░░ Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel
░░
░░ An ExecStartPre= process belonging to unit nginx.service has exited.
░░
░░ The process' exit code is 'exited' and its exit status is 1.
Oct 15 06:46:33 ip-10-10-0-14.ec2.internal systemd[1]: nginx.service: Failed with result 'exit-code'.
░░ Subject: Unit failed
░░ Defined-By: systemd
░░ Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel
░░
░░ The unit nginx.service has entered the 'failed' state with result 'exit-code'.
Oct 15 06:46:33 ip-10-10-0-14.ec2.internal systemd[1]: Failed to start nginx.service - The nginx HTTP and reverse proxy server.
░░ Subject: A start job for unit nginx.service has failed
░░ Defined-By: systemd
░░ Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel
░░
░░ A start job for unit nginx.service has finished with a failure.
░░
░░ The job identifier is 1725 and the job result is failed.
はい、Nginxの起動に失敗しました。
journalも確認しましょう。
$ sudo journalctl --since "2025-10-15 06:46:20" | grep mount-s3
Oct 15 06:46:23 ip-10-10-0-14.ec2.internal sudo[25817]: ec2-user : TTY=pts/0 ; PWD=/home/ec2-user ; USER=root ; COMMAND=/usr/bin/mount-s3 non-97-mountpoint-s3--use1-az6--x-s3 /var/log/nginx --allow-delete --allow-overwrite --incremental-upload --allow-other --dir-mode 0775 --file-mode 0664
Oct 15 06:46:33 ip-10-10-0-14.ec2.internal mount-s3[25831]: [WARN] ThreadId(06) open{req=16 ino=2 pid=25857 name=error.log}: mountpoint_s3_fs::fuse: open failed with errno 1: inode error: inode 2 (partial key "error.log") is already being written
Oct 15 06:46:33 ip-10-10-0-14.ec2.internal mount-s3[25831]: [WARN] ThreadId(08) getxattr{req=18 ino=2 name="security.capability"}: mountpoint_s3_fs::fuse: getxattr failed: operation not supported by Mountpoint
すでに書き込み中とのことでエラーとなっているようです。
試しにアンマウントした状態で正常にNginxが起動できるか確認します。
$ sudo umount /var/log/nginx
$ sudo systemctl start nginx
$ systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; preset: disabled)
Active: active (running) since Wed 2025-10-15 09:01:51 UTC; 7s ago
Process: 30959 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
Process: 30960 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
Process: 30961 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
Main PID: 30962 (nginx)
Tasks: 3 (limit: 1057)
Memory: 3.2M
CPU: 58ms
CGroup: /system.slice/nginx.service
├─30962 "nginx: master process /usr/sbin/nginx"
├─30963 "nginx: worker process"
└─30964 "nginx: worker process"
Oct 15 09:01:51 ip-10-10-0-14.ec2.internal systemd[1]: Starting nginx.service - The nginx HTTP and reverse proxy server...
Oct 15 09:01:51 ip-10-10-0-14.ec2.internal nginx[30960]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
Oct 15 09:01:51 ip-10-10-0-14.ec2.internal nginx[30960]: nginx: configuration file /etc/nginx/nginx.conf test is successful
Oct 15 09:01:51 ip-10-10-0-14.ec2.internal systemd[1]: Started nginx.service - The nginx HTTP and reverse proxy server.
$ sudo lsof -c nginx | grep log
nginx 30962 root 2w REG 259,1 1703 9243309 /var/log/nginx/error.log
nginx 30962 root 6w REG 259,1 1703 9243309 /var/log/nginx/error.log
nginx 30962 root 7w REG 259,1 0 9243312 /var/log/nginx/access.log
nginx 30963 nginx 2w REG 259,1 1703 9243309 /var/log/nginx/error.log
nginx 30963 nginx 6w REG 259,1 1703 9243309 /var/log/nginx/error.log
nginx 30963 nginx 7w REG 259,1 0 9243312 /var/log/nginx/access.log
nginx 30964 nginx 2w REG 259,1 1703 9243309 /var/log/nginx/error.log
nginx 30964 nginx 6w REG 259,1 1703 9243309 /var/log/nginx/error.log
nginx 30964 nginx 7w REG 259,1 0 9243312 /var/log/nginx/access.log
正常に起動できました。
複数のプロセスがNginxの各ログファイルをオープンしていることが分かります。
ということで、同時に書き込み数に制限があるMountPoint for Amazon S3においてはNginxのログ出力と相性が悪いようです。
CloudWatch Logsに出力するか、Fluent Bit経由でS3バケットに出力するか形が良さそう
Mountpoint for Amazon S3でS3バケットをマウントした領域をログ出力にしてみました。
結論、以下を鑑みるとログはCloudWatch Logsに出力するか、Fluent Bit経由でS3バケットに出力するか形が良さそうです。
- 2025/10/15時点では追記をサポートしているのはS3 Express One Zoneのみ
- 複数AZへのデータの保存は行われない
- ストレージクラスの変更はできない
- 追記の上限9,999回というハードリミットがある
- 直接オブジェクトに追記をする場合、S3のAPIにかかるコストも気になる
- 常時ファイルをオープンするようなプロセスを起動しようとすると失敗する
この記事が誰かの助けになれば幸いです。
以上、クラウド事業本部 コンサルティング部の のんピ(@non____97)でした!