Skip to content

feat(kubernetes-nodes): split worker node pool into its own app (Phase 2, additive)#3314

Draft
IvanHunters wants to merge 11 commits into
mainfrom
feat/kubernetes-nodes-phase2a
Draft

feat(kubernetes-nodes): split worker node pool into its own app (Phase 2, additive)#3314
IvanHunters wants to merge 11 commits into
mainfrom
feat/kubernetes-nodes-phase2a

Conversation

@IvanHunters

@IvanHunters IvanHunters commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Phase 2 of the Kubernetes-app split (cozystack/community#8) — the additive half.

Introduces kubernetes-nodes: a per-pool application that renders the worker node-pool objects (KubevirtMachineTemplate, MachineDeployment, MachineHealthCheck, worker WorkloadMonitor, and the talos-reconcile Job + RBAC) extracted from the monolithic kubernetes chart. A KubernetesNodes CR named <cluster>-<pool> attaches to a parent Kubernetes cluster in the same namespace by name convention (kubernetes-<cluster>), mirroring the vm-instance/vm-disk precedent.

This PR is additive: the parent kubernetes chart gets exactly one scoping fix (its old-KMT preservation block is limited to KMTs owned by its own Helm release) so that attaching a kubernetes-nodes pool to a live cluster cannot break the parent's next upgrade. Existing clusters keep provisioning workers via nodeGroups. Removing nodeGroups from the parent and adopting existing pools into kubernetes-nodes releases is a follow-up breaking PR (Phase 2b).

Key properties:

  • Pool objects render byte-identical to the parent for the same group (golden-parity check in tests/render-parity.sh), so the follow-up adoption never churns live worker VMs — the content-hashed KubevirtMachineTemplate name is preserved.
  • cluster-autoscaler (kept in the parent chart) discovers the pool's MachineDeployments cross-release via the unchanged cluster.x-k8s.io/cluster-name label, namespace, and min/max annotations.
  • Registered as a dedicated cozystack.kubernetes-nodes-application PackageSource + kubernetes-nodes-rd ApplicationDefinition, wired into the iaas bundle (mirrors vm-instance/vm-disk).

Downstream repositories

Left unticked deliberately — this is a draft. A new user-facing KubernetesNodes API is added, so cozystack/website (docs) and cozystack/terraform-provider-cozystack likely need follow-ups; the trigger-map walk will be completed before this leaves draft.

Add the `kubernetes-nodes` application: manage the worker node pools of a managed Kubernetes cluster as independent resources, one HelmRelease per pool.

Introduce the kubernetes-nodes application chart: one HelmRelease per
worker node pool, attached to a parent Kubernetes cluster by name
convention (kubernetes-<cluster>). Renders the KubevirtMachineTemplate,
MachineDeployment, MachineHealthCheck, worker WorkloadMonitor and the
talos-reconcile Job with its RBAC, extracted from the monolithic
kubernetes chart. Pool objects are byte-identical to the parent's render
for the same group, so a later adoption never churns live worker VMs.

This is the additive half of the Phase 2 split (community#8); the parent
kubernetes chart is left unchanged.

Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Generated by cozyvalues-gen + controller-gen from values.yaml.

Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Unit tests cover naming/selectors, clusterName wiring, autoscaler
annotations, omitted replicas, bootstrap TCT reference, KMT hash name,
worker WorkloadMonitor, and the empty-cluster / mis-prefixed-release
render guards. render-parity.sh diffs the pool objects against the
parent kubernetes chart and asserts byte-identity.

Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Add the kubernetes-nodes-rd package (ApplicationDefinition), the
cozystack.kubernetes-nodes-application PackageSource (kubevirt variant,
kubernetes-nodes + kubernetes-nodes-rd components), and wire it into the
iaas bundle. Mirrors the vm-instance/vm-disk registration precedent.

Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
@github-actions github-actions Bot added area/uncategorized PR auto-labeler could not map title scope to a known area/*; please review kind/feature Categorizes issue or PR as related to a new feature size/XXL This PR changes 1000+ lines, ignoring generated files labels Jul 15, 2026
The preserve-old-KubevirtMachineTemplate block re-emitted any KMT owned
by the CAPI Cluster and referenced by a MachineSet. A kubernetes-nodes
pool's KMT lives in the same namespace under the same Cluster, so the
parent would re-emit it with a foreign meta.helm.sh/release-name and its
next upgrade would fail Helm ownership validation. Restrict the block to
KMTs whose release-name annotation matches the parent release.

Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
…reign pool names

Replace the collision-prone name-prefix match (pool 'gpu' matched
sibling 'gpu-large-<hash>') with a release-name annotation scope, and
add a render-time guard that fails cleanly when a pool's MachineDeployment
already exists under a different release (e.g. naming a pool after a
parent nodeGroup such as the default md0). Document the naming caveat in
NOTES.txt.

Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
The cluster field referenced x-cozystack-options source 'kubernetes',
which has no provider (cozystack-api returns NotFound), so the dashboard
dropdown 404s. Drop the annotation so the field is a plain text input;
a real provider listing Kubernetes CRs is a follow-up.

Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
…l to the parent

Restore the inline machineconfig comments (nameservers, GPU node labels)
inside the reconcile Job's data block so the applied TalosConfigTemplate
matches the parent's, avoiding drift on adoption.

Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Wire tests/render-parity.sh into the chart's test target so CI verifies
the pool objects stay byte-identical to the parent render.

Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8285ad91-012a-41bd-87b5-63c0f773e210

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/kubernetes-nodes-phase2a

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.

Reference the adoption migration by role (Phase 2b) instead of a number
that does not exist on this branch, and correct the NOTES operational-note
count.

Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
…arity

Extend the golden-parity matrix beyond the resources-sized pool to also
diff a GPU pool and a kubelet-override pool against the parent render, so
future drift in those branches (which would roll the content-hash-named
KubevirtMachineTemplate) is caught in CI.

Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/uncategorized PR auto-labeler could not map title scope to a known area/*; please review kind/feature Categorizes issue or PR as related to a new feature size/XXL This PR changes 1000+ lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant