結果: マージ (2026-10-26 19:58, kubevirt/containerized-data-importer#4319), Issue #3005 クローズ。 2026年10月29日現在、この変更を含むCDIのリリースはまだありません(最新は2026年09-06のv1.66.1)。実際にはGitHubのPR・レビュー・行コメント・本文の修正履歴・タイムライン・テスト の記録、CDIのソース(PRのベースコミット
9cd4fbdb)、local-path-provisionerのソース(タグv0.0.32)、貢献元帳の実測生データ(StorageProfileリスト、48時間ログ集計)と ドラフトから取得しました。時刻は韓国時間です。
目次
- 1行要約
- 1. 何が問題だったのか: 空のStorageProfile
- 2. 原因: ソースのどの行か
- 3. 何を変更したのか: 3回にわたるdiff
- 4. 反応: まとめる、削る、そして再オープンされたIssue
- 5. 学んだこと: オープンソース貢献のコツ
- リンク
1行要約
| PR | kubevirt/containerized-data-importer#4319 Add storage capabilities for rancher.io/local-path |
| 変更点 | storagecapabilities.go 1ファイル。 rancher.io/local-path 項目と、ノードローカルパスプロビジョナーが共用するヘルパー1つ。12行追加、4行削除 |
| 反応 | レビュアー2人からの行コメント各1件(まとめよう、テスト2つは削ろう)、メンテナーが古いIssueを再オープンして紐づけ |
| 結果 | PR公開 10-17 23:38 → /approve 10-19 16:59 → /lgtm 10-26 15:15 → マージ 19:58、約8日20時間20分。コミット3つ、テスト21個を通過 |
1. 何が問題だったのか: 空のStorageProfile
CDI(Containerized Data Importer)はKubeVirt VMのディスクをPVCとして作成するコンポーネントです。DataVolumeを spec.storage として使うと
アクセスモードやボリュームモードを記述しなくても済みますが、そのデフォルト値はStorageClassごとに作成されたStorageProfileから取得します。StorageProfileのデフォルト値は
CDIがプロビジョナー名を見て埋めます。
2026年10月17日にTT Labクラスター(CDI v1.66.0)を読み取りコマンドでスキャンしたところ、StorageProfile 4つのうち2つが空でした(元帳 measure/kv).
| StorageProfile | プロビジョナー | claimPropertySets | Recognized |
|---|---|---|---|
| local-path | rancher.io/local-path |
なし | UnrecognizedProvisioner |
| local-path-retain | rancher.io/local-path |
なし | UnrecognizedProvisioner |
| NFSクラス2つ | nfs.csi.k8s.io |
RWX, Filesystem | RecognizedProvisioner |
2つのlocal-pathクラスは57日前に作成され、プロビジョナーイメージはv0.0.32でした。cdi-deploymentの48時間ログには、各クラスごとに
Set metric:local-path complete:false … degraded:true と同じ行が10回ずつありました。PRの本文に記載した通り、この指標は CDIStorageProfilesIncomplete
アラートが監視している値です。
この状態で spec.storage でアクセスモードを空にしたDataVolumeを作成すると ErrClaimNotValid: no accessMode specified in StorageProfile local-path
で停止するとPRの本文に記載しました。これはドラフトに「ユーザーが実行するコマンドと期待される結果」として記載しておいたものであり、元帳には実際に実行した記録はありません(未実測)。
元帳にはこのエラーによってTT LabのVMが停止したという記録はありません。運用上のインシデントではなく、調査中に見つかった問題です。
2. 原因: ソースのどの行か
CDIの行番号はPRのベースコミット 9cd4fbdb を基準としています。
- プロビジョナー名とデフォルト値のテーブルは
storagecapabilities.go39行目から のCapabilitiesByProvisionerKeyです。hostpath-provisionerとk8s.io/minikube-hostpathは{{rwo, file}}として存在しますが、rancher.io/local-pathは存在しませんでした。 - テーブルにないと
storageprofile-controller.go206–220行目 のreconcileConditionsがRecognizedをFalseに、理由をUnrecognizedProvisioner(メッセージ「Provisioner is not recognized」)に設定します。 1節のログ行は同じファイルの 462行目 で出力されます。
追加する値が {{rwo, file}} である根拠はプロビジョナー側のソースです(local-path-provisioner v0.0.32 provisioner.go).
- 345行目: ノードパスボリュームにRWOやRWOP以外のアクセスモードを
要求すると
NodePath only supports ReadWriteOnce and ReadWriteOncePod (1.22+) access modesとして拒否します。 - 405行目·458行目:
作成されるPVは常に
VolumeMode: &fs(Filesystem)であるため、Blockは出力されません。 - 共有ファイルシステムのパスを別途設定すればRWXも可能ですが、デフォルトではなくStorageClassを見ただけではわかりません。そのようなユーザーはこれまで通りStorageProfileの
spec.claimPropertySetsを直接記述すればよいと本文に書きました。スナップショットやCSIクローン機能がないため、クローン戦略は現在選択されているデフォルト値(copy)をそのまま維持します。
PRの本文にはもう1つ記載しました。CDI自身のkind開発環境(cluster-up/cluster/kind/manifests/local-storage-class.yaml)もこのプロビジョナーを使用します。
この変更後にはその環境のStorageProfileも埋まるため、もしそれが空であることを期待するe2eテストがあれば教えてほしいとお願いしました。
3. 何を変更したのか: 3回にわたるdiff
最初のコミット(10-17)では、テーブルに1行を追加し、StorageProfileコントローラーのテストに新しいプロビジョナー用のテスト1つとRecognizedテーブルの項目1つを追加しました。
類似の先例である #4286(Mayastor、2026-09-27マージ)と同じ形式です。
PRの本文のテスト結果は以下の通りでした(Go 1.27.2、 GOFLAGS=-mod=vendor, main 9cd4fbd).
| テスト | 結果 |
|---|---|
| 新しいテスト、テーブル項目なし | 7個中2個失敗 |
| 新しいテスト、テーブル項目あり | 成功 |
go test ./pkg/controller/ 修正版 / 修正前 |
385成功・3失敗 / 383成功・3失敗 |
失敗した3つは双方とも同じVDDK関連のテスト(Update PVC from POD)であるため、この変更とは無関係であると本文に記載しました。
2番目のコミット(10-18)では、レビュアーの提案を反映しました。ノード1つのディレクトリでボリュームを作成するプロビジョナーは結局すべて {rwo, file} なのでまとめようという
意見でした。そのため createLocalPathCapabilities() ヘルパーを作成し、hostpath-provisioner(CSI・レガシー)、クローン用の k8s.io/minikube-hostpath,
rancher.io/local-path で使用するようにしました。hostpath-provisionerのoverlayバリアントはRWXであるためそのままにしました。ディレクトリではなくドライブを丸ごと提供するDirectPVは除外し、必要であれば追加すると答えました。このとき go test ./pkg/controller/ は388個すべて成功しました(返信に記載した値)。
3番目のコミット(10-26)は、別のレビュアーの意見に従って最初のコミットにあった単体テスト2つを削除しました。新しいプロビジョナーはすでにテストが存在するヘルパーを再利用するだけであり、新しいロジックが存在しないという指摘でした。このコミットは gofmt·go vet のみを実行し、テストは再実行しませんでした(元帳の記録)。マージ前のCIのテストは成功しました。
var CapabilitiesByProvisionerKey = map[string][]StorageCapabilities{
// hostpath-provisioner
- ProvisionerHPPCSI: {{rwo, file}},
+ ProvisionerHPPCSI: createLocalPathCapabilities(),
ProvisionerHPPOverlayCSI: {{rwx, file}},
- ProvisionerHPPLegacy: {{rwo, file}},
- "k8s.io/minikube-hostpath": {{rwo, file}},
+ ProvisionerHPPLegacy: createLocalPathCapabilities(),
+ // other node-local path provisioners
+ "k8s.io/minikube-hostpath": createLocalPathCapabilities(),
+ "rancher.io/local-path": createLocalPathCapabilities(), // local-path-provisioner, default in k3s and kind
...
+// createLocalPathCapabilities is shared by provisioners that back each volume
+// with a directory on a single node, so they only offer RWO filesystem volumes.
+func createLocalPathCapabilities() []StorageCapabilities {
+ return []StorageCapabilities{{rwo, file}}
+}
最終的なdiffは1ファイル、12行追加と4行削除です。最初よりもむしろ小さくなりました。
AIの使用は3つのコミットすべてで Assisted-by: Claude のフッターとDCO署名により、本文の末尾には「プロビジョナーのソースを読み、変更とテストのドラフトを作成するのにClaudeの
助けを借りた。すべての行を検証し、StorageProfileの出力は自分のクラスターのものである」という段落で明らかにしました。KubeVirt組織の
AI貢献ポリシーが推奨する形です。SSH署名は最初のコミットにのみ付いており、
レビューを反映した2番目と3番目のコミットはGitHub上で署名されていないコミットに見えます。
4. 反応: まとめる、削る、そして再オープンされたIssue
| 時刻 | 日 |
|---|---|
| 10-17 23:38 | PR公開。prowが size/S ラベル、「信頼されていない作成者はテストを直接実行できない」という案内、レビュアー2人を指定 |
| 10-18 20:25 | レビュアーAの行コメント: こうしたローカルパスプロビジョナーは結局すべてrwo、fileなのでまとめることができそうだ |
| 10-18 21:03 | ヘルパーにまとめた2番目のコミット、21:05返信。ラベルが size/M に |
| 10-19 16:57 | メンテナーが2024年10月に自動でクローズされたIssue #3005 を /reopen |
| 10-19 16:58, 17:00 | 同じメンテナーがPR本文の「Which issue(s)」欄を修正して Fixes #3005 を追加(本文の修正履歴) |
| 10-19 16:59 | レビュアーAが /approve と /test all。17:13 coverallsがカバレッジ50.288%(+0.08%) |
| 10-25 11:33 | 6日間 /lgtm がなかったため、指定された2人のレビュアーに「approveとテストの通過があるのでlgtmを残すのみとなった」と一度お願い |
| 10-25 17:53 | レビュアーBの行コメント: 新しいロジックがないのに単体テスト2つがなぜ必要なのかわからない |
| 10-26 00:04 | テスト2つを削除した3番目のコミット、00:07返信。ラベルが再び size/S |
| 10-26 15:15 | レビュアーBが /lgtm |
| 10-26 19:58 | tideがマージ、Issue #3005 が同時にクローズ |
今回のPRで最も学ぶべき点が多かった場面は10月19日の2行の出来事でした。私たちはドラフトを書く際、同じ問題を扱ったIssueやPRはないと記載し(元帳の
ドラフトリストにおける「検索 0」)、PR本文のIssue欄にも NONE を入れました。しかし #3005
「StorageProfile needs to be patched for the rancher local-path provisioner」 がすでに存在していました。2023年11月24日にオープンされ、別のメンテナーが「認識されていないプロビジョナーのデフォルトの動作なので、DVにアクセスモードを記述するかプロファイルを修正するか、あるいはデフォルト値を追加するPRを送ってもよい」という趣旨で回答していました(2024年1月)。その後誰もPRを送信しなかったため、2024年10月3日にボットが自動的にクローズしていました。私たちの検索はオープンなものしか見ていなかったようです。
メンテナーはこれを個別に指摘しませんでした。その代わりにIssueを再度オープンし、私たちのPR本文にリンクを追加して、マージとともに2年11ヶ月越しのIssueがクローズされるようにしました。
2つの行コメントにはどちらも一度で受け入れ、短く返信しました。1つ目は「レビューありがとう、2番目のコミットでヘルパーにまとめた、DirectPVはディレクトリではなくドライブを丸ごと提供するので除外した」、2つ目は「その通り、既存のhostpathテストがすでにカバーしているヘルパーを再利用するだけなので両方削除した」でした。2人のレビュアーの意見により、最初のコミットで追加したもの(テスト)と変更した形(ヘルパー)の両方が削減され、結果としてPRが小さくなりました。
5. 学んだこと: オープンソース貢献のコツ
- 「重複の検索にはクローズされたIssueも含める。」自動的にクローズされた(rotten)Issueは「解決済み」ではなく「誰も修正していない」ことが多いです。そのようなIssueを探し出して
Fixes #번호でつなぎ、issueに残されたメンテナの返答(「PRを送ってもよい」)を本文に引用していれば、レビューがより早かったものと推測されます。 - 「値の根拠は、相手プロジェクトのソースから探します。」
{rwo, file}を選んだ理由は local-path-provisioner のエラーメッセージと PV を作成する行に見えたため、レビューで値そのものを尋ねる人はいませんでした。質問はすべてコードの形(まとめ方、テストケース)に関するものでした。 - 「レビューで PR を小さくすればそのまま受け入れられます。」テストをさらに追加することが常に良いとは限りません。新しいロジックがない状態でテストを増やすと、保守すべきコードが増えるだけであるというのがレビューアーの視点でした。最初に作成した人が定めた範囲よりも、メンテナが望む範囲のほうが狭い場合があります。
- 「approve の後に lgtm が長期間ない場合は一度、事実だけを記載して依頼します。」 「approve があり、テストが合格したので lgtm のみ残っている」という一文であり、その日レビューが再び動き出しました。
Titi の一言。 私たちの近所の倉庫管理人は「土の道倉庫」という名前を初めて聞いたそうです。それでそこに預けた箱ごとに「どう保管すべきか不明」のラベルを貼りました。土の道倉庫は1区画に1人のみ、箱の形のものだけを受け付けるということをその倉庫の規約書から見つけてお伝えしました。管理人の男性は似たような倉庫4つを1列にまとめて書こうとおっしゃり、別の男性は確認のハンコは2つも必要ないとおっしゃいました。そして、誰かが3年前に全く同じお願いを書いたメモを引き出しから取り出してきて、私たちのメモと一緒に「解決済み」の箱に入れてくれました。
リンク
すべての資料は 2026-10-29 に閲覧しました。
- PR: kubevirt/containerized-data-importer#4319 (マージコミット
fd4146ac) - クローズされた issue: #3005 (2023-11-24 オープン、2024-10-03 自動クローズ、2026-10-19 再オープン)
- 修正したソース(ベースコミット):
storagecapabilities.go,storageprofile-controller.go - local-path-provisioner ソース(v0.0.32):
provisioner.go345行目, 458行目 - 前例: containerized-data-importer#4286 Mayastor デフォルト値
- 同日、同じ調査から生み出された PR: 第6部、kubevirt/kubevirt#19499