0004. Phase 1 creates three kinds, not seven

Status: Accepted · Date: 2026-10-25 · Design section: 4.1, 4.2, roadmap item 1

Decided: Phase 1 scaffolds only TalosCluster, TalosMachine and TalosConfigPatch, with no controllers yet

Context

The API table lists seven kinds. Roadmap item 1 asks for "CRDs and the kubebuilder project, Helm chart and Kustomize base, deletion protection, e2e scaffolding", without saying which kinds, and the phase ordering puts TalosEtcdBackup in phase 5, TalosOperation and IchorInstallation in phase 6 and TalosStorage in phase 7.

Creating a kind costs one kubebuilder create api call and is additive, so nothing is saved by creating all seven now. Guessing their fields is what costs: anything published in v1alpha1 has to keep working, and a field no code reads yet is a field whose shape nothing has tested.

Decision

Phase 1 creates the three kinds the next two phases actually work on — TalosCluster, TalosMachine, TalosConfigPatch — with --resource=true --controller=false, since reconcilers are phase 2. TalosStorage, TalosEtcdBackup, TalosOperation and IchorInstallation are created in the phase that gives them behaviour.

Within those three, phase 1 defines only the fields phases 1 to 3 need. Later phases add their own, which is backwards compatible within v1alpha1. Deferred for now: documents[] and defaultsRule (phase 2 and 3, see ADR 0003), disks[] / systemDiskLayout / forceRemove / upgradeHold (phase 3), cni and gitops (phase 4), upgradeStrategy (phase 6), monitoring / components[] / integrations[] (phase 9), images (phase 10).

Three field-level decisions that the design leaves open:

  • versionContract is required, not defaulted. Principle 4 pins the version contract in the CR so that a machinery bump cannot change what gets applied. If the field were optional and resolved at reconcile time, a bump would do exactly that. Requiring it needs no webhook; a defaulting webhook that fills it from talosVersion at creation can relax this later without breaking anyone.
  • TalosMachine.spec.nodeLabels, not labels. The design calls it labels; inside a spec that reads as "labels on this object", when what is meant is labels to put on the Kubernetes Node.
  • layer cannot be set to system. The system layer is generated by Ichor, so the enum offers cluster, role, selector and machine only, and the schema rejects the rest rather than a webhook having to.

Consequences

  • Phase 1 ships a small, complete API instead of a large, speculative one, and the chart's CRD set grows one kind at a time as the phases land.

  • A kind's fields get designed next to the code that reads them, so the acceptance criteria for each phase can actually check the shape.

  • The cost is that kubectl get crd won't show the full catalogue until phase 7. The API table in the design doc remains the place to see where it's going.

  • Update: IchorInstallation was created in phase 6 with ADR 0059.

Search the docs

Search pages and headings