feat: implement CAPI failure domain contract for zones#720
feat: implement CAPI failure domain contract for zones#720emanuelebosetti wants to merge 3 commits into
Conversation
|
Thanks! |
2350e2b to
37265c7
Compare
|
I've amended the commit to include the |
|
Thanks. No, we don't have any other policies. The field moves fast and we just didn't get to writing things down yet. |
We're going through the same process internally — introducing AI across dev teams and figuring out contribution policies. Three references we found particularly useful: Could be useful input for #716 as well. |
|
Hi @wikkyk , do you think it would be possible to include these failure domain changes in the upcoming v0.9.0 release? Happy to address any remaining feedback if needed. Thanks! |
|
Sure. v0.9.0 is still a fair bit far off, though. This only adds a field so it could reasonably be released in the 0.8 series. However, as the linter points out, the type of the |
Address review feedback (ionos-cloud#720): the field is optional with no validation, so kube-api-linter requires a pointer. Switch ProxmoxMachineSpec.FailureDomain to *string in v1alpha2 and regen deepcopy. Move the v1alpha2-only restore of FailureDomain into restoreProxmoxMachineSpec so both ProxmoxMachine and ProxmoxMachineTemplate ConvertTo paths preserve the field across the hub→spoke→hub roundtrip. The pointer change shifted the symptom from "" to nil and exposed the pre-existing missing restore on the Template path (TestFuzzyConversion/for_ProxmoxMachineTemplate/hub-spoke-hub). Validated end-to-end on a 10-node Proxmox test cluster: KCP rolled three fresh control plane Machines and both MachineDeployments rolled their workers through the failureDomain path (Machine.Spec.FailureDomain → ApplyFailureDomainNodes → IPAM zone scope → createVM) without errors. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
@wikkyk pushed the pointer fix as a separate commit. Could you re-trigger the workflows? Thanks! |
|
Don't worry about the test workflow 'failing', it just can't upload results to sonarqube. I'm happy with this PR, just rename |
4b68fd4 to
a1d0e00
Compare
|
Please rebase this PR on current main. |
Address review feedback (ionos-cloud#720): the field is optional with no validation, so kube-api-linter requires a pointer. Switch ProxmoxMachineSpec.FailureDomain to *string in v1alpha2 and regen deepcopy. Move the v1alpha2-only restore of FailureDomain into restoreProxmoxMachineSpec so both ProxmoxMachine and ProxmoxMachineTemplate ConvertTo paths preserve the field across the hub→spoke→hub roundtrip. The pointer change shifted the symptom from "" to nil and exposed the pre-existing missing restore on the Template path (TestFuzzyConversion/for_ProxmoxMachineTemplate/hub-spoke-hub). Validated end-to-end on a 10-node Proxmox test cluster: KCP rolled three fresh control plane Machines and both MachineDeployments rolled their workers through the failureDomain path (Machine.Spec.FailureDomain → ApplyFailureDomainNodes → IPAM zone scope → createVM) without errors. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1debab9 to
ee1d111
Compare
|
Hi @wikkyk |
Map existing CAPMOX zones to CAPI failure domains so that KubeadmControlPlane automatically distributes control plane nodes across Proxmox zones. API changes: - Add Nodes []string to ZoneConfigSpec for per-zone node lists - Add ControlPlane *bool to ZoneConfigSpec (defaults to true) - Add FailureDomains to ProxmoxClusterStatus (CAPI v1beta2 contract) - Add spec.failureDomain to ProxmoxMachineSpec (InfraMachine contract) - Add GetZoneNodes() helper on ProxmoxCluster - Add FailureDomainNotReady condition reason Controller changes: - Add reconcileFailureDomains in cluster controller (sorted by name) - Read Machine.Spec.FailureDomain in machine controller with retryable FailureDomainNotReady condition - Use effectiveZone/effectiveAllowedNodes on MachineScope to avoid spec mutation from the controller - Pass zone override to GetInClusterPools for IPAM pool selection - Set Zone on NodeLocation in createVM - Update scheduler to use GetEffectiveAllowedNodes() Conversion: - Restore Status.FailureDomains and Spec.FailureDomain in v1alpha1 conversion webhook - Add manual conversion stub for ProxmoxMachineSpec.FailureDomain Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Address review feedback (ionos-cloud#720): the field is optional with no validation, so kube-api-linter requires a pointer. Switch ProxmoxMachineSpec.FailureDomain to *string in v1alpha2 and regen deepcopy. Move the v1alpha2-only restore of FailureDomain into restoreProxmoxMachineSpec so both ProxmoxMachine and ProxmoxMachineTemplate ConvertTo paths preserve the field across the hub→spoke→hub roundtrip. The pointer change shifted the symptom from "" to nil and exposed the pre-existing missing restore on the Template path (TestFuzzyConversion/for_ProxmoxMachineTemplate/hub-spoke-hub). Validated end-to-end on a 10-node Proxmox test cluster: KCP rolled three fresh control plane Machines and both MachineDeployments rolled their workers through the failureDomain path (Machine.Spec.FailureDomain → ApplyFailureDomainNodes → IPAM zone scope → createVM) without errors. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ee1d111 to
d825a1a
Compare
|
Hi @wikkyk, rebased against 0.9.0 |
| Spec: ProxmoxClusterSpec{ | ||
| ZoneConfigs: []ZoneConfigSpec{ | ||
| { | ||
| Zone: ptr.To("zone-a"), |
There was a problem hiding this comment.
Incomplete port/rebase? ptr.To won't pass make verify. Use new instead.
| clusterv1.Convert_int32_To_Pointer_int32(src.NumSockets, ok, restored.NumSockets, &dst.NumSockets) | ||
| clusterv1.Convert_int32_To_Pointer_int32(src.MemoryMiB, ok, restored.MemoryMiB, &dst.MemoryMiB) | ||
|
|
||
| // Restore FailureDomain (v1alpha2-only field, set by CAPI machine controller). |
There was a problem hiding this comment.
This comment is somewhat superfluous.
| // Convert_v1alpha2_ProxmoxMachineSpec_To_v1alpha1_ProxmoxMachineSpec handles | ||
| // the lossy conversion of ProxmoxMachineSpec from v1alpha2 to v1alpha1. | ||
| // The FailureDomain field is intentionally dropped (it does not exist in v1alpha1 | ||
| // and is restored from annotation on ConvertTo). |
There was a problem hiding this comment.
This comment is extraneous.
| // Use effective allowed nodes (failure-domain override > machine spec > cluster spec). | ||
| allowedNodes := machineScope.GetEffectiveAllowedNodes() | ||
| if len(allowedNodes) == 0 { | ||
| allowedNodes = machineScope.InfraCluster.ProxmoxCluster.Spec.AllowedNodes |
There was a problem hiding this comment.
This comment now describes an implementation detail that might change in the future.
Also, the if(allowedNodes)==0 doesn't make much sense to me. GetEffectiveAllowedNodes either returns the effective nodes override or ProxmoxMachine.Spec.AllowedNodes, yet then when it's called, you also check InfraCluster.ProxmoxCluster.Spec.AllowedNodes. It feels like the implementation of GetEffectiveAllowedNodes is incomplete.
| // controlPlane indicates whether this zone is eligible for control plane machines. | ||
| // Defaults to true when not set. | ||
| // +optional | ||
| ControlPlane *bool `json:"controlPlane,omitempty"` |
There was a problem hiding this comment.
I really don't like the name of this field. Without reading the comment, I would've guessed that it indicates that it is a control plane, which doesn't make a lot of sense, leading to confusion. The name needs to be more explicit about what this field is and does.
There was a problem hiding this comment.
I like the idea but the implementation feels like an attempt at making the minimal change. It doesn't seem fully thought through. I don't like the implementation of GetEffectiveAllowedNodes and I don't like the way every place that touches something that can be overridden needs to check if it might be. It's easy to miss a call/usage site, particularly when merging new changes.
That's not to say that anything in this PR is very bad, the idea is sound and the implementation mostly is sound too. However, merging this as-is (even after applying the cosmetic changes) would increase the maintenance burden.
|
For example, this will conflict with #784. |
Issue: #717
Description of changes:
Map existing CAPMOX zones to CAPI failure domains so that KubeadmControlPlane automatically distributes control plane nodes across Proxmox zones.
API changes (additive, backwards-compatible):
Nodes []stringtoZoneConfigSpecfor per-zone node listsControlPlane *booltoZoneConfigSpec(defaults totrue)FailureDomainstoProxmoxClusterStatus(CAPI v1beta2 contract)spec.failureDomaintoProxmoxMachineSpec(InfraMachine contract)GetZoneNodes()helper onProxmoxClusterFailureDomainNotReadycondition reasonController changes:
reconcileFailureDomainsin cluster controller (sorted by name to prevent reconcile loops)Machine.Spec.FailureDomainin machine controller with retryableFailureDomainNotReadyconditioneffectiveZone/effectiveAllowedNodesonMachineScopeto avoid spec mutation from the controllerGetInClusterPoolsfor IPAM pool selectionZoneonNodeLocationincreateVMGetEffectiveAllowedNodes()Conversion:
Status.FailureDomainsandSpec.FailureDomainin v1alpha1 conversion webhookProxmoxMachineSpec.FailureDomainTesting performed:
make lint test verifypassedzoneConfigwork as before