1. 症状 — UIは「rebuilding」と言っているのに、レプリカは0%のまま動かない
K3sクラスタでLonghornを使ってPersistentVolumeを運用している現場で、こんな経験はないだろうか。
定期メンテナンスでノードを1台再起動した。しばらくしてLonghornのUIを見ると、対象ボリュームは
degradedのまま。詳細を開くとrebuildingと表示され、進んでいるように見える。だが数時間経っても
レプリカ再構築の進捗は0%から動かない。
これは架空の話ではない。Longhornの上流プロジェクトであるHarvesterで、実際にこの症状が報告されている。
あるノード再起動の直後、38個のボリュームが「attached/degraded」のまま37時間も停滞し、
rebuildStatusはisRebuilding: trueを返し続けたという(Harvester #11639)。
UIは「動いている」と主張するが、実態は無限ループで詰んでいる。ここが本記事で扱う静かな障害の正体だ。

この手のトラブルが厄介なのは、アラートが上がりにくいことだ。ボリュームはまだattachedであり
Podは動き続けている。冗長性が失われているだけなので、次にもう1ノード落ちるまで誰も気づかない。
K3s本番運用でLonghornを採用しているなら、レプリカ再構築が本当に進んでいるかを定期的に確認する
仕組みが必要になる。この運用監視の負荷を自前で背負い込むか、Kuboのように
モニタリングが標準搭載されたマネージドK3s基盤に任せるかは、検討する価値のある分岐点だ。
2. 原因 — instance-managerがStorage Networkより1秒早く起動していた
Harvesterのバグ報告を詳しく見ると、原因は驚くほど狭い時間差にある。ノード再起動後、
Longhornのinstance-managerポッドが起動したわずか1秒後に、ストレージ用ネットワークを
提供するrke2-multusが準備完了した。この1秒のずれが致命傷になった。
Longhornは本番環境で、レプリケーション通信をKubernetesの通常CNIネットワークから分離するために
Storage Networkという機能を提供している。共有ネットワーク上でレプリケーション通信を流すと、
他のPod通信と帯域を奪い合い、レイテンシが予測不能になるためだ(Longhorn公式ドキュメント: Storage Network)。
実現方法はMultusによるセカンドネットワークの割り当てで、有効化するとLonghornの
instance-manager・backing-image-manager・backing-image-data-sourceの各Podに
k8s.v1.cni.cncf.io/networksアノテーションが付与され、対象Podがすべて再作成される。
問題の1秒差では、instance-managerがストレージネットワークへの接続を要求したにもかかわらず、
Multus側のk8s.v1.cni.cncf.io/networks-statusアノテーションをまだ受け取れなかった。Longhornは
アノテーションが見つからない場合にPodネットワークIPへフォールバックする実装になっており、
結果としてソースエンジンはストレージネットワークに、ターゲットレプリカはPodネットワークIPに
という経路の不一致が生まれた。これがレプリカ再構築が0%から進まなくなった直接の原因である。

3. なぜこの1秒がクリティカルなのか — Multusのバージョンによる仕様変化
さらに厄介なのは、この問題が単発のタイミング競合にとどまらないことだ。LonghornはStorage Networkの
状態確認を、長らくk8s.v1.cni.cncf.io/networks-statusアノテーションに依存してきた。ところが
Multusはv3.6でこのアノテーションを非推奨化し、v4.0.0で完全に削除した(longhorn/longhorn #6953)。
Multusをアップグレードした構成では、起動タイミングの問題以前に、Longhorn自体がストレージ
ネットワークの状態を認識できなくなる。
つまり「レプリカ再構築が進まない」という同じ症状が、①起動順序の一時的な競合と、 ②Multusのバージョンに起因する恒常的な非互換、という2つの異なる原因から発生しうる。 K3sクラスタでMultusを使ってStorage Networkを構成しているなら、Multusのバージョンと Longhornのバージョンの組み合わせを事前に確認しておく必要がある。
こうしたコンポーネント間のバージョン互換性を自前で追いかけ続けるのは地味に工数がかかる。 Kubo CloudならCNIやストレージ関連コンポーネントのバージョン 整合性を含めて検証済みの構成で提供されるため、この種の「アップグレードしたら壊れた」を 未然に減らせる。
4. 見落としがちな設計 — レプリカ数とノードdrainの「最後の健全レプリカ」保護
起動順序やネットワークの問題を回避できたとしても、レプリカ設計そのものに落とし穴が残っている。
レプリカ数は2か3か
Longhornのレプリカ数はデフォルトで3だが、本番クラスタのチューニングガイドでは デフォルトを2に引き下げることも提案されている。ディスク消費量と書き込みレイテンシを 抑えられるためだ(CloudCasa: Longhorn on Production Clusters)。 一方で別のベストプラクティスガイドは、レプリカ数2は1ノード障害まで、レプリカ数3は 2ノード障害まで耐えられるとしており、本番環境ではレプリカ数3を推奨している (OneUptime: How to Set Longhorn Volume Replica Count)。 どちらが正解かはワークロードの重要度次第だが、両者の間にトレードオフがあることを知らずに デフォルト値のまま運用している現場は少なくない。

ノードdrainが完了しない
もう一つの詰みポイントはノードメンテナンス時だ。ノードをcordonすると、Longhornは
そのノードへの新規スケジューリングを自動的に無効化する。しかしcordon時にレプリカを
自動で退避させる機能は実装されていない(longhorn/longhorn Discussion #5736)。
さらにdrainを実行した際、対象ノードにあるレプリカがそのボリュームにとって最後の健全な
レプリカだった場合、Longhornはデータ保護のためdrainの完了そのものをブロックする
(Longhorn Node Maintenance Guide)。
この状態になると、UIから手動でレプリカの退避を指示するか、Node Drain Policyを変更しない限り、
kubectl drainはいつまでも終わらない。なおkubectl drainには--ignore-daemonsetsの指定が
必須で、これを忘れるとLonghorn manager・CSI plugin・engine imageのDaemonSetによって
drainがそもそも開始できない。
メンテナンス手順を運用ドキュメントに落とし込み、チーム全員が同じ手順を踏めるようにするのは 地味だが重要な仕事だ。Kubo CloudのCaptain UIであれば、 ボリュームごとのレプリカ配置状況が可視化されているため、「どのノードが最後の健全レプリカを 持っているか」を事前に確認しやすい。
5. K3s本番運用でLonghornを安全に使うためのチェックリスト
ここまでの障害パターンを踏まえ、K3s + Longhornを本番運用する前に確認すべき点を整理する。
- レプリカ再構築の進捗を監視する:
isRebuildingだけでなく実際の進捗率をアラート条件に含める - Storage Network導入前にMultusのバージョンを確認する: v4.0.0以上では
networks-statusアノテーションが削除されている前提で検証する(Longhorn Rebuilding docs) - レプリカ数はワークロードの重要度で決める: デフォルト値のまま放置しない
- drain前に「最後の健全レプリカ」を確認する: 事前にボリューム状態を棚卸しし、手動退避が必要なボリュームを洗い出す
- スナップショットの保持ポリシーを設定する: 無制限に蓄積するとディスク枯渇からカスケード障害に発展しうる(Perun Engineering: Longhorn in production, five failure patterns)

これらはどれも単体では難しくない設定だが、ノードの起動順序・CNIのバージョン・レプリカ設計・ メンテナンス手順という複数のレイヤーを横断して初めて事故が起きる。1つのレイヤーだけを 見ていては再現も予防もできない、というのがこの障害の本質だ。
こうしたネットワーク分離やレプリカ設計をクラスタごとに手作業で見直し続けるのは、 本来インフラチームがやりたい仕事だろうか。Kubo Cloudは K3sベースでRancher管理基盤とPrometheus/Grafanaによるモニタリングを標準搭載しており、 こうしたストレージ層の異常も可視化された管理画面から早期に検知しやすい構成になっている。
まとめ
Longhornのレプリカ再構築が0%のまま止まる問題は、単一の設定ミスではなく、 「ノードの起動順序」「Multusのバージョン仕様変化」「レプリカ数設計」「drain時の保護機構」という 複数の要因が重なって発生する。EKS/AKSのマネージドストレージであればこうした コンポーネント間の起動順序やバージョン互換性はクラウドプロバイダー側の責任範囲になるが、 セルフホストのK3s + Longhorn構成ではすべて自前で追いかける必要がある。
K3sの軽量さはそのままに、こうした運用の複雑さを引き受けたいと考えるなら、 Kuboは月額48,000円からフルスペックのKubernetes環境を マネージドで提供している。ストレージ設計を含めた運用の負荷を減らしたい場合は、 お問い合わせから相談してみてほしい。
関連記事: