Skip to content

Commit 4013316

Browse files
authored
feat(k8s): Longhorn Platform component (F1) (#147)
Add `longhorn` to the opt-in Platform component set (chart `longhorn` from charts.longhorn.io, namespace longhorn-system): replicated block storage — RWO volumes with node-to-node replication + snapshots, the tier NFS/local-path don't cover. #Platform.longhorn? schema entry + unit test (chart/ns defaults, values thread-through). Every node needs open-iscsi, installable via a k3s worker pool's nodePrep.packages (E2) — documented in the component comment and schema — or Longhorn's iscsi-installer DaemonSet as a fallback. Opt-in like every component: platform.longhorn.enabled: true.
1 parent fc6ad0a commit 4013316

4 files changed

Lines changed: 48 additions & 4 deletions

File tree

ROADMAP.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,16 @@ prerequisite (Longhorn); the rest are convenience + robustness.
184184
the prereqs. **Makes F1 (Longhorn) usable.**
185185

186186
### F. Storage
187-
- [ ] **F1 — Longhorn Platform component.** Add `longhorn` to the opt-in
188-
Platform set (replicated block storage, the tier NFS/local-path don't
189-
cover). Depends on E1 (open-iscsi on nodes); document the
190-
iscsi-installer DaemonSet as the interim fallback.
187+
- [x] **F1 — Longhorn Platform component.** `longhorn` added to the opt-in
188+
Platform set (chart `longhorn` from `charts.longhorn.io`, ns
189+
`longhorn-system`) — replicated block storage (RWO volumes with
190+
node-to-node replication + snapshots), the tier NFS/local-path don't
191+
cover. `#Platform.longhorn?` schema entry + unit test (chart/ns defaults,
192+
values thread-through). Every node needs `open-iscsi`: install it via a
193+
k3s worker pool's `nodePrep.packages` (**E2**, now shipped) — documented in
194+
both the component comment and schema — or Longhorn's own iscsi-installer
195+
DaemonSet as the interim fallback. Enabling is `platform.longhorn.enabled:
196+
true`.
191197

192198
### G. Public exposure
193199
- [ ] **G1 — expose-app convenience.** A composite (or documented pattern)

plugins/k8s/internal/provider/platform.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ var platformComponents = []component{
5252
// persistent volumes on request. Set nfsProvisioner.values.nfs.{server,path}
5353
// to the NAS export.
5454
{"nfsProvisioner", "https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner", "nfs-subdir-external-provisioner", "nfs-provisioner"},
55+
// longhorn is replicated block storage — the tier NFS/local-path don't
56+
// cover (RWO volumes with node-to-node replication + snapshots). Every node
57+
// needs `open-iscsi` installed; provision it via a k3s worker pool's
58+
// nodePrep (E2) — e.g. nodePrep.packages: ["open-iscsi"] — or Longhorn's
59+
// own iscsi-installer DaemonSet as an interim fallback.
60+
{"longhorn", "https://charts.longhorn.io", "longhorn", "longhorn-system"},
5561
}
5662

5763
// releaseCoord locates an installed component release for Get/Delete/prune.

plugins/k8s/internal/provider/platform_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,33 @@ func TestEnabledComponents_NfsProvisioner(t *testing.T) {
7171
}
7272
}
7373

74+
func TestEnabledComponents_Longhorn(t *testing.T) {
75+
comps := enabledComponents(map[string]any{
76+
"longhorn": map[string]any{
77+
"enabled": true,
78+
"values": map[string]any{"defaultSettings": map[string]any{"defaultReplicaCount": 2}},
79+
},
80+
})
81+
if len(comps) != 1 {
82+
t.Fatalf("enabled = %d, want 1 (longhorn)", len(comps))
83+
}
84+
c := comps[0]
85+
if c.comp.name != "longhorn" {
86+
t.Errorf("component = %q", c.comp.name)
87+
}
88+
if c.chart.Repo != "https://charts.longhorn.io" || c.chart.Name != "longhorn" {
89+
t.Errorf("chart defaults wrong: %+v", c.chart)
90+
}
91+
if c.opts.namespace != "longhorn-system" {
92+
t.Errorf("default namespace = %q, want longhorn-system", c.opts.namespace)
93+
}
94+
// User values (e.g. replica count) thread through to the chart.
95+
ds, _ := c.values["defaultSettings"].(map[string]any)
96+
if ds["defaultReplicaCount"] != 2 {
97+
t.Errorf("longhorn values not threaded: %+v", c.values)
98+
}
99+
}
100+
74101
func TestEnabledComponents_NvidiaDevicePlugin(t *testing.T) {
75102
comps := enabledComponents(map[string]any{
76103
"nvidiaDevicePlugin": map[string]any{"enabled": true},

plugins/k8s/internal/provider/schema.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ const platformSchema = `
112112
// nfsProvisioner gives a dynamic NFS-backed StorageClass for persistent
113113
// volumes (e.g. a Synology share). Set values.nfs.server + values.nfs.path.
114114
nfsProvisioner?: {...}
115+
// longhorn is replicated block storage (RWO volumes with node-to-node
116+
// replication + snapshots). Every node needs open-iscsi — install it via
117+
// a k3s worker pool's nodePrep.packages, or Longhorn's iscsi-installer
118+
// DaemonSet as a fallback.
119+
longhorn?: {...}
115120
}
116121
...
117122
}

0 commit comments

Comments
 (0)