結果: マージ(2026-10-16、 seaweedfs/seaweedfs#11755). )は実際にはGitHubのPR・レビューの原文、SeaweedFSのソース(PRのベースコミット
590a75b9)、TT Labリポジトリのコミット・ドキュメントの記録から取得しました。時刻は韓国時間です。2026-10-17時点でこの変更が含まれているリリースはまだありません(最新リリースは4.48、2026-09-28)。
目次
- 一言まとめ
- 1. 何が問題だったのか:私たちが経験した現象
- 2. 原因:ソースのどの行か
- 3. 何を変更したのか:diffの要点
- 4. ボットとメンテナーはどのように反応したか
- 5. 学んだこと:オープンソースコントリビューションのコツ
- リンク
一言まとめ
| PR | seaweedfs/seaweedfs#11755 mini: note mini.options and Docker filer.toml pitfalls in help |
| 変更内容 | weed mini -h ヘルプの最後にNotesの11行を追加。コードの動作はそのまま |
| 反応 | 3つのレビューボットが9分以内にレビューし、3つの指摘。メンテナーが動作を修正する #11758 を開いて先にマージ |
| 結果 | メンテナーが私たちのブランチにNotes修正コミットを追加して1つのコミットとしてマージ(私たちが著者、メンテナーが共同執筆者) |
| 所要時間 | PR公開 10-15 08:15 → マージ 10-16 10:44、約26時間半 |
1. 何が問題だったのか:私たちが経験した現象
weed mini はSeaweedFSのマスター、ボリュームサーバー、ファラ、S3ゲートウェイを1つのプロセスで起動するモードです。TT Labのクラスターはこれを2つの場所で使っています。コミュニティ・ブログのメディアストレージ、そして本番DBのバックアップストレージです。バックアップストレージはもともとMinIOでしたが、MinIOがバイナリ・イメージの配布を終了したため、2026-09にSeaweedFSへ移行しました。
罠その1:削除したフラグが復活する(2026-09-19)
メディアストレージでボリュームの増設が止まり、原因は再起動を繰り返すうちに引き継がれたマスターのraft状態でした。シングルマスターなので維持すべき状態がないため、 -master.resumeState=false を付与して毎回新しく起動するようにしました。
ところがローカルでテストしてみたところ、この行をコマンドラインから 削除して 再起動しても、もう一度 false の状態で起動しました。miniがコマンドラインフラグをデータディレクトリの mini.options ファイルに書き込み、次回の起動時に再び読み込むためでした。マニフェストには「元に戻すときにこの行を削除するな」というコメントを残しました。 weed mini -h のどこにもこのファイルについての記載はありませんでした。
罠その2:復元したコピーのバケットが空っぽに見える(2026-09-24)
バックアップは復元できてこそバックアップです。バックアップストレージのデータディレクトリをNASにコピーした複製に対して同じイメージでminiを起動し、復元テストを行いました。複製をコンテナの別のパスにアタッチし、 -dir をそのパスに指定したところ、 2つのバケットしか見えずオブジェクトが0個でした。エラーは発生しませんでした。複製を /data にアタッチしたときは、MinIOから移行してきた10,004個のオブジェクトがキー、サイズ、SHA-256に至るまでコピー時と同じように読み込めました。
どちらの件も「設定を間違えた」のではなく、「ツールが教えてくれないルールが存在した」というケースでした。このような罠には、次に触る人も同じように引っかかります。
2. 原因:ソースのどの行か
以下の行番号はすべてPRのベースコミット 590a75b9 を基準としています。TT Labが使用していたバージョン4.29でも同じ関数の内容が同じでした(タグ4.29の mini.go を開いて比較)。
mini.options:「コマンドラインで渡したか」ではなく「デフォルト値と同じか」
- 保存:
saveMiniConfigurationはcmdMini.Flag.Visitで コマンドラインで指定されたすべてのフラグ(dirを除いて)<dir>/mini.optionsに書き込みます(1166–1179行目)。 - 適用:
applyConfigFileOptionsはファイル内の値ごとに、そのフラグの 現在の値がデフォルト値と同じであれば(flag.Value.String() == flag.DefValue、1138行目)、保存された値で上書きします。 - 例外:起動直後に8つのポートフラグのみ「コマンドラインで指定されたか」を 別途記録しておき、指定されたものはスキップします(1130行目)。
そのため、 -master.resumeState=false を一度でも指定するとファイルに残り、その行を削除して次に起動したときは値がデフォルトの true であるため、ファイルの false が再度適用されます。コマンドラインに =true を 明示しても デフォルト値と同じなので結果は同じになります — ポートフラグを除いて。私たちがマニフェストに残した「行を削除せず =true に変更すること」というコメントも、ソースの仕様通りにいえば通用しないアドバイスです(ソースを読み解いた結果であり、実測はしていません)。しかもminiはデフォルトのログ出力を抑制するため、「保存されたオプションを適用した」というメッセージ(V(2))はデフォルト設定では表示されません。
filer.toml:イメージがメタデータの場所を固定してしまう
- 公式イメージはリポジトリの
docker/filer.tomlを/etc/seaweedfs/filer.tomlにコピーします(Dockerfile.go_build82行目)。内容は3行、[leveldb2]ストレージを有効にし、dir = "/data/filerldb2"です。 - filerは
filer_server.go254–264行目 でfiler.tomlを見つけると、デフォルトのストレージの場所を使用せず警告を1行(skipping default store dir)残すだけです。miniが-dirから引き出したデフォルトの場所(1348行目)はこの時破棄されます。
その結果、ボリュームファイルは -dir に、filerのメタデータは /data/filerldb2 に送られます。 -dir を別の場所に移動し、その場所だけを残しておくと、メタデータはコンテナと一緒に消滅します。私たちの復元テストで2つのバケットが見えたのは、起動フラグ -bucket が空のメタデータの上にバケットを新しく作成したためだと推測されます(ソースのバケット作成コードとマニフェストのフラグからの解釈)。
3. 何を変更したのか:diffの要点
コードには手を加えず、 cmdMini の Long のヘルプの最後にNotesを追加しました。最初に送信したバージョンの要点です。
+Notes:
+- Flags are saved to <dir>/mini.options and applied again on the next
+ start to every flag that is not given on the command line. Removing a
+ flag, or passing it with its default value, does not restore the
+ default on the next start. Edit or delete mini.options instead.
+- The official Docker image ships /etc/seaweedfs/filer.toml, which keeps
+ the filer metadata in /data/filerldb2 regardless of -dir. If you set
+ -dir to another path, keep /data on a persistent volume as well.
+ ...
ヘルプのみを修正した理由は2つあります。動作を変更するのはメンテナーが判断すべき設計上の問題であり、外部コントリビューターの最初のPRは小さく検証しやすいものでなければ受け入れられやすいためです。SeaweedFSのPRテンプレートには「AIで作成したPRはすべての行をレビューし最小限に抑えた」というチェック項目があり、両方を満たした上で、本館の最後にAIの助けを借りて作成し自身でレビューしたという一文を記載しました。コミットにはDCO署名(Signed-off-by)とSSH署名を付与しました。テストは gofmt と上記の関数をソースベースで比較したことがすべてであると、本文にそのまま記載しました。
4. ボットとメンテナーはどのように反応したか
9分以内にやってきた3つのボット
PRを開いてすぐ(10-15 08:16–08:24)にDevin、CodeRabbit、Greptileの3つのレビューボットが参加しました。公開された指摘は3つで、すべて最初のNoteに関するものでした。
- CodeRabbit:私たちの文章は「コマンドラインで指定しなかったフラグ」に適用されるとしていたが、実際の基準は「現在の値がデフォルト値と同じか」である。さらに、ポートフラグはデフォルト値を明示すると保存値をスキップする — 例外についても記載せよ。
- Greptile:同様にポートの例外について。ポートフラグはデフォルト値を明示するだけで元に戻せるため、「ファイルを削除せよ」という案内は範囲が広すぎる。
第2節のソースをもう一度見ると、ボットの指摘が正しかったです。私たちの文章は一般的なフラグには当てはまりますが、8つのポートには当てはまりませんでした。例外リスト(portFlagNames)を読んだにもかかわらず、文章に反映させ忘れていたのです。
私たちが返答する前にメンテナーが動いた
率直に言って、これらの指摘に対して私たちは1日の間、返答も修正もしませんでした。その間(10-15 23:15)にメンテナーが私たちのPRに言及し、 #11758 を開きました。問題の定義は私たちのPRが記述した2つの罠そのままであり、解決策はヘルプではなく動作そのものの修正でした。
mini.optionsにコマンドラインフラグを 一切保存しないようにした。 miniが自分で計算した値(現在はボリュームサイズの上限)のみを固定し、再起動しても同じようにする。古いファイルは一度適用された後に計算値のみが残るように再書き込みされる。- ファイルの値は、コマンドラインや
WEED_*環境変数で指定されたフラグを上書きせずスキップする。「デフォルト値と同じか」の比較を廃止し、「指定されたか」で判断する。 - 保存されたオプションが適用された場合、起動時に1行で通知する(パスワードやトークンの値はマスクする)。
filer.tomlが有効にしたローカルストレージの場所が-dirの外にある場合、起動時に警告を発する(warnIfFilerStoreOutsideDir).
#11758が10-16 10:36にマージされ、その3分後にメンテナーは私たちのブランチにNotesを新しい動作に合わせて修正したコミットを追加しました。1つ目のNoteには「コマンドラインフラグは保存されず常に保存された値を上書きする、保存されるのは計算値のみ」、2つ目のNoteには「-dir の外にある場合、起動時に警告を発する」が追加されました。コメントでは、この変更のおかげでデフォルト値の比較やポートの例外を指摘していたボットの指摘がもはや該当しなくなったと整理されました。
ボットの2度目の指摘と順序の説明
新しいコミットに対してGreptileが再び2つの指摘を行いました。「ソースにはコマンドラインフラグを保存するコードがある」、「-dir の外側を検査するコードがない」。ボットは#11758以前のコードを参照していました。メンテナーが2つの行コメントのそれぞれに「このPRは#11758の後の順序であり、そのPRが保存を廃止し検査を追加する」と返答し、ボットは1分も経たずに2つの指摘を取り下げました。そして10:44にマージされました。
マージは2つのコミットを1つにまとめるsquashであり、コミットの著者は私たちのアカウント、メンテナーは Co-authored-by として記録されました。最終的なヘルプ13行のうち、私たちが書いた文章がそのまま残ったのは2つ目のNoteの大半であり、1つ目のNoteはメンテナーが新しい動作に合わせて書き直しました。
5. 学んだこと:オープンソースコントリビューションのコツ
- ドキュメントPRは、最も丁寧なバグ報告になり得る。 「この動作はおかしい」というIssueは議論になりがちですが、「この動作をヘルプに記述しよう」というPRは、メンテナーにその動作と正面から向き合わせることになります。今回はメンテナーが記述するのではなく修正する道を選び、その結果はさらに良いものになりました。
- 動作を説明するときは、例外リストまで読み込むこと。 ボットが指摘したのは、まさに私たちが読みながらも文章に含めなかった
portFlagNamesでした。「大体合っている」ヘルプは、例外にハマった人にとっては間違ったヘルプです。 - ボットの指摘にはすぐに応答すること。 正しければ修正して再アップし、間違っていればソースの行番号で答えます。今回はメンテナーが先に解決してくれましたが、1日中指摘が開いたままになっていたのはこちらの隙でした。現在は、アップしたPRのボットのコメントを毎日確認して対応することをルールにしています。
- ボットはPR間の順序を知りません。 依存するPRがある場合は、本文やコメントに「何の後に入るべきか」と書いておけば、人間もボットも同じ認識を持つことができます。メンテナーがやったのはまさにそれでした。
- 症状と実測値を数値で記載します。 「バケットが空っぽに見える」ではなく「バケット2個、オブジェクト0個、エラーなし、
/dataにつなげると10,004個がSHA-256まで一致する」。こうした文章により、メンテナーは再現手順なしでも問題の大きさを推測できます。 - プロジェクトのAIルールを最初に読みます。 SeaweedFSはAIで作ったPRを受け入れますが、チェック項目としてレビューと最小限の範囲を確認します。プロジェクトごとにルールは異なり、AIが書いたPRを一切受け入れない場所もあります。告知の1文と署名は、どのプロジェクトでも基本としておきます。
TTの一言。 ヘルプに「ここに穴があります」と貼り紙をしたら、管理人がやってきて穴を塞いでしまいました!それでも看板は残しておいてくれたそうです。ボットから「看板の文字が少し間違っています」と言われたら、翌日ではなくその日のうちに書き直すことにしました。
リンク
すべての資料は2026年10月17日に閲覧しました。
- PR: seaweedfs/seaweedfs#11755 (マージコミット
ee2d98f6) - メンテナーの挙動変更: seaweedfs/seaweedfs#11758
- メンテナーのNotes修正コミット:
3c675a57 - ソース(ベースコミット):
weed/command/mini.go,weed/server/filer_server.go,docker/filer.toml - SeaweedFSリリース一覧: https://github.com/seaweedfs/seaweedfs/releases