概要
Proxmox Backup Server (現:PBS 7.0.0) で Wasabi S3 バックエンドにバックアップ中、プロセスが約3時間フリーズして強制終了される事象が多発した。原因は Linux の TCP keepalive のデフォルト値が長すぎることによる「TCPブラックホール」で、keepalive パラメータを調整することで解決した。
環境
- PBS バージョン: 7.0.0-3-pve(Debian GNU/Linux ベース)
- バックアップ先: Wasabi S3(シンガポールリージョン
ap-southeast-1) - 対象 VM: VM 118(64GB ディスク)
- PVE ノード: pve2
症状
定期バックアップジョブ(毎日 04:15 実行)のログを確認すると、VM 118 のバックアップだけが失敗していた。
INFO: 26% (17.1 GiB of 64.0 GiB) in 2m 9s, read: 249.3 MiB/s, write: 40.0 MiB/s
INFO: 26% (17.1 GiB of 64.0 GiB) in 3h 2m 23s, read: 33.0 KiB/s, write: 31.4 KiB/s
ERROR: backup write data failed: command error: write_data upload error:
pipelined request failed: Unable to acquire lock
"/run/proxmox-backup/locks/wasabi/.chunks/2f97/..." -
Interrupted system call (os error 4)
ポイント:
- 2分9秒時点では 249 MiB/s で正常動作
- その後 約3時間、17.1GiB の地点でほぼ完全に停止(33 KiB/s まで低下)
- エラーは
os error 4=EINTR(システムコール割り込み) - PBS の UI を含むプロセス全体がフリーズしていた
原因
1. dirty-bitmap が created new になっていた
通常の差分バックアップであれば dirty-bitmap status: OK (X GiB dirty) と表示され、変更分だけを転送する。しかし今回は:
INFO: scsi0: dirty-bitmap status: created new
以前の失敗でビットマップが消えており、64GB のフルバックアップが必要な状態になっていた。これにより転送時間が大幅に伸び、問題が顕在化しやすくなっていた。
2. TCP ブラックホール(本質的原因)
Wasabi(シンガポールリージョン)との長時間 S3 アップロード中に以下の連鎖が発生した:
- 途中の NAT やファイアウォールがアイドルタイムアウトで TCP コネクションをサイレントにドロップ
- FIN/RST が届かないため、PBS 側の OS はコネクションが生きていると認識し続ける
- PBS の chunk uploader がデッドなソケットへの write でブロック
- プロセス全体がハング
Linux のデフォルトの TCP keepalive 設定は:
net.ipv4.tcp_keepalive_time = 7200 # 2時間アイドル後にプローブ開始
今回の停止時間(約3時間)は、2時間の keepalive タイムアウト + その後のプローブ時間とほぼ一致する。つまり 2時間もデッドなコネクションに気づけなかったことが根本原因だった。
3. 負のサイクル
バックアップ失敗
→ dirty-bitmap リセット(created new)
→ 次回もフルバックアップ(64GB)
→ 転送時間が長くなりハングしやすい
→ また失敗 → dirty-bitmap リセット ...(無限ループ)
解決策?
Step 1:TCP keepalive をチューニング
PBS ホストで以下を設定する:
cat << 'EOF' > /etc/sysctl.d/99-tcp-keepalive.conf
# アイドル10分後にkeepaliveプローブ開始(デフォルト: 7200秒)
net.ipv4.tcp_keepalive_time = 600
# 30秒間隔で再送
net.ipv4.tcp_keepalive_intvl = 30
# 5回失敗でコネクション切断
net.ipv4.tcp_keepalive_probes = 5
EOF
sysctl -p /etc/sysctl.d/99-tcp-keepalive.conf
これにより、デッドコネクションを最大 600 + 30×5 = 750秒(約12.5分) で検出・切断できるようになる。
変更前後の比較:
| パラメータ | デフォルト | 変更後 |
|---|---|---|
tcp_keepalive_time |
7200秒(2時間) | 600秒(10分) |
tcp_keepalive_intvl |
75秒 | 30秒 |
tcp_keepalive_probes |
9回 | 5回 |
| デッド検出までの最大時間 | 約2時間42分 | 約12.5分 |
Step 2:PBS 側タイムアウト設定の確認(結果:なし)
PBS の S3 エンドポイント設定にアプリケーションレベルのタイムアウトが存在するか確認した:
proxmox-backup-manager s3-endpoint update wasabi --help 2>&1 | grep -i timeout
# → 何も出力されない
PBS 7.x の S3 バックエンドにはタイムアウト設定が実装されていないため、OS の TCP keepalive が唯一の防衛ラインとなる。
Step 3:dirty-bitmap を回復させるため手動バックアップを実行
TCP keepalive 適用後、PVE ノード(pve2)で手動バックアップを実行:
vzdump 118 --mode snapshot --storage wasabi-backup --notes-template '{{guestname}}'
結果:
INFO: scsi0: dirty-bitmap status: OK (7.6 GiB of 64.0 GiB dirty)
INFO: transferred 7.60 GiB in 165 seconds (47.2 MiB/s)
INFO: Finished Backup of VM 118 (00:02:47)
INFO: Backup job finished successfully
| 失敗時 | 解決後 | |
|---|---|---|
| dirty-bitmap | created new(フル64GB) | OK・差分 7.6GB |
| 所要時間 | 3時間フリーズ→強制終了 | 2分47秒 |
| 転送速度 | 33 KiB/s(停止状態) | 47.2 MiB/s(安定) |
dirty-bitmap が正常に確立されたため、次回の定期バックアップからも差分モードで動作する。
補足:なぜ他の VM は問題なかったか
同ノード内の他7台の VM(100/101/105/110/115/116/117)は今回問題がなかった。理由は以下の通り:
- VM 100, 101:停止状態からのバックアップで短時間(15〜101秒)
- VM 105〜117:dirty-bitmap が確立済みで差分が小さく(0.5〜14.4 GiB)、転送時間が短い
VM 118 だけが dirty-bitmap なし+64GBフルという組み合わせで長時間接続が必要になり、TCP タイムアウトに引っかかった。
まとめ
| 項目 | 内容 |
|---|---|
| 現象 | PBS が Wasabi S3 バックアップ中に約3時間フリーズ |
| エラー | EINTR (os error 4) – ロック取得失敗 |
| 根本原因 | Linux TCP keepalive のデフォルト(2時間)が長すぎ、デッドコネクションを検出できなかった |
| 対策 | TCP keepalive を 600秒に短縮(/etc/sysctl.d/99-tcp-keepalive.conf) |
| PBS側対策 | タイムアウト設定は未実装(PBS 7.x) |
| 復旧 | 手動バックアップで dirty-bitmap を再確立 |
Wasabi のような海外リージョン S3 を使う場合、NAT タイムアウトの影響を受けやすい。長時間転送が発生しうるバックアップ用途では、TCP keepalive の調整は必須の設定と言える。
詰まるところ、、、早期検出はできるようになったものの根本原因の解決には至っていない。原因は、比較的タイムアウトしやすい海外リージョンへS3してることとPBSが自動リトライしてくれない点が相乗していることだろうか汗
検証環境: PBS 7.0.0-3-pve / Wasabi S3 ap-southeast-1 / 2026-08
追記(2026-09-06):真因はTCPブラックホールではなく、PBS自体のバグだった
上記のTCP keepaliveチューニングを入れてからしばらく安定していたが、今回また同じVM 118で3時間フリーズが再発した。
118: 04:24:09 INFO: 72% (4.0 GiB of 5.5 GiB) in 1m 11s, read: 66.7 MiB/s, write: 66.7 MiB/s
118: 07:24:21 INFO: 72% (4.0 GiB of 5.5 GiB) in 3h 1m 23s, read: 775.0 B/s, write: 775.0 B/s
118: 07:24:21 ERROR: backup write data failed: command error: write_data upload error:
pipelined request failed: Unable to acquire lock
"/run/proxmox-backup/locks/wasabi/.chunks/eb6a/..." - Interrupted system call (os error 4)
keepaliveを詰めたはずなのに、また「3時間」でピタリと止まっている。これはおかしいと思い、PBS側に直接入って調べ直した。
journalctlで見えた「プロセス全体の停止」
root@pbs:~# journalctl -u proxmox-backup-proxy --since "2026-08-05 04:00" --until "2026-08-05 08:00"
Aug 05 04:22:56 pbs proxmox-backup-proxy[575]: Upload backup log to datastore 'wasabi', root namesp>
Aug 05 07:24:07 pbs proxmox-backup-proxy[575]: rrd journal successfully committed (34 files in 0.08>
Aug 05 07:24:21 pbs proxmox-backup-proxy[575]: TASK ERROR: backup ended but finished state is not s>
バックアップとは無関係のはずのRRDジャーナルのコミットまで04:22台から07:24台まで完全に止まっていた。これは単に「1本のTCPソケットが死んでいた」レベルの話ではなく、proxmox-backup-proxyプロセス(非同期ランタイム)自体がまるごとストールしていたことを意味する。
tmpfs上のロックなのでディスクI/Oは無関係
root@pbs:~# cat /etc/proxmox-backup/datastore.cfg
datastore: wasabi
backend bucket=pbs-jpn,client=wasabi,type=s3
path /mnt/wasabi
root@pbs:~# mount | grep -i wasabi
(該当なし)
type=s3のネイティブS3バックエンドで、/mnt/wasabiはNFSやs3fsのマウントではない。エラーに出ていたロックファイル/run/proxmox-backup/locks/wasabi/...は/run=tmpfs(RAM)上にあり、dmesgにもディスク/ハードウェア系のログは一切なし。つまりディスクI/Oや物理層の問題ではないことが確定した。
PBS 4.2.2の変更履歴に、まさにこの症状のバグ修正があった
rust-proxmox-backup (4.2.2-1) trixie; urgency=medium
• api: backup: run synchronous chunk-insert operations off the asynchronous
runtime's worker threads. Blocking those threads, most notably during S3
uploads that can wait up to three hours for a chunk lock, could stall the
I/O and timer drivers of the entire runtime and starve other backup
workers.
「chunk lockの取得を最大3時間待つことがあり、その間ランタイム全体のI/O・タイマーがストールする」——今回の現象と文言レベルで一致していた。つまり原因はTCPブラックホールそのものというより、S3アップロード中の同期処理が非同期ランタイムのワーカースレッドをブロックしてしまうPBS側の設計バグであり、TCP keepaliveの調整はあくまで「ハングのきっかけを減らす」対症療法でしかなかった、ということになる。
バージョン確認とアップデート
root@pbs:~# proxmox-backup-manager version
proxmox-backup-server 4.2.0-1 running version: 4.2.0
このバグが直っている4.2.2より前のバージョンだった。ただしapt updateしても上がってこない:
root@pbs:~# cat /etc/apt/sources.list.d/*.sources
Types: deb
URIs: https://enterprise.proxmox.com/debian/pbs
Suites: trixie
Components: pbs-enterprise
Enabled: false
enterpriseリポジトリはEnabled: falseで無効、かつno-subscriptionリポジトリがそもそも設定されていなかった。これでは永遠にPBS本体のパッケージ更新が降ってこない。no-subscriptionリポジトリを追加してアップデート:
apt update
apt full-upgrade
Setting up proxmox-backup-server (4.2.5-1) ...
root@pbs:~# proxmox-backup-manager version
proxmox-backup-server 4.2.5-1 running version: 4.2.5
4.2.5まで上がり、カーネルも7.0.14-15-pveに更新されたので、サービス再起動後にホスト自体もrebootして反映させた。
まとめ(アップデート版)
| 項目 | 当初の見立て | 今回判明した真因 |
|---|---|---|
| 直接原因 | TCP keepaliveのデフォルト値が長すぎてデッドコネクションに気づけない | PBSの非同期ランタイムが、S3アップロード中の同期的チャンクロック待ち(最大3時間)でブロックされる既知バグ |
| 対策 | TCP keepaliveを600秒に短縮 | PBSを4.2.0→4.2.5にアップデート(4.2.2で修正済み) |
| 気づかなかった理由 | - | enterpriseリポジトリが無効・no-subscriptionリポジトリ未設定で、アップデートがそもそも配信されていなかった |
TCP keepaliveのチューニングは「ハングを早期検出して切る」ための保険としては引き続き有効だが、根本原因はPBS自体のバグだった。海外リージョンS3ゆえのタイムアウトの起きやすさは今回も変わらず存在するが、少なくともチャンクロック待ちでプロセス全体が数時間巻き込まれるという最悪パターンは4.2.2以降で解消されているはず。
同じ症状で悩んでいる人は、まずproxmox-backup-manager versionでバージョンを確認し、PBSのリポジトリ設定(特にno-subscriptionが有効になっているか)を見直すことをお勧めする。
※本記事は当サイト管理人の個人的な備忘録です。情報内容には配慮しておりますが、本記事の参照または付随ソースコード利用後にいかなる損害が発生しても、当サイト及び管理人はいっさいの責任を負いません。
