Skip to content

feat(storage): PV の置き場を OpenEBS LVM LocalPV(thin)にする — Z440 で入れ直すときの切り方 - #642

Merged
5ym merged 4 commits into
mainfrom
storage-openebs-lvm
Oct 30, 2026
Merged

5ym merged 4 commits into
mainfrom
storage-openebs-lvm

Conversation

@5ym

@5ym 5ym commented Oct 30, 2026

Copy link
Copy Markdown
Collaborator

今日 Z440 へ移すときに Talos を入れ直す(SSD は上書き)ので、そのときしか変えられないディスクの切り方を変え、PV の置き場を local-path から OpenEBS LVM LocalPV(thin)にする(docs/decisions.md「Z440 で、ストレージを OpenEBS LVM LocalPV に…」)。machine config を変えるだけで、効くのは入れ直したとき。 いまの DL360 には当てない。VolSync と k8up の置き換えはまだ(ROADMAP)。

ディスクと StorageClass

大きさ(447GB) 作るもの
EPHEMERAL 64GiB(今のまま) Talos
r-lvm 残り全部(380GiB ほど) RawVolumeConfig → LVMVolumeGroupConfig で VG data
data_thinpool VG の 90%。残りは溢れかけたときに足す分 bootstrap/storage.yaml の DaemonSet lvm-thinpool(Talos の LVMLogicalVolumeConfig は linear と raid だけ)
PVC requests が上限の thin の LV(xfs) OpenEBS LVM LocalPV 1.10.1
  • StorageClass は名前を local-path のまま(既定)にしたので、各リポジトリの PVC は書き換えない
  • OpenEBS は thin プールが無いと最初の PVC と同じ大きさで作って広げない(Talos に dmeventd が無い)。lvm-thinpool がプールを作ってからノードにラベルを付け、OpenEBS のノードの Pod はそのラベルで動く(LVM のメタデータを書く者を 1 つにする)
  • storageCapacity: false(thin なので PVC の合計がプールを超えてよい。denpa は 1Ti + 300Gi)
  • dm_thin_pool を machine.kernel.modules に。snapshot-controller と VolumeSnapshot の CRD は chart の同梱ではなく external-snapshotter のタグの URL で(版は talos.sops.yaml の先頭、Renovate が上げる)
  • local-path-provisioner(bootstrap/local-path.yaml)は消した

talos-boot が見ること(足したもの)

VG と thin プール(VG の 9 割)、OpenEBS・snapshot-controller が上がる、infisical の Postgres の PVC が bind、テストの PVC が xfs で bind して書ける、VolumeSnapshot が readyToUse、スナップショットから作った PVC に中身が戻る、talosctl reboot のあとも PV の中身と Postgres が戻る(thin プールの有効化は Talos がする)。

戻す側(recovery/pv.sh)

pv.sh は PVC を Pod から触るだけで、local-path のディレクトリには依存していなかった。変わるのは PVC の requests が本当の上限になること(いまの adguardhome-work は 5Gi に 68 GB 入っている)ので:

  • fit: folder で戻すものの restic stats を PVC の requests と比べ、9 割を超えたら止める。plan-all が表示し、restore-all は上書きする前に見る
  • backup-all: 入れ直す前の最後のバックアップ(Schedule のある namespace ごとに Backup を作って待つ)

ほか

  • adguardhome: クエリログが 2026-10 末から 1 日 10 GB 近い(querylog.json 50 GB + 17 GB)。保持を 7d → 1d、adguardhome-work を 5Gi → 30Gi に。DL360 の上では local-path が広げられず、Argo CD がこの PVC の同期でエラーを出す(入れ直せば消える)。移す前に UI でクエリログを消す(手順書)
  • 新しい PVC の直下は root の 0755(local-path は 0777)。root 以外で fsGroup の無かった worklog は fj.doany.io の doa/worklog-cloud#179 で fsGroup: 1000 を足す
  • docs/z440-migration.md を「入れ直して restic から戻す」流れに(最後のバックアップ → 止める → 載せ替え → ISO → 当てる → bootstrap → Argo CD → Infisical → restore-all)

手元で render.sh と talosctl validate --mode metal、sops -d、renovate-config-validator を通した。

🤖 Generated with Claude Code

https://claude.ai/code/session_01T9PbUfqG4pPxus99UeLiJs

- talos.sops.yaml: UserVolumeConfig local-path をやめ、RawVolumeConfig lvm(残り全部)と
  LVMVolumeGroupConfig data にする。dm_thin_pool を読む。external-snapshotter の版を先頭に
- lvm-localpv-values.yaml / storage.yaml: OpenEBS LVM LocalPV、StorageClass local-path(既定。名前はそのまま)、
  VolumeSnapshotClass、thin プールを VG の 90% で作る DaemonSet lvm-thinpool(Talos は thin を作れない)
- render.sh: local-path-provisioner を外し、chart と snapshot-controller・VolumeSnapshot の CRD(URL)を足す
- talos-boot: PVC の bind、VolumeSnapshot、スナップショットからの PVC、再起動のあとまでを見る
- recovery/pv.sh: fit(戻すものが PVC の requests に入るか)と backup-all(入れ直す前の最後のバックアップ)
- adguardhome: クエリログが 1 日 10 GB 近くあり 5Gi に入らないので、保持を 1d、PVC を 30Gi に
- docs: z440-migration を「入れ直して restic から戻す」流れに。ROADMAP・decisions・README

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T9PbUfqG4pPxus99UeLiJs
@claude

claude Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Claude finished @5ym's task in 54s —— View job


レビュー結果

render.sh / storage.yaml / talos.sops.yaml / pv.sh を中心に読みました。Talos の RawVolumeConfig → LVMVolumeGroupConfig → lvm-thinpool → ノードのラベル → OpenEBS のノードの Pod という順序は筋が通っています。入れ直しのときしか効かない変更であることも、PR 本文のとおり machine config に閉じています。ブロッカーは見つかりませんでした。実機では動かしておらず、talos-boot の結果は見ていません。以下は小さい指摘と要確認です。

不具合・境界値

  1. backup-all は Schedule が 1 つも無いと 30 分待つ (recovery/pv.sh の backup-all)
    Backup を作らなかった場合、st は空文字です。echo "$st" | awk 'NF < 2 {n++}' は空行を 1 行として数えるので n=1 になり、break に届きません。180 回 × 10 秒を待ってから失敗します。ループの前に ns が空なら「Schedule が無い」と言って止めるのがよさそうです。
  2. bytes() が小数の量を扱えない (recovery/pv.sh の bytes())
    1.5Gi は Gi の分岐に入り、$((1.5 * ...)) が sh の算術エラーになります。エラーメッセージも出ません。G・M・m などの 10 進の単位は *[!0-9]* で弾かれるので問題ありません。今の PVC は整数の Gi・Ti だけなら実害は無く、将来の保険です。
  3. fit の前提 (recovery/pv.sh)
    plan の出力の列が _ op pvc id _ であることに依存しています。plan 側の書式を変えたときに黙って壊れます。コメントで列を固定しておくと安全です。
  4. restore-all が fit を呼ぶ時点で PVC があること (要確認)
    forgejo fit が kubectl get pvc を読むのは、Argo CD が PVC を作った後です。WaitForFirstConsumer でも PVC オブジェクトは存在するので問題無いはずです。ただし手順書の「Argo CD → Infisical → restore-all」の順で、forgejo の PVC が必ず先に在るか確認してください。

bootstrap/storage.yaml

  1. lvm-thinpool の ClusterRole が全ノードの patch を許している
    単一ノード構成なので実害はありません。resourceNames: [main] に絞れば、Pod が侵害されても他のノードへ波及しません。main は talos.sops.yaml で固定されています。Z440 側も同じ名前かだけ確認してください。
  2. DaemonSet に tolerations が無い (要確認)
    main が control-plane の taint を持つ構成だと、lvm-thinpool が動きません。そのうえ OpenEBS のノードの Pod はラベル待ちなので、起動できなくなります。allowSchedulingOnControlPlanes の設定か、他の DaemonSet の tolerations と揃っているか見てください。
  3. プールを広げる判定が 1GiB の許容を持つ
    have < want - 1GiB のときだけ lvextend するので、意図どおりです。ただし手で +10G した後は have > want になり、再起動しても縮みません。これは望ましい動きです。
  4. watch の readinessProbe (要確認)
    lvs は thin プールが無いと空を返し、${1%%.*} が空になって [ "" -lt 90 ] がエラーになります。結果は NotReady で意図に近いですが、init の pool が通っていれば起きません。

設計・セキュリティ

  • Pod が privileged + hostPath: /dev なのは、kube-system に置くという説明で足ります。シークレットの混入もありません。talos.sops.yaml の追加ブロックは ^password$ だけ暗号化する既存の形に沿っています。
  • mirror.gcr.io/openebs/lvm-driver:1.10.1 が storage.yaml に直書きです。renovate.json の変更で chart と一緒に上がる前提のようです。Renovate がこの 2 か所を拾うか、PR を作らせて確認してください。
  • snapshot-controller を URL で入れる方式は、版の一元管理としてよい設計です。生成物に chart 同梱のものが混ざらないことを render.sh の「無いこと」の検査で見ているのも堅実です。

テスト

talos-boot に VG・thin プール、bind、xfs、スナップショットからの復元、talosctl reboot 後の復元を足してあり、変更に見合う検証です。足りないのは pv.sh の fit・backup-all で、実機かテストの VM で通した跡がありません。特に backup-all が期待する k8up の Completed condition の reason: Succeeded は、実際の Backup の status で確認してください(要確認)。

総評

問題無し(上の 1 が一番実害に近く、あとは任意の改善と確認事項です)。

- lvcreate の --wipesignatures は thin プールに使えず、lvm-thinpool が CrashLoop していた(talos-boot)
- lvm-thinpool の RBAC をノード main に絞る
- pv.sh: backup-all は Schedule が無ければすぐ止める、bytes は小数をはっきり弾く、fit が読む plan の列を書いておく

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T9PbUfqG4pPxus99UeLiJs
@claude

claude Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Claude finished @5ym's task in 30s —— View job


レビュー結果

最新のコミット (de7e757) 時点で、bootstrap/storage.yaml・recovery/pv.sh の差分を読み直しました。実機では動かしておらず、talos-boot の結果も見ていません。

前回の指摘のうち、次の 4 点はこのコミットで直っています。

  • backup-all は、Schedule が無いときに 30 分待たず、すぐ止まるようになりました。
  • bytes() は、小数の量を明示的なエラーで弾くようになりました。
  • lvm-thinpool の ClusterRole は resourceNames: [main] に絞られました。
  • --wipesignatures は、thin プールの作成から外れました。

ブロッカーはありません。

要確認

  1. lvm-thinpool の DaemonSet に tolerations が無い (bootstrap/storage.yaml)
    • main が control-plane の taint を持つ構成だと、lvm-thinpool が動きません。
    • OpenEBS のノードの Pod は、このDaemonSetが付けるラベル待ちです。起動できなくなり、PVC が永久に bind しません。
    • talos.sops.yaml で allowSchedulingOnControlPlanes を grep しましたが、見つかりませんでした。単一ノード構成なので設定済みのはずですが、Z440 側の設定で確認してください。
    • 保険として、operator: Exists の toleration を足す手もあります。
  2. k8up の Backup の status (recovery/pv.sh の backup-all)
    • 完了の判定は、Completed condition の reason が Succeeded であることに依存しています。
    • 実際の Backup の status がこの形か、k8up のバージョンで確認してください。違うと、成功しても exit 1 になります。
  3. fit が読む plan の列 (recovery/pv.sh)
    • fit は read -r _ op pvc id _ で plan の出力を読みます。コメントで書式は固定されています。
    • plan の folder の行を変えるときは、fit も合わせて直す必要があります。
  4. restore-all の forgejo fit
    • forgejo fit は PVC の存在を前提にします。Argo CD の同期が済んだ後に実行する手順書の順なら問題ありません。
    • WaitForFirstConsumer でも PVC オブジェクトは存在します。

所感

  • RawVolumeConfig → LVMVolumeGroupConfig → lvm-thinpool → ノードのラベル → OpenEBS のノードの Pod という順序は筋が通っています。
  • lvextend の判定には 1GiB の許容があります。手で広げたあとの再起動でも、プールは縮みません。
  • 秘密情報の混入は見つかりませんでした。
  • talos-boot に足した検証 (VG・thin プール、xfs で bind、スナップショットからの復元、reboot 後の復元) は、変更に見合っています。pv.sh の fit・backup-all を実機やテストの VM で通した跡は無いので、入れ直しの前に一度通すと安心です。

総評: 問題無し。上の 1 と 2 だけ、入れ直す前に確かめてください。

t-src は起き直すたびに marker を書いていたので、再起動のあとの中身の確かめが意味をなさなかった。
t-dst の dataSource は yq の代入を括弧でくくり、出来たものを確かめる。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T9PbUfqG4pPxus99UeLiJs
@claude

claude Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Claude finished @5ym's task in 27s —— View job


レビュー結果

最新のコミット 480bf24 (.github/workflows/talos-boot.yml のみ) を読みました。実機や CI は動かしていません。

ブロッカーはありません。 この変更は前回までの指摘を増やしません。

  • t-src の marker: [ -f /data/marker ] || echo hello > /data/marker に変えたので、talosctl reboot で Pod が起き直しても書き直しません。再起動後の「PV の中身が戻る」確認が意味を持つようになります。
  • t-dst の sed: 2 つ目の sed は、前の行と同じ文字列を消します。BRE の || と > は文字どおりに扱われるので、sleep 86400 だけが残るはずです。
  • yq の代入: 括弧でくくった (select(...) | .spec.dataSource) = {...} は、PVC 以外のドキュメントに触りません。
  • 確かめの追加: echo hello が残っていないことと kind: VolumeSnapshot があることを grep で見ます。生成物が崩れたら fail で止まります。

軽い指摘(任意)

  • 2 つ目の sed は、t-src の command の文字列と一字一句そろっている前提です。片方だけ直すと置換が空振りします。ただ、直後の ! grep -q 'echo hello' が止めてくれるので、黙って壊れることはありません。
  • grep -q 'kind: VolumeSnapshot' は /tmp/pvc.yaml に VolumeSnapshot のドキュメントが入ると素通りします。今は入っていません。

前回までの未解決の要確認(入れ直す前に確かめてください)

  1. lvm-thinpool の DaemonSet に tolerations が無い。main に control-plane の taint があると、ラベルが付かず、OpenEBS のノードの Pod が起きません。
  2. backup-all が見る k8up の Backup の status (Completed condition の reason: Succeeded)。実際の status と合っているかを確かめてください。
  3. pv.sh の fit と backup-all を通した跡がありません。

総評: 問題無し。
· ブランチ storage-openebs-lvm

再起動のあと vgchange -ay が dmeventd の無いことで失敗の終了コードを返し、pool が CrashLoop していた(talos-boot)。
PV の中身と Postgres は戻っていた。readiness の間隔も 60 秒に。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T9PbUfqG4pPxus99UeLiJs
@claude

claude Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Claude finished @5ym's task in 21s —— View job


レビュー結果

最新のコミット 1642515 (bootstrap/storage.yaml のみ) を読みました。実機や CI は動かしていません。

ブロッカーはありません。

  • --config 'activation { monitoring = 0 }': 有効な設定で、lvm.conf の上に重ねる形です。vgchange・lvcreate・lvextend の 3 か所すべてに付いており、抜けはありません。dmeventd が無い環境で、再起動後の vgchange -ay が失敗の終了コードを返して CrashLoop していた原因に対応しています。
  • lvs の読み取り: vgs・lvs と readiness の lvs には付いていません。有効化も作成もしないので、これで足ります。
  • periodSeconds: 60: timeoutSeconds: 30 との組み合わせとして問題ありません。

要確認

  1. OpenEBS のノードの Pod が実行する lvcreate(thin の LV 作成)や lvextend にも、同じ dmeventd の失敗が出ないか確認してください。このコミットが直したのは lvm-thinpool だけです。talos-boot では PV の中身も Postgres も戻っているので、少なくとも作成と再起動後の読み出しは通っているようです。PVC を作ったあとに別の LV を触る操作(スナップショットの削除など)は、通した跡が見えません。
  2. 前回までの未解決: lvm-thinpool の tolerations、k8up の Backup の status(reason: Succeeded)、pv.sh の fit・backup-all を通した跡。入れ直す前に確かめてください。

総評: 問題無し。
· ブランチ storage-openebs-lvm

@5ym
5ym merged commit 77c988d into main Oct 30, 2026
6 checks passed
@5ym
5ym deleted the storage-openebs-lvm branch October 30, 2026 18:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant