Cluster API v1.10 compared to v1.11

This document provides an overview over relevant changes between Cluster API v1.10 and v1.11 for maintainers of providers and consumers of our Go API.

Any feedback or contributions to improve following documentation is welcome!

We also recommend to (re)read the Improving status in CAPI resources proposal because most of the changes described below are a consequence of the work for implementing this proposal.

Go version

  • The minimal Go version required to build Cluster API is v1.24.x
  • The Go version used by Cluster API is v1.24.x

Dependencies

  • The Controller Runtime version used by Cluster API is v0.21.x
  • The version of the Kubernetes libraries used by Cluster API is v1.33.x

API Changes

  • APIs have been moved to the top-level api folder (https://github.com/kubernetes-sigs/cluster-api/pull/12262). If you keep using v1alpha / v1beta1 APIs, imports have to be adjusted accordingly:
    • sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1 => sigs.k8s.io/cluster-api/api/bootstrap/kubeadm/v1beta1 (apiGroup: bootstrap.cluster.x-k8s.io)
    • sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta1 => sigs.k8s.io/cluster-api/api/controlplane/kubeadm/v1beta1 (apiGroup: controlplane.cluster.x-k8s.io)
    • sigs.k8s.io/cluster-api/api/v1beta1 => sigs.k8s.io/cluster-api/api/core/v1beta1 (apiGroup: cluster.x-k8s.io)
    • sigs.k8s.io/cluster-api/exp/api/v1beta1 => sigs.k8s.io/cluster-api/api/core/v1beta1 (apiGroup: cluster.x-k8s.io)
    • sigs.k8s.io/cluster-api/exp/ipam/api/v1alpha1 => sigs.k8s.io/cluster-api/api/ipam/v1alpha1 (apiGroup: ipam.cluster.x-k8s.io)
    • sigs.k8s.io/cluster-api/exp/ipam/api/v1beta1 => sigs.k8s.io/cluster-api/api/ipam/v1beta1 (apiGroup: ipam.cluster.x-k8s.io)
    • sigs.k8s.io/cluster-api/exp/runtime/api/v1alpha1 => sigs.k8s.io/cluster-api/api/runtime/v1alpha1 (apiGroup: runtime.cluster.x-k8s.io)
    • sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1 => sigs.k8s.io/cluster-api/api/runtime/hooks/v1alpha1 (apiGroup: hooks.runtime.cluster.x-k8s.io)
  • v1beta1 API version is now deprecated and it will be removed tentatively in August 2026
  • v1beta2 API version has been introduced; see following paragraphs for more details. The APIs have been added in the following packages:
    • sigs.k8s.io/cluster-api/api/bootstrap/kubeadm/v1beta2 (apiGroup: bootstrap.cluster.x-k8s.io)
    • sigs.k8s.io/cluster-api/api/controlplane/kubeadm/v1beta2 (apiGroup: controlplane.cluster.x-k8s.io)
    • sigs.k8s.io/cluster-api/api/addons/v1beta2 (apiGroup: addons.cluster.x-k8s.io)
    • sigs.k8s.io/cluster-api/api/core/v1beta2 (apiGroup: cluster.x-k8s.io)
    • sigs.k8s.io/cluster-api/api/ipam/v1beta2 (apiGroup: ipam.cluster.x-k8s.io)
    • sigs.k8s.io/cluster-api/api/runtime/v1beta2 (apiGroup: runtime.cluster.x-k8s.io)
  • If you are using the runtime.cluster.x-k8s.io API group, please be aware that
    • ExtensionConfig v1alpha1 has been deprecated, and it will be removed in a following release.
    • ExtensionConfig v1beta2 has been created (thus aligning with other Cluster API resources)
  • controllers/remote.ClusterCacheTracker and corresponding types have been removed
  • The unused ClusterStatus struct in the kubeadm bootstrap apiGroup has been removed

All CRDs

  • The transition to the new K8s aligned conditions using metav1.Conditions types and the new condition semantic has been completed for all Kinds:
    • status.conditions has been replaced with status.v1beta2.conditions based on metav1 condition types
    • the old status.conditions based on custom cluster API condition types will continue to exist temporarily under status.deprecated.v1beta1.conditions for the sake of down conversions and to provide a temporary option for users willing to continue using old conditions.
  • Please pay attention to field removals, e.g. if you are using GitOps tools, either migrate to v1beta2 or make sure to stop setting the removed fields. The removed fields won’t be preserved even if setting them via v1beta1 (as they don’t exist in v1beta2).
    • For example, we removed the clusterName field from KubeadmControlPlane.spec.kubeadmConfigSpec.clusterConfiguration

Cluster

  • See changes that apply to all CRDs
  • The spec.controlPlaneRef and spec.infrastructureRef fields are now using ContractVersionedObjectReference type instead of corev1.ObjectReference.
    • The following fields have been removed: namespace, uid, resourceVersion, fieldPath
    • apiVersion has been replaced with apiGroup. As before, the version will be read from the corresponding CRD.
  • The spec.topology.class field has been renamed to spec.topology.classRef.name
  • The spec.topology.classNamespace field has been renamed to spec.topology.classRef.namespace
  • The spec.topology.rolloutAfter field has been removed (the corresponding functionality was never implemented)
  • The definitionFrom field (deprecated since CAPI v1.8) has been removed from
    • spec.topology.variables
    • spec.topology.controlPlane.variables.overrides
    • spec.topology.workers.machineDeployments[].variables.overrides
    • spec.topology.workers.machinePools[].variables.overrides
  • The unhealthyConditions field has been renamed to unhealthyNodeConditions in following struct:
    • spec.topology.controlPlane.machineHealthCheck
    • spec.topology.workers.machineDeployments[].machineHealthCheck
  • All fields of type Duration in spec.topology.{controlPlane,workers.machineDeployments[],workers.machinePools[] have been renamed by adding the Seconds suffix and their type was changed to int32, thus aligning to K8s guidelines.
    • nodeDrainTimeout => nodeDrainTimeoutSeconds
    • nodeVolumeDetachTimeout => nodeVolumeDetachTimeoutSeconds
    • nodeDeletionTimeout => nodeDeletionTimeoutSeconds
  • All fields of type Duration in spec.topology.{controlPlane.machineHealthCheck,workers.machineDeployments[].machineHealthCheck have been renamed by adding the Seconds suffix and their type was changed to int32, thus aligning to K8s guidelines.
    • nodeStartupTimeout => nodeStartupTimeoutSeconds
    • unhealthyNodeConditions[].timeout => unhealthyNodeConditions[].timeoutSeconds
  • All the remediationTemplate fields have been migrated from type corev1.ObjectReference to MachineHealthCheckRemediationTemplateReference:
    • spec.topology.controlPlane.machineHealthCheck.remediationTemplate
    • spec.topology.workers.machineDeployments[].machineHealthCheck.remediationTemplate
    • For all the above, the following fields have been removed from remediationTemplate: namespace, uid, resourceVersion, fieldPath
  • Information about the initial provisioning process are now surfacing under the new status.initialization field.
    • status.infrastructureReady has been replaced by status.initialization.infrastructureProvisioned
    • status.controlPlaneReady has been replaced by status.initialization.controlPlaneInitialized
  • The .status.failureDomains field has been changed from a map to an array
  • New fields for replica counters have been added to the cluster object
    • status.controlPlane now reports replica counters surfaced from the control plane object.
    • status.workers now reports replica counters from MachineDeployments and standalone MachineSet and Machines
  • Support for terminal errors has been dropped.
    • status.failureReason and status.failureMessage will continue to exist temporarily under status.deprecated.v1beta1.
    • The const values for Failed phase has been deprecated in the enum type for status.phase (controllers are not setting this value anymore)
  • The GetIPFamily method (deprecated since CAPI v1.8) has been removed
  • The index.ByClusterClassName, index.ClusterByClusterClassClassName and index.ClusterClassNameField types have been removed in favor of index.ByClusterClassRef, index.ClusterByClusterClassRef and index.ClusterClassRefPath

MachineDeployment

  • See changes that apply to all CRDs
  • The spec.template.spec.bootstrap.configRef and spec.template.spec.infrastructureRef fields are now using ContractVersionedObjectReference type instead of corev1.ObjectReference.
    • The following fields have been removed: namespace, uid, resourceVersion, fieldPath
    • apiVersion has been replaced with apiGroup. As before, the version will be read from the corresponding CRD.
  • The spec.progressDeadlineSeconds field (deprecated since CAPI v1.9) has been removed
  • All fields of type Duration in spec.template.spec have been renamed by adding the Seconds suffix and their type was changed to int32, thus aligning to K8s guidelines.
    • nodeDrainTimeout => nodeDrainTimeoutSeconds
    • nodeVolumeDetachTimeout => nodeVolumeDetachTimeoutSeconds
    • nodeDeletionTimeout => nodeDeletionTimeoutSeconds
  • Replica counters are now consistent with replica counters from other resources
    • status.replicas was made a pointer and omitempty was added
    • status.readyReplicas has now a new semantic based on machine’s Ready condition
    • status.availableReplicas has now a new semantic based on machine’s Available condition
    • status.upToDateReplicas has now a new semantic (and name) based on machine’s UpToDate condition
    • Temporarily, old replica counters will still be available under the status.deprecated.v1beta1 struct
  • Support for terminal errors has been dropped.
    • status.failureReason and status.failureMessage will continue to exist temporarily under status.deprecated.v1beta1.
    • The const values for Failed phase has been deprecated in the enum type for status.phase (controllers are not setting this value anymore)
  • The status.phases field is now computed using the same logic used for ScalingUp and ScalingDown conditions.
  • The spec.revisionHistoryLimit field has been removed. The MachineDeployment controller will now clean up all MachineSets without replicas.
    • The corresponding machinedeployment.clusters.x-k8s.io/revision-history annotation has also been removed.

MachineSet

  • See changes that apply to all CRDs
  • The spec.template.spec.bootstrap.configRef and spec.template.spec.infrastructureRef fields are now using ContractVersionedObjectReference type instead of corev1.ObjectReference.
    • The following fields have been removed: namespace, uid, resourceVersion, fieldPath
    • apiVersion has been replaced with apiGroup. As before, the version will be read from the corresponding CRD.
  • All fields of type Duration in spec.template.spec have been renamed by adding the Seconds suffix and their type was changed to int32, thus aligning to K8s guidelines.
    • nodeDrainTimeout => nodeDrainTimeoutSeconds
    • nodeVolumeDetachTimeout => nodeVolumeDetachTimeoutSeconds
    • nodeDeletionTimeout => nodeDeletionTimeoutSeconds
  • Replica counters fields are now consistent with replica counters from other resources
    • status.replicas was made a pointer and omitempty was added
    • status.readyReplicas has now a new semantic based on machine’s Ready condition
    • status.availableReplicas has now a new semantic based on machine’s Available condition
    • status.upToDateReplicas has now a new semantic (and name) based on machine’s UpToDate condition
    • Temporarily, old replica counters will still be available under the status.deprecated.v1beta1 struct
  • Support for terminal errors has been dropped.
    • status.failureReason and status.failureMessage will continue to exist temporarily under status.deprecated.v1beta1.

MachinePool

  • See changes that apply to all CRDs
  • The spec.template.spec.bootstrap.configRef and spec.template.spec.infrastructureRef fields are now using ContractVersionedObjectReference type instead of corev1.ObjectReference.
    • The following fields have been removed: namespace, uid, resourceVersion, fieldPath
    • apiVersion has been replaced with apiGroup. As before, the version will be read from the corresponding CRD.
  • All fields of type Duration in spec.template.spec have been renamed by adding the Seconds suffix and their type was changed to int32, thus aligning to K8s guidelines.
    • nodeDrainTimeout => nodeDrainTimeoutSeconds
    • nodeVolumeDetachTimeout => nodeVolumeDetachTimeoutSeconds
    • nodeDeletionTimeout => nodeDeletionTimeoutSeconds
  • status.replicas was made a pointer and omitempty was added
  • Support for terminal errors has been dropped.
    • status.failureReason and status.failureMessage will continue to exist temporarily under status.deprecated.v1beta1.
    • The const values for Failed phase has been deprecated in the enum type for status.phase (controllers are not setting this value anymore)

Machine

  • See changes that apply to all CRDs
  • The spec.bootstrap.configRef and spec.infrastructureRef fields are now using ContractVersionedObjectReference type instead of corev1.ObjectReference.
    • The following fields have been removed: namespace, uid, resourceVersion, fieldPath
    • apiVersion has been replaced with apiGroup. As before, the version will be read from the corresponding CRD.
  • All fields of type Duration in spec have been renamed by adding the Seconds suffix and their type was changed to int32, thus aligning to K8s guidelines.
    • nodeDrainTimeout => nodeDrainTimeoutSeconds
    • nodeVolumeDetachTimeout => nodeVolumeDetachTimeoutSeconds
    • nodeDeletionTimeout => nodeDeletionTimeoutSeconds
  • Information about the initial provisioning process is now surfacing under the new status.initialization field.
    • status.infrastructureReady has been replaced by status.initialization.infrastructureProvisioned
    • status.bootstrapReady has been replaced by status.initialization.bootstrapDataSecretCreated
  • Support for terminal errors has been dropped.
    • status.failureReason and status.failureMessage will continue to exist temporarily under status.deprecated.v1beta1.
    • The const values for Failed phase has been deprecated in the enum type for status.phase (controllers are not setting this value anymore)
  • The type of the status.nodeRef field has been changed from corev1.ObjectReference to MachineNodeReference.
    • The following fields have been removed from status.nodeRef: kind, namespace, uid, apiVersion, resourceVersion, fieldPath

MachineHealthCheck

  • See changes that apply to all CRDs
  • All fields of type Duration in spec have been renamed by adding the Seconds suffix and their type was changed to int32, thus aligning to K8s guidelines.
    • nodeStartupTimeout => nodeStartupTimeoutSeconds
  • All fields of type Duration in spec.unhealthyNodeConditions[] have been renamed by adding the Seconds suffix and their type was changed to int32, thus aligning to K8s guidelines.
    • timeout => timeoutSeconds
  • The spec.unhealthyConditions field has been renamed to spec.unhealthyNodeConditions
  • The spec.remediationTemplate field has been migrated from type corev1.ObjectReference to MachineHealthCheckRemediationTemplateReference:
    • The following fields have been removed from remediationTemplate: namespace, uid, resourceVersion, fieldPath

ClusterClass

  • See changes that apply to all CRDs
  • The spec.patches[].external.generateExtension and spec.patches[].external.validateExtension fields have been renamed to spec.patches[].external.generatePatchesExtension and spec.patches[].external.validateTopologyExtension
  • The unhealthyConditions field has been renamed to unhealthyNodeConditions in following struct:
    • spec.controlPlane.machineHealthCheck
    • spec.workers.machineDeployments[].machineHealthCheck
  • The spec.variables[].metadata and .status.variables[].definitions[].metadata fields have been renamed to spec.variables[].deprecatedV1Beta1Metadata and .status.variables[].definitions[].deprecatedV1Beta1Metadata
    • These fields are deprecated and will be removed when support for v1beta1 will be dropped.
    • Please use XMetadata in JSONSchemaProps instead.
  • All fields of type Duration in spec.{controlPlane,workers.machineDeployments[],workers.machinePools[] have been renamed by adding the Seconds suffix and their type was changed to int32, thus aligning to K8s guidelines.
    • nodeDrainTimeout => nodeDrainTimeoutSeconds
    • nodeVolumeDetachTimeout => nodeVolumeDetachTimeoutSeconds
    • nodeDeletionTimeout => nodeDeletionTimeoutSeconds
  • All fields of type Duration in spec.controlPlane.machineHealthCheck and spec.workers.machineDeployments[].machineHealthCheck have been renamed by adding the Seconds suffix and their type was changed to int32, thus aligning to K8s guidelines.
    • nodeStartupTimeout => nodeStartupTimeoutSeconds
    • unhealthyNodeConditions[].timeout => unhealthyNodeConditions[].timeoutSeconds
  • All the fields implementing or embedding a reference to a template are now using the ClusterClassTemplate type instead of corev1.ObjectReference:
    • spec.infrastructure
    • spec.controlPlane and spec.controlPlane.machineInfrastructure
    • spec.workers.machineDeployments[].template.bootstrap and spec.workers.machineDeployments[].template.infrastructure
    • spec.workers.machinePool[].template.bootstrap and spec.workers.machinePool[].template.infrastructure
    • For all the above, the following fields have been removed from *.ref: namespace, uid, resourceVersion, fieldPath
  • All the remediationTemplate fields have been migrated from type corev1.ObjectReference to MachineHealthCheckRemediationTemplateReference:
    • spec.controlPlane.machineHealthCheck.remediationTemplate
    • spec.workers.machineDeployments[].machineHealthCheck.remediationTemplate
    • For all the above, the following fields have been removed from remediationTemplate: namespace, uid, resourceVersion, fieldPath
  • The builtin.cluster.classRef.Name and builtin.cluster.classRef.Namespace variables have been added
    • The builtin.cluster.class and builtin.cluster.classNamespace are deprecated and will be removed with the next apiVersion.
  • The builtin.cluster.network.ipFamily variable has been removed and it cannot be used anymore in patches

KubeadmConfig

  • KubeadmConfig (and the entire CABPK provider) now implements the v1beta2 Cluster API contract.
  • See changes that apply to all CRDs
  • ExtraArg field types have been changed from map[string]sting to []Arg, thus aligning with kubeadm v1beta4 API; however, using multiple args with the same name will be enabled only when v1beta1 is removed, tentatively in August 2026
    • spec.clusterConfiguration.apiServer.extraArgs type has been changed to []Arg
    • spec.clusterConfiguration.controllerManager.extraArgs type has been changed to []Arg
    • spec.clusterConfiguration.scheduler.extraArgs type has been changed to []Arg
    • spec.clusterConfiguration.etcd.local.extraArgs type has been changed to []Arg
    • spec.initConfiguration.nodeRegistration.kubeletExtraArgs type has been changed to []Arg
    • spec.joinConfiguration.nodeRegistration.kubeletExtraArgs type has been changed to []Arg
  • ImagePullPolicy field types have been changed from string to corev1.PullPolicy, thus aligning with kubeadm v1beta4 API
    • spec.initConfiguration.nodeRegistration.imagePullPolicy type has been changed to corev1.PullPolicy
    • spec.joinConfiguration.nodeRegistration.imagePullPolicy type has been changed to corev1.PullPolicy
  • Timeout fields have been aligned with kubeadm v1beta4 API, but field names and types have been adapted according to API guidelines.
    • spec.initConfiguration.timeouts struct has been added with the following fields:
      • controlPlaneComponentHealthCheckSeconds
      • kubeletHealthCheckSeconds
      • kubernetesAPICallSeconds
      • etcdAPICallSeconds
      • tlsBootstrapSeconds
      • discoverySeconds
    • spec.joinConfiguration.timeouts field has been added with the same set of timeouts listed above.
    • spec.clusterConfiguration.apiServer.timeoutForControlPlane field has been removed. Use spec.initConfiguration.timeouts.controlPlaneComponentHealthCheckSeconds and spec.joinConfiguration.timeouts.controlPlaneComponentHealthCheckSeconds instead; however, using different timeouts for init and join will be enabled only when v1beta1 is removed.
    • spec.joinConfiguration.discovery.timeout field has been removed. Use spec.joinConfiguration.timeouts.tlsBootstrapSeconds instead.
  • The spec.useExperimentalRetryJoin field (deprecated in CAPI v1.2!) has been removed.
  • The following spec fields have been removed because they are not necessary (Cluster API automatically applies the right gvk when generating kubeadm config files):
    • clusterConfiguration.apiVersion, clusterConfiguration.kind
    • initConfiguration.apiVersion, initConfiguration.kind
    • joinConfiguration.apiVersion, joinConfiguration.kind
  • The following spec.clusterConfiguration fields have been removed because they are duplicates to fields that already exist in the Cluster object:
    • networking.serviceSubnet (can still be set via Cluster.spec.clusterNetwork.services.cidrBlocks)
    • networking.podSubnet (can still be set via Cluster.spec.clusterNetwork.pods.cidrBlocks)
    • networking.dnsDomain (can still be set via Cluster.spec.clusterNetwork.serviceDomain)
    • kubernetesVersion (can still be set via Machine.spec.version)
    • clusterName (can still be set via Cluster.metadata.name) Note: The ClusterConfiguration fields could previously be used to overwrite the fields from Cluster, now we only use the fields from Cluster.
  • All fields of type Duration in spec.initConfiguration.bootstrapTokens[] have been renamed by adding the Seconds suffix and their type was changed to int32, thus aligning to K8s guidelines.
    • .ttl => .ttlSeconds
  • Information about the initial provisioning process is now surfacing under the new status.initialization field.
    • status.ready has been replaced by status.initialization.dataSecretCreated
  • Support for terminal errors has been dropped (see dataSecretCreated).
    • status.failureReason and status.failureMessage will continue to exist temporarily under status.deprecated.v1beta1.

KubeadmConfigTemplate

KubeadmConfigTemplate spec.template.spec has been aligned to changes in the KubeadmConfig spec struct.

KubeadmControlPlane

  • KubeadmControlPlane (and the entire KCP provider) now implements the v1beta2 Cluster API contract.
  • See changes that apply to all CRDs
  • The spec.machineTemplate.infrastructureRef field is now using ContractVersionedObjectReference type instead of corev1.ObjectReference.
    • The following fields have been removed: namespace, uid, resourceVersion, fieldPath
    • apiVersion has been replaced with apiGroup. As before, the version will be read from the corresponding CRD.
  • ExtraArg field types have been changed from map[string]sting to []Arg, thus aligning with kubeadm v1beta4 API; however, using multiple args with the same name will be enabled only when v1beta1 is removed, tentatively in August 2026
    • spec.kubeadmConfigSpec.clusterConfiguration.apiServer.extraArgs type has been changed to []Arg
    • spec.kubeadmConfigSpec.clusterConfiguration.controllerManager.extraArgs type has been changed to []Arg
    • spec.kubeadmConfigSpec.clusterConfiguration.scheduler.extraArgs type has been changed to []Arg
    • spec.kubeadmConfigSpec.clusterConfiguration.etcd.local.extraArgs type has been changed to []Arg
    • spec.kubeadmConfigSpec.initConfiguration.nodeRegistration.kubeletExtraArgs type has been changed to []Arg
    • spec.kubeadmConfigSpec.joinConfiguration.nodeRegistration.kubeletExtraArgs type has been changed to []Arg
  • ImagePullPolicy field types have been changed from string to corev1.PullPolicy, thus aligning with kubeadm v1beta4 API
    • spec.kubeadmConfigSpec.initConfiguration.nodeRegistration.imagePullPolicy type has been changed to corev1.PullPolicy
    • spec.kubeadmConfigSpec.joinConfiguration.nodeRegistration.imagePullPolicy type has been changed to corev1.PullPolicy
  • Timeout fields have been aligned with kubeadm v1beta4 API, but field names and types have been adapted according to API guidelines.
    • spec.kubeadmConfigSpec.initConfiguration.timeouts struct has been added with the following fields:
      • controlPlaneComponentHealthCheckSeconds
      • kubeletHealthCheckSeconds
      • kubernetesAPICallSeconds
      • etcdAPICallSeconds
      • tlsBootstrapSeconds
      • discoverySeconds
    • spec.kubeadmConfigSpec.joinConfiguration.timeouts field has been added with the same set of timeouts listed above.
    • spec.kubeadmConfigSpec.clusterConfiguration.apiServer.timeoutForControlPlane field has been removed. Use spec.kubeadmConfigSpec.initConfiguration.timeouts.controlPlaneComponentHealthCheckSeconds and spec.kubeadmConfigSpec.joinConfiguration.timeouts.controlPlaneComponentHealthCheckSeconds instead; however, using different timeouts for init and join will be enabled only when v1beta1 is removed.
    • spec.kubeadmConfigSpec.joinConfiguration.discovery.timeout field has been removed. Use spec.kubeadmConfigSpec.joinConfiguration.timeouts.tlsBootstrapSeconds instead.
  • The spec.kubeadmConfigSpec.useExperimentalRetryJoin field (deprecated in CAPI v1.2!) has been removed.
  • The following spec.kubeadmConfigSpec fields have been removed because they are not necessary (Cluster API automatically applies the right gvk when generating kubeadm config files):
    • clusterConfiguration.apiVersion, clusterConfiguration.kind
    • initConfiguration.apiVersion, initConfiguration.kind
    • joinConfiguration.apiVersion, joinConfiguration.kind
  • The following spec.kubeadmConfigSpec.clusterConfiguration fields have been removed because they are duplicates to fields that already exist in the Cluster object:
    • networking.serviceSubnet (can still be set via Cluster.spec.clusterNetwork.services.cidrBlocks)
    • networking.podSubnet (can still be set via Cluster.spec.clusterNetwork.pods.cidrBlocks)
    • networking.dnsDomain (can still be set via Cluster.spec.clusterNetwork.serviceDomain)
    • kubernetesVersion (can still be set via KubeadmControlPlane.spec.version)
    • clusterName (can still be set via Cluster.metadata.name) Note: The ClusterConfiguration fields could previously be used to overwrite the fields from Cluster, now we only use the fields from Cluster.
  • All fields of type Duration in spec.kubeadmConfigSpec.initConfiguration.bootstrapTokens[] have been renamed by adding the Seconds suffix and their type was changed to int32, thus aligning to K8s guidelines.
    • .ttl => .ttlSeconds
  • All fields of type Duration in spec.machineTemplate have been renamed by adding the Seconds suffix and their type was changed to int32, thus aligning to K8s guidelines.
    • nodeDrainTimeout => nodeDrainTimeoutSeconds
    • nodeVolumeDetachTimeout => nodeVolumeDetachTimeoutSeconds
    • nodeDeletionTimeout => nodeDeletionTimeoutSeconds
  • All fields of type Duration in spec.remediationStrategy have been renamed by adding the Seconds suffix and their type was changed to int32, thus aligning to K8s guidelines.
    • retryPeriod => retryPeriodSeconds
    • minHealthyPeriod => minHealthyPeriodSeconds
  • Replica counters fields are now consistent with replica counters from other resources.
    • status.replicas was made a pointer and omitempty was added
    • status.readyReplicas has now a new semantic based on machine’s Ready condition
    • status.availableReplicas has now a new semantic based on machine’s Available condition
    • status.upToDateReplicas has now a new semantic (and name) based on machine’s UpToDate condition
    • Temporarily, old replica counters will still be available under the status.deprecated.v1beta1 struct
  • Information about the initial provisioning process is now surfacing under the new status.initialization field.
    • status.ready has been dropped
    • status.initialized has been replaced by status.initialization.controlPlaneInitialized
  • Support for terminal errors has been dropped.
    • status.failureReason and status.failureMessage will continue to exist temporarily under status.deprecated.v1beta1.

KubeadmControlPlaneTemplate

KubeadmControlPlaneTemplate spec.template.spec has been aligned to changes in the KubeadmControlPlane spec struct.

ClusterResourceSetBinding

  • Remove deprecated ClusterResourceSetBinding.DeleteBinding func

IPAddress

  • The type of the spec.claimRef field has been changed from corev1.LocalObjectReference to IPAddressClaimReference.
  • The type of the spec.poolRef field has been changed from corev1.TypedLocalObjectReference to IPPoolReference.
    • The type of the spec.poolRef.apiGroup field has been changed from *string to string.

IPAddressClaim

  • The type of the spec.poolRef field has been changed from corev1.TypedLocalObjectReference to IPPoolReference.
    • The type of the spec.poolRef.apiGroup field has been changed from *string to string.
  • The type of the status.addressRef field has been changed from corev1.LocalObjectReference to IPAddressReference.

Cluster API Contract changes

  • v1beta1 version of the Cluster API contract is now deprecated

    • In order to ease the transition to the new v1beta2 version of the Cluster API contract, v1beta2 version will implement temporarily compatibility with the deprecated v1beta1 version of the Cluster API contract
      • Compatibility is only intended to ease the transition for providers, and it has some limitations; please read details in following paragraphs.
    • Compatibility support for the v1beta1 version of the Cluster API contract will be removed tentatively in August 2026
    • After compatibility support for the v1beta1 version of the Cluster API contract is removed, providers which are implementing the v1beta1 contract will stop to work (they will work only with older versions of Cluster API).
  • v1beta2 version of the Cluster API contract has been introduced; see following paragraphs for more details

Contract rules for InfraCluster

Following rules have been changed or are not supported anymore; please read corresponding notes about compatibility for providers still implementing the v1beta1 contract.

Contract rules for InfraMachine

Following rules have been changed or are not supported anymore; please read corresponding notes about compatibility for providers still implementing the v1beta1 contract.

  • InfraMachine: provider ID
    • Type of the spec.providerID field was changed from *string to string.
  • InfraMachine: initialization completed
  • InfraMachine: conditions
    • The fact that Providers are not required to implement conditions remains valid
    • In case a provider implements conditions, Cluster API doesn’t require anymore usage of a specific condition type, even if transition to metav1.Conditions is highly recommended.
  • InfraMachine: terminal failures
    • The Machine controller won’t consider the presence of status.failureReason and status.failureMessage info as “terminal failures”
    • MachineHealthCheck controller won’t consider the presence of status.failureReason and status.failureMessage to determine when a Machine needs remediation.

Contract rules for BootstrapConfig

Following rules have been changed or are not supported anymore; please read corresponding notes about compatibility for providers still implementing the v1beta1 contract.

  • BootstrapConfig: initialization completed
  • BootstrapConfig: data secret
    • Type of the status.dataSecretName field was changed from *string to string.
  • BootstrapConfig: conditions
    • The fact that Providers are not required to implement conditions remains valid
    • In case a provider implements conditions, Cluster API doesn’t require anymore usage of a specific condition type, even if transition to metav1.Conditions is highly recommended.
  • BootstrapConfig: terminal failures
    • The Machine controller won’t consider the presence of status.failureReason and status.failureMessage info as “terminal failures”
    • MachineHealthCheck controller won’t consider the presence of status.failureReason and status.failureMessage to determine when a Machine needs remediation.

Contract rules for ControlPlane

Following rules have been changed or are not supported anymore; please read corresponding notes about compatibility for providers still implementing the v1beta1 contract.

Contract rules for IPAM provider

TODO

Contract rules for MachinePool

TODO

clusterctl

  • Stricter validation for provider metadata: clusterctl now enforces validation rules when reading provider metadata files to ensure they are properly formatted and contain required information. These changes help surface mis-shaped metadata early and make failures easier to troubleshoot. Providers with invalid metadata.yaml files will need to update them to comply with these validation rules. The following validation rules are now enforced:
    • apiVersion must be set to clusterctl.cluster.x-k8s.io/v1alpha3
    • kind must be set to Metadata
    • releaseSeries must contain at least one entry
  • The --v1beta2 flag in clusterctl describe now defaults to true; the flag will be removed as soon as v1beta1 API is removed.

Deprecations

  • v1beta1 API version is deprecated and it will be removed tentatively in August 2026

    • All the fields under status.deprecated.v1beta1 in the new v1beta2 API are deprecated and whey will be removed. This includes:
      • status.deprecated.v1beta1.conditions based on custom cluster API condition types
      • status.deprecated.v1beta1.failureReason
      • status.deprecated.v1beta1.failureMessage
      • status.deprecated.v1beta1.readyReplicas with old semantic for MachineDeployments, MachineSet and KubeadmControlPlane
      • status.deprecated.v1beta1.availableReplicas with old semantic for MachineDeployments, MachineSet
      • status.deprecated.v1beta1.unavailableReplicas with old semantic for MachineDeployments, KubeadmControlPlane
      • status.deprecated.v1beta1.updatedReplicas with old semantic (and name) for MachineDeployments, KubeadmControlPlane
      • status.deprecated.v1beta1.fullyLabeledReplicas for MachineSet
  • v1beta1 conditions utils are now deprecated, and will removed as soon as v1beta1 API will be removed

  • v1beta1 support in the patch helper is now deprecated, and will removed as soon as v1beta1 API will be removed

  • As a consequence of dropping support for terminal errors from all Kinds, the const values for Failed phase has been deprecated in the following enum types (controllers are not setting this value anymore):

    • ClusterPhase, used in cluster.status.phase
    • MachineDeploymentPhase, used in machineDeployment.status.phase
    • MachinePoolPhase, used in machinePool.status.phase
    • MachinePhase, used in machine.status.phase

clusterctl changes

  • The clusterctl alpha rollout undo command has been removed as the corresponding revision history feature has been removed from MachineDeployment

Removals scheduled for future releases

As documented in Suggested changes for providers, it is highly recommended to start planning for future removals:

  • v1beta1 API version will be removed tentatively in August 2026
  • Starting from the CAPI release when v1beta1 removal will happen (tentative Aug 2026), the Cluster API project will remove the Cluster API condition type, the util/conditions/deprecated/v1beta1 package, the util/deprecated/v1beta1 package, the code handling old conditions in util/patch.Helper and everything related to the custom Cluster API custom condition type.
  • Compatibility support for the v1beta1 version of the Cluster API contract will be removed tentatively in August 2026

Suggested changes for providers

  • We highly recommend providers to start using Cluster API v1beta2 types when bumping to CAPI v1.11. This requires changing following import:

    import (
        ...
        clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta1"
    )
    

    into:

    import (
        ...
        clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta2"
    )
    

    Please refer to API Changes for more details about the changes introduced by this release.

    Note: it is technically possible for providers to keep using v1beta1 types from CAPI v1.11, but this is not recommended because it will lead to additional conversion calls.

    Additionally, in v1.11 all the CAPI utils like e.g. IsControlPlaneMachine are now using v1beta2 API types. This might lead to additional work for providers to keep using v1beta1 types from CAPI v1.11 (you have to fork all utils the provider is using from an older CAPI release or replace them with something else).

    Last but not least, please be aware that given the issues above, this approach was not tested during the implementation, and we don’t know if there are road blockers.

  • If providers are using Conditions from Cluster API resources, e.g. by looking at the ControlPlaneInitialized condition on the Cluster object, we highly recommend providers to use new conditions instead of old ones. Utils for working with new conditions ara available in the sigs.k8s.io/cluster-api/util/conditions package.

    • To keep using old conditions from the Cluster object, temporarily present under status.deprecated.v1beta1.conditions it is required to use utils from the util/conditions/deprecated/v1beta1 package. Please note that status.deprecated.v1beta1.conditions will be removed tentatively in August 2026.
  • We highly recommend providers to start planning the move to the new v1beta2 version of the Cluster API contract for their own resources, e.g. in the AWSCluster or the AWSMachine resource; the transition MUST be completed before compatibility support for the v1beta1 version of the Cluster API contract will be removed tentatively in August 2026

  • Depending on which Cluster API contract version you are choosing to implement in the provider’s own CRDs, please refer to:

  • We highly recommend providers to define their future strategy for condition management for their own resources, e.g. in the AWSCluster or the AWSMachine resource; also in this case the transition to the new condition management strategy MUST be completed before compatibility support for the v1beta1 version of the Cluster API contract will be removed tentatively in August 2026. Available options are:

    • Migrate to metav1.Conditions like Cluster API (recommended)
    • Replace Cluster API’s v1beta1 Conditions with a custom condition implementation that is compliant with what is required by the v1beta2 Cluster API contract.
      • Starting from the CAPI release when v1beta1 removal will happen (tentative August 2026), the Cluster API project will remove the Cluster API condition type, the util/conditions/deprecated/v1beta1 package, the util/deprecated/v1beta1 package, the code handling old conditions in util/patch.Helper and everything related to the custom Cluster API custom condition type.
  • Depending on which option you are choosing for condition management in the provider’s own CRDs, please refer to:

  • References on Cluster, KubeadmControlPlane, MachineDeployment, MachinePool, MachineSet and Machine are now using the ContractVersionedObjectReference type instead of corev1.ObjectReference. These references can now be resolved with external.GetObjectFromContractVersionedRef instead of external.Get:

    external.GetObjectFromContractVersionedRef(ctx, r.Client, cluster.Spec.InfrastructureRef, cluster.Namespace)
    
  • core Cluster API added the new CRD migrator component in the v1.9 release. For more details, see: https://github.com/kubernetes-sigs/cluster-api/issues/11894

    • CRD migration in clusterctl has been deprecated and will be removed in CAPI v1.13, so it’s recommended to adopt the CRD migrator in providers instead.
    • Please see the examples in https://github.com/kubernetes-sigs/cluster-api/pull/11889, the following high-level steps are required:
      • Add the --skip-crd-migration-phases command-line flag that allows to skip CRD migration phases
      • Setup the CRDMigrator component with the manager.
      • Configure all CRDs owned by your provider, only set UseCache for the objects for which your provider already has an informer.
      • Add the following RBAC:
      • resources: customresourcedefinitions, verbs: get;list;watch
      • resources: customresourcedefinitions;customresourcedefinitions/status, resourceNames: <crd-name>, verbs: update;patch
        • Note: The CRD migrator will add the crd-migration.cluster.x-k8s.io/observed-generation annotation on the CRD object, please ensure that if these CRD objects are deployed with a tool like kapp / Argo / Flux the annotation is not continuously removed.
      • For all CRs that should be migrated by the CRDMigrator: verbs: get;list;watch;patch;update
      • For all CRs with UseStatusForStorageVersionMigration: true verbs: update;patch on their /status resource (e.g. ipaddressclaims/status)

How to bump to CAPI V1.11 but keep implementing the deprecated v1beta1 contract

CAPI v1.11 implements the v1beta2 version of the Cluster API contract.

However, in order to ease the transition for providers, the v1beta2 version of the Cluster API contract temporarily preserves compatibility with the deprecated v1beta1 contract; a few limitations apply, please read Cluster API Contract changes for more details.

Provider’s implementing the deprecated v1beta1 contract can leverage compatibility support without any change, but it is crucial for them to start planning for the implementation of the new v1beta2 version of the Cluster API contract as soon a possible.

The implementation of the new v1beta2 version of the Cluster API contract MUST be completed before compatibility support for the v1beta1 version of the Cluster API contract will be removed tentatively in August 2026.

After compatibility support for the v1beta1 version of the Cluster API contract will be removed, providers which are still implementing the v1beta1 contract will stop to work (they will work only with older versions of Cluster API).

Please see Cluster API Contract changes and provider contracts for more details.

How to implement the new v1beta2 contract

We highly recommend providers to start planning the move to the new v1beta2 version of the Cluster API contract as soon as possible.

Implementing the new v1beta2 contract for providers is a two step operation:

  1. Implement changes defined for a specific provider type; See Cluster API Contract changes and provider contracts for more details.
  • In most cases, v1beta2 contract introduced changes in the initialization completed, conditions, terminal failures rules; Also replicas rule is changed for control plane providers.
  1. While implementing the changes above, It is also highly recommended to check the implementation of all the other rules (documentation for contract rules have been improved in recent releases, worth to take a look!).
  2. Change the CRD annotation that document which Cluster API contract is implemented by your Provider. e.g.
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  annotations:
    cluster.x-k8s.io/v1beta2: <your API version>
  name: <your CRD name>

How to bump to CAPI V1.11 but keep using deprecated v1beta1 conditions

A provider can continue to use deprecated v1beta1 conditions also after bumping to CAPI V1.11, but to do so it is required to change following imports:

import (
	...
    "sigs.k8s.io/cluster-api/util/conditions"
    "sigs.k8s.io/cluster-api/util/patch"
)

into:

import (
	...
    v1beta1conditions "sigs.k8s.io/cluster-api/util/deprecated/v1beta1/conditions"
    v1beta1patch "sigs.k8s.io/cluster-api/util/deprecated/v1beta1/patch"
)

Important! Please pay special attention to use sigs.k8s.io/cluster-api/util/deprecated/v1beta1/patch import everywhere, because using sigs.k8s.io/cluster-api/util/patch by mistake could in some cases lead to dropping conditions at runtime.

Also, please note that starting from the CAPI release when v1beta1 removal will happen (tentative Aug 2026), the Cluster API project will remove the Cluster API condition type, the util/conditions/deprecated/v1beta1 package, the util/deprecated/v1beta1 package, the code handling old conditions in util/patch.Helper and everything related to the custom Cluster API custom condition type.

This means that if a provider wants to keep using deprecated v1beta1 conditions after this date, they have to maintain their own custom copy of the types and related utils.

Also note that the v1beta2 contract is not going to require a specific condition type, so it will be also possible to use a custom condition type,

See Suggested changes for providers and Cluster API Contract changes for more details.

How to start using metav1.conditions

If providers choose to migrate metav1.Conditions, the process described in Improving status in CAPI resources can be used as a reference about how to implement a phased transition.

As a quick summary, transition should go through following phases:

Stage 1

Add status.v1beta2.conditions to your API (existing conditions will remain at status.conditions)

If you are at this stage, you must use following util packages from CAPI v1.11 (or following releases, see note below):

import (
	...
    v1beta1conditions "sigs.k8s.io/cluster-api/util/deprecated/v1beta1/conditions"
    v1beta2conditions "sigs.k8s.io/cluster-api/util/deprecated/v1beta1/conditions/v1beta2"
    v1beta1patch "sigs.k8s.io/cluster-api/util/deprecated/v1beta1/patch"
)
  • the v1beta1conditions package alias provides access to utils for managing clusterv1beta1.Conditions in status.conditions
  • the v1beta2conditions package alias provides access to utils for managing metav1.Conditions in status.v1beta2.conditions
  • the v1beta1patch package alias provides access to utils for patching objects in this phase.

Important!

  • Please pay special attention to use sigs.k8s.io/cluster-api/util/deprecated/v1beta1/patch import everywhere, because using sigs.k8s.io/cluster-api/util/patch by mistake could in some cases lead to dropping conditions at runtime (note: sigs.k8s.io/cluster-api/util/patch is the package we assume you are using before stage 1).
  • All packages from the import above (all packages below sigs.k8s.io/cluster-api/util/deprecated/v1beta1) are going to be removed from CAPI when the v1beta1 removal will happen (tentative Aug 2026).

Stage 2

Create a new API version, swap old conditions and new conditions, implement conversions

  • Move old conditions from status.conditions to status.deprecated.v1beta1.conditions
  • Move new conditions from status.v1beta2.conditions to status.conditions

If you are at this stage, you must use following util packages from CAPI v1.11 (or following releases, see note below):

import (
	...
    "sigs.k8s.io/cluster-api/util/conditions"
    deprecatedv1beta1conditions "sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1"
    "sigs.k8s.io/cluster-api/util/patch"
)
  • the conditions package provides access to utils for managing metav1.Conditions in status.conditions
  • the deprecatedv1beta1conditions package alias provides access to utils for managing clusterv1.Conditions in status.deprecated.v1beta1.conditions
  • the patch package provides access to utils for patching objects in this phase

Important!

  • Please pay special attention to use sigs.k8s.io/cluster-api/util/patch import everywhere, because using sigs.k8s.io/cluster-api/util/deprecated/v1beta1/patch by mistake could in some cases lead to dropping conditions at runtime (note: sigs.k8s.io/cluster-api/util/deprecated/v1beta1/patch is the package you were using in stage 1, it should not be used in stage 2).
  • The package sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1“ is going to be removed from CAPI when the v1beta1 removal will happen (tentative Aug 2026).

Stage 3

When removing the old API version, remove status.deprecated.v1beta1

Following util packages from CAPI v1.11 (or following releases) should be still in use:

import (
	...
    "sigs.k8s.io/cluster-api/util/conditions"
    "sigs.k8s.io/cluster-api/util/patch"
)
  • the conditions package provides access to utils for managing metav1.Conditions in status.conditions
  • the patch package provides access to utils for patching objects in this phase

Important!

  • Please pay special attention to use sigs.k8s.io/cluster-api/util/patch import everywhere, because using sigs.k8s.io/cluster-api/util/deprecated/v1beta1/patch by mistake could in some cases lead to dropping conditions at runtime (note: sigs.k8s.io/cluster-api/util/deprecated/v1beta1/patch is the package in stage 1, if should not be used in following stages).

Annex

Imports for conditions and patch helper utils

In order to help users to transition away from the CAPI conditions type, CAPI v1.11 supports different versions of conditions and patch helper utils.

Following table should help to pick the right utils.

Field to changeImport for condition utilImport for patch helper
status.conditions of type clusterv1beta1.Conditionsv1beta1conditions "sigs.k8s.io/cluster-api/util/deprecated/v1beta1/conditions"v1beta1patch "sigs.k8s.io/cluster-api/util/deprecated/v1beta1/patch"
status.v1beta2.conditions of type []metav1.Conditionsv1beta2conditions "sigs.k8s.io/cluster-api/util/deprecated/v1beta1/conditions/v1beta2"v1beta1patch "sigs.k8s.io/cluster-api/util/deprecated/v1beta1/patch"
status.deprecated.v1beta1.conditions of type clusterv1.Conditionsdeprecatedv1beta1conditions "sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1""sigs.k8s.io/cluster-api/util/patch"
status.conditions of type []metav1.Conditions"sigs.k8s.io/cluster-api/util/conditions""sigs.k8s.io/cluster-api/util/patch"
Important!
- Please pay special attention to use the correct patch helper import everywhere, because using a wrong
one could in some cases lead to dropping conditions at runtime while not having compile errors.