Skip to content

fix(linstor-scheduler): re-vendor to upstream 0.3.1 with native admission webhook - #3201

Merged
Aleksei Sviridkin (lexfrei) merged 1 commit into
mainfrom
fix/bump-linstor-scheduler-extender-0.3.5
Jul 16, 2026
Merged

Aleksei Sviridkin (lexfrei) merged 1 commit into
mainfrom
fix/bump-linstor-scheduler-extender-0.3.5

Conversation

@lexfrei

@lexfrei Aleksei Sviridkin (lexfrei) commented Jul 4, 2026 •

Copy link
Copy Markdown
Contributor

What this PR does

Re-vendors the linstor-scheduler chart from upstream 0.3.1 (appVersion v0.3.6). Upstream now ships the admission webhook natively (contributed via piraeusdatastore/helm-charts#94), so the loose downstream admission templates — which round-tripped every Pod through an old k8s.io/api and silently stripped fields they did not know about, the image volume source and the native-sidecar restartPolicy among them, breaking KubeVirt containerDisk VMs and native sidecars cluster-wide — are dropped in favour of the upstream copy.

  • The admission webhook comes from the upstream chart now; the previous downstream copy and its patch are removed. make update pulls 0.3.1 and applies only cozystack-scheduler-deployment.patch (the scheduler pod component label and the distro-suffix-stripped kube-scheduler image tag, neither of which is upstream yet), so vendoring stays deterministic and reproducible.
  • The upstream admission Deployment keeps the same name but changes its immutable pod selector, so an in-place upgrade of an existing install would fail with field is immutable. Migration 52 deletes the old admission Deployment before the upgrade so the new one is recreated cleanly (targetVersion 52 → 53).
  • appVersion v0.3.6 also carries the webhook's TLS certificate hot-reload fix (piraeusdatastore/linstor-scheduler-extender#22): the webhook used to load its certificate once at startup, so after the mounted Secret was rotated it kept serving a stale certificate and — with failurePolicy: Ignore — silently stopped mutating until it was restarted. It now reloads on rotation, so no external cert-reload workaround is needed here.
  • Wrapper values keep replicaCount: 2, now that the admission Pods have their own PodDisruptionBudget and no longer share the scheduler's.
  • Adds a helm-unittest suite covering the admission resources, PodDisruptionBudget selector isolation, least-privilege RBAC, the TLS provisioning modes and their rejection paths, the scheduler image-tag strip, and backward compatibility with the webhook disabled.

Closes #3198.

Screenshots

N/A — no UI changes.

Downstream repositories

I walked the trigger map against the diff, file by file. It touches packages/system/linstor-scheduler/ and, under packages/core/platform/, only migration 52 and the migrations.targetVersion bump — an internal, release-managed counter, not a user-facing spec.components.platform.values.* key documented on the website. No trigger matches.

Release note

fix(linstor-scheduler): the LINSTOR scheduler admission webhook no longer strips unknown Pod fields (the `image` volume source and native-sidecar `restartPolicy`), which had broken KubeVirt containerDisk VMs and native sidecars, and it now reloads its TLS certificate after rotation instead of silently failing. The chart is re-vendored from upstream 0.3.1; an automatic upgrade migration replaces the admission Deployment whose immutable selector changed.

Summary by CodeRabbit

  • New Features
    • Expanded the optional Linstor Scheduler admission webhook with richer configuration, including automated schedulerName mutation for LINSTOR CSI-backed PVC Pods.
  • Improvements
    • Updated the Linstor Scheduler Helm chart to 0.3.1 (scheduler app v0.3.6), including updated admission webhook behavior, safer defaults, and 2 replicas.
    • Platform migrations now advance to version 53, with upgrade-safe cleanup of the existing admission deployment.
  • Documentation
    • Updated Helm README and post-install notes with detailed guidance for admission webhook and TLS modes.

@github-actions github-actions Bot added area/storage Issues or PRs related to storage (linstor, seaweedfs, bucket, velero, harbor) kind/bug Categorizes issue or PR as related to a bug size/XS This PR changes 0-9 lines, ignoring generated files labels Jul 4, 2026
@coderabbitai

coderabbitai Bot commented Jul 4, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The linstor-scheduler chart is upgraded to v0.3.6 with expanded admission webhook configuration, TLS provisioning, dedicated runtime resources, scheduler deployment safeguards, validation tests, and platform migration 53.

Changes

linstor-scheduler admission upgrade

Layer / File(s) Summary
Chart release and platform migration
packages/system/linstor-scheduler/charts/linstor-scheduler/Chart.yaml, packages/core/platform/...
Chart metadata advances to 0.3.1/v0.3.6; platform migrations advance to 53 and remove the legacy admission Deployment.
Admission configuration and TLS resources
packages/system/linstor-scheduler/charts/linstor-scheduler/values.yaml, templates/*
Admission values, helper names, webhook validation, Helm TLS generation, and cert-manager Issuer/Certificate resources are added.
Admission runtime and access wiring
packages/system/linstor-scheduler/charts/linstor-scheduler/templates/*
Admission Deployment, Service, ServiceAccount, PDB, selectors, probes, affinity, and PVC/PV-scoped RBAC are updated.
Scheduler integration and validation
packages/system/linstor-scheduler/Makefile, patches/*, tests/*, README.md, templates/NOTES.txt
The pinned chart update applies the scheduler patch; replicas and image tags are configured, operational guidance is documented, and admission/TLS/PDB/RBAC behavior is tested.

Estimated code review effort: 4 (Complex) | ~60 minutes

Suggested labels: area/kubernetes, area/testing

Suggested reviewers: kvaps, lllamnyp

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR replaces the old cluster-wide admission webhook with the upstream native webhook, addressing the unknown-field stripping issue in #3198.
Out of Scope Changes check ✅ Passed The changes stay focused on the scheduler re-vendor, admission webhook replacement, migration, and related tests/docs.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly reflects the main change: re-vendoring the linstor-scheduler chart and adding the native admission webhook.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/bump-linstor-scheduler-extender-0.3.5

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Note

Gemini is unable to generate a summary for this pull request due to the file types involved not being currently supported.

@dosubot dosubot Bot added area/virtualization Issues or PRs related to virtualization (kubevirt, cdi, vmi, vm-import) security/fixed Fix released labels Jul 4, 2026

@IvanHunters IvanHunters left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: request-changes

The fix is correct and needed, but the delivery mechanism will silently revert.

[MAJOR] appVersion bump is not durable — reverts on next make update

packages/system/linstor-scheduler/charts/linstor-scheduler/Chart.yaml:2

The appVersion is edited directly in the vendored chart, but there is no
corresponding entry in patches/*. The update target in the Makefile does
rm -rf charts && helm pull and re-applies only the two existing patches
(disable-ca-key-rotation, add-scheduler-component-label), neither of which
touches Chart.yaml. As you note yourself, no upstream chart ships appVersion
v0.3.5 yet. Result: the next make update silently reverts both containers to
v0.3.4 and the KubeVirt containerDisk regression returns with no error.

Requested changes

  • Add patches/bump-appversion-to-v0.3.5.patch capturing the Chart.yaml change.
  • Apply it from the update target:
    patch --no-backup-if-mismatch -p4 < patches/bump-appversion-to-v0.3.5.patch
  • Add a TODO above the line: drop the patch once piraeus-charts ships a chart
    whose appVersion is >= v0.3.5.

Non-blocking follow-up: consider pinning the image via @sha256: (cozy-lib.image)
for air-gapped installs.

@myasnikovdaniil myasnikovdaniil left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approve — one-line, well-scoped fix.

Verified the mechanism: both the extender sidecar (deployment.yaml) and the admission webhook (admission-deployment.yaml) derive their image from extender.image.tag | default .Chart.AppVersion, extender.image.tag is empty, and this package sets admission.enabled: true, so the bump moves both containers to v0.3.5. Independently confirmed quay.io/piraeusdatastore/linstor-scheduler-extender:v0.3.5 exists (multi-arch manifest list, digest sha256:ccdc2fb4…, matching the PR body). No package version bump needed (Chart.yaml uses the 0.0.0 build-time placeholder) and there's no Helm-vendoring drift check in CI.

Non-blocking nit: the subchart's version stays 0.2.3 while appVersion is pinned 3 patch releases ahead of any published chart, and the package's make update target pulls the chart with no version pin. Until piraeus ships a chart whose appVersion >= v0.3.5, the next make update will silently regress this to v0.3.4 and look like a routine re-vendor. Worth a breadcrumb comment on the appVersion line so a future maintainer doesn't undo the fix by accident. Not a blocker.

@lexfrei
Aleksei Sviridkin (lexfrei) force-pushed the fix/bump-linstor-scheduler-extender-0.3.5 branch from b83ae69 to 16d6532 Compare July 15, 2026 08:57
IvanHunters
IvanHunters previously approved these changes Jul 15, 2026

@IvanHunters IvanHunters left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. The bump (appVersion v0.3.2 -> v0.3.5) is a correct, idempotent metadata change: the v0.3.5 image is pullable (multi-arch, digest matches), both the extender and admission deployments derive the tag from Chart.AppVersion, and the admission webhook is enabled at package level so the fix (#3198) actually applies. Upgrade rolls two deployments with no RBAC/schema/migration change.

On the earlier change-request: the concern about make update silently reverting appVersion is no longer reachable, since upstream piraeus now ships appVersion v0.3.5 as latest, so a re-vendor will not regress. The cleaner fix is still to run a real make update and commit the re-vendored chart rather than hand-editing Chart.yaml, so the vendored tree stays internally consistent. Non-blocking.

@lexfrei
Aleksei Sviridkin (lexfrei) marked this pull request as draft July 15, 2026 13:29
@lexfrei
Aleksei Sviridkin (lexfrei) force-pushed the fix/bump-linstor-scheduler-extender-0.3.5 branch from 16d6532 to 8fbe6a7 Compare July 15, 2026 13:57
@github-actions github-actions Bot added size/L This PR changes 100-499 lines, ignoring generated files and removed size/XS This PR changes 0-9 lines, ignoring generated files labels Jul 15, 2026
@lexfrei Aleksei Sviridkin (lexfrei) changed the title fix(linstor): bump scheduler-extender to v0.3.5 fix(linstor-scheduler): re-vendor to upstream 0.3.0 with native admission webhook Jul 15, 2026
@lexfrei
Aleksei Sviridkin (lexfrei) marked this pull request as ready for review July 15, 2026 13:58
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request updates the linstor-scheduler component by aligning with the upstream 0.3.0 chart. By transitioning to the native admission webhook, the system resolves critical issues where unknown Pod fields were being stripped, which previously caused failures for KubeVirt containerDisk VMs and native sidecars. The changes include necessary migration logic for seamless upgrades, improved HA configurations, and robust test coverage to ensure future stability.

Highlights

  • Upstream Re-vendoring: Re-vendored the linstor-scheduler chart to upstream version 0.3.0, adopting the native admission webhook and removing the legacy downstream templates.
  • Migration and Upgrade: Added migration 52 to delete the old admission Deployment, preventing 'immutable field' errors during the upgrade to the new native webhook.
  • Reliability and HA: Increased replica counts to 2 for both the scheduler and admission pods to ensure high availability and node drainability, while adding Reloader support for certificate rotation.
  • Testing: Introduced a comprehensive helm-unittest suite to validate admission resources, RBAC, TLS provisioning, and scheduler image tag handling.
New Features

🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Ignored Files
  • Ignored by pattern: **/*.patch (3)
    • packages/system/linstor-scheduler/patches/add-scheduler-component-label.patch
    • packages/system/linstor-scheduler/patches/cozystack-scheduler-deployment.patch
    • packages/system/linstor-scheduler/patches/disable-ca-key-rotation.patch
  • Ignored by pattern: **/charts/** (14)
    • packages/system/linstor-scheduler/charts/linstor-scheduler/Chart.yaml
    • packages/system/linstor-scheduler/charts/linstor-scheduler/README.md
    • packages/system/linstor-scheduler/charts/linstor-scheduler/templates/NOTES.txt
    • packages/system/linstor-scheduler/charts/linstor-scheduler/templates/_helpers.tpl
    • packages/system/linstor-scheduler/charts/linstor-scheduler/templates/admission-certmanager.yaml
    • packages/system/linstor-scheduler/charts/linstor-scheduler/templates/admission-deployment.yaml
    • packages/system/linstor-scheduler/charts/linstor-scheduler/templates/admission-poddisruptionbudget.yaml
    • packages/system/linstor-scheduler/charts/linstor-scheduler/templates/admission-service.yaml
    • packages/system/linstor-scheduler/charts/linstor-scheduler/templates/admission-serviceaccount.yaml
    • packages/system/linstor-scheduler/charts/linstor-scheduler/templates/admission-webhook.yaml
    • packages/system/linstor-scheduler/charts/linstor-scheduler/templates/certmanager.yaml
    • packages/system/linstor-scheduler/charts/linstor-scheduler/templates/mutatingwebhookconfiguration.yaml
    • packages/system/linstor-scheduler/charts/linstor-scheduler/templates/rbac.yaml
    • packages/system/linstor-scheduler/charts/linstor-scheduler/values.yaml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment Gemini (@gemini-code-assist) Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on Gemini (@gemini-code-assist) comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request upgrades the linstor-scheduler package to upstream version 0.3.0, adds a migration script (52 -> 53) to recreate the admission webhook deployment, and introduces comprehensive Helm unit tests. It also configures the scheduler to run with two replicas for high availability and enables automatic webhook reloading on certificate changes. Feedback is provided regarding a POSIX compatibility issue in the migration script, where the non-standard pipefail option is used with #!/bin/sh.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

# creation. Safe when absent: fresh installs and clusters without the linstor
# stack simply skip it via --ignore-not-found.

set -euo pipefail

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The script uses #!/bin/sh as its shebang, but specifies set -euo pipefail. The pipefail option is a non-standard shell option (a bashism) and is not supported by POSIX-compliant shells like dash (which is the default /bin/sh on Debian/Ubuntu systems). Running this script in such environments will cause it to fail with a set: Illegal option -o pipefail error.\n\nSince there are no pipelines used in this migration script, the pipefail option is redundant and can be safely removed to ensure POSIX compatibility.

Suggested change
set -euo pipefail
set -eu

…sion webhook

Re-vendor the linstor-scheduler chart from upstream 0.3.1 (appVersion
v0.3.6), which carries the admission webhook binary that stopped
stripping unknown Pod fields — the image VolumeSource and native-sidecar
restartPolicy, which broke KubeVirt containerDisk VMs and native sidecars
cluster-wide — and now reloads its TLS certificate on rotation instead of
serving a stale one until restarted.

The admission webhook ships in the upstream chart, so the previous
downstream copy is dropped: `make update` pulls it directly and applies
only cozystack-scheduler-deployment.patch (pod component label and a
distro-suffix-stripped image tag), keeping the vendoring deterministic.
Because the webhook now reloads its own certificate, the external
cert-reload workaround is dropped.

The upstream admission Deployment keeps the same name but changes its
immutable pod selector, so an in-place upgrade of an existing install
would fail. A migration deletes the old admission Deployment before the
upgrade so the new one is recreated cleanly, and bumps the migration
target version.

Add a helm-unittest suite covering the admission resources, PDB selector
isolation, least-privilege RBAC, the scheduler image tag, and backward
compatibility.

Assisted-By: Claude <[email protected]>
Signed-off-by: Aleksei Sviridkin <[email protected]>
@lexfrei
Aleksei Sviridkin (lexfrei) force-pushed the fix/bump-linstor-scheduler-extender-0.3.5 branch from 8fbe6a7 to f4aef73 Compare July 16, 2026 14:09
@lexfrei Aleksei Sviridkin (lexfrei) changed the title fix(linstor-scheduler): re-vendor to upstream 0.3.0 with native admission webhook fix(linstor-scheduler): re-vendor to upstream 0.3.1 with native admission webhook Jul 16, 2026
@github-actions github-actions Bot added the area/uncategorized PR auto-labeler could not map title scope to a known area/*; please review label Jul 16, 2026

@kvaps Andrei Kvapil (kvaps) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

APPROVE — re-vendoring is byte-for-byte faithful, the field-stripping fix is real and delivered, and the upgrade path is safe. Verified against the actual upstream chart and the extender changelogs.

Vendoring fidelity — verified byte-for-byte

Reproduced make update exactly (helm pull piraeus-charts/linstor-scheduler --version 0.3.1 → rm -rf charts/linstor-scheduler/tests → patch -p4 < patches/cozystack-scheduler-deployment.patch) and diff -ru against the vendored copy in this PR: identical. So every admission template here (the createTLS enum, helm-mode genCA, dedicated ServiceAccount + PDB kept off the base scheduler's immutable selectors, the fail-guards, the readiness/liveness probes, the admission _helpers.tpl funcs) is genuine upstream 0.3.1 content from the merged piraeusdatastore/helm-charts#94 — not downstream code that would silently drift on the next re-vendor. appVersion: v0.3.6 matches upstream.

cozystack specifics preserved

The two old downstream patches were correctly consolidated, nothing dropped by accident:

  • add-scheduler-component-label.patch → carried as hunk (a) of cozystack-scheduler-deployment.patch (the wrapper's extender-service.yaml selects scheduler pods by app.kubernetes.io/component: scheduler).
  • disable-ca-key-rotation.patch → now the upstream default (admission.tls.certManager.rotationPolicy: Never), so correctly removed rather than re-applied.
  • New hunk (b) derives the kube-scheduler image tag from the distro-stripping kubeVersion helper; rendered output confirms registry.k8s.io/kube-scheduler:v1.34.0 with no +k3s1/+rke2r1 suffix. Pinned by a new test.

The webhook no longer strips unknown Pod fields — confirmed at the source

This is a binary-level fix, delivered by the v0.3.2 → v0.3.6 image bump the chart carries. Per the extender v0.3.5 changelog (#19): the webhook now returns a targeted RFC-6902 JSON Patch that only sets schedulerName, instead of deserializing the whole Pod into a struct built against an older k8s.io/api and re-serializing it. Because it no longer round-trips the object, all unknown fields survive — the native-sidecar initContainers[].restartPolicy and the image volume source alike. v0.3.6 then adds TLS cert hot-reload (#22). Rendered admission image is linstor-scheduler-extender:v0.3.6; failurePolicy: Ignore (fails open), timeoutSeconds: 5, admissionReviewVersions: ["v1"].

Cert hot-reload wired correctly

v0.3.6 serves its certificate via tls.Config.GetCertificate with content-hash reload across kubelet's atomic ..data swap, so the wrapper rightly leaves reloadOnCertChange: false and documents why. The vendored chart's own README/values text still says "does not hot-reload" — that's upstream text predating the v0.3.6 binary; leaving it unpatched avoids downstream drift and the wrapper values.yaml explains the discrepancy. No Reloader annotation is emitted (pinned by a test).

Upgrade safety

Migration 52 deletes the old linstor-scheduler-admission Deployment in cozy-linstor (namespace verified against sources/linstor-scheduler.yaml) before the component reconciles, because the upstream admission Deployment keeps the same name but changes its immutable pod selector — an in-place upgrade would fail field is immutable. --ignore-not-found makes it a no-op on fresh installs and clusters without the LINSTOR stack, and failurePolicy: Ignore covers the brief gap. Service / MutatingWebhookConfiguration / ClusterRole names are unchanged, so those update in place. The base scheduler 1 → 2 replicas also fixes a pre-existing drain deadlock (minAvailable: 1 PDB + 1 replica = undrainable node).

Render / tests

  • helm template renders the full stack cleanly (admission Deployment/Service/SA/PDB/MutatingWebhook + cert-manager Issuer/Certificate chain; base scheduler + extender Service).
  • helm unittest: 22/22 passed across both suites.
  • helm lint's missing these dependencies: linstor-scheduler is the standard cozystack umbrella pattern (vendored subchart not declared under dependencies:) — pre-existing on main, not introduced here.
  • CI is green; merge is BLOCKED only by REVIEW_REQUIRED (this review), no red checks. E2E still pending at review time.

Clean, well-tested, faithfully-vendored consumption of an upstream fix. LGTM.

@lexfrei
Aleksei Sviridkin (lexfrei) merged commit 0238231 into main Jul 16, 2026
16 checks passed
@lexfrei
Aleksei Sviridkin (lexfrei) deleted the fix/bump-linstor-scheduler-extender-0.3.5 branch July 16, 2026 16:08
Timofei Larkin (lllamnyp) added a commit that referenced this pull request Aug 26, 2026
…pgrade (Phase 2, breaking) (#3315)

## What this PR does

Phase 2 of the Kubernetes-app split
([cozystack/community#8](cozystack/community#8))
— the **breaking** half. Stacked on #3314 (review that first).

Removes worker node pools from the `kubernetes` chart (they moved to
`kubernetes-nodes` in #3314) and adopts existing pools on upgrade:

- `kubernetes` chart is now **control-plane only**: drops the pool
`range` block, the `talos-reconcile` Job + RBAC (deleted; moved to
`kubernetes-nodes`), the preserve-old-KMT block, the
`kubernetes.nodeGroups` helper, and the per-group dashboard RBAC.
- **`spec.nodeGroups` is removed from the `Kubernetes` CR** (BREAKING).
Worker pools are now separate `KubernetesNodes` resources.
- **Migration 54** (bumps `targetVersion` to 55): pre-upgrade hook that,
for every `kubernetes-<cluster>` release, creates one
`kubernetes-nodes-<cluster>-<pool>` HelmRelease and re-annotates the
existing worker objects onto it with `helm.sh/resource-policy=keep`, so
the now control-plane-only parent upgrade does not prune running
workers. The default `md0` (implicit when `nodeGroups` was empty) is
materialised explicitly. Idempotent. Genuine infrastructure/read
failures fail closed (`exit 1`, retried on the next upgrade); hostile
stored shapes (a pool name over Helm's 53-char release-name cap, an
RFC-1123-invalid or whitespace/slash map key, a non-object `nodeGroups`)
are warned, pinned, and skipped rather than deadlocking the entire
fleet's upgrade.
- The `ingressNginx` addon no longer auto-provisions a node (the
implicit `md0` default is gone). If enabled without a pool carrying
`roles: [ingress-nginx]`, the controller DaemonSet simply schedules
nothing (degraded, not failed) — the requirement is documented in the
chart NOTES.txt rather than enforced at render time.

Because the child chart renders the pool objects **byte-identically** to
the old parent render (golden parity in #3314; the
KubevirtMachineTemplate content-hash name is preserved), adoption does
not churn live worker VMs.

### Migration number

`54` is contiguous with main (latest is `53`) and `targetVersion` is
`55`. The `52`/#3201 collision noted in earlier revisions has been
resolved: this branch was rebased and merged past it, so the numbering
is contiguous and `run-migrations.sh` has no gap to hard-fail on.

### Not yet done (blocking draft → ready)

- [ ] **dev e2e upgrade validation** (`cozystack-pr-test`): upgrade a
custom-`nodeGroups` cluster and a default-`md0` cluster; assert zero
worker-VM churn (KMT hash, Machine uid/creationTimestamp stable) and
that the adopted child HRs reconcile.
- [ ] downstream trigger-map walk (website docs for the `nodeGroups` →
`KubernetesNodes` change; terraform-provider for the removed API field).

### Downstream repositories

Deliberately unticked (draft) — the breaking API change affects docs and
the terraform provider; follow-ups to be filed before ready.

- [ ] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:

```release-note
Worker node pools of a managed Kubernetes cluster are now managed as separate `KubernetesNodes` resources. `spec.nodeGroups` on the `Kubernetes` CR is removed; existing pools are adopted automatically on upgrade.
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Worker pools are now separate `KubernetesNodes` resources with their
own lifecycle.
* Added a render-time compatibility guard to prevent worker pools from
running ahead of the parent control-plane minor version.
* Improved upgrade/uninstall behavior to better preserve already-adopted
worker objects.

* **Breaking Changes**
* Removed per-pool `nodeGroups` and worker node health settings from the
`Kubernetes` chart/CR; pool configuration now lives in
`KubernetesNodes`.
* Ingress requires at least one `KubernetesNodes` pool with `roles:
[ingress-nginx]`.
* `cluster` and `storageClass` are immutable after creation; pool
`version` may lag but must not be ahead of the parent minor.

* **Documentation**
* Updated READMEs, notes, and schemas to reflect the `KubernetesNodes`
split and the immutability/version rules.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Andrei Kvapil (kvaps) pushed a commit that referenced this pull request Sep 7, 2026
…pgrade (Phase 2, breaking) (#3315)

## What this PR does

Phase 2 of the Kubernetes-app split
([cozystack/community#8](cozystack/community#8))
— the **breaking** half. Stacked on #3314 (review that first).

Removes worker node pools from the `kubernetes` chart (they moved to
`kubernetes-nodes` in #3314) and adopts existing pools on upgrade:

- `kubernetes` chart is now **control-plane only**: drops the pool
`range` block, the `talos-reconcile` Job + RBAC (deleted; moved to
`kubernetes-nodes`), the preserve-old-KMT block, the
`kubernetes.nodeGroups` helper, and the per-group dashboard RBAC.
- **`spec.nodeGroups` is removed from the `Kubernetes` CR** (BREAKING).
Worker pools are now separate `KubernetesNodes` resources.
- **Migration 54** (bumps `targetVersion` to 55): pre-upgrade hook that,
for every `kubernetes-<cluster>` release, creates one
`kubernetes-nodes-<cluster>-<pool>` HelmRelease and re-annotates the
existing worker objects onto it with `helm.sh/resource-policy=keep`, so
the now control-plane-only parent upgrade does not prune running
workers. The default `md0` (implicit when `nodeGroups` was empty) is
materialised explicitly. Idempotent. Genuine infrastructure/read
failures fail closed (`exit 1`, retried on the next upgrade); hostile
stored shapes (a pool name over Helm's 53-char release-name cap, an
RFC-1123-invalid or whitespace/slash map key, a non-object `nodeGroups`)
are warned, pinned, and skipped rather than deadlocking the entire
fleet's upgrade.
- The `ingressNginx` addon no longer auto-provisions a node (the
implicit `md0` default is gone). If enabled without a pool carrying
`roles: [ingress-nginx]`, the controller DaemonSet simply schedules
nothing (degraded, not failed) — the requirement is documented in the
chart NOTES.txt rather than enforced at render time.

Because the child chart renders the pool objects **byte-identically** to
the old parent render (golden parity in #3314; the
KubevirtMachineTemplate content-hash name is preserved), adoption does
not churn live worker VMs.

### Migration number

`54` is contiguous with main (latest is `53`) and `targetVersion` is
`55`. The `52`/#3201 collision noted in earlier revisions has been
resolved: this branch was rebased and merged past it, so the numbering
is contiguous and `run-migrations.sh` has no gap to hard-fail on.

### Not yet done (blocking draft → ready)

- [ ] **dev e2e upgrade validation** (`cozystack-pr-test`): upgrade a
custom-`nodeGroups` cluster and a default-`md0` cluster; assert zero
worker-VM churn (KMT hash, Machine uid/creationTimestamp stable) and
that the adopted child HRs reconcile.
- [ ] downstream trigger-map walk (website docs for the `nodeGroups` →
`KubernetesNodes` change; terraform-provider for the removed API field).

### Downstream repositories

Deliberately unticked (draft) — the breaking API change affects docs and
the terraform provider; follow-ups to be filed before ready.

- [ ] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:

```release-note
Worker node pools of a managed Kubernetes cluster are now managed as separate `KubernetesNodes` resources. `spec.nodeGroups` on the `Kubernetes` CR is removed; existing pools are adopted automatically on upgrade.
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Worker pools are now separate `KubernetesNodes` resources with their
own lifecycle.
* Added a render-time compatibility guard to prevent worker pools from
running ahead of the parent control-plane minor version.
* Improved upgrade/uninstall behavior to better preserve already-adopted
worker objects.

* **Breaking Changes**
* Removed per-pool `nodeGroups` and worker node health settings from the
`Kubernetes` chart/CR; pool configuration now lives in
`KubernetesNodes`.
* Ingress requires at least one `KubernetesNodes` pool with `roles:
[ingress-nginx]`.
* `cluster` and `storageClass` are immutable after creation; pool
`version` may lag but must not be ahead of the parent minor.

* **Documentation**
* Updated READMEs, notes, and schemas to reflect the `KubernetesNodes`
split and the immutability/version rules.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/storage Issues or PRs related to storage (linstor, seaweedfs, bucket, velero, harbor) area/uncategorized PR auto-labeler could not map title scope to a known area/*; please review area/virtualization Issues or PRs related to virtualization (kubevirt, cdi, vmi, vm-import) kind/bug Categorizes issue or PR as related to a bug security/fixed Fix released size/L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

linstor-scheduler-admission (v0.3.2) strips unknown pod fields cluster-wide → breaks image volumes / KubeVirt containerDisk and native sidecars

4 participants