Repository navigation
Migrate off the removed Talos MachineConfig.Kubelet / ClusterConfig.CoreDNS accessorsΒ #6776
Description
π€ Generated by the Agentic Engineer
Evidence
chore(deps): bump github.com/siderolabs/omni/client from 1.9.1 to 1.10.4 (#6724) has been red and conflicting since 2026-08-27. It is not a flaky or transient failure β the bump is structurally unmergeable as it stands.
go.mod on main holds both Talos modules at the same version:
github.com/siderolabs/talos v1.14.0-alpha.2
github.com/siderolabs/talos/pkg/machinery v1.14.0-alpha.2
omni/client v1.10.4 requires github.com/siderolabs/talos/pkg/machinery v1.14.0-beta.1 (read from its published go.mod on the module proxy), so the bump raises machinery alone and leaves the pair mismatched. beta.1 removed accessors that both KSail and talos v1.14.0-alpha.2 still call:
pkg/fsutil/configmanager/talos/configs.go:615 cp.Machine().Kubelet undefined
pkg/fsutil/configmanager/talos/configs.go:619 cp.Machine().Kubelet undefined
pkg/fsutil/configmanager/talos/version.go:223 machineCfg.Kubelet undefined
talos@v1.14.0-alpha.2/pkg/images/list.go:43 config.Cluster().CoreDNS undefined
talos@v1.14.0-alpha.2/pkg/images/list.go:45 config.Machine().Kubelet undefined
The last two are inside the pinned talos module itself, so the dependency graph is internally inconsistent β this cannot be fixed in KSail's code alone while talos stays at alpha.2.
Confirmed against machinery v1.14.0-rc.2: config.MachineConfig no longer declares Kubelet(), and CoreDNS survives only as K8sCoreDNSConfig in config/config/k8s.go. Upstream moved kubelet and CoreDNS settings out of the machine/cluster config into a separate K8s config document.
Problem and who it affects
Every omni/client bump is blocked behind this, so KSail silently stops receiving Omni updates β including security fixes. Renovate/Dependabot will keep reopening the bump and it will keep failing, which also burns CI on every attempt.
What needs to happen
Bump github.com/siderolabs/talos and github.com/siderolabs/talos/pkg/machinery together to a matched version (v1.14.0-rc.2 is the newest published pair), then migrate KSail's three call sites off the removed accessors onto the new K8s config document API.
Acceptance criteria
- Both Talos modules pinned to the same version in
go.mod. - The three call sites above read kubelet/CoreDNS settings through the new document API.
- The absent-document case is handled explicitly β a config with no K8s document must not silently read as "no kubelet configured" (this is the fail-open shape, not a nil check to wave through).
- Existing tests pass unmodified; behaviour is preserved.
- chore(deps): bump github.com/siderolabs/omni/client from 1.9.1 to 1.10.4Β #6724 (or its successor bump) goes green and merges.
Size
Medium. Three call sites, but the new accessor pattern and the absent-document semantics need to be understood first, so it is not a mechanical rename.
Blocker: loft-sh/vcluster k8s.io 0.37 compatibility | upstream | last-verified 2026-10-24: the old apiserver claim is superseded: the official Go proxy now selects loft-sh/apiserver v0.0.0-20261015114517-9c2b700ef6e6 with k8s.io/apiserver and client-go v0.37.1. The latest stable vcluster v0.37.4 still requires both at v0.36.0, leaving that integration prerequisite unmet.
Generated by Claude Code
Metadata
Metadata
Assignees
Labels
Type
Fields
Projects
- StatusShow more project fieldsπ§ Icebox
Activity
devantler commentedon Sep 1, 2026
Raising the priority signal on this: two open dependency PRs are now parked on this migration, and neither can build until it lands.
siderolabs/talos/pkg/machinerybumpBoth fail identically at the current head, with compile errors in
pkg/fsutil/configmanager/talos/version.goandconfigs.gonaming exactly the accessors this issue covers (machineCfg.Kubelet,cp.Machine().Kubelet,config.Cluster().CoreDNS). Verified against both heads on 2026-09-01.Worth noting for whoever picks this up: the failures present as 29 jobs all failing at a step called
π¦ Cache KSail Binary, which reads like one shared infrastructure flake. It is not β that step is where the binary is compiled. Only the job annotations reveal the real cause, so diagnose this class from annotations rather than from the failing step name.Neither PR was closed, because closing a Dependabot PR emits a persistent ignore for that release and would suppress the bump after this merges. Rebase both once this lands.
devantler commentedon Sep 1, 2026
Measured: this is blocked upstream, and the "three call sites" framing understates it
I attempted the migration end to end today (bumped both Talos modules to the matched pair
v1.14.0-rc.2, rango mod tidy, built). The three KSail call sites are real and small β but they are not what stops this landing.Every Talos version that removed the accessors also moves Kubernetes to 0.37
Read from the module proxy:
siderolabs/talosk8s.io/apiv1.14.0-alpha.2(current pin)v0.36.2v1.14.0-beta.0v0.37.0-beta.0v1.14.0-beta.1v0.37.0-beta.0v1.14.0-rc.1v0.37.0-rc.0v1.14.0-rc.2v0.37.0-rc.1The accessors were removed in the same line that jumps to Kubernetes 0.37, so the code migration and the whole-stack Kubernetes bump are inseparable.
machinery v1.14.0-alpha.2does not declareK8sKubeletConfig()/K8sCoreDNSConfig()at all (checked itsconfig/config/{config,k8s}.go), so there is also no forward-compatible rewrite that works against both pins.With the bump applied, two transitive dependencies stop compiling β one is fixable, one is not
go build ./...after the bump:k8s.io/cri-client v0.36.1β missingCheckpointPodforcri-api0.37. Fixable:v0.37.0-rc.1is published; bumping it clears these errors entirely (verified).github.com/loft-sh/apiserverβ not fixable by us:It reaches us as
ksail/pkg/svc/provisioner/cluster/vclusterβloft-sh/vcluster/pkg/cliβloft-sh/agentapi/v4βloft-sh/apiserver/pkg/builders. Its newest published revision isv0.0.0-20260707184419-aef558a5ae8d(2026-07-07), which pinsk8s.io/apiserver v0.36.0. Upgradingvclusterdoes not help: evenv0.37.0-rc.4still requires that exact sameloft-sh/apiserverrevision and still pinsk8s.io/apiserver v0.36.0.After bumping
cri-client,loft-sh/apiserveris the only remaining non-KSail wall β the conjunct is isolated.A hazard for whoever picks this up
The absent-document criterion above is sharper than it looks, and it is the same shape as the #5947 phantom-upgrade defence already documented in
detect_inplace.go.Old:
provider.Machine().Kubelet()returns nil when the config carries nomachine.kubeletsection, soKubernetesVersionFromProviderfalls through and returns"".New:
K8sKubeletConfig()returns a non-nil, defaulted&KubeletConfig{}in that case, and itsImage()yields the machinery's compiled-inKubeletImage:v<DefaultKubernetesVersion>. A literal!= nilport therefore makes the function report Talos's bundled default as if it were the cluster's running version β exactly the phantom worker kubelet upgradealignKubernetesVersionwas written to prevent. The new interface exposes no "was this document present" signal, so the guard has to be explicit.Effect on the blocked PRs
#6724, #6796 and #6813 all fail with the identical three-call-site compile errors and are parked on this issue. Size is not Medium; it is gated on an upstream release.
chore: agent-claim #6776 nonce=74d4df5e698bfc20759ff3aabef52a57
devantler commentedon Sep 2, 2026
Re-verified today against
talos/machinery v1.14.0-rc.2. The blocker is unchanged and stillcorrect, so this stays blocked β but the KSail-side work is now fully scoped, so it can be executed
directly once the upstream ships rather than re-investigated.
Verified accessor mapping (each confirmed present in
rc.2and absent from thealpha.2thatmainpins, which is why none of this can land ahead of the bump):cfg.Machine().Kubelet()cfg.K8sKubeletConfig()configmanager/talos/configs.go:615,619;version.go:243cfg.Cluster().Endpoint()cfg.K8sClusterConfig().ClusterEndpoint()provisioner/cluster/talos/detect_inplace.go:270,320,324;provisioner_hetzner.go:550,554;update.go:436,440,1206cfg.Cluster().IssuingCA()cfg.K8sAPIServerCAConfig().IssuingCA()detect_inplace.go:41312 sites total.
K8sKubeletConfigreturns the sameExtraArgs() map[string][]stringandImage() stringshape the oldKubeletinterface had, so the call sites change but their logic doesnot. I applied the 3 kubelet sites locally and confirmed those specific compile errors disappear;
the remaining 9 are a mechanical application of the same pattern.
Note the repository has already done this migration once for a sibling document β the
K8sAPIServerConfigcomment inversion.gorecords the same move forcluster.apiServerβ so thisfollows existing in-repo precedent rather than introducing a new pattern.
Also worth recording, because it changes the shape of the blocker: of the two Kubernetes 0.37
skews, only one is external.
k8s.io/cri-client@v0.36.1(missingCheckpointPod) is fixable βv0.37.0-rc.1exists andclears that error; verified locally.
loft-sh/apiserveris the only genuinely external half, and it is unmoved: newest publishedrevision is still
v0.0.0-20260707184419-aef558a5ae8d(2026-07-07), andloft-sh/vcluster v0.37.0-rc.4still requires exactly that revision.
Blocker: loft-sh/apiserver β needs a revision built against Kubernetes 0.37 apiserver | last-verified 2026-09-02: not shipped
devantler commentedon Sep 2, 2026
Blast radius is wider than the body records
The body cites
#6724(omni/client) as the affected bump. Measured today, this blocker strands every open dependency PR in KSail that pullsmachinerypastalpha.2β it is now the queue-level blocker, not a single-bump one:machinery#6826v1.14.0-rc.2#6845image-factory1.3.3 β 1.5.1v1.14.0-rc.2.0.20260825161121#6845is worth calling out because it is not a Talos bump by name βimage-factorydragsmachineryforward transitively, so this blocker is reached by bumps that never mention Talos.Both fail with a byte-identical error triple, read from their own build logs (
#6826job100032940941,#6845job100396113250):Only the first line is KSail's own code and in scope for the migration in this issue's acceptance criteria. The other two are the
loft-sh/apiserverblocker already recorded in the**Blocker:**line, which independently re-confirms it: the pinned revision still carries the 0.36 apiserver, so the KSail-side migration alone cannot turn these PRs green.No change to actionability
The
**Blocker:**line was re-verified today and remains accurate; this issue stays correctlyblocked. Recording the radius so a later run does not re-diagnose#6826/#6845from scratch, and so the priority of the upstream wait is visible.Note one detail for whoever picks this up: the blocker line records
k8s.io/cri-clientreaching a stablev0.37.0, but both PRs still resolvecri-client@v0.36.1, so that half has not actually moved in the built graph yet.devantler commentedon Sep 7, 2026
The migration is now a solved, measured quantity β only the upstream blocker (#6728) remains.
I carried this out end-to-end on #6826's head (talos + machinery
v1.14.0-rc.2) to find out whether anything here is actually hard. Nothing is: every call site is a receiver-preserving accessor move, and the whole thing builds.The complete mapping β 28 call sites, 11 files:
X.Machine().Kubelet()X.K8sKubeletConfig()X.Cluster().Endpoint()X.K8sClusterConfig().ClusterEndpoint()X.Cluster().IssuingCA()X.K8sAPIServerCAConfig().IssuingCA()All three land on the
Configinterface, the sameK8s*Configfamily the code already uses forK8sAPIServerConfig()andK8sFlannelCNIConfig(), so this finishes a migration that is already half-done.ExtraArgs()needs no work β it was already adapted tomap[string][]string.Two shapes simplify rather than just move:
IsKubeletCertRotationEnabledloses itscp.Machine() == nilguard, since the kubelet document is reached directly from the config.KubernetesVersionFromProviderloses a nesting level for the same reason.Measured result: with this migration applied and
k8s.io/cri-clientraised tov0.37.0-rc.1(published since this issue was filed β it clears theCheckpointPodmismatch),go build ./...leaves exactly one error, inloft-sh/apiserver. That is #6728, and it is not ours to fix.So the ordering is settled: this issue is mechanical and low-risk, but cannot land alone β the replacement accessors do not exist in the pinned
v1.14.0-alpha.2(verified against the module cache), so the change only compiles with the bump. It rides with whichever dependency PR lands once #6728 clears; it is not startable before then.devantler commentedon Sep 16, 2026
This migration provably cannot be done ahead of the bump
Worth stating plainly, because the issue title reads like ordinary prep work that could land on its own: it cannot. Verified directly against the module cache at the version
mainpins today (v1.14.0-alpha.2):MachineConfig.Kubelet()still exists βconfig/config/machine.go:35Config.K8sKubeletConfig()does not exist yet β 0 occurrences inconfig/config/config.go, against a control grep forMachine()in the same file returning 1, so the absence is a real absence and not a failed readSo at the pinned version there is nothing to migrate to, and the old accessor only disappears at the moment the bump lands. The accessor migration and the version bump have to be one change β either an agent-authored PR that does both, or an adaptation commit on the bump PR itself. Splitting them is not an option that exists.
Consolidating #6962 into this issue
#6962 describes the same root cause and the same three call sites. I am closing it as a duplicate of this issue (older, and broader β it also covers
ClusterConfig.CoreDNS). Its analysis is better in one respect, so it is preserved here:Diffing the
config/config/machine.gointerfaces across the window shows this is a relocation, not a rename, and that eight methods leftMachineConfig:Controlplane,Pods,Kubelet,Kernel,NodeLabels,NodeAnnotations,NodeTaints,BaseRuntimeSpecOverrides. The build only ever reportsKubeletbecause compilation stops at the first failure β the three-error list understates the work. Kubelet config now hangs off the root config asConfig.K8sKubeletConfig() K8sKubeletConfig.The true root blocker is #6728, not this issue
Live today on #6826 and #6845 (both re-created by Dependabot, both re-locked minutes later by
ksail-bot's module sync, both now parked),ποΈ Buildfails with an identical three-class error set:loft-sh/apiserverβ*DefaultStorageStrategy does not implement rest.RESTUpdateStrategy (wrong type for method AllowCreateOnUpdate)k8s.io/cri-client@v0.36.3β*remoteRuntimeService does not implement RuntimeService (missing method CheckpointPod)Classes 2 and 3 are the k8s 0.36/0.37 pin conflict tracked by #6728, and they cannot be fixed from this repository. Fixing the accessors alone will not make any talos bump green β #6728 gates the whole lane, and this issue is downstream of it.
Blocker re-verified 2026-09-16 β still real, unchanged
Re-checked via the Go module proxy (not the upstream repository):
loft-sh/apiserver@lateststill resolves tov0.0.0-20260903125814-2353e4b52582(2026-09-03) β no new revision since the last record β and its publishedgo.modstill requiresk8s.io/apiserver v0.36.0. Thereplace k8s.io/apiserver => github.com/loft-sh/k8s-apiserver v0.36.0-loft.0it carries is ignored by consumers, so it does not reach ksail.Blocker: loft-sh/apiserver β needs a revision built against Kubernetes 0.37 apiserver | upstream | last-verified 2026-09-16: not shipped (
@latest= v0.0.0-20260903125814-2353e4b52582, go.mod still requires k8s.io/apiserver v0.36.0); see ksail#6728 for the full pin conflictchore: agent-claim #6776 nonce=c9e98a297bb263ddbc8944bf82cfebdf