Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Kubernetes Cluster API

Cluster API is a Kubernetes sub-project focused on providing declarative APIs and tooling to simplify provisioning, upgrading, and operating multiple Kubernetes clusters.

Started by the Kubernetes Special Interest Group (SIG) Cluster Lifecycle, the Cluster API project uses Kubernetes-style APIs and patterns to automate cluster lifecycle management for platform operators. The supporting infrastructure, like virtual machines, networks, load balancers, and VPCs, as well as the Kubernetes cluster configuration are all defined in the same way that application developers operate deploying and managing their workloads. This enables consistent and repeatable cluster deployments across a wide variety of infrastructure environments.

Getting started

Why build Cluster API?

Kubernetes is a complex system that relies on several components being configured correctly to have a working cluster. Recognizing this as a potential stumbling block for users, the community focused on simplifying the bootstrapping process. Today, over 100 Kubernetes distributions and installers have been created, each with different default configurations for clusters and supported infrastructure providers. SIG Cluster Lifecycle saw a need for a single tool to address a set of common overlapping installation concerns and started kubeadm.

Kubeadm was designed as a focused tool for bootstrapping a best-practices Kubernetes cluster. The core tenet behind the kubeadm project was to create a tool that other installers can leverage and ultimately alleviate the amount of configuration that an individual installer needed to maintain. Since it began, kubeadm has become the underlying bootstrapping tool for several other applications, including Kubespray, minikube, kind, etc.

However, while kubeadm and other bootstrap providers reduce installation complexity, they don’t address how to manage a cluster day-to-day or a Kubernetes environment long term. You are still faced with several questions when setting up a production environment, including:

  • How can I consistently provision machines, load balancers, VPC, etc., across multiple infrastructure providers and locations?
  • How can I automate cluster lifecycle management, including things like upgrades and cluster deletion?
  • How can I scale these processes to manage any number of clusters?

SIG Cluster Lifecycle began the Cluster API project as a way to address these gaps by building declarative, Kubernetes-style APIs, that automate cluster creation, configuration, and management. Using this model, Cluster API can also be extended to support any infrastructure provider (AWS, Azure, vSphere, etc.) or bootstrap provider (kubeadm is default) you need. See the growing list of available providers.

Goals

  • To manage the lifecycle (create, scale, upgrade, destroy) of Kubernetes-conformant clusters using a declarative API.
  • To work in different environments, both on-premises and in the cloud.
  • To define common operations, provide a default implementation, and provide the ability to swap out implementations for alternative ones.
  • To reuse and integrate existing ecosystem components rather than duplicating their functionality (e.g. node-problem-detector, cluster autoscaler, SIG-Multi-cluster).
  • To provide a transition path for Kubernetes lifecycle products to adopt Cluster API incrementally. Specifically, existing cluster lifecycle management tools should be able to adopt Cluster API in a staged manner, over the course of multiple releases, or even adopting a subset of Cluster API.

Non-goals

  • To add these APIs to Kubernetes core (kubernetes/kubernetes).
    • This API should live in a namespace outside the core and follow the best practices defined by api-reviewers, but is not subject to core-api constraints.
  • To manage the lifecycle of infrastructure unrelated to the running of Kubernetes-conformant clusters.
  • To force all Kubernetes lifecycle products (kOps, Kubespray, GKE, AKS, EKS, IKS etc.) to support or use these APIs.
  • To manage non-Cluster API provisioned Kubernetes-conformant clusters.
  • To manage a single cluster spanning multiple infrastructure providers.
  • To configure a machine at any time other than create or upgrade.
  • To duplicate functionality that exists or is coming to other tooling, e.g., updating kubelet configuration (c.f. dynamic kubelet configuration), or updating apiserver, controller-manager, scheduler configuration (c.f. component-config effort) after the cluster is deployed.

🤗 Community, discussion, contribution, and support

Cluster API is developed in the open, and is constantly being improved by our users, contributors, and maintainers. It is because of you that we are able to automate cluster lifecycle management for the community. Join us!

If you have questions or want to get the latest project news, you can connect with us in the following ways:

  • Chat with us on the Kubernetes Slack in the #cluster-api channel
  • Subscribe to the SIG Cluster Lifecycle Google Group for access to documents and calendars
  • Join our Cluster API working group sessions where we share the latest project news, demos, answer questions, and triage issues

Pull Requests and feedback on issues are very welcome! See the issue tracker if you’re unsure where to start, especially the Good first issue and Help wanted tags, and also feel free to reach out to discuss.

See also our contributor guide and the Kubernetes community page for more details on how to get involved.

Code of conduct

Participation in the Kubernetes community is governed by the Kubernetes Code of Conduct.

Quick Start

In this tutorial we’ll cover the basics of how to use Cluster API to create one or more Kubernetes clusters.

Installation

There are two major quickstart paths: Using clusterctl or the Cluster API Operator.

This article describes a path that uses the clusterctl CLI tool to handle the lifecycle of a Cluster API management cluster.

The clusterctl command line interface is specifically designed for providing a simple “day 1 experience” and a quick start with Cluster API. It automates fetching the YAML files defining provider components and installing them.

Additionally it encodes a set of best practices in managing providers, that helps the user in avoiding mis-configurations or in managing day 2 operations such as upgrades.

The Cluster API Operator is a Kubernetes Operator built on top of clusterctl and designed to empower cluster administrators to handle the lifecycle of Cluster API providers within a management cluster using a declarative approach. It aims to improve user experience in deploying and managing Cluster API, making it easier to handle day-to-day tasks and automate workflows with GitOps. Visit the CAPI Operator quickstart if you want to experiment with this tool.

Common Prerequisites

Install and/or configure a Kubernetes cluster

Cluster API requires an existing Kubernetes cluster accessible via kubectl. During the installation process the Kubernetes cluster will be transformed into a management cluster by installing the Cluster API provider components, so it is recommended to keep it separated from any application workload.

It is a common practice to create a temporary, local bootstrap cluster which is then used to provision a target management cluster on the selected infrastructure provider.

Choose one of the options below:

  1. Existing Management Cluster

    For production use-cases a “real” Kubernetes cluster should be used with appropriate backup and disaster recovery policies and procedures in place. The Kubernetes cluster must be at least v1.20.0.

    export KUBECONFIG=<...>
    

OR

  1. Kind

    kind can be used for creating a local Kubernetes cluster for development environments or for the creation of a temporary bootstrap cluster used to provision a target management cluster on the selected infrastructure provider.

    The installation procedure depends on the version of kind; if you are planning to use the Docker infrastructure provider, please follow the additional instructions in the dedicated tab:

    Create the kind cluster:

    kind create cluster
    

    Test to ensure the local kind cluster is ready:

    kubectl cluster-info
    

    Run the following command to create a kind config file for allowing the Docker provider to access Docker on the host:

    cat > kind-cluster-with-extramounts.yaml <<EOF
    kind: Cluster
    apiVersion: kind.x-k8s.io/v1alpha4
    networking:
      ipFamily: dual
    nodes:
    - role: control-plane
      extraMounts:
        - hostPath: /var/run/docker.sock
          containerPath: /var/run/docker.sock
    EOF
    

    Then follow the instruction for your kind version using kind create cluster --config kind-cluster-with-extramounts.yaml to create the management cluster using the above file.

    Create the Kind Cluster

    KubeVirt is a cloud native virtualization solution. The virtual machines we’re going to create and use for the workload cluster’s nodes, are actually running within pods in the management cluster. In order to communicate with the workload cluster’s API server, we’ll need to expose it. We are using Kind which is a limited environment. The easiest way to expose the workload cluster’s API server (a pod within a node running in a VM that is itself running within a pod in the management cluster, that is running inside a Docker container), is to use a LoadBalancer service.

    To allow using a LoadBalancer service, we can’t use the kind’s default CNI (kindnet), but we’ll need to install another CNI, like Calico. In order to do that, we’ll need first to initiate the kind cluster with two modifications:

    1. Disable the default CNI
    2. Add the Docker credentials to the cluster, to avoid the Docker Hub pull rate limit of the calico images; read more about it in the docker documentation, and in the kind documentation.

    Create a configuration file for kind. Please notice the Docker config file path, and adjust it to your local setting:

    cat <<EOF > kind-config.yaml
    kind: Cluster
    apiVersion: kind.x-k8s.io/v1alpha4
    networking:
    # the default CNI will not be installed
      disableDefaultCNI: true
    nodes:
    - role: control-plane
      extraMounts:
       - containerPath: /var/lib/kubelet/config.json
         hostPath: <YOUR DOCKER CONFIG FILE PATH>
    EOF
    

    Now, create the kind cluster with the configuration file:

    kind create cluster --config=kind-config.yaml
    

    Test to ensure the local kind cluster is ready:

    kubectl cluster-info
    

    Install the Calico CNI

    Now we’ll need to install a CNI. In this example, we’re using calico, but other CNIs should work as well. Please see calico installation guide for more details (use the “Manifest” tab). Below is an example of how to install calico version v3.29.1.

    Use the Calico manifest to create the required resources; e.g.:

    kubectl create -f  https://raw.githubusercontent.com/projectcalico/calico/v3.29.1/manifests/calico.yaml
    

Install clusterctl

The clusterctl CLI tool handles the lifecycle of a Cluster API management cluster.

Install clusterctl binary with curl on Linux

If you are unsure you can determine your computers architecture by running uname -a

Download for AMD64:

curl -L https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.14.0/clusterctl-linux-amd64 -o clusterctl

Download for ARM64:

curl -L https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.14.0/clusterctl-linux-arm64 -o clusterctl

Download for PPC64LE:

curl -L https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.14.0/clusterctl-linux-ppc64le -o clusterctl

Install clusterctl:

sudo install -o root -g root -m 0755 clusterctl /usr/local/bin/clusterctl

Test to ensure the version you installed is up-to-date:

clusterctl version

Install clusterctl binary with curl on macOS

If you are unsure you can determine your computers architecture by running uname -a

Download for AMD64:

curl -L https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.14.0/clusterctl-darwin-amd64 -o clusterctl

Download for M CPU (“Apple Silicon”) / ARM64:

curl -L https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.14.0/clusterctl-darwin-arm64 -o clusterctl

Make the clusterctl binary executable.

chmod +x ./clusterctl

Move the binary in to your PATH.

sudo mv ./clusterctl /usr/local/bin/clusterctl

Test to ensure the version you installed is up-to-date:

clusterctl version

Install clusterctl with homebrew on macOS and Linux

Install the latest release using homebrew:

brew install clusterctl

Test to ensure the version you installed is up-to-date:

clusterctl version

Install clusterctl binary with curl on Windows using PowerShell

Go to the working directory where you want clusterctl downloaded.

Download the latest release; on Windows, type:

curl.exe -L https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.14.0/clusterctl-windows-amd64.exe -o clusterctl.exe

Append or prepend the path of that directory to the PATH environment variable.

Test to ensure the version you installed is up-to-date:

clusterctl.exe version

Initialize the management cluster

Now that we’ve got clusterctl installed and all the prerequisites in place, let’s transform the Kubernetes cluster into a management cluster by using clusterctl init.

The command accepts as input a list of providers to install; when executed for the first time, clusterctl init automatically adds to the list the cluster-api core provider, and if unspecified, it also adds the kubeadm bootstrap and kubeadm control-plane providers.

Enabling Feature Gates

Feature gates can be enabled by exporting environment variables before executing clusterctl init. For example, the ClusterTopology feature, which is required to enable support for managed topologies and ClusterClass, can be enabled via:

export CLUSTER_TOPOLOGY=true

Additional documentation about experimental features can be found in Experimental Features.

Initialization for common providers

Depending on the infrastructure provider you are planning to use, some additional prerequisites should be satisfied before getting started with Cluster API. See below for the expected settings for common providers.

export LINODE_TOKEN=<your-access-token>

# Initialize the management cluster
clusterctl init --infrastructure linode-linode

Download the latest binary of clusterawsadm from the AWS provider releases. The clusterawsadm command line utility assists with identity and access management (IAM) for Cluster API Provider AWS.

Download the latest release; on Linux, type:

curl -L https://github.com/kubernetes-sigs/cluster-api-provider-aws/releases/download/v2.13.0/clusterawsadm-linux-amd64 -o clusterawsadm

Make it executable

chmod +x clusterawsadm

Move the binary to a directory present in your PATH

sudo mv clusterawsadm /usr/local/bin

Check version to confirm installation

clusterawsadm version

Example Usage

export AWS_REGION=us-east-1 # This is used to help encode your environment variables
export AWS_ACCESS_KEY_ID=<your-access-key>
export AWS_SECRET_ACCESS_KEY=<your-secret-access-key>
export AWS_SESSION_TOKEN=<session-token> # If you are using Multi-Factor Auth.

# The clusterawsadm utility takes the credentials that you set as environment
# variables and uses them to create a CloudFormation stack in your AWS account
# with the correct IAM resources.
clusterawsadm bootstrap iam create-cloudformation-stack

# Create the base64 encoded credentials using clusterawsadm.
# This command uses your environment variables and encodes
# them in a value to be stored in a Kubernetes Secret.
export AWS_B64ENCODED_CREDENTIALS=$(clusterawsadm bootstrap credentials encode-as-profile)

# Finally, initialize the management cluster
clusterctl init --infrastructure aws

Download the latest release; on macOs, type:

curl -L https://github.com/kubernetes-sigs/cluster-api-provider-aws/releases/download/v2.13.0/clusterawsadm-darwin-amd64 -o clusterawsadm

Or if your Mac has an M1 CPU (”Apple Silicon”):

curl -L https://github.com/kubernetes-sigs/cluster-api-provider-aws/releases/download/v2.13.0/clusterawsadm-darwin-arm64 -o clusterawsadm

Make it executable

chmod +x clusterawsadm

Move the binary to a directory present in your PATH

sudo mv clusterawsadm /usr/local/bin

Check version to confirm installation

clusterawsadm version

Example Usage

export AWS_REGION=us-east-1 # This is used to help encode your environment variables
export AWS_ACCESS_KEY_ID=<your-access-key>
export AWS_SECRET_ACCESS_KEY=<your-secret-access-key>
export AWS_SESSION_TOKEN=<session-token> # If you are using Multi-Factor Auth.

# The clusterawsadm utility takes the credentials that you set as environment
# variables and uses them to create a CloudFormation stack in your AWS account
# with the correct IAM resources.
clusterawsadm bootstrap iam create-cloudformation-stack

# Create the base64 encoded credentials using clusterawsadm.
# This command uses your environment variables and encodes
# them in a value to be stored in a Kubernetes Secret.
export AWS_B64ENCODED_CREDENTIALS=$(clusterawsadm bootstrap credentials encode-as-profile)

# Finally, initialize the management cluster
clusterctl init --infrastructure aws

Install the latest release using homebrew:

brew install clusterawsadm

Check version to confirm installation

clusterawsadm version

Example Usage

export AWS_REGION=us-east-1 # This is used to help encode your environment variables
export AWS_ACCESS_KEY_ID=<your-access-key>
export AWS_SECRET_ACCESS_KEY=<your-secret-access-key>
export AWS_SESSION_TOKEN=<session-token> # If you are using Multi-Factor Auth.

# The clusterawsadm utility takes the credentials that you set as environment
# variables and uses them to create a CloudFormation stack in your AWS account
# with the correct IAM resources.
clusterawsadm bootstrap iam create-cloudformation-stack

# Create the base64 encoded credentials using clusterawsadm.
# This command uses your environment variables and encodes
# them in a value to be stored in a Kubernetes Secret.
export AWS_B64ENCODED_CREDENTIALS=$(clusterawsadm bootstrap credentials encode-as-profile)

# Finally, initialize the management cluster
clusterctl init --infrastructure aws

Download the latest release; on Windows, type:

curl.exe -L https://github.com/kubernetes-sigs/cluster-api-provider-aws/releases/download/v2.13.0/clusterawsadm-windows-amd64.exe -o clusterawsadm.exe

Append or prepend the path of that directory to the PATH environment variable. Check version to confirm installation

clusterawsadm.exe version

Example Usage in Powershell

$Env:AWS_REGION="us-east-1" # This is used to help encode your environment variables
$Env:AWS_ACCESS_KEY_ID="<your-access-key>"
$Env:AWS_SECRET_ACCESS_KEY="<your-secret-access-key>"
$Env:AWS_SESSION_TOKEN="<session-token>" # If you are using Multi-Factor Auth.

# The clusterawsadm utility takes the credentials that you set as environment
# variables and uses them to create a CloudFormation stack in your AWS account
# with the correct IAM resources.
clusterawsadm bootstrap iam create-cloudformation-stack

# Create the base64 encoded credentials using clusterawsadm.
# This command uses your environment variables and encodes
# them in a value to be stored in a Kubernetes Secret.
$Env:AWS_B64ENCODED_CREDENTIALS=$(clusterawsadm bootstrap credentials encode-as-profile)

# Finally, initialize the management cluster
clusterctl init --infrastructure aws

See the AWS provider prerequisites document for more details.

For more information about authorization, AAD, or requirements for Azure, visit the Azure provider prerequisites document.

export AZURE_SUBSCRIPTION_ID="<SubscriptionId>"

# Create an Azure Service Principal and paste the output here
export AZURE_TENANT_ID="<Tenant>"
export AZURE_CLIENT_ID="<AppId>"
export AZURE_CLIENT_ID_USER_ASSIGNED_IDENTITY=$AZURE_CLIENT_ID # for compatibility with CAPZ v1.16 templates
export AZURE_CLIENT_SECRET="<Password>"

# Settings needed for AzureClusterIdentity used by the AzureCluster
export AZURE_CLUSTER_IDENTITY_SECRET_NAME="cluster-identity-secret"
export CLUSTER_IDENTITY_NAME="cluster-identity"
export AZURE_CLUSTER_IDENTITY_SECRET_NAMESPACE="default"

# Create a secret to include the password of the Service Principal identity created in Azure
# This secret will be referenced by the AzureClusterIdentity used by the AzureCluster
kubectl create secret generic "${AZURE_CLUSTER_IDENTITY_SECRET_NAME}" --from-literal=clientSecret="${AZURE_CLIENT_SECRET}" --namespace "${AZURE_CLUSTER_IDENTITY_SECRET_NAMESPACE}"

# Finally, initialize the management cluster
clusterctl init --infrastructure azure
# The cloudscale API token.
# You may want to set this in `$XDG_CONFIG_HOME/cluster-api/clusterctl.yaml` so your token is not in
# bash history
export CLOUDSCALE_API_TOKEN="AAAEXAMPLE"

# initialize the management cluster
clusterctl init --infrastructure cloudscale-ch-cloudscale

For more information about the CAPI provider for cloudscale, see the cloudscale cluster-api project.

Create a file named cloud-config in the repo’s root directory, substituting in your own environment’s values

[Global]
api-url = <cloudstackApiUrl>
api-key = <cloudstackApiKey>
secret-key = <cloudstackSecretKey>

Create the base64 encoded credentials by catting your credentials file. This command uses your environment variables and encodes them in a value to be stored in a Kubernetes Secret.

export CLOUDSTACK_B64ENCODED_SECRET=`cat cloud-config | base64 | tr -d '\n'`

Finally, initialize the management cluster

clusterctl init --infrastructure cloudstack
export DIGITALOCEAN_ACCESS_TOKEN=<your-access-token>
export DO_B64ENCODED_CREDENTIALS="$(echo -n "${DIGITALOCEAN_ACCESS_TOKEN}" | base64 | tr -d '\n')"

# Initialize the management cluster
clusterctl init --infrastructure digitalocean

The Docker provider requires the ClusterTopology and MachinePool features to deploy ClusterClass-based clusters. We are only supporting ClusterClass-based cluster-templates in this quickstart as ClusterClass makes it possible to adapt configuration based on Kubernetes version. This is required to install Kubernetes clusters < v1.24 and for the upgrade from v1.23 to v1.24 as we have to use different cgroupDrivers depending on Kubernetes version.

# Enable the experimental Cluster topology feature.
export CLUSTER_TOPOLOGY=true

# Initialize the management cluster
clusterctl init --infrastructure docker
# Create the base64 encoded credentials by catting your credentials json.
# This command uses your environment variables and encodes
# them in a value to be stored in a Kubernetes Secret.
export GCP_B64ENCODED_CREDENTIALS=$( cat /path/to/gcp-credentials.json | base64 | tr -d '\n' )

# Finally, initialize the management cluster
clusterctl init --infrastructure gcp
clusterctl init --infrastructure harvester-harvester

For more information, please visit the Harvester project.

Please visit the Hetzner project.

# Please ensure that the values for `CLOUD_SDK_AK` and `CLOUD_SDK_SK` are base64 encoded.
export CLOUD_SDK_AK=$( echo $AccessKey | base64 | tr -d '\n' )
export CLOUD_SDK_SK=$( echo $SecretKey | base64 | tr -d '\n' )

# Finally, initialize the management cluster
clusterctl init --infrastructure huawei

In order to initialize the IBM Cloud Provider you have to expose the environment variable IBMCLOUD_API_KEY. This variable is used to authorize the infrastructure provider manager against the IBM Cloud API. To create one from the UI, refer here.

export IBMCLOUD_API_KEY=<you_api_key>

# Finally, initialize the management cluster
clusterctl init --infrastructure ibmcloud

The IONOS Cloud credentials are configured in the IONOSCloudCluster. Therefore, there is no need to specify them during the provider initialization.

clusterctl init --infrastructure ionoscloud-ionoscloud

For more information, please visit the IONOS Cloud project.

# Initialize the management cluster
clusterctl init --infrastructure k0sproject-k0smotron

Kairos Fleet claims already-enrolled Kairos nodes from an AuroraBoot fleet rather than provisioning machines, so no cloud credentials are required. Ensure an AuroraBoot instance is reachable with enrolled, unclaimed nodes. As an infrastructure provider for Kairos nodes, it is used together with the Kairos bootstrap and control-plane providers.

# Initialize the management cluster
clusterctl init --bootstrap kairos-io --control-plane kairos-io --infrastructure kairos-io-fleet
# Initialize the management cluster
clusterctl init --infrastructure kubekey

KubeSwift runs the workload machines on the management cluster, so no cloud credentials are required. Ensure KubeSwift is installed on the management cluster first.

# Initialize the management cluster
clusterctl init --infrastructure kubeswift-io

Please visit the KubeVirt project for more information.

As described above, we want to use a LoadBalancer service in order to expose the workload cluster’s API server. In the example below, we will use MetalLB solution to implement load balancing to our kind cluster. Other solution should work as well.

Install MetalLB for load balancing

Install MetalLB, as described here; for example:

METALLB_VER=$(curl "https://api.github.com/repos/metallb/metallb/releases/latest" | jq -r ".tag_name")
kubectl apply -f "https://raw.githubusercontent.com/metallb/metallb/${METALLB_VER}/config/manifests/metallb-native.yaml"
kubectl wait pods -n metallb-system -l app=metallb,component=controller --for=condition=Ready --timeout=10m
kubectl wait pods -n metallb-system -l app=metallb,component=speaker --for=condition=Ready --timeout=2m

Now, we’ll create the IPAddressPool and the L2Advertisement custom resources. For that, we’ll need to set the IP range. First, we’ll read the kind network in order to find its subnet:

SUBNET=$(docker network inspect kind | jq -r 'first(.[0].IPAM.Config[].Subnet | select(test("^[0-9]+\\.")))')
PREFIX=$(echo $SUBNET | sed -E 's|^([0-9]+\.[0-9]+)\..*$|\1|g')

cat <<EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: capi-ip-pool
  namespace: metallb-system
spec:
  addresses:
  - ${PREFIX}.255.200-${PREFIX}.255.250
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: empty
  namespace: metallb-system
EOF

Install KubeVirt on the kind cluster

# get KubeVirt version
KV_VER=$(curl "https://api.github.com/repos/kubevirt/kubevirt/releases/latest" | jq -r ".tag_name")
# deploy required CRDs
kubectl apply -f "https://github.com/kubevirt/kubevirt/releases/download/${KV_VER}/kubevirt-operator.yaml"
# deploy the KubeVirt custom resource
kubectl apply -f "https://github.com/kubevirt/kubevirt/releases/download/${KV_VER}/kubevirt-cr.yaml"
kubectl wait -n kubevirt kv kubevirt --for=condition=Available --timeout=10m

Initialize the management cluster with the KubeVirt Provider

clusterctl init --infrastructure kubevirt

Please visit the Metal3 project.

clusterctl init --infrastructure metal-stack

Please follow the Cluster API Provider for metal-stack Getting Started Guide

Please follow the Cluster API Provider for Nutanix Getting Started Guide

Please follow the Cluster API Provider for Oracle Cloud Infrastructure (OCI) Getting Started Guide

# Initialize the management cluster
clusterctl init --infrastructure opennebula

Please visit OpenNebula Cluster API Provider Wiki.

Cluster API Provider OpenStack depends on openstack-resource-controller since v0.12.

# Install ORC (needed for CAPO >=v0.12)
kubectl apply -f https://github.com/k-orc/openstack-resource-controller/releases/latest/download/install.yaml
# Initialize the management cluster
clusterctl init --infrastructure openstack
export OSC_SECRET_KEY=<your-secret-key>
export OSC_ACCESS_KEY=<your-access-key>
export OSC_REGION=<you-region>
# Create namespace
kubectl create namespace cluster-api-provider-outscale-system
# Create secret
kubectl create secret generic cluster-api-provider-outscale --from-literal=access_key=${OSC_ACCESS_KEY} --from-literal=secret_key=${OSC_SECRET_KEY} --from-literal=region=${OSC_REGION}  -n cluster-api-provider-outscale-system
# Initialize the management cluster
clusterctl init --infrastructure outscale
export OXIDE_HOST=<silo host>
export OXIDE_TOKEN=<token>
# Create secret
kubectl create secret generic cluster-api-provider-oxide \
  --from-literal=oxide-host=${OXIDE_HOST} \
  --from-literal=oxide-token=${OXIDE_TOKEN}
# Initialize the management cluster
clusterctl init --infrastructure oxide

The Proxmox credentials are optional, when creating a cluster they can be set in the ProxmoxCluster resource, if you do not set them here.

# The host for the Proxmox cluster
export PROXMOX_URL="https://pve.example:8006"
# The Proxmox token ID to access the remote Proxmox endpoint
export PROXMOX_TOKEN='root@pam!capi'
# The secret associated with the token ID
# You may want to set this in `$XDG_CONFIG_HOME/cluster-api/clusterctl.yaml` so your password is not in
# bash history
export PROXMOX_SECRET="1234-1234-1234-1234"


# Finally, initialize the management cluster
clusterctl init --infrastructure proxmox --ipam in-cluster

For more information about the CAPI provider for Proxmox, see the Proxmox project.

# Initialize the management cluster
clusterctl init --infrastructure scaleway

Please follow the Cluster API Provider for Cloud Director Getting Started Guide

# Initialize the management cluster
clusterctl init --infrastructure vcd
clusterctl init --infrastructure vcluster

Please follow the Cluster API Provider for vcluster Quick Start Guide

# Initialize the management cluster
clusterctl init --infrastructure virtink
# The username used to access the remote vSphere endpoint
export VSPHERE_USERNAME="vi-admin@vsphere.local"
# The password used to access the remote vSphere endpoint
# You may want to set this in `$XDG_CONFIG_HOME/cluster-api/clusterctl.yaml` so your password is not in
# bash history
export VSPHERE_PASSWORD="admin!23"

# Finally, initialize the management cluster
clusterctl init --infrastructure vsphere

For more information about prerequisites, credentials management, or permissions for vSphere, see the vSphere project.

export VULTR_API_KEY="$(echo -n "${VULTR_API_KEY}" | base64 | tr -d '\n')"

# initialize the management cluster
clusterctl init --infrastructure vultr-vultr

The output of clusterctl init is similar to this:

Fetching providers
Installing cert-manager Version="v1.11.0"
Waiting for cert-manager to be available...
Installing Provider="cluster-api" Version="v1.0.0" TargetNamespace="capi-system"
Installing Provider="bootstrap-kubeadm" Version="v1.0.0" TargetNamespace="capi-kubeadm-bootstrap-system"
Installing Provider="control-plane-kubeadm" Version="v1.0.0" TargetNamespace="capi-kubeadm-control-plane-system"
Installing Provider="infrastructure-docker" Version="v1.0.0" TargetNamespace="capd-system"

Your management cluster has been initialized successfully!

You can now create your first workload cluster by running the following:

  clusterctl generate cluster [name] --kubernetes-version [version] | kubectl apply -f -

Create your first workload cluster

Once the management cluster is ready, you can create your first workload cluster.

Preparing the workload cluster configuration

The clusterctl generate cluster command returns a YAML template for creating a workload cluster.

Required configuration for common providers

Depending on the infrastructure provider you are planning to use, some additional prerequisites should be satisfied before configuring a cluster with Cluster API. Instructions are provided for common providers below.

Otherwise, you can look at the clusterctl generate cluster command documentation for details about how to discover the list of variables required by a cluster templates.

export LINODE_REGION=us-ord
export LINODE_TOKEN=<your linode PAT>
export LINODE_CONTROL_PLANE_MACHINE_TYPE=g6-standard-2
export LINODE_MACHINE_TYPE=g6-standard-2

See the Akamai (Linode) provider for more information.

export AWS_REGION=us-east-1
export AWS_SSH_KEY_NAME=default
# Select instance types
export AWS_CONTROL_PLANE_MACHINE_TYPE=t3.large
export AWS_NODE_MACHINE_TYPE=t3.large

See the AWS provider prerequisites document for more details.

# Name of the Azure datacenter location. Change this value to your desired location.
export AZURE_LOCATION="centralus"

# Select VM types.
export AZURE_CONTROL_PLANE_MACHINE_TYPE="Standard_D2s_v3"
export AZURE_NODE_MACHINE_TYPE="Standard_D2s_v3"

# [Optional] Select resource group. The default value is ${CLUSTER_NAME}.
export AZURE_RESOURCE_GROUP="<ResourceGroupName>"

A ClusterAPI compatible image must be available in your cloudscale project. For instructions on how to build a compatible VM template see image-builder.

# The cloudscale API token.
# You may want to set this in `$XDG_CONFIG_HOME/cluster-api/clusterctl.yaml` so your token is not in
# bash history
export CLOUDSCALE_API_TOKEN="AAAEXAMPLE"
# SSH public key added to nodes
export CLOUDSCALE_SSH_PUBLIC_KEY="ssh-ed25519 AAAA..."
# cloudscale.ch region
export CLOUDSCALE_REGION="lpg"
# Server image for nodes
export CLOUDSCALE_MACHINE_IMAGE="custom:ubuntu-2404-kube-v1.36.1"
# Flavor for control plane nodes
export CLOUDSCALE_CONTROL_PLANE_MACHINE_FLAVOR="flex-4-2"
# Flavor for worker nodes 
export CLOUDSCALE_WORKER_MACHINE_FLAVOR="flex-4-2"
# Root volume size in GB
export CLOUDSCALE_ROOT_VOLUME_SIZE="50"

For more information about the setup for cloudscale, see the cloudscale cluster-api project.

A Cluster API compatible image must be available in your CloudStack installation. For instructions on how to build a compatible image see image-builder (CloudStack)

Prebuilt images can be found here

To see all required CloudStack environment variables execute:

clusterctl generate cluster --infrastructure cloudstack --list-variables capi-quickstart

Apart from the script, the following CloudStack environment variables are required.

# Set this to the name of the zone in which to deploy the cluster
export CLOUDSTACK_ZONE_NAME=<zone name>
# The name of the network on which the VMs will reside
export CLOUDSTACK_NETWORK_NAME=<network name>
# The endpoint of the workload cluster
export CLUSTER_ENDPOINT_IP=<cluster endpoint address>
export CLUSTER_ENDPOINT_PORT=<cluster endpoint port>
# The service offering of the control plane nodes
export CLOUDSTACK_CONTROL_PLANE_MACHINE_OFFERING=<control plane service offering name>
# The service offering of the worker nodes
export CLOUDSTACK_WORKER_MACHINE_OFFERING=<worker node service offering name>
# The capi compatible template to use
export CLOUDSTACK_TEMPLATE_NAME=<template name>
# The ssh key to use to log into the nodes
export CLOUDSTACK_SSH_KEY_NAME=<ssh key name>

A full configuration reference can be found in configuration.md.

A ClusterAPI compatible image must be available in your DigitalOcean account. For instructions on how to build a compatible image see image-builder.

export DO_REGION=nyc1
export DO_SSH_KEY_FINGERPRINT=<your-ssh-key-fingerprint>
export DO_CONTROL_PLANE_MACHINE_TYPE=s-2vcpu-2gb
export DO_CONTROL_PLANE_MACHINE_IMAGE=<your-capi-image-id>
export DO_NODE_MACHINE_TYPE=s-2vcpu-2gb
export DO_NODE_MACHINE_IMAGE==<your-capi-image-id>

The Docker provider does not require additional configurations for cluster templates.

However, if you require special network settings you can set the following environment variables:

# The list of service CIDR, default ["10.128.0.0/12"]
export SERVICE_CIDR=["10.96.0.0/12"]

# The list of pod CIDR, default ["192.168.0.0/16"]
export POD_CIDR=["192.168.0.0/16"]

# The service domain, default "cluster.local"
export SERVICE_DOMAIN="k8s.test"

It is also possible but not recommended to disable the per-default enabled Pod Security Standard:

export POD_SECURITY_STANDARD_ENABLED="false"
# Name of the GCP datacenter location. Change this value to your desired location
export GCP_REGION="<GCP_REGION>"
export GCP_PROJECT="<GCP_PROJECT>"
# Make sure to use same Kubernetes version here as building the GCE image
export KUBERNETES_VERSION=1.23.3
# This is the image you built. See https://github.com/kubernetes-sigs/image-builder
export IMAGE_ID=projects/$GCP_PROJECT/global/images/<built image>
export GCP_CONTROL_PLANE_MACHINE_TYPE=n1-standard-2
export GCP_NODE_MACHINE_TYPE=n1-standard-2
export GCP_NETWORK_NAME=<GCP_NETWORK_NAME or default>
export CLUSTER_NAME="<CLUSTER_NAME>"

See the GCP provider for more information.

# Cloud Provider credentials, which are a Kubeconfig generated using this process: https://docs.harvesterhci.io/v1.3/rancher/cloud-provider/#deploying-to-the-rke2-custom-cluster-experimental
# Since v0.1.5, this can be left "", because the controller can update it automatically
export CLOUD_CONFIG_KUBECONFIG_B64=""
# Name of the CAPI Cluster
export CLUSTER_NAME="<CLUSTER_NAME>"
# Number of Control Plane machines
export CONTROL_PLANE_MACHINE_COUNT=3
# URL to access the Harvester Cluster, this will be overridden by the controller
export HARVESTER_ENDPOINT=""
# Base64-Encoded Kubeconfig to access Harvester, which can be downloaded from Harvester's UI or from a Harvester Manager Node.
export HARVESTER_KUBECONFIG_B64="<HARVESTER_KUBECONFIG_ENCODED_IN_BASE64>"
# Namespace for all resources in the Management Cluster
export NAMESPACE="test"
# Pod CIDR for the Workload Cluster, it should have the format: 192.168.0.0/16
export POD_CIDR="10.42.0.0/16"
# Service CIDR for the Workload Cluster, it should have the format : 192.168.0.0/16 and be different from POD_CIDR
export SERVICE_CIDR="10.43.0.0/16"
# Reference to SSH Keypair in Harvester. It should follow the format <NAMESPACE>/<NAME>
export SSH_KEYPAIR="default/ssk-key-pair"
# Namespace in Harvester where the VMs will be created.
export TARGET_HARVESTER_NAMESPACE="default"
# Disk Size to be used by the VMs
export VM_DISK_SIZE="50Gi"
# Reference to OS Image in Harvester which will be used for creating VMs, It must follow the format <NAMESPACE>/<NAME>
export VM_IMAGE_NAME="default/jammy-server"
# Reference to VM Network in Harvester. It must follow the format <NAMESPACE>/<NAME>
export VM_NETWORK="default/untagged"
# Linux Username for the VMs
export VM_SSH_USER="ubuntu"
# Number of Worker nodes in the target Workload cluster
export WORKER_MACHINE_COUNT=2

See the Harvester provider for more information.

# huawei cloud region
export HC_REGION="cn-east-1"
# ECS SSH key name
export HC_SSH_KEY_NAME="default"
# kubernetes version
export KUBERNETES_VERSION="1.32.0"
# number of control plane machines
export CONTROL_PLANE_MACHINE_COUNT="1"
# number of worker machines
export WORKER_MACHINE_COUNT="1"
# control plane machine type
export HC_CONTROL_PLANE_MACHINE_TYPE="x1e.2u.4g"
# worker node machine type
export HC_NODE_MACHINE_TYPE="x1e.2u.4g"
# ECS image ID
export ECS_IMAGE_ID="218ca5t7-bxf3-5dg0-852p-y703c9fe1a52"

See the Huawei Cloud provider for more information.

# Required environment variables for VPC
# VPC region
export IBMVPC_REGION=us-south
# VPC zone within the region
export IBMVPC_ZONE=us-south-1
# ID of the resource group in which the VPC will be created
export IBMVPC_RESOURCEGROUP=<your-resource-group-id>
# Name of the VPC
export IBMVPC_NAME=ibm-vpc-0
export IBMVPC_IMAGE_ID=<you-image-id>
# Profile for the virtual server instances
export IBMVPC_PROFILE=bx2-4x16
export IBMVPC_SSHKEY_ID=<your-sshkey-id>

# Required environment variables for PowerVS
export IBMPOWERVS_SSHKEY_NAME=<your-ssh-key>
# Internal and external IP of the network
export IBMPOWERVS_VIP=<internal-ip>
export IBMPOWERVS_VIP_EXTERNAL=<external-ip>
export IBMPOWERVS_VIP_CIDR=29
export IBMPOWERVS_IMAGE_NAME=<your-capi-image-name>
# ID of the PowerVS service instance
export IBMPOWERVS_SERVICE_INSTANCE_ID=<service-instance-id>
export IBMPOWERVS_NETWORK_NAME=<your-capi-network-name>

Please visit the IBM Cloud provider for more information.

A ClusterAPI compatible image must be available in your IONOS Cloud contract. For instructions on how to build a compatible Image, see our docs.

# The token which is used to authenticate against the IONOS Cloud API
export IONOS_TOKEN=<your-token>
# The datacenter ID where the cluster will be deployed
export IONOSCLOUD_DATACENTER_ID="<your-datacenter-id>"
# The IP of the control plane endpoint
export CONTROL_PLANE_ENDPOINT_IP=10.10.10.4
# The location of the data center where the cluster will be deployed
export CONTROL_PLANE_ENDPOINT_LOCATION=de/txl
# The image ID of the custom image that will be used for the VMs
export IONOSCLOUD_MACHINE_IMAGE_ID="<your-image-id>"
# The SSH key that will be used to access the VMs
export IONOSCLOUD_MACHINE_SSH_KEYS="<your-ssh-key>"

For more configuration options check our list of available variables

Please visit the K0smotron provider for more information.

The default cluster-template.yaml variables have defaults; only the control-plane endpoint is operator-supplied. Point the provider at your AuroraBoot fleet:

export CONTROL_PLANE_ENDPOINT_HOST=<your-control-plane-host>
export AURORABOOT_URL=http://<auroraboot-host>:8080

Please visit the cluster-api-provider-kairos-fleet repository for more information.

# Required environment variables
# The KKZONE is used to specify where to download the binaries. (e.g. "", "cn")
export KKZONE=""
# The ssh name of the all instance Linux user. (e.g. root, ubuntu)
export USER_NAME=<your-linux-user>
# The ssh password of the all instance Linux user.
export PASSWORD=<your-linux-user-password>
# The ssh IP address of the all instance. (e.g. "[{address: 192.168.100.3}, {address: 192.168.100.4}]")
export INSTANCES=<your-linux-ip-address>
# The cluster control plane VIP. (e.g. "192.168.100.100")
export CONTROL_PLANE_ENDPOINT_IP=<your-control-plane-virtual-ip>

Please visit the KubeKey provider for more information.

KubeSwift runs the workload machines as VMs on the management cluster, so no cloud credentials are required. Ensure the management cluster has a Ready SwiftImage (for example ubuntu-noble) and the cluster-scoped SwiftGuestClasses referenced by the template (capi-controlplane, capi-worker).

The template variables all have defaults; override them only if your names differ:

export KUBESWIFT_IMAGE="ubuntu-noble"
export KUBESWIFT_CONTROL_PLANE_CLASS="capi-controlplane"
export KUBESWIFT_WORKER_CLASS="capi-worker"

Please visit the cluster-api-provider-kubeswift repository for more information.

In this example, we’ll use the image for Kubernetes v1.32.1:

export NODE_VM_IMAGE_TEMPLATE="quay.io/capk/ubuntu-2404-container-disk:v1.32.1"
export CAPK_GUEST_K8S_VERSION="${NODE_VM_IMAGE_TEMPLATE/*:/}"
export CRI_PATH="unix:///var/run/containerd/containerd.sock"

Please visit the KubeVirt project for more information.

Note: If you are running CAPM3 release prior to v0.5.0, make sure to export the following environment variables. However, you don’t need them to be exported if you use CAPM3 release v0.5.0 or higher.

# The URL of the kernel to deploy.
export DEPLOY_KERNEL_URL="http://172.22.0.1:6180/images/ironic-python-agent.kernel"
# The URL of the ramdisk to deploy.
export DEPLOY_RAMDISK_URL="http://172.22.0.1:6180/images/ironic-python-agent.initramfs"
# The URL of the Ironic endpoint.
export IRONIC_URL="http://172.22.0.1:6385/v1/"
# The URL of the Ironic inspector endpoint.
export IRONIC_INSPECTOR_URL="http://172.22.0.1:5050/v1/"
# Do not use a dedicated CA certificate for Ironic API. Any value provided in this variable disables additional CA certificate validation.
# To provide a CA certificate, leave this variable unset. If unset, then IRONIC_CA_CERT_B64 must be set.
export IRONIC_NO_CA_CERT=true
# Disables basic authentication for Ironic API. Any value provided in this variable disables authentication.
# To enable authentication, leave this variable unset. If unset, then IRONIC_USERNAME and IRONIC_PASSWORD must be set.
export IRONIC_NO_BASIC_AUTH=true
# Disables basic authentication for Ironic inspector API. Any value provided in this variable disables authentication.
# To enable authentication, leave this variable unset. If unset, then IRONIC_INSPECTOR_USERNAME and IRONIC_INSPECTOR_PASSWORD must be set.
export IRONIC_INSPECTOR_NO_BASIC_AUTH=true

Please visit the Metal3 getting started guide for more details.

export METAL_PARTITION=<metal-stack-partition>
export METAL_PROJECT_ID=<metal-stack-project-id>
export CONTROL_PLANE_IP=<metal-stack-control-plane-ip>

export FIREWALL_MACHINE_IMAGE=<firewall-os-image>
export FIREWALL_MACHINE_SIZE=<firewall-size>

export CONTROL_PLANE_MACHINE_IMAGE=<machine-os-image>
export CONTROL_PLANE_MACHINE_SIZE=<machine-size>
export WORKER_MACHINE_IMAGE=<machine-os-image>
export WORKER_MACHINE_SIZE=<machine-size>

Please visit the metal-stack getting started guide for more details.

A ClusterAPI compatible image must be available in your Nutanix image library. For instructions on how to build a compatible image see image-builder.

To see all required Nutanix environment variables execute:

clusterctl generate cluster --infrastructure nutanix --list-variables capi-quickstart
# OpenNebula API endpoint and credentials
export ONE_XMLRPC='http://10.2.11.40:2633/RPC2'
export ONE_AUTH='oneadmin:opennebula'

# VM and VR templates to construct workload clusters from
export MACHINE_TEMPLATE_NAME='capone131'
export ROUTER_TEMPLATE_NAME='capone131-vr'

# VNs to deploy workload clusters into
export PUBLIC_NETWORK_NAME='service'
export PRIVATE_NETWORK_NAME='private'

# Name of the new workload cluster
export CLUSTER_NAME='one'

# Cloud-Provider image to deploy inside the new workload cluster
export CCM_IMG='ghcr.io/opennebula/cloud-provider-opennebula:latest'

# Initial size of the new workload cluster
export CONTROL_PLANE_MACHINE_COUNT='1'
export WORKER_MACHINE_COUNT='1'

Please visit OpenNebula Cluster API Provider Wiki.

A ClusterAPI compatible image must be available in your OpenStack. For instructions on how to build a compatible image see image-builder. Depending on your OpenStack and underlying hypervisor the following options might be of interest:

To see all required OpenStack environment variables execute:

clusterctl generate cluster --infrastructure openstack --list-variables capi-quickstart

The following script can be used to export some of them:

wget https://raw.githubusercontent.com/kubernetes-sigs/cluster-api-provider-openstack/master/templates/env.rc -O /tmp/env.rc
source /tmp/env.rc <path/to/clouds.yaml> <cloud>

Apart from the script, the following OpenStack environment variables are required.

# The list of nameservers for OpenStack Subnet being created.
# Set this value when you need create a new network/subnet while the access through DNS is required.
export OPENSTACK_DNS_NAMESERVERS=<dns nameserver>
# FailureDomain is the failure domain the machine will be created in.
export OPENSTACK_FAILURE_DOMAIN=<availability zone name>
# The flavor reference for the flavor for your server instance.
export OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR=<flavor>
# The flavor reference for the flavor for your server instance.
export OPENSTACK_NODE_MACHINE_FLAVOR=<flavor>
# The name of the image to use for your server instance. If the RootVolume is specified, this will be ignored and use rootVolume directly.
export OPENSTACK_IMAGE_NAME=<image name>
# The SSH key pair name
export OPENSTACK_SSH_KEY_NAME=<ssh key pair name>
# The external network
export OPENSTACK_EXTERNAL_NETWORK_ID=<external network ID>

A full configuration reference can be found in configuration.md.

A ClusterAPI compatible image must be available in your Outscale account. For instructions on how to build a compatible image see image-builder.

# The outscale root disk iops
export OSC_IOPS="<IOPS>"
# The outscale root disk size
export OSC_VOLUME_SIZE="<VOLUME_SIZE>"
# The outscale root disk volumeType
export OSC_VOLUME_TYPE="<VOLUME_TYPE>"
# The outscale key pair
export OSC_KEYPAIR_NAME="<KEYPAIR_NAME>"
# The outscale subregion name
export OSC_SUBREGION_NAME="<SUBREGION_NAME>"
# The outscale vm type
export OSC_VM_TYPE="<VM_TYPE>"
# The outscale image name
export OSC_IMAGE_NAME="<IMAGE_NAME>"

A ClusterAPI compatible image must be available in your Oxide silo. For additional instructions on how to build a compatible image see image-builder.

## 1. Upload an Ubuntu 24.04 base image to your Oxide Silo
## 2. Export the base image ID (Ubuntu 24.04)
export OXIDE_BOOT_DISK_IMAGE_ID="<ubuntu-24-04-id>"
## 3. Set the Project for packer to build in
export OXIDE_PROJECT="<project>"
## 4. clone image-builder
git clone https://github.com/kubernetes-sigs/image-builder.git
## 5. Build CAPI image for Oxide
cd image-builder/images/capi && make build-oxide-ubuntu-2404

The cluster template requires the following environment variables:

# The Oxide Project to deploy to (required)
export OXIDE_PROJECT="<Project>"
# The Oxide Image built from image-builder (required)
export OXIDE_IMAGE_ID="<image-id from image-builder result>"
# The Oxide VPC to use
export OXIDE_VPC="default"

## To discover additional optional environment variables and their defaults run: 
clusterctl generate cluster capi-quickstart --list-variables

We need to create a firewall rule that allows inbound TCP communication over port 6443. This will allow the nodes to join to the cluster and for you to use kubectl to interact with the workload cluster.

OXIDE_RULES_FILE="$(mktemp)"

oxide vpc firewall-rules view --project "$OXIDE_PROJECT" --vpc "$OXIDE_VPC" \
| jq --arg vpc "$OXIDE_VPC" --arg name "allow-kube-apiserver" '{
    rules: (
      [ .rules[]
        | select(.name != $name)
        | {action, description, direction, filters, name, priority, status, targets} ]
      + [ {
          name: $name,
          description: "Allow kube-apiserver (TCP 6443) from anywhere (https://github.com/oxidecomputer/cluster-api-provider-oxide/docs/getting-started.md)",
          action: "allow",
          direction: "inbound",
          priority: 0,
          status: "enabled",
          filters: { protocols: [ {type:"tcp"} ], ports: ["6443"] },
          targets: [ { type: "vpc", value: $vpc } ]
        } ]
    )
  }' > "$OXIDE_RULES_FILE"


oxide vpc firewall-rules update --project "$OXIDE_PROJECT" --vpc "$OXIDE_VPC" --json-body "$OXIDE_RULES_FILE"

A ClusterAPI compatible image must be available in your Proxmox cluster. For instructions on how to build a compatible VM template see image-builder.

# The node that hosts the VM template to be used to provision VMs
export PROXMOX_SOURCENODE="pve"
# The template VM ID used for cloning VMs
export TEMPLATE_VMID=100
# The ssh authorized keys used to ssh to the machines.
export VM_SSH_KEYS="ssh-ed25519 ..., ssh-ed25519 ..."
# The IP address used for the control plane endpoint
export CONTROL_PLANE_ENDPOINT_IP=10.10.10.4
# The IP ranges for Cluster nodes
export NODE_IP_RANGES="[10.10.10.5-10.10.10.50, 10.10.10.55-10.10.10.70]"
# The gateway for the machines network-config.
export GATEWAY="10.10.10.1"
# Subnet Mask in CIDR notation for your node IP ranges
export IP_PREFIX=24
# The Proxmox network device for VMs
export BRIDGE="vmbr1"
# The dns nameservers for the machines network-config.
export DNS_SERVERS="[8.8.8.8,8.8.4.4]"
# The Proxmox nodes used for VM deployments
export ALLOWED_NODES="[pve1,pve2,pve3]"

For more information about prerequisites and advanced setups for Proxmox, see the Proxmox getting started guide.

# Scaleway credentials, project ID and region.
export SCW_ACCESS_KEY="<ACCESS_KEY>"
export SCW_SECRET_KEY="<SECRET_KEY>"
export SCW_PROJECT_ID="<PROJECT_ID>"
export SCW_REGION="fr-par"

# Scaleway Instance image names that will be used to provision servers.
export CONTROL_PLANE_MACHINE_IMAGE="<IMAGE_NAME>"
export WORKER_MACHINE_IMAGE="<IMAGE_NAME>"

For more information about prerequisites and advanced setups for CAPS, see the CAPS getting started guide.

export TINKERBELL_IP=<hegel ip>

For more information please visit Tinkerbell getting started guide.

A ClusterAPI compatible image must be available in your VCD catalog. For instructions on how to build and upload a compatible image see CAPVCD

To see all required VCD environment variables execute:

clusterctl generate cluster --infrastructure vcd --list-variables capi-quickstart
export CLUSTER_NAME=kind
export CLUSTER_NAMESPACE=vcluster
export VCLUSTER_YAML=""
export KUBERNETES_VERSION=1.23.4
export HELM_VALUES="service:\n  type: NodePort"

Please see the vcluster installation instructions for more details.

To see all required Virtink environment variables execute:

clusterctl generate cluster --infrastructure virtink --list-variables capi-quickstart

See the Virtink provider document for more details.

It is required to use an official CAPV machine images for your vSphere VM templates. See uploading CAPV machine images for instructions on how to do this.

# The vCenter server IP or FQDN
export VSPHERE_SERVER="10.0.0.1"
# The vSphere datacenter to deploy the management cluster on
export VSPHERE_DATACENTER="SDDC-Datacenter"
# The vSphere datastore to deploy the management cluster on
export VSPHERE_DATASTORE="vsanDatastore"
# The VM network to deploy the management cluster on
export VSPHERE_NETWORK="VM Network"
# The vSphere resource pool for your VMs
export VSPHERE_RESOURCE_POOL="*/Resources"
# The VM folder for your VMs. Set to "" to use the root vSphere folder
export VSPHERE_FOLDER="vm"
# The VM template to use for your VMs
export VSPHERE_TEMPLATE="ubuntu-1804-kube-v1.17.3"
# The public ssh authorized key on all machines
export VSPHERE_SSH_AUTHORIZED_KEY="ssh-rsa AAAAB3N..."
# The certificate thumbprint for the vCenter server
export VSPHERE_TLS_THUMBPRINT="97:48:03:8D:78:A9..."
# The storage policy to be used (optional). Set to "" if not required
export VSPHERE_STORAGE_POLICY="policy-one"
# The IP address used for the control plane endpoint
export CONTROL_PLANE_ENDPOINT_IP="1.2.3.4"

For more information about prerequisites, credentials management, or permissions for vSphere, see the vSphere getting started guide.

A Cluster API compatible image must be available in your Vultr account. For instructions on how to build a compatible image see image-builder for Vultr

export CLUSTER_NAME=<clustername>
export KUBERNETES_VERSION=v1.28.9
export CONTROL_PLANE_MACHINE_COUNT=1
export CONTROL_PLANE_PLANID=<plan_id>
export WORKER_MACHINE_COUNT=1
export WORKER_PLANID=<plan_id>
export MACHINE_IMAGE=<snapshot_id>
export REGION=<region>
export PLANID=<plan_id>
export VPCID=<vpc_id>
export SSHKEY_ID=<sshKey_id>

Generating the cluster configuration

For the purpose of this tutorial, we’ll name our cluster capi-quickstart.

clusterctl generate cluster capi-quickstart --flavor development \
  --kubernetes-version v1.36.1 \
  --control-plane-machine-count=3 \
  --worker-machine-count=3 \
  > capi-quickstart.yaml

Note: If you want to use MachinePools use flavor development-mp.

export CLUSTER_NAME=kind
export CLUSTER_NAMESPACE=vcluster
export VCLUSTER_YAML=""
export KUBERNETES_VERSION=1.31.2
export HELM_VALUES="service:\n  type: NodePort"

kubectl create namespace ${CLUSTER_NAMESPACE}
clusterctl generate cluster ${CLUSTER_NAME} \
    --infrastructure vcluster \
    --kubernetes-version ${KUBERNETES_VERSION} \
    --target-namespace ${CLUSTER_NAMESPACE} > capi-quickstart.yaml

As we described above, in this tutorial, we will use a LoadBalancer service in order to expose the API server of the workload cluster, so we want to use the load balancer (lb) template (rather than the default one). We’ll use the clusterctl’s --flavor flag for that:

clusterctl generate cluster capi-quickstart \
  --infrastructure="kubevirt" \
  --flavor lb \
  --kubernetes-version ${CAPK_GUEST_K8S_VERSION} \
  --control-plane-machine-count=1 \
  --worker-machine-count=1 \
  > capi-quickstart.yaml
clusterctl generate cluster capi-quickstart \
  --infrastructure azure \
  --kubernetes-version v1.36.1 \
  --control-plane-machine-count=3 \
  --worker-machine-count=3 \
  > capi-quickstart.yaml

# Cluster templates authenticate with Workload Identity by default. Modify the AzureClusterIdentity for ServicePrincipal authentication.
# See https://capz.sigs.k8s.io/topics/identities for more details.
yq -i "with(. | select(.kind == \"AzureClusterIdentity\"); .spec.type |= \"ServicePrincipal\" | .spec.clientSecret.name |= \"${AZURE_CLUSTER_IDENTITY_SECRET_NAME}\" | .spec.clientSecret.namespace |= \"${AZURE_CLUSTER_IDENTITY_SECRET_NAMESPACE}\")" capi-quickstart.yaml
clusterctl generate cluster capi-quickstart \
  --kubernetes-version v1.36.1 \
  --control-plane-machine-count=3 \
  --worker-machine-count=3 \
  > capi-quickstart.yaml

This creates a YAML file named capi-quickstart.yaml with a predefined list of Cluster API objects; Cluster, Machines, Machine Deployments, etc.

The file can be eventually modified using your editor of choice.

See clusterctl generate cluster for more details.

Apply the workload cluster

When ready, run the following command to apply the cluster manifest.

kubectl apply -f capi-quickstart.yaml

The output is similar to this:

cluster.cluster.x-k8s.io/capi-quickstart created
dockercluster.infrastructure.cluster.x-k8s.io/capi-quickstart created
kubeadmcontrolplane.controlplane.cluster.x-k8s.io/capi-quickstart-control-plane created
dockermachinetemplate.infrastructure.cluster.x-k8s.io/capi-quickstart-control-plane created
machinedeployment.cluster.x-k8s.io/capi-quickstart-md-0 created
dockermachinetemplate.infrastructure.cluster.x-k8s.io/capi-quickstart-md-0 created
kubeadmconfigtemplate.bootstrap.cluster.x-k8s.io/capi-quickstart-md-0 created

Accessing the workload cluster

The cluster will now start provisioning. You can check status with:

kubectl get cluster

You can also get an “at glance” view of the cluster and its resources by running:

clusterctl describe cluster capi-quickstart

and see an output similar to this:

NAME              PHASE         AGE   VERSION
capi-quickstart   Provisioned   8s    v1.36.1

To verify the first control plane is up:

kubectl get kubeadmcontrolplane

You should see an output is similar to this:

NAME                    CLUSTER           INITIALIZED   API SERVER AVAILABLE   REPLICAS   READY   UPDATED   UNAVAILABLE   AGE    VERSION
capi-quickstart-g2trk   capi-quickstart   true                                 3                  3         3             4m7s   v1.36.1

After the first control plane node is up and running, we can retrieve the workload cluster Kubeconfig.

clusterctl get kubeconfig capi-quickstart > capi-quickstart.kubeconfig
For Docker Desktop on macOS, Linux or Windows use kind to retrieve the kubeconfig. Docker Engine for Linux works with the default clusterctl approach.
kind get kubeconfig --name capi-quickstart > capi-quickstart.kubeconfig

Install a Cloud Provider

The Kubernetes in-tree cloud provider implementations are being removed in favor of external cloud providers (also referred to as “out-of-tree”). This requires deploying a new component called the cloud-controller-manager which is responsible for running all the cloud specific controllers that were previously run in the kube-controller-manager. To learn more, see this blog post.

Install the official cloud-provider-azure Helm chart on the workload cluster:

helm install --kubeconfig=./capi-quickstart.kubeconfig --repo https://raw.githubusercontent.com/kubernetes-sigs/cloud-provider-azure/master/helm/repo cloud-provider-azure --generate-name --set infra.clusterName=capi-quickstart --set cloudControllerManager.clusterCIDR="192.168.0.0/16"

For more information, see the CAPZ book.

Before deploying the OpenStack external cloud provider, configure the cloud.conf file for integration with your OpenStack environment:

cat > cloud.conf <<EOF
[Global]
auth-url=<your_auth_url>
application-credential-id=<your_credential_id>
application-credential-secret=<your_credential_secret>
region=<your_region>
domain-name=<your_domain_name>
EOF

For more detailed information on configuring the cloud.conf file, see the OpenStack Cloud Controller Manager documentation.

Next, create a Kubernetes secret using this configuration to securely store your cloud environment details. You can create this secret for example with:

kubectl --kubeconfig=./capi-quickstart.kubeconfig -n kube-system create secret generic cloud-config --from-file=cloud.conf

Now, you are ready to deploy the external cloud provider!

kubectl apply --kubeconfig=./capi-quickstart.kubeconfig -f https://raw.githubusercontent.com/kubernetes/cloud-provider-openstack/master/manifests/controller-manager/cloud-controller-manager-roles.yaml
kubectl apply --kubeconfig=./capi-quickstart.kubeconfig -f https://raw.githubusercontent.com/kubernetes/cloud-provider-openstack/master/manifests/controller-manager/cloud-controller-manager-role-bindings.yaml
kubectl apply --kubeconfig=./capi-quickstart.kubeconfig -f https://raw.githubusercontent.com/kubernetes/cloud-provider-openstack/master/manifests/controller-manager/openstack-cloud-controller-manager-ds.yaml

Alternatively, refer to the helm chart.

The Oxide Cloud Controller Manager (CCM) provides information about nodes from the cloud provider like the providerID.

The CCM requires a Kubernetes secret with credentials to authenticate to the Oxide API, so we’ll create that secret first:

kubectl create secret -n kube-system generic capi-quickstart-oxide-cloud-controller-manager \
    --kubeconfig ./capi-quickstart.kubeconfig \
    --from-literal=oxide-host=${OXIDE_HOST} \
    --from-literal=oxide-token=${OXIDE_TOKEN} \
    --from-literal=oxide-project=${OXIDE_PROJECT}

helm upgrade --install capi-quickstart \
    oci://ghcr.io/oxidecomputer/helm-charts/oxide-cloud-controller-manager \
    --namespace kube-system \
    --kubeconfig ./capi-quickstart.kubeconfig \
    --wait

Before deploying the Scaleway external cloud provider, you will need:

  • Your Scaleway credentials (access key and secret key)
  • Your Scaleway project ID
  • The Scaleway region where your workload cluster is deployed
  • The Private Network ID of your cluster (optional)

First, create the Secret named scaleway-secret in your workload cluster:

kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: scaleway-secret
  namespace: kube-system
type: Opaque
stringData:
  SCW_ACCESS_KEY: "xxxxxxxxxxxxxxxx"
  SCW_SECRET_KEY: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  SCW_DEFAULT_PROJECT_ID: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx"
  SCW_DEFAULT_REGION: "fr-par"
  SCW_DEFAULT_ZONE: "fr-par-1"
  PN_ID: "" # If your have a private network on your cluster, you may set its ID here.
EOF

Finally, you can deploy the scaleway-cloud-controller-manager:

kubectl apply -f https://raw.githubusercontent.com/scaleway/scaleway-cloud-controller-manager/master/examples/k8s-scaleway-ccm-latest.yml

For more detailed information on configuring and using the Scaleway external cloud provider, see the scaleway-cloud-controller-manager repository.

Deploy a CNI solution

Calico is used here as an example.

Install the official Calico Helm chart on the workload cluster:

helm repo add projectcalico https://docs.tigera.io/calico/charts --kubeconfig=./capi-quickstart.kubeconfig && \
helm install calico projectcalico/tigera-operator --kubeconfig=./capi-quickstart.kubeconfig -f https://raw.githubusercontent.com/kubernetes-sigs/cluster-api-provider-azure/main/templates/addons/calico/values.yaml --namespace tigera-operator --create-namespace

After a short while, our nodes should be running and in Ready state, let’s check the status using kubectl get nodes:

kubectl --kubeconfig=./capi-quickstart.kubeconfig get nodes
NAME                                          STATUS   ROLES           AGE    VERSION
capi-quickstart-vs89t-gmbld                   Ready    control-plane   5m33s  v1.36.1
capi-quickstart-vs89t-kf9l5                   Ready    control-plane   6m20s  v1.36.1
capi-quickstart-vs89t-t8cfn                   Ready    control-plane   7m10s  v1.36.1
capi-quickstart-md-0-55x6t-5649968bd7-8tq9v   Ready    <none>          6m5s   v1.36.1
capi-quickstart-md-0-55x6t-5649968bd7-glnjd   Ready    <none>          6m9s   v1.36.1
capi-quickstart-md-0-55x6t-5649968bd7-sfzp6   Ready    <none>          6m9s   v1.36.1

Calico not required for vcluster.

Before deploying the Calico CNI, make sure the VMs are running:

kubectl get vm

If our new VMs are running, we should see a response similar to this:

NAME                                  AGE    STATUS    READY
capi-quickstart-control-plane-7s945   167m   Running   True
capi-quickstart-md-0-zht5j            164m   Running   True

We can also read the virtual machine instances:

kubectl get vmi

The output will be similar to:

NAME                                  AGE    PHASE     IP             NODENAME             READY
capi-quickstart-control-plane-7s945   167m   Running   10.244.82.16   kind-control-plane   True
capi-quickstart-md-0-zht5j            164m   Running   10.244.82.17   kind-control-plane   True

Since our workload cluster is running within the kind cluster, we need to prevent conflicts between the kind (management) cluster’s CNI, and the workload cluster CNI. The following modifications in the default Calico settings are enough for these two CNI to work on (actually) the same environment.

  • Change the CIDR to a non-conflicting range
  • Change the value of the CLUSTER_TYPE environment variable to k8s
  • Change the value of the CALICO_IPV4POOL_IPIP environment variable to Never
  • Change the value of the CALICO_IPV4POOL_VXLAN environment variable to Always
  • Add the FELIX_VXLANPORT environment variable with the value of a non-conflicting port, e.g. "6789".

The following script downloads the Calico manifest and modifies the required field. The CIDR and the port values are examples.

curl https://raw.githubusercontent.com/projectcalico/calico/v3.29.1/manifests/calico.yaml -o calico-workload.yaml

sed -i -E 's|^( +)# (- name: CALICO_IPV4POOL_CIDR)$|\1\2|g;'\
's|^( +)# (  value: )"192.168.0.0/16"|\1\2"10.243.0.0/16"|g;'\
'/- name: CLUSTER_TYPE/{ n; s/( +value: ").+/\1k8s"/g };'\
'/- name: CALICO_IPV4POOL_IPIP/{ n; s/value: "Always"/value: "Never"/ };'\
'/- name: CALICO_IPV4POOL_VXLAN/{ n; s/value: "Never"/value: "Always"/};'\
'/# Set Felix endpoint to host default action to ACCEPT./a\            - name: FELIX_VXLANPORT\n              value: "6789"' \
calico-workload.yaml

Now, deploy the Calico CNI on the workload cluster:

kubectl --kubeconfig=./capi-quickstart.kubeconfig create -f calico-workload.yaml

After a short while, our nodes should be running and in Ready state, let’s check the status using kubectl get nodes:

kubectl --kubeconfig=./capi-quickstart.kubeconfig get nodes

Install Calico via the official helm chart using vxlan encapsulation rather than the default IP-in-IP:

helm repo add projectcalico https://docs.tigera.io/calico/charts

helm install calico-crds projectcalico/crd.projectcalico.org.v1 \
  --kubeconfig=./capi-quickstart.kubeconfig

helm upgrade --install calico projectcalico/tigera-operator \
  --kubeconfig=./capi-quickstart.kubeconfig \
  --namespace tigera-operator \
  --create-namespace \
  --set 'installation.calicoNetwork.ipPools[0].encapsulation=VXLAN' \
  --set 'installation.calicoNetwork.ipPools[0].cidr=192.168.0.0/16' \
  --set 'installation.calicoNetwork.bgp=Disabled'

Alternatively, you can install Cilium using the cilium CLI.

kubectl --kubeconfig=./capi-quickstart.kubeconfig \
  apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml

After a short while, our nodes should be running and in Ready state, let’s check the status using kubectl get nodes:

kubectl --kubeconfig=./capi-quickstart.kubeconfig get nodes
NAME                                          STATUS   ROLES           AGE    VERSION
capi-quickstart-vs89t-gmbld                   Ready    control-plane   5m33s  v1.36.1
capi-quickstart-vs89t-kf9l5                   Ready    control-plane   6m20s  v1.36.1
capi-quickstart-vs89t-t8cfn                   Ready    control-plane   7m10s  v1.36.1
capi-quickstart-md-0-55x6t-5649968bd7-8tq9v   Ready    <none>          6m5s   v1.36.1
capi-quickstart-md-0-55x6t-5649968bd7-glnjd   Ready    <none>          6m9s   v1.36.1
capi-quickstart-md-0-55x6t-5649968bd7-sfzp6   Ready    <none>          6m9s   v1.36.1

Clean Up

Delete workload cluster.

kubectl delete cluster capi-quickstart

Delete management cluster

kind delete cluster

Next steps

  • Create a second workload cluster. Simply follow the steps outlined above, but remember to provide a different name for your second workload cluster.
  • Deploy applications to your workload cluster. Use the CNI deployment steps for pointers.
  • See the clusterctl documentation for more detail about clusterctl supported actions.

Cluster API Operator Quickstart

This section provides a quickstart guide for using the Cluster API Operator to create a Kubernetes cluster. To use the clusterctl quickstart path, visit this quickstart guide.

Quickstart

This is a quickstart guide for getting Cluster API Operator up and running on your Kubernetes cluster.

For more detailed information, please refer to the full documentation.

Prerequisites

Install and configure Cluster API Operator

Configuring credential for cloud providers

Instead of using environment variables as clusterctl does, Cluster API Operator uses Kubernetes secrets to store credentials for cloud providers. Refer to provider documentation on which credentials are required.

This example uses AWS provider, but the same approach can be used for other providers.

export CREDENTIALS_SECRET_NAME="credentials-secret"
export CREDENTIALS_SECRET_NAMESPACE="default"

kubectl create secret generic "${CREDENTIALS_SECRET_NAME}" --from-literal=AWS_B64ENCODED_CREDENTIALS="${AWS_B64ENCODED_CREDENTIALS}" --namespace "${CREDENTIALS_SECRET_NAMESPACE}"

Installing Cluster API Operator

Add CAPI Operator & cert manager helm repository:

helm repo add capi-operator https://kubernetes-sigs.github.io/cluster-api-operator
helm repo add jetstack https://charts.jetstack.io --force-update
helm repo update

Install cert manager:

helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --set installCRDs=true

Deploy Cluster API components with docker provider using a single command during operator installation

helm install capi-operator capi-operator/cluster-api-operator --create-namespace -n capi-operator-system --set infrastructure.docker.enabled=true --set configSecret.name=${CREDENTIALS_SECRET_NAME} --set configSecret.namespace=${CREDENTIALS_SECRET_NAMESPACE}  --wait --timeout 90s

Docker provider can be replaced by any provider supported by clusterctl.

Other options for installing Cluster API Operator are described in full documentation.

Example API Usage

Deploy latest version of core Cluster API components:

apiVersion: operator.cluster.x-k8s.io/v1alpha2
kind: CoreProvider
metadata:
  name: cluster-api
  namespace: capi-system

Deploy Cluster API AWS provider with specific version, custom manager options and flags:

---
apiVersion: operator.cluster.x-k8s.io/v1alpha2
kind: InfrastructureProvider
metadata:
 name: aws
 namespace: capa-system
spec:
 version: v2.1.4
 configSecret:
   name: credentials-secret

Concepts

Similar to how you can use StatefulSets or Deployments in Kubernetes to manage a group of Pods, in Cluster API you can use custom resources like KubeadmControlPlane (a control plane implementation) to manage a set of control plane Machines, or you can use MachineDeployments to manage a group of worker Machines, each one of them representing a host server and the corresponding Kubernetes Node.

Extensibility is at the core of Cluster API and Cluster API providers like Cluster API provider VSphere, AWS, GCP etc. can be used to deploy Cluster API managed Clusters to your preferred infrastructure, as well as to configure many other parts of the system.

See also Quick start.

Management cluster

A Kubernetes cluster where Cluster API and one or more Cluster API providers run, and that can be used to manage the lifecycle of your Kubernetes Cluster via a set of custom resources such as Cluster or Machines.

Cluster

A “Cluster” is a custom resource that represent a Kubernetes cluster whose lifecycle is managed by Cluster API, usually also referred to as workload cluster.

Common properties such as network CIDRs are modeled as fields on the Cluster’s spec. Any information that is provider-specific is part of the custom resources referenced via infrastructureRef or controlPlaneRef and is not portable between different providers.

apiVersion: cluster.x-k8s.io/v1beta2
kind: Cluster
metadata:
  name: my-cluster
spec:
  clusterNetwork:
    pods:
      cidrBlocks:
      - 192.168.0.0/16
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    kind: VSphereCluster
    name: my-cluster-infrastructure
  controlPlaneRef:
    apiGroup: controlplane.cluster.x-k8s.io
    kind: KubeadmControlPlane
    name: my-control-plane

In most recent versions of Cluster API, the Cluster object can be used as a single point of control for the entire cluster. See ClusterClass

Machine

A “Machine” is a custom resource providing the declarative spec for infrastructure hosting a Kubernetes Node (for example, a VM).

apiVersion: cluster.x-k8s.io/v1beta2
kind: Machine
metadata:
  name: my-machine
spec:
  clusterName: my-cluster
  version: v1.35.0
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    kind: VSphereMachineTemplate
    name: my-machine-infrastructure
  bootstrap:
    configRef:
      apiGroup: bootstrap.cluster.x-k8s.io
      kind: KubeadmConfigTemplate
      name: my-bootstrap-config
status:
  nodeRef:
    name: the-node-running-on-my-machine

Common fields such as the Kubernetes version are modeled as fields on the Machine’s spec. Any information that is provider-specific is part of the custom resources referenced via infrastructureRef or bootstrap.configRef and is not portable between different providers.

If a new Machine object is created, a provider-specific controller will provision and install a new host to register as a new Node matching the Machine spec. If a Machine object is deleted, its underlying infrastructure and corresponding Node will be deleted.

Like for Pods in Kubernetes, also for Machines in Cluster API it is more convenient to not manage single Machines directly. Instead you should use resources like KubeadmControlPlane (a control plane implementation), MachineDeployments or MachinePools to manage a group of Machines.

Machine Immutability (In-place update vs. Replace)

From the perspective of Cluster API, all Machines are immutable: once they are created, they are never updated (except for labels, annotations and status), only deleted.

For this reason, MachineDeployments are preferable. MachineDeployments handle changes to machines by replacing them, in the same way core Deployments handle changes to Pod specifications.

Over time several improvement have been applied to Cluster API in oder to perform machine rollout only when necessary and for minimizing risks and impact of this operation on users workloads.

Starting from Cluster API v1.12, users can intentionally trade off some of the benefits that they get of Machine immutability by using Cluster API extensions points to add the capability to perform in-place updates under well-defined circumstances.

Notably, the Cluster API user experience will remain the same no matter of the in-place update feature is enabled or not, because ultimately users should care ONLY about the desired state.

Cluster API is responsible to choose the best strategy to achieve desired state, and with the introduction of update extensions, Cluster API is expanding the set of tools that can be used to achieve the desired state.

Infrastructure provider

A component responsible for the provisioning of infrastructure/computational resources required by the Cluster or by Machines (e.g. VMs, networking, etc.). For example, cloud Infrastructure Providers include AWS, Azure, and Google, and bare metal Infrastructure Providers include VMware, MAAS, and metal3.io.

When there is more than one way to obtain resources from the same Infrastructure Provider (such as AWS offering both EC2 and EKS), each way is referred to as a variant.

Control plane provider

A component responsible for the provisioning and for the management of the control plane of your Kubernetes Cluster, like e.g. the KubeadmControlPlane provider.

Control plane providers can take different approach on how to manage the control plane;

  • Self-provisioned: A Kubernetes control plane consisting of pods or machines wholly managed by a single Cluster API deployment. e.g kubeadm uses static pods for running components such as kube-apiserver, kube-controller-manager and kube-scheduler on control plane machines.

  • Pod-based deployments require an external hosting cluster. The control plane components are deployed using standard Deployment and StatefulSet objects and the API is exposed using a Service.

  • External or Managed control planes are offered and controlled by some system other than Cluster API, such as GKE, AKS, EKS, or IKS.

Bootstrap provider

A component responsible for turning a server into a Kubernetes node as well as for:

  1. Generating the cluster certificates, if not otherwise specified
  2. Initializing the control plane, and gating the creation of other nodes until it is complete
  3. Joining control plane and worker nodes to the cluster

Boostrap provider achieve this goal by generating BootstrapData, which contains the Machine or Node role-specific initialization data (usually cloud-init). The bootstrap data is used by the Infrastructure Provider to bootstrap a Machine into a Node.

KubeadmControlPlane

The KubeadmControlPlane is a custom resource that is provided by the Kubeadm provider, and that allows to manage a set of Machines hosting control plane Nodes created with kubeadm.

Other control plane providers implement similar resources as well.

MachineDeployment

A MachineDeployment provides declarative updates for Machines and MachineSets.

A MachineDeployment works similarly to a core Kubernetes Deployment. A MachineDeployment reconciles changes to a Machine spec by rolling out changes to 2 MachineSets, the old and the newly updated.

MachinePool

A MachinePool is a declarative spec for a group of Machines. It is similar to a MachineDeployment, but is specific to a particular Infrastructure Provider. For more information, please check out MachinePool.

MachineSet

A MachineSet’s purpose is to maintain a stable set of Machines running at any given time.

A MachineSet works similarly to a core Kubernetes ReplicaSet. MachineSets are not meant to be used directly, but are the mechanism MachineDeployments use to reconcile desired state.

MachineHealthCheck

A MachineHealthCheck defines the conditions when a Node should be considered missing or unhealthy.

If the Node matches these unhealthy conditions for a given user-configured time, the MachineHealthCheck initiates remediation of the Node. Remediation of Nodes is performed by replacing the corresponding Machine.

MachineHealthChecks will only remediate Nodes if they are owned by a MachineSet. This ensures that the Kubernetes cluster does not lose capacity, since the MachineSet will create a new Machine to replace the failed Machine.

Custom Resource Definitions (CRDs)

A CustomResourceDefinition is a built-in resource that lets you extend the Kubernetes API. Each CustomResourceDefinition represents a customization of a Kubernetes installation. The Cluster API provides and relies on several CustomResourceDefinitions:

Cluster API Manifesto

Intro

Taking inspiration from Tim Hockin’s talk at KubeCon NA 2023, also for the Cluster API project is important to define the long term vision, the manifesto of “where we are going” and “why”.

This document would hopefully provide valuable context for all users, contributors and companies investing in this project, as well as act as compass for all reviewers and maintainers currently working on it.

Community

Together we can go far.

The Cluster API community is the foundation for this project’s past, present and future. The project will continue to encourage and praise active participation and contribution.

We are an active part of a bigger ecosystem

The Cluster API community is an active part of Kubernetes SIG Cluster Lifecycle, of the broader Kubernetes community and of the CNCF.

CNCF provides the core values this project recognizes and contributes to. The Kubernetes community provides most of the practices and policies this project abides to or is inspired by.

Core goals and design principles

The project remains true to its original goals and design principles:

Cluster API is a Kubernetes sub-project focused on providing declarative APIs and tooling to simplify provisioning, upgrading, and operating multiple Kubernetes clusters.

Nowadays, like at the beginning of the project, some concepts from the above statement deserve further clarification.

Declarative APIs

The Cluster API project motto is “Kubernetes all the way down”, and this boils down to two elements.

The target state of a cluster can be defined using Kubernetes declarative APIs.

The project also implements controllers – Kubernetes reconcile loops – ensuring that desired and current state of the cluster will remain consistent over time.

The combination of those elements, declarative APIs and controllers, defines “how” this project aims to make Kubernetes and Cluster API a stable, reliable and consistent platform that just works to enable higher order business value supported by cloud-native applications.

Simplicity

Kubernetes Cluster lifecycle management is a complex problem space, especially if you consider doing this across so many different types of infrastructures.

Hiding this complexity behind a simple declarative API is “why” the Cluster API project ultimately exists.

The project is strongly committed to continue its quest in defining a set of common API primitives working consistently across all infrastructures (one API to rule them all).

Working towards graduating our API to v1 will be the next step in this journey.

While doing so, the project should be inspired by Tim Hockin’s talk, and continue to move forward without increasing operational and conceptual complexity for Cluster API’s users.

The right to be Unfinished

Like Kubernetes, also the Cluster API project claims the right to remain unfinished, because there is still a strong, foundational need to continuously evolve, improve and adapt to the changing needs of Cluster API’s users and to the growing Cloud Native ecosystem.

What is important to notice, is that being a project that is “continuously evolving” is not in contrast with another request from Cluster API’s users, which is about the project being stable, as expected by a system that has “crossed the chasm”.

Those two requests from Cluster API’s users are two sides of the same coin, a reminder that Cluster API must “evolve responsibly” by ensuring upgrade paths and avoiding (or at least minimizing) disruptions for users.

The Cluster API project will continue to “evolve responsibly” by abiding to the same guarantees that Kubernetes offers for its own API resources, and by cleanly defining the guarantees offered for the public go modules and packages.

Also ensuring a continuous and obsessive focus on CI signal, test coverage and test flakes, a predictable release calendar, and clear documentation of the release support policies and of the compatibility matrix for each release are part of the continuous effort to “evolve responsibly”.

The complexity budget

Tim Hockins explains the idea of complexity budget very well in his talk:

There is a finite amount of complexity that a project can absorb over a certain amount of time; when the complexity budget runs out, bad things happen, quality decreases, we can’t fix bugs timely etc.

Since the beginning of the Cluster API project, its maintainers intuitively handled the complexity budget by following this approach:

“We’ve got to say no to things today, so we can afford to do interesting things tomorrow”.

This is something that is never done lightly, and it is always the result of an open discussion considering the status of the codebase, the status of the project CI signal, the complexity of the new feature etc. .

Being very pragmatic, also the resources committed to implement and to maintain a feature over time must be considered when doing such an evaluation, because a model where everything falls on the shoulders of a small set of core maintainers is not sustainable.

On the other side of this coin, Cluster API maintainer’s also claim the right to reconsider new ideas or ideas previously put on hold whenever there are the conditions and the required community consensus to work on it.

Probably the most well-known case of this is about Cluster API maintainers repeatedly deferring on change requests about nodes mutability in the initial phases of the project, while starting to embrace some mutable behavior in recent releases.

Core and providers

Together we can go far.

The Cluster API project is committed to keep working with the broader CAPI community – all the Cluster API providers – as a single team in order to continuously improve and expand the capability of this solution.

As we learned the hard way, the extensibility model implemented by CAPI to support so many providers requires a complementary effort to continuously explore new ways to offer a cohesive solution, not a bag of parts.

It is important to continue and renew efforts to make it easier to bootstrap and operate a system composed of many components, to ensure consistent APIs and behaviors, to ensure quality across the board.

This effort lays its foundation in all the provider maintainers being committed to this goal, while the Cluster API project will be the venue where common guidelines are discussed and documented, as well as the place of choice where common components or utilities are developed and hosted.

Cluster Management Tasks

This section provides details for some of the operations that need to be performed when managing clusters.

Certificate Management

This section details some tasks related to certificate management.

Using Custom Certificates

Using Custom Certificates

Cluster API expects certificates and keys used for bootstrapping to follow the below convention. CABPK generates new certificates using this convention if they do not already exist.

Each certificate must be stored in a single secret named one of:

NameTypeExample
[cluster name]-caCAopenssl req -x509 -subj “/CN=Kubernetes API” -new -newkey rsa:2048 -nodes -keyout tls.key -sha256 -days 3650 -out tls.crt
[cluster name]-etcdCAopenssl req -x509 -subj “/CN=ETCD CA” -new -newkey rsa:2048 -nodes -keyout tls.key -sha256 -days 3650 -out tls.crt
[cluster name]-proxyCAopenssl req -x509 -subj “/CN=Front-End Proxy” -new -newkey rsa:2048 -nodes -keyout tls.key -sha256 -days 3650 -out tls.crt
[cluster name]-saKey Pairopenssl genrsa -out tls.key 2048 && openssl rsa -in tls.key -pubout -out tls.crt

The certificates must also be labeled with the key-value pair cluster.x-k8s.io/cluster-name=[cluster name] (where [cluster name] is the name of the cluster it should be used with).

Example

apiVersion: v1
kind: Secret
metadata:
  name: cluster1-ca
  labels:
    cluster.x-k8s.io/cluster-name: cluster1
type: kubernetes.io/tls
data:
  tls.crt: <base 64 encoded PEM>
  tls.key: <base 64 encoded PEM>

Generating a Kubeconfig

Generating a Kubeconfig with your own CA

This guide applies when you are using custom certificates for a Cluster API workload cluster, rather than relying on automatically generated certificates.

  1. Create a new Certificate Signing Request (CSR) for the admin user with the system:masters Kubernetes role, or specify any other role under O.

    openssl req  -subj "/CN=admin/O=system:masters" -new -newkey rsa:2048 -nodes -keyout admin.key  -out admin.csr
    
  2. Sign the CSR using the [cluster-name]-ca key:

    openssl x509 -req -in admin.csr -CA tls.crt -CAkey tls.key -CAcreateserial -out admin.crt -days 5 -sha256
    
  3. Update your kubeconfig with the sign key:

    kubectl config set-credentials cluster-admin --client-certificate=admin.crt --client-key=admin.key --embed-certs=true
    

Auto Rotate Certificates in KCP

Automatically rotating certificates using Kubeadm Control Plane provider

When using Kubeadm Control Plane provider (KCP) it is possible to configure automatic certificate rotations. KCP does this by triggering a rollout when the certificates on the control plane machines are about to expire.

If configured, the certificate rollout feature is available for all new and existing control plane machines.

Configuring Machine Rollout

To configure a rollout on the KCP machines you need to set .rolloutBefore.certificatesExpiryDays (minimum of 7 days).

Example:

apiVersion: controlplane.cluster.x-k8s.io/v1beta2
kind: KubeadmControlPlane
metadata:
  name: example-control-plane
spec:
  rollout:
    before:
      certificatesExpiryDays: 21 # trigger a rollout if certificates expire within 21 days
  kubeadmConfigSpec:
    clusterConfiguration:
      ...
    initConfiguration:
      ...
    joinConfiguration:
      ...
  machineTemplate:
    spec:
      infrastructureRef:
        ...
  replicas: 1
  version: v1.23.3

It is strongly recommended to set the certificatesExpiryDays to a large enough value so that all the machines will have time to complete rollout well in advance before the certificates expire.

Triggering Machine Rollout for Certificate Expiry

KCP uses the value in the corresponding Control Plane machine’s Machine.Status.CertificatesExpiryDate to check if a machine’s certificates are going to expire and if it needs to be rolled out.

Machine.Status.CertificatesExpiryDate gets its value from one of the following 2 places:

  • machine.cluster.x-k8s.io/certificates-expiry annotation value on the Machine object. This annotation is not applied by default and it can be set by users to manually override the certificate expiry information.
  • machine.cluster.x-k8s.io/certificates-expiry annotation value on the Bootstrap Config object referenced by the machine. This value is automatically set for machines bootstrapped with CABPK that are owned by the KCP resource.

The annotation value is a RFC3339 format timestamp. The annotation value on the machine object, if provided, will take precedence.

Bootstrap

This section provides details about bootstrap providers.

Cluster API bootstrap provider kubeadm

What is the Cluster API bootstrap provider kubeadm?

Cluster API bootstrap provider Kubeadm (CABPK) is a component responsible for generating a cloud-init script to turn a Machine into a Kubernetes Node. This implementation uses kubeadm for Kubernetes bootstrap.

Resources

How does CABPK work?

Assuming you have deployed the CAPI and CAPD controllers, create a Cluster object and its corresponding DockerCluster infrastructure object.

kind: DockerCluster
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
metadata:
  name: my-cluster-docker
---
kind: Cluster
apiVersion: cluster.x-k8s.io/v1beta2
metadata:
  name: my-cluster
spec:
  infrastructureRef:
    kind: DockerCluster
    apiGroup: infrastructure.cluster.x-k8s.io
    name: my-cluster-docker

Now you can start creating machines by defining a Machine, its corresponding DockerMachine object, and the KubeadmConfig bootstrap object.

kind: KubeadmConfig
apiVersion: bootstrap.cluster.x-k8s.io/v1beta2
metadata:
  name: my-control-plane1-config
---
kind: DockerMachine
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
metadata:
  name: my-control-plane1-docker
---
kind: Machine
apiVersion: cluster.x-k8s.io/v1beta2
metadata:
  name: my-control-plane1
  labels:
    cluster.x-k8s.io/cluster-name: my-cluster
    cluster.x-k8s.io/control-plane: "true"
    set: controlplane
spec:
  bootstrap:
    configRef:
      apiGroup: bootstrap.cluster.x-k8s.io
      kind: KubeadmConfig
      name: my-control-plane1-config
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    kind: DockerMachine
    name: my-control-plane1-docker
  version: "v1.19.1"

CABPK’s main responsibility is to convert a KubeadmConfig bootstrap object into a cloud-init script that is going to turn a Machine into a Kubernetes Node using kubeadm.

The cloud-init script will be saved into a secret KubeadmConfig.Status.DataSecretName and then the infrastructure provider (CAPD in this example) will pick up this value and proceed with the machine creation and the actual bootstrap.

KubeadmConfig objects

The KubeadmConfig object allows full control of Kubeadm init/join operations by exposing raw InitConfiguration, ClusterConfiguration and JoinConfiguration objects.

InitConfiguration and JoinConfiguration exposes Patches field which can be used to specify the patches from a directory, this support is available from K8s 1.22 version onwards.

CABPK will fill in some values if they are left empty with sensible defaults:

KubeadmConfig fieldDefault
clusterConfiguration.KubernetesVersionMachine.Spec.Version[1]
clusterConfiguration.clusterNameCluster.metadata.name
clusterConfiguration.controlPlaneEndpointCluster.status.apiEndpoints[0]
clusterConfiguration.networking.dnsDomainCluster.spec.clusterNetwork.serviceDomain
clusterConfiguration.networking.serviceSubnetCluster.spec.clusterNetwork.service.cidrBlocks[0]
clusterConfiguration.networking.podSubnetCluster.spec.clusterNetwork.pods.cidrBlocks[0]
joinConfiguration.discoverya short lived BootstrapToken generated by CABPK

IMPORTANT! overriding above defaults could lead to broken Clusters.

[1] if both clusterConfiguration.KubernetesVersion and Machine.Spec.Version are empty, the latest Kubernetes version will be installed (as defined by the default kubeadm behavior).

Examples

Valid combinations of configuration objects are:

  • for KCP, InitConfiguration and ClusterConfiguration for the first control plane node; JoinConfiguration for additional control plane nodes
  • for machine deployments, JoinConfiguration for worker nodes

Bootstrap control plane node:

kind: KubeadmConfig
apiVersion: bootstrap.cluster.x-k8s.io/v1beta2
metadata:
  name: my-control-plane1-config

Additional control plane nodes:

kind: KubeadmConfig
apiVersion: bootstrap.cluster.x-k8s.io/v1beta2
metadata:
  name: my-control-plane2-config
spec:
  joinConfiguration:
    controlPlane: {}

worker nodes:

kind: KubeadmConfig
apiVersion: bootstrap.cluster.x-k8s.io/v1beta2
metadata:
  name: my-worker1-config

Bootstrap Orchestration

CABPK supports multiple control plane machines initing at the same time. The generation of cloud-init scripts of different machines is orchestrated in order to ensure a cluster bootstrap process that will be compliant with the correct Kubeadm init/join sequence. More in detail:

  1. cloud-config-data generation starts only after Cluster.Status.InfrastructureReady flag is set to true.
  2. at this stage, cloud-config-data will be generated for the first control plane machine only, keeping on hold additional control plane machines existing in the cluster, if any (kubeadm init).
  3. after the ControlPlaneInitialized conditions on the cluster object is set to true, the cloud-config-data for all the other machines are generated (kubeadm join/join —control-plane).

Certificate Management

The user can choose two approaches for certificate management:

  1. provide required certificate authorities (CAs) to use for kubeadm init/kubeadm join --control-plane; such CAs should be provided as a Secrets objects in the management cluster.
  2. let KCP to generate the necessary Secrets objects with a self-signed certificate authority for kubeadm

See here for more info about certificate management with kubeadm.

Additional Features

The KubeadmConfig object supports customizing the content of the config-data. The following examples illustrate how to specify these options. They should be adapted to fit your environment and use case.

  • KubeadmConfig.Files specifies additional files to be created on the machine, either with content inline or by referencing a secret.

    files:
    - contentFrom:
        secret:
          key: node-cloud.json
          name: ${CLUSTER_NAME}-md-0-cloud-json
      owner: root:root
      path: /etc/kubernetes/cloud.json
      permissions: "0644"
    - path: /etc/kubernetes/cloud.json
      owner: "root:root"
      permissions: "0644"
      content: |
        {
          "cloud": "CustomCloud"
        }
    
  • KubeadmConfig.BootCommands specifies a list of commands to be executed very early in the boot process

    bootCommands:
      - cloud-init-per once mymkfs mkfs /dev/vdb
    
  • KubeadmConfig.PreKubeadmCommands specifies a list of commands to be executed before kubeadm init/join

    preKubeadmCommands:
      - hostname "{{ ds.meta_data.hostname }}"
      - echo "{{ ds.meta_data.hostname }}" >/etc/hostname
    
  • KubeadmConfig.PostKubeadmCommands same as above, but after kubeadm init/join

    postKubeadmCommands:
      - echo "success" >/var/log/my-custom-file.log
    
  • KubeadmConfig.Users specifies a list of users to be created on the machine

    users:
      - name: capiuser
        sshAuthorizedKeys:
        - '${SSH_AUTHORIZED_KEY}'
        sudo: ALL=(ALL) NOPASSWD:ALL
    
  • KubeadmConfig.NTP specifies NTP settings for the machine

    ntp:
      servers:
        - IP_ADDRESS
      enabled: true
    
  • KubeadmConfig.DiskSetup specifies options for the creation of partition tables and file systems on devices.

    diskSetup:
      filesystems:
      - device: /dev/disk/azure/scsi1/lun0
        extraOpts:
        - -E
        - lazy_itable_init=1,lazy_journal_init=1
        filesystem: ext4
        label: etcd_disk
      - device: ephemeral0.1
        filesystem: ext4
        label: ephemeral0
        replaceFS: ntfs
      partitions:
      - device: /dev/disk/azure/scsi1/lun0
        layout: true
        overwrite: false
        tableType: gpt
    
  • KubeadmConfig.Mounts specifies a list of mount points to be setup.

    mounts:
    - - LABEL=etcd_disk
      - /var/lib/etcddisk
    
  • KubeadmConfig.Verbosity specifies the kubeadm log level verbosity

    verbosity: 10
    

For more information on cloud-init options, see cloud config examples.

Kubelet Configuration

CAPBK has several ways to configure kubelet.

Pass KubeletConfiguration file via KubeadmConfigSpec.files

You can use KubeadmConfigSpec.files to put any files on nodes. This example puts a KubeletConfiguration file on nodes via KubeadmConfigSpec.files, and makes kubelet use it via KubeadmConfigSpec.kubeletExtraArgs. You can check available configurations of KubeletConfiguration on Kubelet Configuration (v1beta1) | Kubernetes.

This method is easy to replace the whole kubelet configuration generated by kubeadm, but it is not easy to replace only a part of the kubelet configuration.

KubeadmControlPlaneTemplate

apiVersion: controlplane.cluster.x-k8s.io/v1beta2
kind: KubeadmControlPlaneTemplate
metadata:
  name: cloudinit-control-plane
  namespace: default
spec:
  template:
    spec:
      kubeadmConfigSpec:
        files:
        # We put a KubeletConfiguration file on nodes via KubeadmConfigSpec.files
        # In this example, we directly put the file content in the KubeadmConfigSpec.files.content field.
        - path: /etc/kubernetes/kubelet/config.yaml
          owner: "root:root"
          permissions: "0644"
          content: |
            apiVersion: kubelet.config.k8s.io/v1beta1
            kind: KubeletConfiguration
            kubeReserved:
              cpu: "1"
              memory: "2Gi"
              ephemeral-storage: "1Gi"
            systemReserved:
              cpu: "500m"
              memory: "1Gi"
              ephemeral-storage: "1Gi"
            evictionHard:
              memory.available: "500Mi"
              nodefs.available: "10%"
            authentication:
              anonymous:
                enabled: false
              webhook:
                cacheTTL: 0s
                enabled: true
              x509:
                clientCAFile: /etc/kubernetes/pki/ca.crt
            authorization:
              mode: Webhook
              webhook:
                cacheAuthorizedTTL: 0s
                cacheUnauthorizedTTL: 0s
            cgroupDriver: systemd
            clusterDNS:
            - 10.128.0.10
            clusterDomain: cluster.local
            containerRuntimeEndpoint: ""
            cpuManagerReconcilePeriod: 0s
            evictionPressureTransitionPeriod: 0s
            fileCheckFrequency: 0s
            healthzBindAddress: 127.0.0.1
            healthzPort: 10248
            httpCheckFrequency: 0s
            imageMinimumGCAge: 0s
            logging:
              flushFrequency: 0
              options:
                json:
                  infoBufferSize: "0"
              verbosity: 0
            memorySwap: {}
            nodeStatusReportFrequency: 0s
            nodeStatusUpdateFrequency: 0s
            rotateCertificates: true
            runtimeRequestTimeout: 0s
            shutdownGracePeriod: 0s
            shutdownGracePeriodCriticalPods: 0s
            staticPodPath: /etc/kubernetes/manifests
            streamingConnectionIdleTimeout: 0s
            syncFrequency: 0s
            volumeStatsAggPeriod: 0s
        initConfiguration:
          nodeRegistration:
            criSocket: unix:///var/run/containerd/containerd.sock
            # Here we configure kubelet to use the KubeletConfiguration file we put on nodes via KubeadmConfigSpec.files
            kubeletExtraArgs:
              - name: config
                value: "/etc/kubernetes/kubelet/config.yaml"
        joinConfiguration:
          nodeRegistration:
            criSocket: unix:///var/run/containerd/containerd.sock
            # Here we configure kubelet to use the KubeletConfiguration file we put on nodes via KubeadmConfigSpec.files
            kubeletExtraArgs:
              - name: config
                value: "/etc/kubernetes/kubelet/config.yaml"

KubeadmConfigTemplate

apiVersion: bootstrap.cluster.x-k8s.io/v1beta2
kind: KubeadmConfigTemplate
metadata:
  name: cloudinit-default-worker-bootstraptemplate
  namespace: default
spec:
  template:
    spec:
      files:
      # We puts a KubeletConfiguration file on nodes via KubeadmConfigSpec.files
      # In this example, we directly put the file content in the KubeadmConfigSpec.files.content field.
      - path: /etc/kubernetes/kubelet/config.yaml
        owner: "root:root"
        permissions: "0644"
        content: |
          apiVersion: kubelet.config.k8s.io/v1beta1
          kind: KubeletConfiguration
          kubeReserved:
            cpu: "1"
            memory: "2Gi"
            ephemeral-storage: "1Gi"
          systemReserved:
            cpu: "500m"
            memory: "1Gi"
            ephemeral-storage: "1Gi"
          evictionHard:
            memory.available: "500Mi"
            nodefs.available: "10%"
          authentication:
            anonymous:
              enabled: false
            webhook:
              cacheTTL: 0s
              enabled: true
            x509:
              clientCAFile: /etc/kubernetes/pki/ca.crt
          authorization:
            mode: Webhook
            webhook:
              cacheAuthorizedTTL: 0s
              cacheUnauthorizedTTL: 0s
          cgroupDriver: systemd
          clusterDNS:
          - 10.128.0.10
          clusterDomain: cluster.local
          containerRuntimeEndpoint: ""
          cpuManagerReconcilePeriod: 0s
          evictionPressureTransitionPeriod: 0s
          fileCheckFrequency: 0s
          healthzBindAddress: 127.0.0.1
          healthzPort: 10248
          httpCheckFrequency: 0s
          imageMinimumGCAge: 0s
          logging:
            flushFrequency: 0
            options:
              json:
                infoBufferSize: "0"
            verbosity: 0
          memorySwap: {}
          nodeStatusReportFrequency: 0s
          nodeStatusUpdateFrequency: 0s
          rotateCertificates: true
          runtimeRequestTimeout: 0s
          shutdownGracePeriod: 0s
          shutdownGracePeriodCriticalPods: 0s
          staticPodPath: /etc/kubernetes/manifests
          streamingConnectionIdleTimeout: 0s
          syncFrequency: 0s
          volumeStatsAggPeriod: 0s
      joinConfiguration:
        nodeRegistration:
          criSocket: unix:///var/run/containerd/containerd.sock
          # Here we configure kubelet to use the KubeletConfiguration file we put on nodes via KubeadmConfigSpec.files
          kubeletExtraArgs:
            - name: config
              value: "/etc/kubernetes/kubelet/config.yaml"

Set kubelet flags via KubeadmConfigSpec.kubeletExtraArgs

We can pass kubelet command-line flags via KubeadmConfigSpec.kubeletExtraArgs. This example is equivalent to setting --kube-reserved, --system-reserved, and --eviction-hard flags for the kubelet command.

This method is useful when you want to set kubelet flags that are not configurable via the KubeletConfiguration file, however, it is not recommended to use this method to set flags that are configurable via the KubeletConfiguration file.

KubeadmControlPlaneTemplate

apiVersion: controlplane.cluster.x-k8s.io/v1beta2
kind: KubeadmControlPlaneTemplate
metadata:
  name: kubelet-extra-args-control-plane
  namespace: default
spec:
  template:
    spec:
      kubeadmConfigSpec:
        initConfiguration:
          nodeRegistration:
            criSocket: unix:///var/run/containerd/containerd.sock
            # Set kubelet flags via KubeadmConfigSpec.kubeletExtraArgs
            kubeletExtraArgs:
              - name: kube-reserved
                value: "cpu=1,memory=2Gi,ephemeral-storage=1Gi"
              - name: system-reserved
                value: "cpu=500m,memory=1Gi,ephemeral-storage=1Gi"
              - name: eviction-hard
                value: "memory.available<500Mi,nodefs.available<10%"
        joinConfiguration:
          nodeRegistration:
            criSocket: unix:///var/run/containerd/containerd.sock
            # Set kubelet flags via KubeadmConfigSpec.kubeletExtraArgs
            kubeletExtraArgs:
              - name: kube-reserved
                value: "cpu=1,memory=2Gi,ephemeral-storage=1Gi"
              - name: system-reserved
                value: "cpu=500m,memory=1Gi,ephemeral-storage=1Gi"
              - name: eviction-hard
                value: "memory.available<500Mi,nodefs.available<10%"

KubeadmConfigTemplate

apiVersion: bootstrap.cluster.x-k8s.io/v1beta2
kind: KubeadmConfigTemplate
metadata:
  name: kubelet-extra-args-default-worker-bootstraptemplate
  namespace: default
spec:
  template:
    spec:
      joinConfiguration:
        nodeRegistration:
          criSocket: unix:///var/run/containerd/containerd.sock
          # Set kubelet flags via KubeadmConfigSpec.kubeletExtraArgs
          kubeletExtraArgs:
            - name: kube-reserved
              value: "cpu=1,memory=2Gi,ephemeral-storage=1Gi"
            - name: system-reserved
              value: "cpu=500m,memory=1Gi,ephemeral-storage=1Gi"
            - name: eviction-hard
              value: "memory.available<500Mi,nodefs.available<10%"

Use kubeadm’s kubeletconfiguration patch target

We can use kubeadm’s kubeletconfiguration patch target to patch the kubelet configuration file. In this example, we put a patch file for kubeletconfiguration target in strategic patchtype on nodes via KubeadmConfigSpec.files. For more details, see Customizing components with the kubeadm API | Kubernetes

This method is useful when you want to change the kubelet configuration file partially on specific nodes. For example, you can deploy a partially patched kubelet configuration file on specific nodes based on the default configuration used for kubeadm init or kubeadm join.

KubeadmControlPlaneTemplate

apiVersion: controlplane.cluster.x-k8s.io/v1beta2
kind: KubeadmControlPlaneTemplate
metadata:
  name: kubeadm-config-template-control-plane
  namespace: default
spec:
  template:
    spec:
      kubeadmConfigSpec:
        files:
        # Here we put a patch file for kubeletconfiguration target in strategic patchtype on nodes via KubeadmConfigSpec.files
        # The naming convention of the patch file is kubeletconfiguration{suffix}+{patchtype}.json where {suffix} is an string and {patchtype} is one of the following: strategic, merge, json.
        # {suffix} determines the order of the patch files. The patches are applied in the alpha-numerical order of the {suffix}.
        - path: /etc/kubernetes/patches/kubeletconfiguration0+strategic.json
          owner: "root:root"
          permissions: "0644"
          content: |
            {
              "apiVersion": "kubelet.config.k8s.io/v1beta1",
              "kind": "KubeletConfiguration",
              "kubeReserved": {
                "cpu": "1",
                "memory": "2Gi",
                "ephemeral-storage": "1Gi",
              },
              "systemReserved": {
                "cpu": "500m",
                "memory": "1Gi",
                "ephemeral-storage": "1Gi",
              },
              "evictionHard": {
                "memory.available": "500Mi",
                "nodefs.available": "10%",
              },
            }
        initConfiguration:
          nodeRegistration:
            criSocket: unix:///var/run/containerd/containerd.sock
          # Here we specify the directory that contains the patch files
          patches:
            directory: /etc/kubernetes/patches
        joinConfiguration:
          nodeRegistration:
            criSocket: unix:///var/run/containerd/containerd.sock
          # Here we specify the directory that contains the patch files
          patches:
            directory: /etc/kubernetes/patches

KubeadmConfigTemplate

apiVersion: bootstrap.cluster.x-k8s.io/v1beta2
kind: KubeadmConfigTemplate
metadata:
  name: kubeadm-config-template-default-worker-bootstraptemplate
  namespace: default
spec:
  template:
    spec:
      files:
      # Here we put a patch file for kubeletconfiguration target in strategic patchtype on nodes via KubeadmConfigSpec.files
      # The naming convention of the patch file is kubeletconfiguration{suffix}+{patchtype}.json where {suffix} is an string and {patchtype} is one of the following: strategic, merge, json.
      # {suffix} determines the order of the patch files. The patches are applied in the alpha-numerical order of the {suffix}.
      - path: /etc/kubernetes/patches/kubeletconfiguration0+strategic.json
        owner: "root:root"
        permissions: "0644"
        content: |
          {
            "apiVersion": "kubelet.config.k8s.io/v1beta1",
            "kind": "KubeletConfiguration",
            "kubeReserved": {
              "cpu": "1",
              "memory": "2Gi",
              "ephemeral-storage": "1Gi",
            },
            "systemReserved": {
              "cpu": "500m",
              "memory": "1Gi",
              "ephemeral-storage": "1Gi",
            },
            "evictionHard": {
              "memory.available": "500Mi",
              "nodefs.available": "10%",
            },
          }
      joinConfiguration:
        nodeRegistration:
          criSocket: unix:///var/run/containerd/containerd.sock
        # Here we specify the directory that contains the patch files
        patches:
          directory: /etc/kubernetes/patches

Cluster API bootstrap provider MicroK8s

What is the Cluster API bootstrap provider MicroK8s?

Cluster API bootstrap provider MicroK8s (CABPM) is a component responsible for generating a cloud-init script to turn a Machine into a Kubernetes Node. This implementation uses MicroK8s for Kubernetes bootstrap.

Resources

CABPM configuration options

MicroK8s defines a MicroK8sControlPlane definition as well as the MachineDeployment to configure the control plane and worker nodes respectively. The MicroK8sControlPlane is linked in the cluster definition as shown in the following example:

apiVersion: cluster.x-k8s.io/v1beta2
kind: Cluster
spec:
  controlPlaneRef:
    apiGroup: controlplane.cluster.x-k8s.io
    kind: MicroK8sControlPlane
    name: capi-aws-control-plane

A control plane manifest section includes the Kubernetes version, the replica number as well as the MicroK8sConfig:

apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: MicroK8sControlPlane
spec:
  controlPlaneConfig:
    initConfiguration:
      addons:
      - dns
      - ingress
  replicas: 3
  version: v1.23.0
  ......

The worker nodes are configured through the MachineDeployment object:

apiVersion: cluster.x-k8s.io/v1beta2
kind: MachineDeployment
metadata:
  name: capi-aws-md-0
  namespace: default
spec:
  clusterName: capi-aws
  replicas: 2
  selector:
    matchLabels: null
  template:
    spec:
      clusterName: capi-aws
      version: v1.23.0     
      bootstrap:
        configRef:
          apiGroup: bootstrap.cluster.x-k8s.io
          kind: MicroK8sConfigTemplate
          name: capi-aws-md-0
---
apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
kind: MicroK8sConfigTemplate
metadata:
  name: capi-aws-md-0
  namespace: default
spec:
  template:
    spec: {}
......

In both the MicroK8sControlPlane and MicroK8sConfigTemplate you can set a MicroK8sConfig object. In the MicroK8sControlPlane case MicroK8sConfig is under MicroK8sConfig.spec.controlPlaneConfig whereas in MicroK8sConfigTemplate it is under MicroK8sConfigTemplate.spec.template.spec.

Some of the configuration options available via MicroK8sConfig are:

  • MicroK8sConfig.spec.initConfiguration.joinTokenTTLInSecs: the time-to-live (TTL) of the token used to join nodes, defaults to 10 years.
  • MicroK8sConfig.spec.initConfiguration.httpsProxy: the https proxy to be used, defaults to none.
  • MicroK8sConfig.spec.initConfiguration.httpProxy: the http proxy to be used, defaults to none.
  • MicroK8sConfig.spec.initConfiguration.noProxy: the no-proxy to be used, defaults to none.
  • MicroK8sConfig.spec.initConfiguration.addons: the list of addons to be enabled, defaults to dns.
  • MicroK8sConfig.spec.clusterConfiguration.portCompatibilityRemap: option to reuse the security group ports set for kubeadm, defaults to true.

How does CABPM work?

The main purpose of the MicroK8s bootstrap provider is to translate the users needs to a number of cloud-init files applicable for each type of cluster nodes. There are three types of cloud-inits:

  • The first node cloud-init. That node will be a control plane node and will be the one where the addons are enabled.
  • The control plane node cloud-init. The control plane nodes need to join a cluster and contribute to its HA.
  • The worker node cloud-init. These nodes join the cluster as workers.

The cloud-init scripts are saved as secrets that then the infrastructure provider uses during the machine creation. For more information on cloud-init options, see cloud config examples.

Upgrading management and workload clusters

Considerations

Supported versions of Kubernetes

If you are upgrading the version of Kubernetes for a cluster managed by Cluster API, check that the running version of Cluster API on the Management Cluster supports the target Kubernetes version.

You may need to upgrade the version of Cluster API in order to support the target Kubernetes version.

In addition, you must always upgrade between Kubernetes minor versions in sequence, e.g. if you need to upgrade from Kubernetes v1.17 to v1.19, you must first upgrade to v1.18.

Images

For kubeadm based clusters, infrastructure providers require a “machine image” containing pre-installed, matching versions of kubeadm and kubelet, ensure that relevant infrastructure machine templates reference the appropriate image for the Kubernetes version.

Upgrading using Cluster API

The high level steps to fully upgrading a cluster are to first upgrade the control plane and then upgrade the worker machines.

Upgrading the control plane machines

How to upgrade the underlying machine image

To upgrade the control plane machines underlying machine images, the MachineTemplate resource referenced by the KubeadmControlPlane must be changed. Since MachineTemplate resources are immutable, the recommended approach is to

  1. Copy the existing MachineTemplate.
  2. Modify the values that need changing, such as instance type or image ID.
  3. Create the new MachineTemplate on the management cluster.
  4. Modify the existing KubeadmControlPlane resource to reference the new MachineTemplate resource in the infrastructureRef field.

The next step will trigger a rolling update of the control plane using the new values found in the new MachineTemplate.

How to upgrade the Kubernetes control plane version

To upgrade the Kubernetes control plane version make a modification to the KubeadmControlPlane resource’s Spec.Version field. This will trigger a rolling upgrade of the control plane and, depending on the provider, also upgrade the underlying machine image.

Some infrastructure providers, such as AWS, require that if a specific machine image is specified, it has to match the Kubernetes version specified in the KubeadmControlPlane spec. In order to only trigger a single upgrade, the new MachineTemplate should be created first and then both the Version and InfrastructureTemplate should be modified in a single transaction.

How to schedule a machine rollout

The KubeadmControlPlane and MachineDepoyment resources have a spec.rollout.after field that can be set to a timestamp (RFC-3339) after which a rollout should be triggered regardless of whether there were any changes to KubeadmControlPlane.spec/MachineDeployment.spec.template or not. This would roll out replacement nodes which can be useful e.g. to perform certificate rotation, reflect changes to machine templates, move to new machines, etc.

Note that this field can only be used for triggering a rollout, not for delaying one. Specifically, a rollout can also happen before the time specified in spec.rollout.after if any changes are made to the spec before that time.

The rollout can be triggered by running the following command:

# Trigger a KubeadmControlPlane rollout.
clusterctl alpha rollout restart kubeadmcontrolplane/my-kcp

# Trigger a MachineDeployment rollout.
clusterctl alpha rollout restart machinedeployment/my-md-0

Upgrading machines managed by a MachineDeployment

Upgrades are not limited to just the control plane. This section is not related to Kubeadm control plane specifically, but is the final step in fully upgrading a Cluster API managed cluster.

It is recommended to manage machines with one or more MachineDeployments. MachineDeployments will transparently manage MachineSets and Machines to allow for a seamless scaling experience. A modification to the MachineDeployments spec will begin a rolling update of the machines. Follow these instructions for changing the template for an existing MachineDeployment.

MachineDeployments support different strategies for rolling out changes to Machines:

  • RollingUpdate

Changes are rolled out by honouring MaxUnavailable and MaxSurge values. Only values allowed are of type Int or Strings with an integer and percentage symbol e.g “5%”.

  • OnDelete

Changes are rolled out driven by the user or any entity deleting the old Machines. Only when a Machine is fully deleted a new one will come up.

For a more in-depth look at how MachineDeployments manage scaling events, take a look at the MachineDeployment controller documentation and the MachineSet controller documentation.

Support for external etcd

Cluster API Bootstrap Provider Kubeadm supports using an external etcd cluster for your workload Kubernetes clusters.

⚠️ Warnings ⚠️

Before getting started you should be aware of the expectations that come with using an external etcd cluster.

  • Cluster API is unable to manage any aspect of the external etcd cluster.
  • Depending on how you configure your etcd nodes you may incur additional cloud costs in data transfer.
    • As an example, cross availability zone traffic can cost money on cloud providers. You don’t have to deploy etcd across availability zones, but if you do please be aware of the costs.

Getting started

To use this, you will need to create an etcd cluster and generate an apiserver-etcd-client certificate and private key. This behaviour can be tested using kubeadm and etcdadm.

Setting up etcd with kubeadm

CA certificates are required to setup etcd cluster. If you already have a CA then the CA’s crt and key must be copied to /etc/kubernetes/pki/etcd/ca.crt and /etc/kubernetes/pki/etcd/ca.key.

If you do not already have a CA then run command kubeadm init phase certs etcd-ca. This creates two files:

  • /etc/kubernetes/pki/etcd/ca.crt
  • /etc/kubernetes/pki/etcd/ca.key

This certificate and private key are used to sign etcd server and peer certificates as well as other client certificates (like the apiserver-etcd-client certificate or the etcd-healthcheck-client certificate). More information on how to setup external etcd with kubeadm can be found here.

Once the etcd cluster is setup, you will need the following files from the etcd cluster:

  1. /etc/kubernetes/pki/apiserver-etcd-client.crt and /etc/kubernetes/pki/apiserver-etcd-client.key
  2. /etc/kubernetes/pki/etcd/ca.crt

You’ll use these files to create the necessary Secrets on the management cluster (see the “Creating the required Secrets” section).

Setting up etcd with etcdadm (Alpha)

etcdadm creates the CA if one does not exist, uses it to sign its server and peer certificates, and finally to sign the API server etcd client certificate. The CA’s crt and key generated using etcdadm are stored in /etc/etcd/pki/ca.crt and /etc/etcd/pki/ca.key. etcdadm also generates a certificate for the API server etcd client; the certificate and private key are found at /etc/etcd/pki/apiserver-etcd-client.crt and /etc/etcd/pki/apiserver-etcd-client.key, respectively.

Once the etcd cluster has been bootstrapped using etcdadm, you will need the following files from the etcd cluster:

  1. /etc/etcd/pki/apiserver-etcd-client.crt and /etc/etcd/pki/apiserver-etcd-client.key
  2. /etc/etcd/pki/etcd/ca.crt

You’ll use these files in the next section to create the necessary Secrets on the management cluster.

Creating the required Secrets

Regardless of the method used to bootstrap the etcd cluster, you will need to use the certificates copied from the etcd cluster to create some Kubernetes Secrets on the management cluster.

In the commands below to create the Secrets, substitute $CLUSTER_NAME with the name of the workload cluster to be created by CAPI, and substitute $CLUSTER_NAMESPACE with the name of the namespace where the workload cluster will be created. The namespace can be omitted if the workload cluster will be created in the default namespace.

First, you will need to create a Secret containing the API server etcd client certificate and key. This command assumes the certificate and private key are in the current directory; adjust your command accordingly if they are not:

# Kubernetes API server etcd client certificate and key
kubectl create secret tls $CLUSTER_NAME-apiserver-etcd-client \
  --cert apiserver-etcd-client.crt \
  --key apiserver-etcd-client.key \
  --namespace $CLUSTER_NAMESPACE

Next, create a Secret for the etcd cluster’s CA certificate. The kubectl create secret tls command requires both a certificate and a key, but the key isn’t needed by CAPI. Instead, use the kubectl create secret generic command, and note that the file containing the CA certificate must be named tls.crt:

# Etcd's CA crt file to validate the generated client certificates
kubectl create secret generic $CLUSTER_NAME-etcd \
  --from-file tls.crt \
  --namespace $CLUSTER_NAMESPACE

Note: The above commands will base64 encode the certificate/key files by default.

Alternatively you can base64 encode the files and put them in two secrets. The secrets must be formatted as follows and the cert material must be base64 encoded:

# Kubernetes APIServer etcd client certificate
kind: Secret
apiVersion: v1
metadata:
  name: $CLUSTER_NAME-apiserver-etcd-client
  namespace: $CLUSTER_NAMESPACE
data:
  tls.crt: |
    LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCRENDQWV5Z0F3SUJBZ0lJZFlkclZUMzV0
    NW93RFFZSktvWklodmNOQVFFTEJRQXdEekVOTUFzR0ExVUUKQXhNRVpYUmpaREFlRncweE9UQTVN
    ...
  tls.key: |
    LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBdlFlTzVKOE5j
    VCtDeGRubFR3alpuQ3YwRzByY0tETklhZzlSdFdrZ1p4MEcxVm1yClA4Zy9BRkhXVHdxSTUrNi81
    ...
# Etcd's CA crt file to validate the generated client certificates
kind: Secret
apiVersion: v1
metadata:
  name: $CLUSTER_NAME-etcd
  namespace: $CLUSTER_NAMESPACE
data:
  tls.crt: |
    LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURBRENDQWVpZ0F3SUJBZ0lJRDNrVVczaDIy
    K013RFFZSktvWklodmNOQVFFTEJRQXdEekVOTUFzR0ExVUUKQXhNRVpYUmpaREFlRncweE9UQTVN
    ...

The Secrets must be created before creating the workload cluster.

Configuring CABPK

Once the Secrets are in place on the management cluster, the rest of the process leverages standard kubeadm configuration. Configure your ClusterConfiguration for the workload cluster as follows:

apiVersion: bootstrap.cluster.x-k8s.io/v1beta2
kind: KubeadmConfig
metadata:
  name: CLUSTER_NAME-controlplane-0
  namespace: CLUSTER_NAMESPACE
spec:
  ... # initConfiguration goes here
  clusterConfiguration:
    etcd:
      external:
        endpoints:
          - https://10.0.0.230:2379
        caFile: /etc/kubernetes/pki/etcd/ca.crt
        certFile: /etc/kubernetes/pki/apiserver-etcd-client.crt
        keyFile: /etc/kubernetes/pki/apiserver-etcd-client.key
    ... # other clusterConfiguration goes here

Create your workload cluster as normal. The new workload cluster should use the configured external etcd nodes instead of creating co-located etcd Pods on the control plane nodes.

Additional Notes/Caveats

  • Depending on the provider, additional changes to the workload cluster’s manifest may be necessary to ensure the new CAPI-managed nodes have connectivity to the existing etcd nodes. For example, on AWS you will need to leverage the additionalSecurityGroups field on the AWSMachine and/or AWSMachineTemplate objects to add the CAPI-managed nodes to a security group that has connectivity to the existing etcd cluster. Other mechanisms exist for other providers.

Using Kustomize with Workload Cluster Manifests

Although the clusterctl generate cluster command exposes a number of different configuration values for customizing workload cluster YAML manifests, some users may need additional flexibility above and beyond what clusterctl generate cluster or the example “flavor” templates that some CAPI providers supply (as an example, see these flavor templates for the Cluster API Provider for Azure). In the future, a templating solution may be integrated into clusterctl to help address this need, but in the meantime users can use kustomize as a solution to this need.

This document provides a few examples of using kustomize with Cluster API. All of these examples assume that you are using a directory structure that looks something like this:

.
├── base
│   ├── base.yaml
│   └── kustomization.yaml
└── overlays
    ├── custom-ami
    │   ├── custom-ami.json
    │   └── kustomization.yaml
    └── mhc
        ├── kustomization.yaml
        └── workload-mhc.yaml

In the overlay directories, the “base” (unmodified) Cluster API configuration (perhaps generated using clusterctl generate cluster) would be referenced as a resource in kustomization.yaml using ../../base.

Example: Using Kustomize to Specify Custom Images

Users can use kustomize to specify custom OS images for Cluster API nodes. Using the Cluster API Provider for AWS (CAPA) as an example, the following kustomization.yaml would leverage a JSON 6902 patch to modify the AMI for nodes in a workload cluster:

---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - ../../base
patchesJson6902:
  - path: custom-ami.json
    target:
      group: infrastructure.cluster.x-k8s.io
      kind: AWSMachineTemplate
      name: ".*"
      version: v1alpha3

The referenced JSON 6902 patch in custom-ami.json would look something like this:

[
    { "op": "add", "path": "/spec/template/spec/ami", "value": "ami-042db61632f72f145"}
]

This configuration assumes that the workload cluster only uses MachineDeployments. Since MachineDeployments and the KubeadmControlPlane both leverage AWSMachineTemplates, this kustomize configuration would catch all nodes in the workload cluster.

Example: Adding a MachineHealthCheck for a Workload Cluster

Users could also use kustomize to combine additional resources, like a MachineHealthCheck (MHC), with the base Cluster API manifest. In an overlay directory, specify the following in kustomization.yaml:

---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - ../../base
  - workload-mhc.yaml

The content of the workload-mhc.yaml file would be the definition of a standard MHC:

apiVersion: cluster.x-k8s.io/v1beta2
kind: MachineHealthCheck
metadata:
  name: md-0-mhc
spec:
  clusterName: test
  # maxUnhealthy: 40%
  nodeStartupTimeout: 10m
  selector:
    matchLabels:
      cluster.x-k8s.io/deployment-name: md-0
  unhealthyNodeConditions:
  - type: Ready
    status: Unknown
    timeout: 300s
  - type: Ready
    status: "False"
    timeout: 300s
  unhealthyMachineConditions:
  - type: "NodeReady"
    status: Unknown
    timeout: 1800s
  - type: "InfrastructureReady"
    status: "False"
    timeout: 1800s

You would want to ensure the clusterName field in the MachineHealthCheck manifest appropriately matches the name of the workload cluster, taking into account any transformations you may have specified in kustomization.yaml (like the use of “namePrefix” or “nameSuffix”).

Running kustomize build . with this configuration would append the MHC to the base Cluster API manifest, thus creating the MHC at the same time as the workload cluster.

Modifying Names

The kustomize “namePrefix” and “nameSuffix” transformers are not currently “Cluster API aware.” Although it is possible to use these transformers with Cluster API manifests, doing so requires separate patches for Clusters versus infrastructure-specific equivalents (like an AzureCluster or a vSphereCluster). This can significantly increase the complexity of using kustomize for this use case.

Modifying the transformer configurations for kustomize can make it more effective with Cluster API. For example, changes to the nameReference transformer in kustomize will enable kustomize to know about the references between Cluster API objects in a manifest. See here for more information on transformer configurations.

Add the following content to the namereference.yaml transformer configuration:

- kind: Cluster
  group: cluster.x-k8s.io
  version: v1beta2
  fieldSpecs:
  - path: spec/clusterName
    kind: MachineDeployment
  - path: spec/template/spec/clusterName
    kind: MachineDeployment

- kind: AWSCluster
  group: infrastructure.cluster.x-k8s.io
  version: v1alpha3
  fieldSpecs:
  - path: spec/infrastructureRef/name
    kind: Cluster

- kind: KubeadmControlPlane
  group: controlplane.cluster.x-k8s.io
  version: v1alpha3
  fieldSpecs:
  - path: spec/controlPlaneRef/name
    kind: Cluster

- kind: AWSMachine
  group: infrastructure.cluster.x-k8s.io
  version: v1alpha3
  fieldSpecs:
  - path: spec/infrastructureRef/name
    kind: Machine

- kind: KubeadmConfig
  group: bootstrap.cluster.x-k8s.io
  version: v1alpha3
  fieldSpecs:
  - path: spec/bootstrap/configRef/name
    kind: Machine

- kind: AWSMachineTemplate
  group: infrastructure.cluster.x-k8s.io
  version: v1alpha3
  fieldSpecs:
  - path: spec/template/spec/infrastructureRef/name
    kind: MachineDeployment
  - path: spec/infrastructureTemplate/name
    kind: KubeadmControlPlane

- kind: KubeadmConfigTemplate
  group: bootstrap.cluster.x-k8s.io
  version: v1alpha3
  fieldSpecs:
  - path: spec/template/spec/bootstrap/configRef/name
    kind: MachineDeployment

Including this custom configuration in a kustomization.yaml would then enable the use of simple “namePrefix” and/or “nameSuffix” directives, like this:

---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - ../../base
configurations:
  - namereference.yaml
namePrefix: "blue-"
nameSuffix: "-dev"

Running kustomize build . with this configuration would modify the name of all the Cluster API objects and the associated referenced objects, adding “blue-” at the beginning and appending “-dev” at the end.

Upgrading Cluster API components

When to upgrade

In general, it’s recommended to upgrade to the latest version of Cluster API to take advantage of bug fixes, new features and improvements.

Considerations

If moving between different API versions, there may be additional tasks that you need to complete. See below for detailed instructions.

Ensure that the version of Cluster API is compatible with the Kubernetes version of the management cluster.

Upgrading to newer versions of 1.0.x

Use clusterctl to upgrade between versions of Cluster API 1.0.x.

Control Plane Management

This section provides details about control plane providers.

Kubeadm control plane

Using the Kubeadm control plane type to manage a control plane provides several ways to upgrade control plane machines.

Kubeconfig management

KCP will generate and manage the admin Kubeconfig for clusters. The client certificate for the admin user is created with a valid lifespan of a year, and will be automatically regenerated when the cluster is reconciled and has less than 6 months of validity remaining.

Upgrades

See the section on upgrading clusters.

Running workloads on control plane machines

We don’t suggest running workloads on control planes, and highly encourage avoiding it unless absolutely necessary.

However, in the case the user wants to run non-control plane workloads on control plane machines they are ultimately responsible for ensuring the proper functioning of those workloads, given that KCP is not aware of the specific requirements for each type of workload (e.g. preserving quorum, shutdown procedures etc.).

In order to do so, the user could leverage on the same assumption that applies to all the Cluster API Machines:

  • The Kubernetes node hosted on the Machine will be cordoned & drained before removal (with well known exceptions like full Cluster deletion).
  • The Machine will respect PreDrainDeleteHook and PreTerminateDeleteHook. see the Machine Deletion Phase Hooks proposal for additional details.

In-place propagation

Changes to the following fields of KubeadmControlPlane are propagated in-place to the Machines and do not trigger a full rollout:

  • .spec.machineTemplate.metadata.labels
  • .spec.machineTemplate.metadata.annotations
  • .spec.nodeDrainTimeout
  • .spec.nodeDeletionTimeout
  • .spec.nodeVolumeDetachTimeout

Changes to the following fields of KubeadmControlPlane are propagated in-place to the InfrastructureMachine and KubeadmConfig:

  • .spec.machineTemplate.metadata.labels
  • .spec.machineTemplate.metadata.annotations

Note: Changes to these fields will not be propagated to Machines, InfraMachines and KubeadmConfigs that are marked for deletion (example: because of scale down).

MicroK8s control plane provider

What is the Cluster API MicroK8s control plane provider ?

Cluster API MicroK8s control plane provider (CACPM) is a component responsible for managing the control plane of the provisioned clusters. This implementation uses MicroK8s for cluster provisioning and management.

Currently the CACPM does not expose any functionality. It serves however the following purposes:

  • Sets the ProviderID on the provisioned nodes. MicroK8s will not set the provider ID automatically so the control plane provider identifies the VMs’ provider IDs and updates the respective machine objects.
  • Updates the machine state.
  • Generates and provisions the kubeconfig file used for accessing the cluster. The kubeconfig file is stored as a secret and the user can retrieve via clusterctl.

Updating Machine Infrastructure and Bootstrap Templates

Updating Infrastructure Machine Templates

Several different components of Cluster API leverage infrastructure machine templates, including KubeadmControlPlane, MachineDeployment, and MachineSet. These MachineTemplate resources should be immutable, unless the infrastructure provider documentation indicates otherwise for certain fields (see below for more details).

The correct process for modifying an infrastructure machine template is as follows:

  1. Duplicate an existing template. Users can use kubectl get <MachineTemplateType> <name> -o yaml > file.yaml to retrieve a template configuration from a running cluster to serve as a starting point.
  2. Update the desired fields. Fields that might need to be modified could include the SSH key, the AWS instance type, or the Azure VM size. Refer to the provider-specific documentation for more details on the specific fields that each provider requires or accepts.
  3. Give the newly-modified template a new name by modifying the metadata.name field (or by using metadata.generateName).
  4. Create the new infrastructure machine template on the API server using kubectl. (If the template was initially created using the command in step 1, be sure to clear out any extraneous metadata, including the resourceVersion field, before trying to send it to the API server.)

Once the new infrastructure machine template has been persisted, users may modify the object that was referencing the infrastructure machine template. For example, to modify the infrastructure machine template for the KubeadmControlPlane object, users would modify the spec.infrastructureTemplate.name field. For a MachineDeployment, users would need to modify the spec.template.spec.infrastructureRef.name field and the controller would orchestrate the upgrade by managing MachineSets pointing to the new and old references. In the case of a MachineSet with no MachineDeployment owner, if its template reference is changed, it will only affect upcoming Machines.

In all cases, the name field should be updated to point to the newly-modified infrastructure machine template. This will trigger a rolling update. (This same process is described in the documentation for upgrading the underlying machine image for KubeadmControlPlane in the “How to upgrade the underlying machine image” section.)

Some infrastructure providers may, at their discretion, choose to support in-place modifications of certain infrastructure machine template fields. This may be useful if an infrastructure provider is able to make changes to running instances/machines, such as updating allocated memory or CPU capacity. In such cases, however, Cluster API will not trigger a rolling update.

Updating Bootstrap Templates

Several different components of Cluster API leverage bootstrap templates, including MachineDeployment, and MachineSet. When used in MachineDeployment or MachineSet changes to those templates do not trigger rollouts of already existing Machines. New Machines are created based on the current version of the bootstrap template.

The correct process for modifying a bootstrap template is as follows:

  1. Duplicate an existing template. Users can use kubectl get <BootstrapTemplateType> <name> -o yaml > file.yaml to retrieve a template configuration from a running cluster to serve as a starting point.
  2. Update the desired fields.
  3. Give the newly-modified template a new name by modifying the metadata.name field (or by using metadata.generateName).
  4. Create the new bootstrap template on the API server using kubectl. (If the template was initially created using the command in step 1, be sure to clear out any extraneous metadata, including the resourceVersion field, before trying to send it to the API server.)

Once the new bootstrap template has been persisted, users may modify the object that was referencing the bootstrap template. For example, to modify the bootstrap template for the MachineDeployment object, users would modify the spec.template.spec.bootstrap.configRef.name field. The name field should be updated to point to the newly-modified bootstrap template. This will trigger a rolling update.

Workload bootstrap using GitOps

Cluster API can be utilized in combination with the Cluster API addon provider for helm (CAAPH) to install and configure a GitOps agent and then the GitOps agent hydrates clusters automatically with various workloads.

Prerequisites

Follow the quickstart setup guide for your provider but ensure that CAAPH is installed via including the addon=helm with either:

  1. clusterctl using clusterctl init --infrastructure ### --addon helm or
  2. Cluster API Operator using helm install capi-operator capi-operator/cluster-api-operator ... --set infrastructure=#### --set addon=helm

Bootstrap ManagedCluster using ArgoCD

Add the labels argoCDChart: enabled and guestbook: enabled to your desired workload cluster yaml file in the Cluster metadata section, for example:

apiVersion: cluster.x-k8s.io/v1beta2
kind: Cluster
metadata:
  name: my-cluster
  namespace: default
  labels:
    argoCDChart: enabled
    guestbook: enabled

Then create and kubectl apply -f the following file on the management cluster to install the ArgoCD agent and the sample guestbook app to the workload cluster via the argo helm charts using CAAPH:

apiVersion: addons.cluster.x-k8s.io/v1alpha1
kind: HelmChartProxy
metadata:
  name: argocd
spec:
  clusterSelector:
    matchLabels:
      argoCDChart: enabled
  repoURL: https://argoproj.github.io/argo-helm
  chartName: argo-cd
  options:
    waitForJobs: true
    wait: true
    timeout: 5m
    install:
      createNamespace: true
---
apiVersion: addons.cluster.x-k8s.io/v1alpha1
kind: HelmChartProxy
metadata:
  name: argocdguestbook
spec:
  clusterSelector:
    matchLabels:
      guestbook: enabled
  repoURL: https://argoproj.github.io/argo-helm
  chartName: argocd-apps
  options:
    waitForJobs: true
    wait: true
    timeout: 5m
    install:
      createNamespace: true
  valuesTemplate: |
    applications:
      - name: guestbook
        namespace: argocd
        finalizers:
        - resources-finalizer.argocd.argoproj.io
        project: default
        sources:
          - repoURL: https://github.com/argoproj/argocd-example-apps.git
            path: guestbook
            targetRevision: HEAD
        destination:
          server: https://kubernetes.default.svc
          namespace: guestbook
        syncPolicy:
          automated:
            prune: false
            selfHeal: false
          syncOptions:
          - CreateNamespace=true
        revisionHistoryLimit: null
    ignoreDifferences:
      - group: apps
        kind: Deployment
        jsonPointers:
        - /spec/replicas
    info:
    - name: url
      value: https://argoproj.github.io/

This will automatically install ArgoCD in the ArgoCD namespace and the guestbook application into the guestbook namespace. Adding or labeling additional clusters with argoCDChart: enabled and guestbook: enabled will automatically install the ArgoCD agent and the guestbook application and there is no need to create additional CAAPH HelmChartProxy entries.

The ArgoCD console can be viewed by connecting to the workload cluster and then doing the following:

# Get the admin password
kubectl get secrets argocd-initial-admin-secret -n argocd --template="{{index .data.password | base64decode}}"
kubectl port-forward service/capiargo-argocd-server -n default 8080:443
# and then open the browser on http://localhost:8080 and accept the certificate

The Guestbook application deployment can be seen once logged into the ArgoCD console. Since the GitOps agent points to the git repository, any changes to the repository will automatically update the workload cluster. The git repository could be configured to utilize the App of Apps pattern to install all platform requirements for the cluster. The App of Apps pattern is a single application that installs all other applications and configurations for the cluster.

This same pattern could also utilize the Flux agent using the Flux helm charts being installed and configured by CAAPH.

Automated Machine management

This section details some tasks related to automated Machine management.

Scaling Nodes

This section applies only to worker Machines. You can add or remove compute capacity for your cluster workloads by creating or removing Machines. A Machine expresses intent to have a Node with a defined form factor.

Machines can be owned by scalable resources i.e. MachineSet and MachineDeployments.

You can scale MachineSets and MachineDeployments in or out by expressing intent via .spec.replicas or updating the scale subresource e.g kubectl scale machinedeployment foo --replicas=5.

If you need to prioritize which Machines get deleted during scale-down, add the cluster.x-k8s.io/delete-machine label to the Machine. KCP or a MachineSet will delete labeled control plane or worker Machines first, and this label has top priority over all delete policies.

Note: The label only affects MachineSet scale-down; in a MachineDeployment, the choice of MachineSet to scale-down may bypass labeled Machines.

When you delete a Machine directly or by scaling down, the same process takes place in the same order:

  • The Node backed by that Machine will try to be drained indefinitely and will wait for any volume to be detached from the Node unless you specify a .spec.nodeDrainTimeout.
    • CAPI uses default kubectl draining implementation with -–ignore-daemonsets=true. If you needed to ensure DaemonSets eviction you’d need to do so manually by also adding proper taints to avoid rescheduling.
  • The infrastructure backing that Node will try to be deleted indefinitely.
  • Only when the infrastructure is gone, the Node will try to be deleted indefinitely unless you specify .spec.nodeDeletionTimeout.

Using the Cluster Autoscaler

This section applies only to worker Machines. Cluster Autoscaler is a tool that automatically adjusts the size of the Kubernetes cluster based on the utilization of Pods and Nodes in your cluster. For more general information about the Cluster Autoscaler, please see the project documentation.

The following instructions are a reproduction of the Cluster API provider specific documentation from the Autoscaler project documentation.

Cluster Autoscaler on Cluster API

The cluster autoscaler on Cluster API uses the cluster-api project to manage the provisioning and de-provisioning of nodes within a Kubernetes cluster.

Table of Contents:

Kubernetes Version

The cluster-api provider requires Kubernetes v1.16 or greater to run the v1alpha3 version of the API.

Starting the Autoscaler

To enable the Cluster API provider, you must first specify it in the command line arguments to the cluster autoscaler binary. For example:

cluster-autoscaler --cloud-provider=clusterapi

Please note, this example only shows the cloud provider options, you will most likely need other command line flags. For more information you can invoke cluster-autoscaler --help to see a full list of options.

Configuring node group auto discovery

You must configure node group auto discovery to inform cluster autoscaler which cluster in which to find for scalable node groups.

Limiting cluster autoscaler to only match against resources in the blue namespace

--node-group-auto-discovery=clusterapi:namespace=blue

Limiting cluster autoscaler to only match against resources belonging to Cluster test1

--node-group-auto-discovery=clusterapi:clusterName=test1

Limiting cluster autoscaler to only match against resources matching the provided labels

--node-group-auto-discovery=clusterapi:color=green,shape=square

These can be mixed and matched in any combination, for example to only match resources in the staging namespace, belonging to the purple cluster, with the label owner=jim:

--node-group-auto-discovery=clusterapi:namespace=staging,clusterName=purple,owner=jim

Connecting cluster-autoscaler to Cluster API management and workload Clusters

Important

--cloud-config is the flag for specifying a mount volume path to the kubernetes configuration (ie KUBECONFIG) to the cluster-autoscaler for communicating with the cluster-api management cluster for the purpose of scaling machines.

Important

``–kubeconfig` is the flag for specifying a mount volume path to the kubernetes configuration (ie KUBECONFIG) to the cluster-autoscaler for communicating with the cluster-api workload cluster for the purpose of watching Nodes and Pods. This flag can be affected by the desired topology for deploying the cluster-autoscaler, please see the diagrams below for more information.

You will also need to provide the path to the kubeconfig(s) for the management and workload cluster you wish cluster-autoscaler to run against. To specify the kubeconfig path for the workload cluster to monitor, use the --kubeconfig option and supply the path to the kubeconfig. If the --kubeconfig option is not specified, cluster-autoscaler will attempt to use an in-cluster configuration. To specify the kubeconfig path for the management cluster to monitor, use the --cloud-config option and supply the path to the kubeconfig. If the --cloud-config option is not specified it will fall back to using the kubeconfig that was provided with the --kubeconfig option.

Autoscaler running in a joined cluster using service account credentials

+-----------------+
| mgmt / workload |
| --------------- |
|    autoscaler   |
+-----------------+

Use in-cluster config for both management and workload cluster:

cluster-autoscaler --cloud-provider=clusterapi

Autoscaler running in workload cluster using service account credentials, with separate management cluster

+--------+              +------------+
|  mgmt  |              |  workload  |
|        | cloud-config | ---------- |
|        |<-------------+ autoscaler |
+--------+              +------------+

Use in-cluster config for workload cluster, specify kubeconfig for management cluster:

cluster-autoscaler --cloud-provider=clusterapi \
                   --cloud-config=/mnt/kubeconfig

Autoscaler running in management cluster using service account credentials, with separate workload cluster

+------------+             +----------+
|    mgmt    |             | workload |
| ---------- | kubeconfig  |          |
| autoscaler +------------>|          |
+------------+             +----------+

Use in-cluster config for management cluster, specify kubeconfig for workload cluster:

cluster-autoscaler --cloud-provider=clusterapi \
                   --kubeconfig=/mnt/kubeconfig \
                   --clusterapi-cloud-config-authoritative

Autoscaler running anywhere, with separate kubeconfigs for management and workload clusters

+--------+               +------------+             +----------+
|  mgmt  |               |     ?      |             | workload |
|        |  cloud-config | ---------- | kubeconfig  |          |
|        |<--------------+ autoscaler +------------>|          |
+--------+               +------------+             +----------+

Use separate kubeconfigs for both management and workload cluster:

cluster-autoscaler --cloud-provider=clusterapi \
                   --kubeconfig=/mnt/workload.kubeconfig \
                   --cloud-config=/mnt/management.kubeconfig

Autoscaler running anywhere, with a common kubeconfig for management and workload clusters

+---------------+             +------------+
| mgmt/workload |             |     ?      |
|               |  kubeconfig | ---------- |
|               |<------------+ autoscaler |
+---------------+             +------------+

Use a single provided kubeconfig for both management and workload cluster:

cluster-autoscaler --cloud-provider=clusterapi \
                   --kubeconfig=/mnt/workload.kubeconfig

Enabling Autoscaling

To enable the automatic scaling of components in your cluster-api managed cloud there are a few annotations you need to provide. These annotations must be applied to either MachineSet, MachineDeployment, or MachinePool resources depending on the type of cluster-api mechanism that you are using.

There are two annotations that control how a cluster resource should be scaled:

  • cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size - This specifies the minimum number of nodes for the associated resource group. The autoscaler will not scale the group below this number. Please note that the cluster-api provider will not scale down to, or from, zero unless that capability is enabled (see Scale from zero support).

  • cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size - This specifies the maximum number of nodes for the associated resource group. The autoscaler will not scale the group above this number.

The autoscaler will monitor any MachineSet, MachineDeployment, or MachinePool containing both of these annotations.

Note: The cluster autoscaler does not enforce the node group sizes. If a node group is below the minimum number of nodes, or above the maximum number of nodes, the cluster autoscaler will not scale that node group up or down. The cluster autoscaler can be configured to enforce the minimum node group size by enabling the --enforce-node-group-min-size flag. Please see this entry in the Cluster Autoscaler FAQ for more information.

Note: MachinePool support in cluster-autoscaler requires a provider implementation that supports the “MachinePool Machines” feature.

Scale from zero support

The Cluster API community has defined an opt-in method for infrastructure providers to enable scaling from zero-sized node groups in the Opt-in Autoscaling from Zero enhancement. As defined in the enhancement, each provider may add support for scaling from zero to their provider, but they are not required to do so. If you are expecting built-in support for scaling from zero, please check with the Cluster API infrastructure providers that you are using.

If your Cluster API provider does not have support for scaling from zero, you may still use this feature through the capacity annotations. You may add these annotations to your MachineDeployments, or MachineSets if you are not using MachineDeployments (it is not needed on both), to instruct the cluster autoscaler about the sizing of the nodes in the node group. At the minimum, you must specify the CPU and memory annotations, these annotations should match the expected capacity of the nodes created from the infrastructure.

Note: The scale from zero annotations will override any capacity information supplied by the Cluster API provider in the infrastructure machine templates. If both the annotations and the provider supplied capacity information are present, the annotations will take precedence.

For example, if my MachineDeployment will create nodes that have “16000m” CPU, “128G” memory, “100Gi” ephemeral disk storage, 2 NVidia GPUs, and can support 200 max pods, the following annotations will instruct the autoscaler how to expand the node group from zero replicas:

apiVersion: cluster.x-k8s.io/v1alpha4
kind: MachineDeployment
metadata:
  annotations:
    cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "5"
    cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "0"
    capacity.cluster-autoscaler.kubernetes.io/memory: "128G"
    capacity.cluster-autoscaler.kubernetes.io/cpu: "16"
    capacity.cluster-autoscaler.kubernetes.io/ephemeral-disk: "100Gi"
    capacity.cluster-autoscaler.kubernetes.io/maxPods: "200"
    // Device Plugin
    // Comment out the below annotation if DRA is enabled on your cluster running k8s v1.32.0 or greater
    capacity.cluster-autoscaler.kubernetes.io/gpu-type: "nvidia.com/gpu"
    // Dynamic Resource Allocation (DRA)
    // Uncomment the below annotation if DRA is enabled on your cluster running k8s v1.32.0 or greater
    // capacity.cluster-autoscaler.kubernetes.io/dra-driver: "gpu.nvidia.com"
    // Common in Device Plugin and DRA
    capacity.cluster-autoscaler.kubernetes.io/gpu-count: "2"

Note: the maxPods annotation will default to 110 if it is not supplied. This value is inspired by the Kubernetes best practices Considerations for large clusters.

Note: User should select the annotation for GPU either gpu-type or dra-driver depends on whether using Device Plugin or Dynamic Resource Allocation(DRA). gpu-count is a common parameter in both.

RBAC changes for scaling from zero

If you are using the opt-in support for scaling from zero as defined by the Cluster API infrastructure provider, you will need to add the infrastructure machine template types to your role permissions for the service account associated with the cluster autoscaler deployment. The service account will need permission to get, list, and watch the infrastructure machine templates for your infrastructure provider.

For example, when using the Kubemark provider you will need to set the following permissions:

rules:
  - apiGroups:
    - infrastructure.cluster.x-k8s.io
    resources:
    - kubemarkmachinetemplates
    verbs:
    - get
    - list
    - watch

Pre-defined labels and taints on nodes scaled from zero

Taints for scale from zero can be configured in two ways, listed below in order of precedence (highest first):

1. Capacity annotation (highest priority)

The capacity.cluster-autoscaler.kubernetes.io/taints annotation accepts a comma-separated list of taints and always takes precedence over taints defined in the scalable resource spec.

apiVersion: cluster.x-k8s.io/v1alpha4
kind: MachineDeployment
metadata:
  annotations:
    cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "5"
    cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "0"
    capacity.cluster-autoscaler.kubernetes.io/memory: "128G"
    capacity.cluster-autoscaler.kubernetes.io/cpu: "16"
    capacity.cluster-autoscaler.kubernetes.io/labels: "key1=value1,key2=value2"
    capacity.cluster-autoscaler.kubernetes.io/taints: "key1=value1:NoSchedule,key2=value2:NoExecute"

2. Scalable resource spec (requires CAPI v1.12+ with MachineTaintPropagation feature gate enabled)

When the MachineTaintPropagation feature gate is enabled in Cluster API, taints defined in spec.template.spec.taints of a MachineSet, MachineDeployment, or MachinePool are read directly by the cluster autoscaler. If an annotation taint has the same key and effect as a spec taint, the annotation value takes precedence.

apiVersion: cluster.x-k8s.io/v1beta2
kind: MachineDeployment
metadata:
  annotations:
    cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "5"
    cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "0"
    capacity.cluster-autoscaler.kubernetes.io/memory: "128G"
    capacity.cluster-autoscaler.kubernetes.io/cpu: "16"
    # Override the value of the "dedicated" taint defined in spec below.
    capacity.cluster-autoscaler.kubernetes.io/taints: "dedicated=gpu-override:NoSchedule"
spec:
  template:
    spec:
      taints:
        - key: dedicated
          value: gpu
          effect: NoSchedule
          propagation: Always
        - key: node-setup
          value: "true"
          effect: NoSchedule
          propagation: Always

Note: For labels, the capacity annotation values are merged with the labels propagated from the scalable Cluster API resource. If the same label key is defined in both, the annotation value takes precedence. Please see the Cluster API Book chapter on Metadata propagation for more information.

For taints, annotation taints are merged with spec taints. If the same key and effect is defined in both, the annotation value takes precedence. Spec taints without a matching annotation taint are preserved.

Pre-defined csi driver information on nodes scaled from zero

To provide CSI driver information for scale from zero, the optional capacity annotation may be supplied as a comma separated list of driver name and volume limit key/value pairs, as demonstrated in the example below:

apiVersion: cluster.x-k8s.io/v1alpha4
kind: MachineDeployment
metadata:
  annotations:
    cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "5"
    cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "0"
    capacity.cluster-autoscaler.kubernetes.io/memory: "128G"
    capacity.cluster-autoscaler.kubernetes.io/cpu: "16"
    capacity.cluster-autoscaler.kubernetes.io/csi-driver: "ebs.csi.aws.com=25,efs.csi.aws.com=16"

Note: The CSI driver information supplied through the capacity annotation specifies which CSI drivers will be installed on nodes scaled from zero, along with their respective volume limits. The format is driver-name=volume-limit with multiple drivers separated by commas.

Per-NodeGroup autoscaling options

Custom autoscaling options per node group (MachineDeployment/MachinePool/MachineSet) can be specified as annoations with a common prefix:

apiVersion: cluster.x-k8s.io/v1beta1
kind: MachineDeployment
metadata:
  annotations:
    # overrides --scale-down-utilization-threshold global value for that specific MachineDeployment
    cluster.x-k8s.io/autoscaling-options-scaledownutilizationthreshold: "0.5"
    # overrides --scale-down-gpu-utilization-threshold global value for that specific MachineDeployment
    cluster.x-k8s.io/autoscaling-options-scaledowngpuutilizationthreshold: "0.5"
    # overrides --scale-down-unneeded-time global value for that specific MachineDeployment
    cluster.x-k8s.io/autoscaling-options-scaledownunneededtime: "10m0s"
    # overrides --scale-down-unready-time global value for that specific MachineDeployment
    cluster.x-k8s.io/autoscaling-options-scaledownunreadytime: "20m0s"
    # overrides --max-node-provision-time global value for that specific MachineDeployment
    cluster.x-k8s.io/autoscaling-options-maxnodeprovisiontime: "20m0s"
    # overrides --max-node-startup-time global value for that specific MachineDeployment
    cluster.x-k8s.io/autoscaling-options-maxnodestartuptime: "20m0s"

CPU Architecture awareness for single-arch clusters

Users of single-arch non-amd64 clusters who are using scale from zero support should also set the CAPI_SCALE_ZERO_DEFAULT_ARCH environment variable to set the architecture of the nodes they want to default the node group templates to. The autoscaler will default to amd64 if it is not set, and the node group templates may not match the nodes’ architecture, specifically when the workload triggering the scale-up uses a node affinity predicate checking for the node’s architecture.

Specifying a Custom Resource Group

By default all Kubernetes resources consumed by the Cluster API provider will use the group cluster.x-k8s.io, with a dynamically acquired version. In some situations, such as testing or prototyping, you may wish to change this group variable. For these situations you may use the environment variable CAPI_GROUP to change the group that the provider will use.

Please note that setting the CAPI_GROUP environment variable will also cause the annotations for minimum and maximum size to change. This behavior will also affect the machine annotation on nodes, the machine deletion annotation, and the cluster name label. For example, if CAPI_GROUP=test.k8s.io then the minimum size annotation key will be test.k8s.io/cluster-api-autoscaler-node-group-min-size, the machine annotation on nodes will be test.k8s.io/machine, the machine deletion annotation will be test.k8s.io/delete-machine, and the cluster name label will be test.k8s.io/cluster-name.

Specifying a Custom Resource Version

When determining the group version for the Cluster API types, by default the autoscaler will look for the latest version of the group. For example, if MachineDeployments exist in the cluster.x-k8s.io group at versions v1alpha1 and v1beta1, the autoscaler will choose v1beta1.

In some cases it may be desirable to specify which version of the API the cluster autoscaler should use. This can be useful in debugging scenarios, or in situations where you have deployed multiple API versions and wish to ensure that the autoscaler uses a specific version.

Setting the CAPI_VERSION environment variable will instruct the autoscaler to use the version specified. This works in a similar fashion as the API group environment variable with the exception that there is no default value. When this variable is not set, the autoscaler will use the behavior described above.

Sample manifest

A sample manifest that will create a deployment running the autoscaler is available. It can be deployed by passing it through envsubst, providing these environment variables to set the namespace to deploy into as well as the image and tag to use:

export AUTOSCALER_NS=kube-system
export AUTOSCALER_IMAGE=registry.k8s.io/autoscaling/cluster-autoscaler:v1.29.0
envsubst < examples/deployment.yaml | kubectl apply -f-

A note on permissions

The cluster-autoscaler-management role for accessing cluster api scalable resources is scoped to ClusterRole. This may not be ideal for all environments (eg. Multi tenant environments). In such cases, it is recommended to scope it to a Role mapped to a specific namespace.

Autoscaling with ClusterClass and Managed Topologies

For users using ClusterClass and Managed Topologies the Cluster Topology controller attempts to set MachineDeployment replicas based on the spec.topology.workers.machineDeployments[].replicas field. In order to use the Cluster Autoscaler this field can be left unset in the Cluster definition.

The below Cluster definition shows which field to leave unset:

apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  name: "my-cluster"
  namespace: default
spec:
  clusterNetwork:
    services:
      cidrBlocks: ["10.128.0.0/12"]
    pods:
      cidrBlocks: ["192.168.0.0/16"]
    serviceDomain: "cluster.local"
  topology:
    class: "quick-start"
    version: v1.24.0
    controlPlane:
      replicas: 1
    workers:
      machineDeployments:
        - class: default-worker
          name: linux
       ## replicas field is not set.
       ## replicas: 1

If the replica field is unset in the Cluster definition Autoscaling can be enabled as described above

Special note on GPU instances

As with other providers, if the device plugin on nodes that provides GPU resources takes some time to advertise the GPU resource to the cluster, this may cause Cluster Autoscaler to unnecessarily scale out multiple times.

To avoid this, you can configure kubelet on your GPU nodes to label the node before it joins the cluster by passing it the --node-labels flag. For the CAPI cloudprovider, the label format is as follows:

cluster-api/accelerator=<gpu-type>

<gpu-type> is arbitrary.

It is important to note that if you are using the --gpu-total flag to limit the number of GPU resources in your cluster that the <gpu-type> value must match between the command line flag and the node labels. Setting these values incorrectly can lead to the autoscaler creating too many GPU resources.

For example, if you are using the autoscaler command line flag --gpu-total=gfx-hardware:1:2 to limit the number of gfx-hardware resources to a minimum of 1 and maximum of 2, then you should use the kubelet node label flag --node-labels=cluster-api/accelerator=gfx-hardware.

Special note on balancing similar node groups

The Cluster Autoscaler feature to enable balancing similar node groups (activated with the --balance-similar-node-groups flag) is a powerful and popular feature. When enabled, the Cluster Autoscaler will attempt to create new nodes by adding them in a manner that balances the creation between similar node groups. With Cluster API, these node groups correspond directly to the scalable resources associated (usually MachineDeployments and MachineSets) with the nodes in question. In order for the nodes of these scalable resources to be considered similar by the Cluster Autoscaler, they must have the same capacity, labels, and taints for the nodes which will be created from them.

To help assist the Cluster Autoscaler in determining which node groups are similar, the command line flags --balancing-ignore-label and --balancing-label are provided. For an expanded discussion about balancing similar node groups and the options which are available, please see the Cluster Autoscaler FAQ.

Because Cluster API can address many different cloud providers, it is important to configure the balancing labels to ignore provider-specific labels which are used for carrying zonal information on Kubernetes nodes. The Cluster Autoscaler implementation for Cluster API does not assume any labels (aside from the well-known Kubernetes labels) to be ignored when running. Users must configure their Cluster Autoscaler deployment to ignore labels which might be different between nodes, but which do not otherwise affect node behavior or size (for example when two MachineDeployments are the same except for their deployment zones). The Cluster API community has decided not to carry cloud provider specific labels in the Cluster Autoscaler to reduce the possibility for labels to clash between providers. Additionally, the community has agreed to promote documentation and the use of the --balancing-ignore-label flag as the preferred method of deployment to reduce the extended need for maintenance on the Cluster Autoscaler when new providers are added or updated. For further context around this decision, please see the Cluster API Deep Dive into Cluster Autoscaler Node Group Balancing discussion from 2022-09-12.

The following table shows some of the most common labels used by cloud providers to designate regional or zonal information on Kubernetes nodes. It is shared here as a reference for users who might be deploying on these infrastructures.

Cloud ProviderLabel to ignoreNotes
Alibaba Cloudtopology.diskplugin.csi.alibabacloud.com/zoneUsed by the Alibaba Cloud CSI driver as a target for persistent volume node affinity
AWSalpha.eksctl.io/instance-idUsed by eksctl to identify instances
AWSalpha.eksctl.io/nodegroup-nameUsed by eksctl to identify node group names
AWSeks.amazonaws.com/nodegroupUsed by EKS to identify node groups
AWSk8s.amazonaws.com/eniConfigUsed by the AWS CNI for custom networking
AWSlifecycleUsed by AWS as a label for spot instances
AWStopology.ebs.csi.aws.com/zoneUsed by the AWS EBS CSI driver as a target for persistent volume node affinity
Azuretopology.disk.csi.azure.com/zoneUsed as the topology key by the Azure Disk CSI driver
AzureagentpoolLegacy label used to specify to which Azure node pool a particular node belongs
Azurekubernetes.azure.com/agentpoolUsed by AKS to identify to which node pool a particular node belongs
GCEtopology.gke.io/zoneUsed to specify the zone of the node
IBM Cloudibm-cloud.kubernetes.io/worker-idUsed by the IBM Cloud Cloud Controller Manager to identify the node
IBM Cloudvpc-block-csi-driver-labelsUsed by the IBM Cloud CSI driver as a target for persistent volume node affinity
IBM Cloudibm-cloud.kubernetes.io/vpc-instance-idUsed when a VPC is in use on IBM Cloud

Configure a MachineHealthCheck

Prerequisites

Before attempting to configure a MachineHealthCheck, you should have a working management cluster with at least one MachineDeployment or MachineSet deployed.

What is a MachineHealthCheck?

A MachineHealthCheck is a resource within the Cluster API which allows users to define conditions under which Machines within a Cluster should be considered unhealthy. A MachineHealthCheck is defined on a management cluster and scoped to a particular workload cluster.

When defining a MachineHealthCheck, users specify a timeout for each of the conditions that they define to check on the Machine’s Node. If any of these conditions are met for the duration of the timeout, the Machine will be remediated. By default, the action of remediating a Machine should trigger a new Machine to be created to replace the failed one, but providers are allowed to plug in more sophisticated external remediation solutions.

Creating a MachineHealthCheck

Use the following example as a basis for creating a MachineHealthCheck for worker nodes:

apiVersion: cluster.x-k8s.io/v1beta2
kind: MachineHealthCheck
metadata:
  name: capi-quickstart-node-unhealthy-5m
spec:
  # clusterName is required to associate this MachineHealthCheck with a particular cluster
  clusterName: capi-quickstart
  # selector is used to determine which Machines should be health checked
  selector:
    matchLabels:
      nodepool: nodepool-0
  # checks are the checks that are used to evaluate if a Machine is healthy.
  checks:
      # (Optional) nodeStartupTimeout determines how long a MachineHealthCheck should wait for
      # a Node to join the cluster, before considering a Machine unhealthy.
      # Defaults to 10 minutes if not specified.
      # Set to 0 to disable the node startup timeout.
      # Disabling this timeout will prevent a Machine from being considered unhealthy when
      # the Node it created has not yet registered with the cluster. This can be useful when
      # Nodes take a long time to start up or when you only want condition based checks for
      # Machine health.
      nodeStartupTimeoutSeconds: 600
    
      # Conditions to check on Nodes for matched Machines, if any condition is matched for the duration of its timeout, the Machine is considered unhealthy
      unhealthyNodeConditions:
      - type: Ready
        status: Unknown
        timeoutSeconds: 300
      - type: Ready
        status: "False"
        timeoutSeconds: 300
      unhealthyMachineConditions:
      - type: "NodeReady"
        status: Unknown
        timeoutSeconds: 1800
      - type: "InfrastructureReady"
        status: "False"
        timeoutSeconds: 1800
  # remediation configures if and how remediation is triggered if a Machine is unhealthy.
  remediation:
    triggerIf:
      # (Optional) unhealthyLessThanOrEqualTo prevents further remediation if the cluster is already partially unhealthy
      unhealthyLessThanOrEqualTo: 40%

Use this example as the basis for defining a MachineHealthCheck for control plane nodes managed via the KubeadmControlPlane:

apiVersion: cluster.x-k8s.io/v1beta2
kind: MachineHealthCheck
metadata:
  name: capi-quickstart-kcp-unhealthy-5m
spec:
  clusterName: capi-quickstart
  selector:
    matchLabels:
      cluster.x-k8s.io/control-plane: ""
  checks:
    unhealthyNodeConditions:
    - type: Ready
      status: Unknown
      timeoutSeconds: 300
    - type: Ready
      status: "False"
      timeoutSeconds: 300
  remediation:
    triggerIf:
      unhealthyLessThanOrEqualTo: 100%

Controlling remediation retries

KubeadmControlPlane allows to control how remediation happen by defining an optional remediation; this feature can be used for preventing unnecessary load on infrastructure provider e.g. in case of quota problems,or for allowing the infrastructure provider to stabilize in case of temporary problems.

apiVersion: cluster.x-k8s.io/v1beta2
kind: KubeadmControlPlane
metadata:
  name: my-control-plane
spec:
  ...
  remediation:
    maxRetry: 5
    retryPeriodSeconds: 120 # 2m
    minHealthyPeriodSeconds: 7200 # 2h

maxRetry is the maximum number of retries while attempting to remediate an unhealthy machine. A retry happens when a machine that was created as a replacement for an unhealthy machine also fails. For example, given a control plane with three machines M1, M2, M3:

  • M1 become unhealthy; remediation happens, and M1-1 is created as a replacement.
  • If M1-1 (replacement of M1) has problems while bootstrapping it will become unhealthy, and then be remediated. This operation is considered a retry - remediation-retry #1.
  • If M1-2 (replacement of M1-1) becomes unhealthy, remediation-retry #2 will happen, etc.

A retry will only happen after the retryPeriodSeconds from the previous retry has elapsed. If retryPeriodSeconds is not set (default), a retry will happen immediately.

If a machine is marked as unhealthy after minHealthyPeriodSeconds (default 3600) has passed since the previous remediation this is no longer considered a retry because the new issue is assumed unrelated from the previous one.

If maxRetry is not set (default), remediation will be retried infinitely.

Remediation Short-Circuiting

To ensure that MachineHealthChecks do not perform excessive remediation of Machines, short-circuiting is implemented to prevent further remediation via the remediation.triggerIf field within the MachineHealthCheck spec.

Unhealthy less than or equal to

If the user defines a value for the unhealthyLessThanOrEqualTo field (either an absolute number or a percentage of the total Machines checked by this MachineHealthCheck), before remediating any Machines, the MachineHealthCheck will compare the value of unhealthyLessThanOrEqualTo with the number of Machines it has determined to be unhealthy. If the number of unhealthy Machines exceeds the limit set by unhealthyLessThanOrEqualTo, remediation will not be performed.

With an Absolute Value

If unhealthyLessThanOrEqualTo is set to 2:

  • If 2 or fewer nodes are unhealthy, remediation will be performed
  • If 3 or more nodes are unhealthy, remediation will not be performed

These values are independent of how many Machines are being checked by the MachineHealthCheck.

With Percentages

If unhealthyLessThanOrEqualTo is set to 40% and there are 25 Machines being checked:

  • If 10 or fewer nodes are unhealthy, remediation will be performed
  • If 11 or more nodes are unhealthy, remediation will not be performed

If unhealthyLessThanOrEqualTo is set to 40% and there are 6 Machines being checked:

  • If 2 or fewer nodes are unhealthy, remediation will be performed
  • If 3 or more nodes are unhealthy, remediation will not be performed

Note, when the percentage is not a whole number, the allowed number is rounded down.

Unhealthy in Range

If the user defines a value for the unhealthyInRange field (bracketed values that specify a start and an end value), before remediating any Machines, the MachineHealthCheck will check if the number of Machines it has determined to be unhealthy is within the range specified by unhealthyInRange. If it is not within the range set by unhealthyInRange, remediation will not be performed.

With a range of values

If unhealthyInRange is set to [3-5] and there are 10 Machines being checked:

  • If 2 or fewer nodes are unhealthy, remediation will not be performed.
  • If 6 or more nodes are unhealthy, remediation will not be performed.
  • In all other cases, remediation will be performed.

Note, the above example had 10 machines as sample set. But, this would work the same way for any other number. This is useful for dynamically scaling clusters where the number of machines keep changing frequently.

Skipping Remediation

There are scenarios where remediation for a machine may be undesirable (eg. during cluster migration using clusterctl move). For such cases, MachineHealthCheck skips marking a Machine for remediation if:

  • the Machine has the cluster.x-k8s.io/skip-remediation annotation
  • the Machine has the cluster.x-k8s.io/paused annotation
  • the MachineHealthCheck has the cluster.x-k8s.io/paused annotation
  • the Cluster has .spec.paused set to true

Limitations and Caveats of a MachineHealthCheck

Before deploying a MachineHealthCheck, please familiarise yourself with the following limitations and caveats:

  • Only Machines owned by a MachineSet or a KubeadmControlPlane can be remediated by a MachineHealthCheck (since a MachineDeployment uses a MachineSet, then this includes Machines that are part of a MachineDeployment)
  • Machines managed by a KubeadmControlPlane are remediated according to the delete-and-recreate guidelines described in the KubeadmControlPlane proposal
    • The following rules should be satisfied in order to start remediation of a control plane machine:
      • One of the following apply:
        • The cluster MUST not be initialized yet (the failure happens before KCP reaches the initialized state)
        • The cluster MUST have at least two control plane machines, because this is the smallest cluster size that can be remediated.
      • Previous remediation (delete and re-create) MUST have been completed. This rule prevents KCP from remediating more machines while the replacement for the previous machine is not yet created.
      • The cluster MUST have no machines with a deletion timestamp. This rule prevents KCP taking actions while the cluster is in a transitional state.
      • Remediation MUST preserve etcd quorum. This rule ensures that we will not remove a member that would result in etcd losing a majority of members and thus become unable to field new requests (note: this rule applies only to CP already initialized and with managed etcd)
  • If the Node for a Machine is removed from the cluster, a MachineHealthCheck will consider this Machine unhealthy and remediate it immediately
  • If no Node joins the cluster for a Machine after the NodeStartupTimeout, the Machine will be remediated
  • Important: if the kubelet on the node hosting the etcd leader member is not working, this prevents KCP from doing some checks it is expecting to do on the leader - and specifically on the leader -. This prevents remediation to happen. There are ongoing discussions about how to overcome this limitation in https://github.com/kubernetes-sigs/cluster-api/issues/8465; as of today users facing this situation are recommended to manually forward leadership to another etcd member and manually delete the corresponding machine.

Machine deletion process

Machine deletions occur in various cases, for example:

  • Control plane (e.g. KCP) or MachineDeployment rollouts
  • Scale downs of MachineDeployments / MachineSets
  • Machine remediations
  • Machine deletions (e.g. kubectl delete machine)

This page describes how Cluster API deletes Machines.

Machine deletion can be broken down into the following phases:

  1. Machine deletion is triggered (i.e. the metadata.deletionTimestamp is set)
  2. Machine controller waits until all pre-drain hooks succeeded, if any are registered
    • Pre-drain hooks can be registered by adding annotations with the pre-drain.delete.hook.machine.cluster.x-k8s.io prefix to the Machine object
  3. Machine controller checks if the Machine should be drained, drain is skipped if:
    • The Machine has the machine.cluster.x-k8s.io/exclude-node-draining annotation
    • The Machine.spec.nodeDrainTimeout field is set and already expired (unset or 0 means no timeout)
    • The Machine is owned by a KubeadmControlPlane and the pre-terminate hook has been already removed
  4. If the Machine should be drained, the Machine controller evicts all relevant Pods from the Node (see details in Node drain)
  5. Machine controller checks if we should wait until all volumes are detached, this is skipped if:
    • The Machine has the machine.cluster.x-k8s.io/exclude-wait-for-node-volume-detach annotation
    • The Machine.spec.nodeVolumeDetachTimeout field is set and already expired (unset or 0 means no timeout)
    • The Machine is owned by a KubeadmControlPlane and the pre-terminate hook has been already removed
  6. If we should wait for volume detach, the Machine controller waits until Node.status.volumesAttached is empty and there are no more VolumeAttachment objects that indicate that there are still volumes attached to the Node
    • Typically the volumes are getting detached by CSI after the corresponding Pods have been evicted during drain
  7. Machine controller waits until all pre-terminate hooks succeeded, if any are registered
    • Pre-terminate hooks can be registered by adding annotations with the pre-terminate.delete.hook.machine.cluster.x-k8s.io prefix to the Machine object
  8. Machine controller deletes the InfrastructureMachine object (e.g. DockerMachine) of the Machine and waits until it is gone
  9. Machine controller deletes the BootstrapConfig object (e.g. KubeadmConfig) of the machine and waits until it is gone
  10. Machine controller deletes the Node object in the workload cluster
    • Node deletion will be retried until either the Node object is gone or Machine.spec.nodeDeletionTimeout is expired (0 means no timeout, but the field defaults to 10s)
    • Note: Nodes are usually also deleted by cloud controller managers, which is why Cluster API per default only tries to delete Nodes for 10s.

Note: There are cases where Node drain, wait for volume detach and Node deletion is skipped. For these please take a look at the implementation of the isDeleteNodeAllowed function.

Node drain

This section describes details of the Node drain process in Cluster API. Cluster API implements Node drain aligned with kubectl drain. One major difference is that the Cluster API controller does not actively wait during Reconcile until all Pods are drained from the Node. Instead it continuously evicts Pods and requeues after 20s until all relevant Pods have been drained from the Node or until the Machine.spec.nodeDrainTimeout is reached (if configured).

Node drain can be broken down into the following phases:

  • Node is cordoned (i.e. the Node.spec.unschedulable field is set, which leads to the node.kubernetes.io/unschedulable:NoSchedule taint being added to the Node)
    • This prevents that Pods that already have been evicted are rescheduled to the same Node. Please only tolerate this taint if you know what you are doing! Otherwise it can happen that the Machine controller is stuck continuously evicting the same Pods.
  • Machine controller calculates the list of Pods that have to be drained from the Node. Pods can be categorized as follows:
    • Pods that are skipped/ignored during drain:
      • Pods belonging to an existing DaemonSet (orphaned DaemonSet Pods have to be evicted as well)
      • Mirror Pods, i.e. Pods with the kubernetes.io/config.mirror annotation (usually static Pods managed by kubelet, like kube-apiserver)
      • Pods with the cluster.x-k8s.io/drain=skip label
      • Pods that match a MachineDrainRule with behavior Skip
    • Pods that should not be evicted, but we have to wait for their completion:
      • Pods with the cluster.x-k8s.io/drain=wait-completed label
      • Pods that match a MachineDrainRule with behavior WaitCompleted
    • Pods that should be evicted:
      • Pods that match a MachineDrainRule with behavior Drain
      • All Pods not belonging to any of the other categories
  • If there are no more Pods that have to be drained Node drain is completed
  • Otherwise we have to wait for Pods to complete and/or evict Pods
    • There are various reasons why an eviction could fail:
      • The eviction would violate a PodDisruptionBudget, i.e. not enough Pod replicas would be available if the Pod would be evicted
      • The namespace is in terminating, in this case the kube-controller-manager is responsible for setting the .metadata.deletionTimestamp on the Pod
      • Other errors, e.g. a connection issue when calling the eviction API of the workload cluster
    • Please note that when an eviction goes through, this only means that the .metadata.deletionTimestamp is set on the Pod, but the Pod also has to be terminated and the Pod object has to go away for the drain to complete.
  • These steps are repeated every 20s until all relevant Pods have been drained from the Node

Per default all Pods are drained at the same time. But with MachineDrainRules it’s also possible to define a drain order for Pods with behavior Drain (Pods with WaitCompleted have a hard-coded order of 0). The Machine controller will drain Pods in batches based on their order, lowest order first. Pods that don’t match any rule have a default order of 0, so a rule with a negative order will drain its pods before unmatched pods, and a rule with a positive order will drain its pods after.

Example: To drain pods in a specific namespace first and Rook Ceph OSDs last:

apiVersion: cluster.x-k8s.io/v1beta2
kind: MachineDrainRule
metadata:
  name: drain-managed-namespaces-first
spec:
  pods:
  - selector:
      matchExpressions:
      - key: kubernetes.io/metadata.name
        operator: In
        values: ["my-app-namespace"]
  drain:
    behavior: Drain
    order: -100  # Negative order: drain before default (0)
---
apiVersion: cluster.x-k8s.io/v1beta2
kind: MachineDrainRule
metadata:
  name: drain-rook-ceph-osd-last
spec:
  pods:
  - selector:
      matchLabels:
        app: rook-ceph-osd
  drain:
    behavior: Drain
    order: 100  # Positive order: drain after default (0)

For more details about MachineDrainRules, please see the corresponding proposal.

Special cases:

  • If the Node doesn’t exist anymore, Node drain is entirely skipped
  • If the Node is unreachable (i.e. the Node Ready condition is in status Unknown):
    • Pods with .metadata.deletionTimestamp more than 1s in the past are ignored
    • Pod evictions will use 1s GracePeriodSeconds, i.e. the terminationGracePeriodSeconds field from the Pod spec will be ignored.
    • Note: PodDisruptionBudgets are still respected, because both of these changes are only relevant if the call to trigger the Pod eviction goes through. But Pod eviction calls are rejected when PodDisruptionBudgets would be violated by the eviction.

Observability

The drain process can be observed through the DrainingSucceeded condition on the Machine and various logs.

Example condition

To determine which Pods are blocking the drain and why you can take a look at the DrainingSucceeded condition on the Machine, e.g.:

status:
  ...
  conditions:
  ...
  - lastTransitionTime: "2024-08-30T13:36:27Z"
    message: |-
      Drain not completed yet:
      * Pods with deletionTimestamp that still exist: cert-manager/cert-manager-756d54fb98-hcb6k
      * Pods with eviction failed:
        * Cannot evict pod as it would violate the pod's disruption budget. The disruption budget nginx needs 10 healthy pods and has 10 currently: test-namespace/nginx-deployment-6886c85ff7-2jtqm, test-namespace/nginx-deployment-6886c85ff7-7ggsd, test-namespace/nginx-deployment-6886c85ff7-f6z4s, ... (7 more)
    reason: Draining
    severity: Info
    status: "False"
    type: DrainingSucceeded

Example logs

When cordoning the Node:

I0830 12:50:13.961156      17 machine_controller.go:716] "Cordoning Node" ... Node="my-cluster-md-0-wxtcg-mtg57-k9qvz"

When starting the drain:

I0830 12:50:13.961156      17 machine_controller.go:716] "Draining Node" ... Node="my-cluster-md-0-wxtcg-mtg57-k9qvz"

Immediately before Pods are evicted:

I0830 12:52:58.739093      17 drain.go:172] "Drain not completed yet, there are still Pods on the Node that have to be drained" ... Node="my-cluster-md-0-wxtcg-mtg57-ssfg8" podsToTriggerEviction="test-namespace/nginx-deployment-6886c85ff7-4r297, test-namespace/nginx-deployment-6886c85ff7-5gl2h, test-namespace/nginx-deployment-6886c85ff7-64tf9, test-namespace/nginx-deployment-6886c85ff7-9k5gp, test-namespace/nginx-deployment-6886c85ff7-9mdjw, ... (5 more)" podsWithDeletionTimestamp="kube-system/calico-kube-controllers-7dc5458bc6-rdjj4, kube-system/coredns-7db6d8ff4d-9cbhn"

On log level 4 it is possible to observe details of the Pod evictions, e.g.:

I0830 13:29:56.211951      17 drain.go:224] "Evicting Pod" ... Node="my-cluster-2-md-0-wxtcg-mtg57-24lvh" Pod="test-namespace/nginx-deployment-6886c85ff7-77fpw"
I0830 13:29:56.211951      17 drain.go:229] "Pod eviction successfully triggered" ... Node="my-cluster-2-md-0-wxtcg-mtg57-24lvh" Pod="test-namespace/nginx-deployment-6886c85ff7-77fpw"

After Pods have been evicted, either the drain is directly completed:

I0830 13:29:56.235398      17 machine_controller.go:727] "Drain completed, remaining Pods on the Node have been evicted" ... Node="my-cluster-2-md-0-wxtcg-mtg57-24lvh"

or we are requeuing:

I0830 13:29:56.235398      17 machine_controller.go:736] "Drain not completed yet, requeuing in 20s" ... Node="my-cluster-2-md-0-wxtcg-mtg57-24lvh" podsFailedEviction="test-namespace/nginx-deployment-6886c85ff7-77fpw, test-namespace/nginx-deployment-6886c85ff7-8dq4q, test-namespace/nginx-deployment-6886c85ff7-8gjhf, test-namespace/nginx-deployment-6886c85ff7-jznjw, test-namespace/nginx-deployment-6886c85ff7-l5nj8, ... (5 more)" podsWithDeletionTimestamp="kube-system/calico-kube-controllers-7dc5458bc6-rdjj4, kube-system/coredns-7db6d8ff4d-9cbhn"

Eventually the Machine controller should log

I0830 13:29:56.235398      17 machine_controller.go:702] "Drain completed" ... Node="my-cluster-2-md-0-wxtcg-mtg57-24lvh"

If this doesn’t happen, please take a closer at the logs to determine which Pods still have to be evicted or haven’t gone away yet (i.e. deletionTimestamp is set but the Pod objects still exist).

For more information, please see:

Experimental Features

Cluster API now ships with a new experimental package that lives under the exp/ directory. This is a temporary location for features which will be moved to their permanent locations after graduation. Users can experiment with these features by enabling them using feature gates.

Currently Cluster API has the following experimental features:

  • ClusterTopology (env var: CLUSTER_TOPOLOGY): ClusterClass
  • InPlaceUpdates (env var: EXP_IN_PLACE_UPDATES):
    • Allows users to execute changes on existing machines without deleting the Machine and creating a new one.
    • See the proposal for more details.
  • KubeadmBootstrapFormatIgnition (env var: EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION): Ignition
  • MachinePool (env var: EXP_MACHINE_POOL): MachinePools
  • MachineSetPreflightChecks (env var: EXP_MACHINE_SET_PREFLIGHT_CHECKS): MachineSetPreflightChecks
  • MachineTaintPropagation (env var: EXP_MACHINE_TAINT_PROPAGATION): Taint propagation
  • PriorityQueue (env var: EXP_PRIORITY_QUEUE): Enables the usage of the controller-runtime PriorityQueue: https://github.com/kubernetes-sigs/controller-runtime/issues/2374
  • ReconcilerRateLimiting (env var: EXP_RECONCILER_RATE_LIMITING): Enables reconciler rate-limiting: https://github.com/kubernetes-sigs/cluster-api/issues/13005
    • Note: starting from CAPI v1.12.4 ReconcilerRateLimiting also requires PriorityQueue
  • RuntimeSDK (env var: EXP_RUNTIME_SDK): RuntimeSDK

Enabling Experimental Features for Management Clusters Started with clusterctl

Users can enable/disable features by setting OS environment variables before running clusterctl init, e.g.:

export EXP_SOME_FEATURE_NAME=true

clusterctl init --infrastructure vsphere

As an alternative to environment variables, it is also possible to set variables in the clusterctl config file located at $XDG_CONFIG_HOME/cluster-api/clusterctl.yaml, e.g.:

# Values for environment variable substitution
EXP_SOME_FEATURE_NAME: "true"

In case a variable is defined in both the config file and as an OS environment variable, the environment variable takes precedence. For more information on how to set variables for clusterctl, see clusterctl Configuration File

Some features like MachinePools may require infrastructure providers to implement a separate CRD that handles the infrastructure side of the feature too. For such a feature to work, infrastructure providers should also enable their controllers if it is implemented as a feature. If it is not implemented as a feature, no additional step is necessary. As an example, Cluster API Provider Azure (CAPZ) has support for MachinePool through the infrastructure type AzureMachinePool.

Enabling Experimental Features for e2e Tests

One way is to set experimental variables on the clusterctl config file. For CAPI, these configs are under ./test/e2e/config/… such as docker.yaml:

variables:
  CLUSTER_TOPOLOGY: "true"
  EXP_RUNTIME_SDK: "true"
  EXP_MACHINE_SET_PREFLIGHT_CHECKS: "true"

Another way is to set them as environmental variables before running e2e tests.

Enabling Experimental Features on Tilt

On development environments started with Tilt, features can be enabled by setting the feature variables in kustomize_substitutions, e.g.:

kustomize_substitutions:
  CLUSTER_TOPOLOGY: 'true'
  EXP_RUNTIME_SDK: 'true'
  EXP_MACHINE_SET_PREFLIGHT_CHECKS: 'true'

For more details on setting up a development environment with tilt, see Developing Cluster API with Tilt

Enabling Experimental Features on Existing Management Clusters

To enable/disable features on existing management clusters, users can edit the corresponding controller manager deployments, which will then trigger a restart with the requested features. E.g. for the CAPI controller manager deployment:

kubectl edit -n capi-system deployment.apps/capi-controller-manager
// Enable/disable available features by modifying Args below.
    Args:
      --leader-elect
      --feature-gates=MachinePool=true,ClusterResourceSet=true

Similarly, to validate if a particular feature is enabled, see the arguments by issuing:

kubectl describe -n capi-system deployment.apps/capi-controller-manager

Following controller manager deployments have to be edited in order to enable/disable their respective experimental features:

Active Experimental Features

Warning: Experimental features are unreliable, i.e., some may one day be promoted to the main repository, or they may be modified arbitrarily or even disappear altogether. In short, they are not subject to any compatibility or deprecation promise.

Experimental Feature: MachinePool (beta)

Feature gate name: MachinePool

Variable name to enable/disable the feature gate: EXP_MACHINE_POOL

Table of Contents

Introduction

Cluster API (CAPI) manages Kubernetes worker nodes primarily through Machine, MachineSet, and MachineDeployment objects. These primitives manage nodes individually (Machines), and have served well across a wide variety of providers.

However, many infrastructure providers already offer first-class abstractions for groups of compute instances (AWS: Auto Scaling Groups (ASG), Azure: Virtual Machine Scale Sets (VMSS), or GCP: Managed Instance Groups (MIG)). These primitives natively support scaling, rolling upgrades, and health management.

MachinePool brings these provider features into Cluster API by introducing a higher-level abstraction for managing a group of machines as a single unit.

What is a MachinePool?

A MachinePool is a Cluster API resource representing a group of worker nodes. Instead of reconciling each machine individually, CAPI delegates lifecycle management to the infrastructure provider.

  • MachinePool (core API): defines desired state (replicas, Kubernetes version, bootstrap template, infrastructure reference).
  • InfrastructureMachinePool (provider API): provides an implementation that backs a pool. A provider may offer more than one type depending on how it is managed. For example:
    • AWSMachinePool: self-managed ASG
    • AWSManagedMachinePool: EKS managed node group
    • AzureMachinePool: VM Scale Set
    • AzureManagedMachinePool: AKS managed node pool
    • GCPManagedMachinePool: GKE managed node pool
    • OCIManagedMachinePool: OKE managed node pool
    • ScalewayManagedMachinePool: Scaleway Kapsule node pool
  • Bootstrap configuration: still applies (e.g., kubeadm configs), ensuring that new nodes join the cluster with the correct setup.

The MachinePool controller coordinates between the Cluster API core and provider-specific implementations:

  • Reconciles desired replicas with the infrastructure pool.
  • Matches provider IDs from the infrastructure resource with Kubernetes Nodes in the workload cluster.
  • Updates MachinePool status (ready replicas, conditions, etc.)

Why MachinePool?

Leverage provider primitives

Most cloud providers already manage scaling, instance replacement, and health monitoring at the group level. MachinePool lets CAPI delegate lifecycle operations instead of duplicating that logic.

Example:

  • AWS Auto Scaling Groups replace failed nodes automatically.
  • Azure VM Scale Sets support rolling upgrades with configurable surge/availability strategies.

Simplify upgrades and scaling

Upgrades and scaling events are managed at the pool level:

  • Update Kubernetes version or bootstrap template → cloud provider handles rolling replacement.
  • Scale up/down replicas → provider adjusts capacity.

This provides more predictable, cloud-native semantics compared to reconciling many individual Machine objects.

Autoscaling integration

MachinePool integrates with the Cluster Autoscaler in the same way that MachineDeployments do. In practice, the autoscaler treats a MachinePool as a node group, enabling scale-up and scale-down decisions based on cluster load.

Tradeoffs and limitations

While powerful, MachinePool comes with tradeoffs:

  • Infrastructure provider complexity: requires infrastructure providers to implement and maintain an InfrastructureMachinePool type.
  • Less per-machine granularity: you cannot configure each node individually; the pool defines a shared template.

    Note: While this is typically true, certain cloud providers do offer flexibility. Example: AWS allows AWSMachinepool.spec.mixedInstancesPolicy.instancesDistribution while Azure allows AzureMachinePool.spec.orchestrationMode.

  • Complex reconciliation: node-to-providerID matching introduces edge cases (delays, inconsistent states).
  • Draining: The cloud resources for MachinePool may not necessarily support draining of Kubernetes worker nodes. For example, with an AWSMachinePool, AWS would normally terminate instances as quickly as possible. To solve this, tools like aws-node-termination-handler combined with ASG lifecycle hooks (defined in AWSMachine.spec.lifecycleHooks) must be installed, and is not a built-in feature of the infrastructure provider (CAPA in this example).
  • Maturity: The MachinePool API is still considered experimental/beta.

When to use MachinePool vs MachineDeployment

Both MachineDeployment and MachinePool are valid options for managing worker nodes in Cluster API. The right choice depends on your infrastructure provider’s capabilities and your operational requirements.

Use MachinePool when:

  • Cloud provider supports scaling group primitives: AWS Auto Scaling Groups, Azure Virtual Machine Scale Sets, GCP Managed Instance Groups, OCI Compute Instances, Scaleway Kapsule. These resources natively handle scaling, rolling upgrades, and health checks.
  • You want to leverage cloud provider-level features: MachinePool enables direct use of cloud-native upgrade strategies (e.g., surge, maxUnavailable) and autoscaling behaviors.

Use MachineDeployment when:

  • The provider does not support scaling groups: Common in environments such as bare metal, vSphere, or Docker.
  • You need fine-grained per-machine control: MachineDeployments allow unique bootstrap configurations, labels, and taints across different MachineSets.
  • You prefer maturity and portability: MachineDeployment is stable, GA, and supported across all providers. MachinePool remains experimental in some implementations.

Enabling MachinePool

Starting from Cluster API v1.7, MachinePool is enabled by default. No additional configuration is needed.

For Cluster API versions prior to v1.7, you need to set the EXP_MACHINE_POOL environment variable:

export EXP_MACHINE_POOL=true
clusterctl init

Or when upgrading an existing management cluster:

export EXP_MACHINE_POOL=true
clusterctl upgrade

MachinePool provider implementations

The following Cluster API infrastructure providers have implemented support for MachinePools:

ProviderImplementationsStatusMachinePool Machines support
AWSAWSManagedMachinePool
AWSMachinePool
ROSAMachinePool
ImplementedYes; has support for deletion of single machine
AzureAzureASOManagedMachinePool
AzureManagedMachinePool
AzureMachinePool
ImplementedYes; has support for deletion of single machine
GCPGCPMachinePoolIn ProgressUnknown
OCIOCIManagedMachinePool
OCIMachinePool
ImplementedYes; doesn’t have support for deletion of single machine
ScalewayScalewayManagedMachinePoolImplementedNo

Providers may support the deletion of single machine pool Machine objects. That allows, for example, using MachineHealthCheck to remediate machines that became unhealthy (requires this PR to be merged and released).

Additional Resources

Experimental Feature: MachineSetPreflightChecks (beta)

The MachineSetPreflightChecks feature can provide additional safety while creating new Machines and remediating existing unhealthy Machines of a MachineSet.

When a MachineSet creates machines under certain circumstances, the operation fails or leads to a new machine that will be deleted and recreated in a short timeframe, leading to unwanted Machine churn. Some of these circumstances include, but not limited to, creating a new Machine when Kubernetes version skew could be violated or joining a Machine when the Control Plane is upgrading leading to failure because of mixed kube-apiserver version or due to the cluster load balancer delays in adapting to the changes.

Enabling MachineSetPreflightChecks provides safety in such circumstances by making sure that a Machine is only created when it is safe to do so.

Feature gate name: MachineSetPreflightChecks

Variable name to enable/disable the feature gate: EXP_MACHINE_SET_PREFLIGHT_CHECKS

Supported PreflightChecks

ControlPlaneIsStable

  • This preflight check ensures that the ControlPlane is currently stable i.e. the ControlPlane is currently neither provisioning, upgrading.
  • For Clusters with a managed topology it also checks if a control plane upgrade is pending.
  • This preflight check is only performed if:
    • The Cluster uses a ControlPlane provider.
    • ControlPlane version is defined (ControlPlane.spec.version is set).

KubernetesVersionSkew

  • This preflight check ensures that the MachineSet and the ControlPlane conform to the Kubernetes version skew.
  • This preflight check is only performed if:
    • The Cluster uses a ControlPlane provider.
    • ControlPlane version is defined (ControlPlane.spec.version is set).
    • MachineSet version is defined (MachineSet.spec.template.spec.version is set).

KubeadmVersionSkew

  • This preflight check ensures that the MachineSet and the ControlPlane conform to the kubeadm version skew.
  • This preflight check is only performed if:
    • The Cluster uses a ControlPlane provider.
    • ControlPlane version is defined (ControlPlane.spec.version is set).
    • MachineSet version is defined (MachineSet.spec.template.spec.version is set).
    • MachineSet uses the Kubeadm Bootstrap provider.

ControlPlaneVersionSkew

  • This preflight check ensures that the MachineSet and the ControlPlane have the same version. The idea behind this check is that it doesn’t make sense to create a Machine with an old version, if we already know based on the control plane version that the Machine has to be replaced soon.
  • This preflight check is only performed if:
    • The Cluster has a managed topology
    • The Cluster uses a ControlPlane provider.
    • ControlPlane version is defined (ControlPlane.spec.version is set).
    • MachineSet version is defined (MachineSet.spec.template.spec.version is set).

Configuring MachineSet PreflightChecks

Per default all preflight checks are enabled for all MachineSets including new and existing MachineSets. The enabled preflight checks can be overwritten with the --machineset-preflight-checks command-line flag.

It is also possible to opt-out of one or all of the preflight checks on a per MachineSet basis by specifying a comma-separated list of the preflight checks via the machineset.cluster.x-k8s.io/skip-preflight-checks annotation on the MachineSet or on the corresponding BootstrapConfigTemplate (annotation on the MachineSet has higher priority).

Examples:

  • To opt out of all the preflight checks set the machineset.cluster.x-k8s.io/skip-preflight-checks: All annotation.
  • To opt out of the ControlPlaneIsStable preflight check set the machineset.cluster.x-k8s.io/skip-preflight-checks: ControlPlaneIsStable annotation.
  • To opt out of multiple preflight checks set the machineset.cluster.x-k8s.io/skip-preflight-checks: ControlPlaneIsStable,KubernetesVersionSkew annotation.

Experimental Feature: ClusterClass (alpha)

The ClusterClass feature introduces a new way to create clusters which reduces boilerplate and enables flexible and powerful customization of clusters. ClusterClass is a powerful abstraction implemented on top of existing interfaces and offers a set of tools and operations to streamline cluster lifecycle management while maintaining the same underlying API.

Feature gate name: ClusterTopology

Variable name to enable/disable the feature gate: CLUSTER_TOPOLOGY

Additional documentation:

Writing a ClusterClass

A ClusterClass becomes more useful and valuable when it can be used to create many Cluster of a similar shape. The goal of this document is to explain how ClusterClasses can be written in a way that they are flexible enough to be used in as many Clusters as possible by supporting variants of the same base Cluster shape.

Table of Contents

Basic ClusterClass

The following example shows a basic ClusterClass. It contains templates to shape the control plane, infrastructure and workers of a Cluster. When a Cluster is using this ClusterClass, the templates are used to generate the objects of the managed topology of the Cluster.

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
metadata:
  name: docker-clusterclass-v0.1.0
spec:
  controlPlane:
    templateRef:
      apiVersion: controlplane.cluster.x-k8s.io/v1beta2
      kind: KubeadmControlPlaneTemplate
      name: docker-clusterclass-v0.1.0
    machineInfrastructure:
      templateRef:
        apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
        kind: DockerMachineTemplate
        name: docker-clusterclass-v0.1.0
  infrastructure:
    templateRef:
      apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
      kind: DockerClusterTemplate
      name: docker-clusterclass-v0.1.0-control-plane
  workers:
    machineDeployments:
    - class: default-worker
      bootstrap:
        templateRef:
          apiVersion: bootstrap.cluster.x-k8s.io/v1beta2
          kind: KubeadmConfigTemplate
          name: docker-clusterclass-v0.1.0-default-worker
      infrastructure:
        templateRef:
          apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
          kind: DockerMachineTemplate
          name: docker-clusterclass-v0.1.0-default-worker

The following example shows a Cluster using this ClusterClass. In this case a KubeadmControlPlane with the corresponding DockerMachineTemplate, a DockerCluster and a MachineDeployment with the corresponding KubeadmConfigTemplate and DockerMachineTemplate will be created. This basic ClusterClass is already very flexible. Via the topology on the Cluster the following can be configured:

  • .spec.topology.version: the Kubernetes version of the Cluster
  • .spec.topology.controlPlane: ControlPlane replicas and their metadata
  • .spec.topology.workers: MachineDeployments and their replicas, metadata and failure domain
apiVersion: cluster.x-k8s.io/v1beta2
kind: Cluster
metadata:
  name: my-docker-cluster
spec:
  topology:
    classRef:
      name: docker-clusterclass-v0.1.0
    version: v1.22.4
    controlPlane:
      replicas: 3
      metadata:
        labels:
          cpLabel: cpLabelValue 
        annotations:
          cpAnnotation: cpAnnotationValue
    workers:
      machineDeployments:
      - class: default-worker
        name: md-0
        replicas: 4
        metadata:
          labels:
            mdLabel: mdLabelValue
          annotations:
            mdAnnotation: mdAnnotationValue
        failureDomain: region

Best practices:

  • The ClusterClass name should be generic enough to make sense across multiple clusters, i.e. a name which corresponds to a single Cluster, e.g. “my-cluster”, is not recommended.
  • Try to keep the ClusterClass names short and consistent (if you publish multiple ClusterClasses).
  • As a ClusterClass usually evolves over time and you might want to rebase Clusters from one version of a ClusterClass to another, consider including a version suffix in the ClusterClass name. For more information about changing a ClusterClass please see: Changing a ClusterClass.
  • Prefix the templates used in a ClusterClass with the name of the ClusterClass.
  • Don’t reuse the same template in multiple ClusterClasses. This is automatically taken care of by prefixing the templates with the name of the ClusterClass.

ClusterClass with MachinePools

ClusterClass also supports MachinePool workers. They work very similar to MachineDeployments. MachinePools can be specified in the ClusterClass template under the workers section like so:

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
metadata:
  name: docker-clusterclass-v0.1.0
spec:
  workers:
    machinePools:
    - class: default-worker
      bootstrap:
        templateRef:
          apiVersion: bootstrap.cluster.x-k8s.io/v1beta2
          kind: KubeadmConfigTemplate
          name: quick-start-default-worker-bootstraptemplate
      infrastructure:
        templateRef:
          apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
          kind: DockerMachinePoolTemplate
          name: quick-start-default-worker-machinepooltemplate

They can then be similarly defined as workers in the cluster template like so:

apiVersion: cluster.x-k8s.io/v1beta2
kind: Cluster
metadata:
  name: my-docker-cluster
spec:
  topology:
    workers:
      machinePools:
      - class: default-worker
        name: mp-0
        replicas: 4
        metadata:
          labels:
            mpLabel: mpLabelValue
          annotations:
            mpAnnotation: mpAnnotationValue
        failureDomain: region

ClusterClass with MachineHealthChecks

MachineHealthChecks can be configured in the ClusterClass for the control plane and for a MachineDeployment class. The following configuration makes sure a MachineHealthCheck is created for the control plane and for every MachineDeployment using the default-worker class.

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
metadata:
  name: docker-clusterclass-v0.1.0
spec:
  controlPlane:
    ...
    healthCheck:
      checks:
        nodeStartupTimeoutSeconds: 900
        unhealthyNodeConditions:
        - type: Ready
          status: Unknown
          timeoutSeconds: 300
        - type: Ready
          status: "False"
          timeoutSeconds: 300
        unhealthyMachineConditions:
        - type: "NodeReady"
          status: Unknown
          timeoutSeconds: 1800
        - type: "InfrastructureReady"
          status: "False"
          timeoutSeconds: 1800
      remediation:
        triggerIf:
          unhealthyLessThanOrEqualTo: 33%
  workers:
    machineDeployments:
    - class: default-worker
      ...
      healthCheck:
        checks:
          nodeStartupTimeoutSeconds: 600
          unhealthyNodeConditions:
          - type: Ready
            status: Unknown
            timeoutSeconds: 300
          - type: Ready
            status: "False"
            timeoutSeconds: 300
          unhealthyMachineConditions:
          - type: NodeReady
            status: Unknown
            timeoutSeconds: 1800
          - type: InfrastructureReady
            status: "False"
            timeoutSeconds: 1800
        remediation:
          triggerIf:
            unhealthyInRange: "[0-2]"

ClusterClass with patches

As shown above, basic ClusterClasses are already very powerful. But there are cases where more powerful mechanisms are required. Let’s assume you want to manage multiple Clusters with the same ClusterClass, but they require different values for a field in one of the referenced templates of a ClusterClass.

A concrete example would be to deploy Clusters with different registries. In this case, every cluster needs a Cluster-specific value for .spec.kubeadmConfigSpec.clusterConfiguration.imageRepository in KubeadmControlPlane. Use cases like this can be implemented with ClusterClass patches.

Defining variables in the ClusterClass

The following example shows how variables can be defined in the ClusterClass. A variable definition specifies the name and the schema of a variable and if it is required. The schema defines how a variable is defaulted and validated. It supports a subset of the schema of CRDs. For more information please see the godoc.

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
metadata:
  name: docker-clusterclass-v0.1.0
spec:
  ...
  variables:
  - name: imageRepository
    required: true
    schema:
      openAPIV3Schema:
        type: string
        description: ImageRepository is the container registry to pull images from.
        default: registry.k8s.io
        example: registry.k8s.io

Defining patches in the ClusterClass

The variable can then be used in a patch to set a field on a template referenced in the ClusterClass. The selector specifies on which template the patch should be applied. jsonPatches specifies which JSON patches should be applied to that template. In this case we set the imageRepository field of the KubeadmControlPlaneTemplate to the value of the variable imageRepository. For more information please see the godoc.

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
metadata:
  name: docker-clusterclass-v0.1.0
spec:
  ...
  patches:
  - name: imageRepository
    definitions:
    - selector:
        apiVersion: controlplane.cluster.x-k8s.io/v1beta2
        kind: KubeadmControlPlaneTemplate
        matchResources:
          controlPlane: true
      jsonPatches:
      - op: add
        path: /spec/template/spec/kubeadmConfigSpec/clusterConfiguration/imageRepository
        valueFrom:
          variable: imageRepository

Setting variable values in the Cluster

After creating a ClusterClass with a variable definition, the user can now provide a value for the variable in the Cluster as in the example below.

apiVersion: cluster.x-k8s.io/v1beta2
kind: Cluster
metadata:
  name: my-docker-cluster
spec:
  topology:
    ...
    variables:
    - name: imageRepository
      value: my.custom.registry

ClusterClass with custom naming strategies

The controller needs to generate names for new objects when a Cluster is getting created from a ClusterClass. These names have to be unique for each namespace. The naming strategy enables this by concatenating the cluster name with a random suffix.

It is possible to provide a custom template for the name generation of ControlPlane, MachineDeployment and MachinePool objects.

The generated names must comply with the RFC 1123 standard.

Defining a custom naming strategy for ControlPlane objects

The naming strategy for ControlPlane supports the following properties:

  • template: Custom template which is used when generating the name of the ControlPlane object.

The following variables can be referenced in templates:

  • .cluster.name: The name of the cluster object.
  • .random: A random alphanumeric string, without vowels, of length 5.

Example which would match the default behavior:

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
metadata:
  name: docker-clusterclass-v0.1.0
spec:
  controlPlane:
    ...
    naming:
      template: "{{ .cluster.name }}-{{ .random }}"
  ...

Defining a custom naming strategy for MachineDeployment objects

The naming strategy for MachineDeployments supports the following properties:

  • template: Custom template which is used when generating the name of the MachineDeployment object.

The following variables can be referenced in templates:

  • .cluster.name: The name of the cluster object.
  • .random: A random alphanumeric string, without vowels, of length 5.
  • .machineDeployment.topologyName: The name of the MachineDeployment topology (Cluster.spec.topology.workers.machineDeployments[].name)

Example which would match the default behavior:

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
metadata:
  name: docker-clusterclass-v0.1.0
spec:
  controlPlane:
    ...
  workers:
    machineDeployments:
    - class: default-worker
      ...
      naming:
        template: "{{ .cluster.name }}-{{ .machineDeployment.topologyName }}-{{ .random }}"

Defining a custom naming strategy for MachinePool objects

The naming strategy for MachinePools supports the following properties:

  • template: Custom template which is used when generating the name of the MachinePool object.

The following variables can be referenced in templates:

  • .cluster.name: The name of the cluster object.
  • .random: A random alphanumeric string, without vowels, of length 5.
  • .machinePool.topologyName: The name of the MachinePool topology (Cluster.spec.topology.workers.machinePools[].name).

Example which would match the default behavior:

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
metadata:
  name: docker-clusterclass-v0.1.0
spec:
  controlPlane:
    ...
  workers:
    machinePools:
    - class: default-worker
      ...
      naming:
        template: "{{ .cluster.name }}-{{ .machinePool.topologyName }}-{{ .random }}"

Defining a custom namespace for ClusterClass object

As a user, I may need to create a Cluster from a ClusterClass object that exists only in a different namespace. To uniquely identify the ClusterClass, a NamespacedName ref is constructed from combination of:

  • cluster.spec.topology.classNamespace - namespace of the ClusterClass object.
  • cluster.spec.topology.class - name of the ClusterClass object.

Example of the Cluster object with the name/namespace reference:

apiVersion: cluster.x-k8s.io/v1beta2
kind: Cluster
metadata:
  name: my-docker-cluster
  namespace: default
spec:
  topology:
    classRef:
      name: docker-clusterclass-v0.1.0
      namespace: default
    version: v1.22.4
    controlPlane:
      replicas: 3
    workers:
      machineDeployments:
      - class: default-worker
        name: md-0
        replicas: 4
        failureDomain: region

Securing cross-namespace reference to the ClusterClass

It is often desirable to restrict free cross-namespace ClusterClass access for the Cluster object. This can be implemented by defining a ValidatingAdmissionPolicy on the Cluster object.

An example of such policy may be:

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: "cluster-class-ref.cluster.x-k8s.io"
spec:
  failurePolicy: Fail
  paramKind:
    apiVersion: v1
    kind: Secret
  matchConstraints:
    resourceRules:
    - apiGroups:   ["cluster.x-k8s.io"]
      apiVersions: ["v1beta2"]
      operations:  ["CREATE", "UPDATE"]
      resources:   ["clusters"]
  validations:
    - expression: "!has(object.spec.topology.classRef.namespace) || object.spec.topology.classRef.namespace in params.data"
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
  name: "cluster-class-ref-binding.cluster.x-k8s.io"
spec:
  policyName: "cluster-class-ref.cluster.x-k8s.io"
  validationActions: [Deny]
  paramRef:
    name: "allowed-namespaces.cluster-class-ref.cluster.x-k8s.io"
    namespace: "default"
    parameterNotFoundAction: Deny
---
apiVersion: v1
kind: Secret
metadata:
  name: "allowed-namespaces.cluster-class-ref.cluster.x-k8s.io"
  namespace: "default"
data:
  default: ""

Advanced features of ClusterClass with patches

This section will explain more advanced features of ClusterClass patches.

MachineDeployment and MachinePool variable overrides

If you want to use many variations of MachineDeployments in Clusters, you can either define a MachineDeployment class for every variation or you can define patches and variables to make a single MachineDeployment class more flexible. The same applies for MachinePools.

In the following example we make the instanceType of a AWSMachineTemplate customizable. First we define the workerMachineType variable and the corresponding patch:

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
metadata:
  name: aws-clusterclass-v0.1.0
spec:
  ...
  variables:
  - name: workerMachineType
    required: true
    schema:
      openAPIV3Schema:
        type: string
        default: t3.large
  patches:
  - name: workerMachineType
    definitions:
    - selector:
        apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
        kind: AWSMachineTemplate
        matchResources:
          machineDeploymentClass:
            names:
            - default-worker
      jsonPatches:
      - op: add
        path: /spec/template/spec/instanceType
        valueFrom:
          variable: workerMachineType
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: AWSMachineTemplate
metadata:
  name: aws-clusterclass-v0.1.0-default-worker
spec:
  template:
    spec:
      # instanceType: workerMachineType will be set by the patch.
      iamInstanceProfile: "nodes.cluster-api-provider-aws.sigs.k8s.io"
---
...

In the Cluster resource the workerMachineType variable can then be set cluster-wide and it can also be overridden for an individual MachineDeployment or MachinePool.

apiVersion: cluster.x-k8s.io/v1beta2
kind: Cluster
metadata:
  name: my-aws-cluster
spec:
  ...
  topology:
    classRef:
      name: aws-clusterclass-v0.1.0
    version: v1.22.0
    controlPlane:
      replicas: 3
    workers:
      machineDeployments:
      - class: "default-worker"
        name: "md-small-workers"
        replicas: 3
        variables:
          overrides:
          # Overrides the cluster-wide value with t3.small.
          - name: workerMachineType
            value: t3.small
      # Uses the cluster-wide value t3.large.
      - class: "default-worker"
        name: "md-large-workers"
        replicas: 3
    variables:
    - name: workerMachineType
      value: t3.large

Builtin variables

In addition to variables specified in the ClusterClass, the following builtin variables can be referenced in patches:

  • builtin.cluster.{name,namespace,uid,metadata.labels,metadata.annotations}
  • builtin.cluster.topology.{version,classRef.name,classRef.namespace,class,classNamespace}
    • Note: class and classNamespace are deprecated and will be removed with the next apiVersion.
  • builtin.cluster.network.{serviceDomain,services,pods}
  • builtin.controlPlane.{replicas,version,name,metadata.labels,metadata.annotations}
    • Please note, these variables are only available when patching control plane or control plane machine templates.
  • builtin.controlPlane.machineTemplate.infrastructureRef.name
    • Please note, these variables are only available when using a control plane with machines and when patching control plane or control plane machine templates.
  • builtin.machineDeployment.{replicas,version,class,name,topologyName,metadata.labels,metadata.annotations}
    • Please note, these variables are only available when patching the templates of a MachineDeployment and contain the values of the current MachineDeployment topology.
  • builtin.machineDeployment.{infrastructureRef.name,bootstrap.configRef.name}
    • Please note, these variables are only available when patching the templates of a MachineDeployment and contain the values of the current MachineDeployment topology.
  • builtin.machinePool.{replicas,version,class,name,topologyName,metadata.labels,metadata.annotations}
    • Please note, these variables are only available when patching the templates of a MachinePool and contain the values of the current MachinePool topology.
  • builtin.machinePool.{infrastructureRef.name,bootstrap.configRef.name}
    • Please note, these variables are only available when patching the templates of a MachinePool and contain the values of the current MachinePool topology.

Builtin variables can be referenced just like regular variables, e.g.:

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
metadata:
  name: docker-clusterclass-v0.1.0
spec:
  ...
  patches:
  - name: clusterName
    definitions:
    - selector:
      ...
      jsonPatches:
      - op: add
        path: /spec/template/spec/kubeadmConfigSpec/clusterConfiguration/controllerManager/extraArgs/cluster-name
        valueFrom:
          variable: builtin.cluster.name

Tips & Tricks

Builtin variables can be used to dynamically calculate image names. The version used in the patch will always be the same as the one we set in the corresponding MachineDeployment or MachinePool (works the same way with .builtin.controlPlane.version).

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
metadata:
  name: docker-clusterclass-v0.1.0
spec:
  ...
  patches:
  - name: customImage
    description: "Sets the container image that is used for running dockerMachines."
    definitions:
    - selector:
        apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
        kind: DockerMachineTemplate
        matchResources:
          machineDeploymentClass:
            names:
            - default-worker
      jsonPatches:
      - op: add
        path: /spec/template/spec/customImage
        valueFrom:
          template: |
            kindest/node:{{ .builtin.machineDeployment.version }}

Complex variable types

Variables can also be objects, maps and arrays. An object is specified with the type object and by the schemas of the fields of the object. A map is specified with the type object and the schema of the map values. An array is specified via the type array and the schema of the array items.

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
metadata:
  name: docker-clusterclass-v0.1.0
spec:
  ...
  variables:
  - name: httpProxy
    schema:
      openAPIV3Schema:
        type: object
        properties: 
          # Schema of the url field.
          url: 
            type: string
          # Schema of the noProxy field.
          noProxy:
            type: string
  - name: mdConfig
    schema:
      openAPIV3Schema:
        type: object
        additionalProperties:
          # Schema of the map values.
          type: object
          properties:
            osImage:
              type: string
  - name: dnsServers
    schema:
      openAPIV3Schema:
        type: array
        items:
          # Schema of the array items.
          type: string

Objects, maps and arrays can be used in patches either directly by referencing the variable name, or by accessing individual fields. For example:

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
metadata:
  name: docker-clusterclass-v0.1.0
spec:
  ...
  jsonPatches:
  - op: add
    path: /spec/template/spec/httpProxy/url
    valueFrom:
      # Use the url field of the httpProxy variable.
      variable: httpProxy.url
  - op: add
    path: /spec/template/spec/customImage
    valueFrom:
      # Use the osImage field of the mdConfig variable for the current MD class.
      template: "{{ (index .mdConfig .builtin.machineDeployment.class).osImage }}"
  - op: add
    path: /spec/template/spec/dnsServers
    valueFrom:
      # Use the entire dnsServers array.
      variable: dnsServers
  - op: add
    path: /spec/template/spec/dnsServer
    valueFrom:
      # Use the first item of the dnsServers array.
      variable: dnsServers[0]

Tips & Tricks

Complex variables can be used to make references in templates configurable, e.g. the identityRef used in AzureCluster. Of course it’s also possible to only make the name of the reference configurable, including restricting the valid values to a pre-defined enum.

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
metadata:
  name: azure-clusterclass-v0.1.0
spec:
  ...
  variables:
  - name: clusterIdentityRef
    schema:
      openAPIV3Schema:
        type: object
        properties:
          kind:
            type: string
          name:
            type: string

Even if OpenAPI schema allows defining free form objects, e.g.

variables:
  - name: freeFormObject
    schema:
      openAPIV3Schema:
        type: object

User should be aware that the lack of the validation of users provided data could lead to problems when those values are used in patch or when the generated templates are created (see e.g. 6135).

As a consequence we recommend avoiding this practice while we are considering alternatives to make it explicit for the ClusterClass authors to opt in this feature, thus accepting the implied risks.

Using variable values in JSON patches

We already saw above that it’s possible to use variable values in JSON patches. It’s also possible to calculate values via Go templating or to use hard-coded values.

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
metadata:
  name: docker-clusterclass-v0.1.0
spec:
  ...
  patches:
  - name: etcdImageTag
    definitions:
    - selector:
      ...
      jsonPatches:
      - op: add
        path: /spec/template/spec/kubeadmConfigSpec/clusterConfiguration/etcd
        valueFrom:
          # This template is first rendered with Go templating, then parsed by 
          # a YAML/JSON parser and then used as value of the JSON patch.
          # For example, if the variable etcdImageTag is set to `3.5.1-0` the 
          # .../clusterConfiguration/etcd field will be set to:
          # {"local": {"imageTag": "3.5.1-0"}}
          template: |
            local:
              imageTag: {{ .etcdImageTag }}
  - name: imageRepository
    definitions:
    - selector:
      ...
      jsonPatches:
      - op: add
        path: /spec/template/spec/kubeadmConfigSpec/clusterConfiguration/imageRepository
        # This hard-coded value is used directly as value of the JSON patch.
        value: "my.custom.registry"

Tips & Tricks

Templates can be used to implement defaulting behavior during JSON patch value calculation. This can be used if the simple constant default value which can be specified in the schema is not enough.

        valueFrom:
          # If .vnetName is set, it is used. Otherwise, we will use `{{.builtin.cluster.name}}-vnet`.  
          template: "{{ if .vnetName }}{{.vnetName}}{{else}}{{.builtin.cluster.name}}-vnet{{end}}"

When writing templates, a subset of functions from the Sprig library can be used to write expressions, e.g., {{ .name | upper }}. Only functions that are guaranteed to evaluate to the same result for a given input are allowed (e.g. upper or max can be used, while now or randAlpha cannot be used).

Optional patches

Patches can also be conditionally enabled. This can be done by configuring a Go template via enabledIf. The patch is then only applied if the Go template evaluates to true. In the following example the httpProxy patch is only applied if the httpProxy variable is set (and not empty).

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
metadata:
  name: docker-clusterclass-v0.1.0
spec:
  ...
  variables:
  - name: httpProxy
    schema:
      openAPIV3Schema:
        type: string
  patches:
  - name: httpProxy
    enabledIf: "{{ if .httpProxy }}true{{end}}"
    definitions:
    ...  

Tips & Tricks:

Hard-coded values can be used to test the impact of a patch during development, gradually roll out patches, etc. .

    enabledIf: false

A boolean variable can be used to enable/disable a patch (or “feature”). This can have opt-in or opt-out behavior depending on the default value of the variable.

    enabledIf: "{{ .httpProxyEnabled }}"

Of course the same is possible by adding a boolean variable to a configuration object.

    enabledIf: "{{ .httpProxy.enabled }}"

Builtin variables can be leveraged to apply a patch only for a specific Kubernetes version.

    enabledIf: '{{ semverCompare "1.21.1" .builtin.controlPlane.version }}'

With semverCompare and coalesce a feature can be enabled in newer versions of Kubernetes for both KubeadmConfigTemplate and KubeadmControlPlane.

    enabledIf: '{{ semverCompare "^1.22.0" (coalesce .builtin.controlPlane.version .builtin.machineDeployment.version )}}'

Version-aware patches

In some cases the ClusterClass authors want a patch to be computed according to the Kubernetes version in use.

While this is not a problem “per se” and it does not differ from writing any other patch, it is important to keep in mind that there could be different Kubernetes version in a Cluster at any time, all of them accessible via built in variables:

  • builtin.cluster.topology.version defines the Kubernetes version from cluster.topology, and it acts as the desired Kubernetes version for the entire cluster. However, during an upgrade workflow it could happen that some objects in the Cluster are still at the older version.
  • builtin.controlPlane.version, represent the desired version for the control plane object; usually this version changes immediately after cluster.topology.version is updated (unless there are other operations in progress preventing the upgrade to start).
  • builtin.machineDeployment.version, represent the desired version for each specific MachineDeployment object; this version changes only after the upgrade for the control plane is completed, and in case of many MachineDeployments in the same cluster, they are upgraded sequentially.
  • builtin.machinePool.version, represent the desired version for each specific MachinePool object; this version changes only after the upgrade for the control plane is completed, and in case of many MachinePools in the same cluster, they are upgraded sequentially.

This info should provide the bases for developing version-aware patches, allowing the patch author to determine when a patch should adapt to the new Kubernetes version by choosing one of the above variables. In practice the following rules applies to the most common use cases:

  • When developing a version-aware patch for the control plane, builtin.controlPlane.version must be used.
  • When developing a version-aware patch for MachineDeployments, builtin.machineDeployment.version must be used.
  • When developing a version-aware patch for MachinePools, builtin.machinePool.version must be used.

Tips & Tricks:

Sometimes users need to define variables to be used by version-aware patches, and in this case it is important to keep in mind that there could be different Kubernetes versions in a Cluster at any time.

A simple approach to solve this problem is to define a map of version-aware variables, with the key of each item being the Kubernetes version. Patch could then use the proper builtin variables as a lookup entry to fetch the corresponding values for the Kubernetes version in use by each object.

JSON patches tips & tricks

JSON patches specification RFC6902 requires that the target of add operation must exist.

As a consequence ClusterClass authors should pay special attention when the following conditions apply in order to prevent errors when a patch is applied:

  • the patch tries to add a value to an array (which is a slice in the corresponding go struct)
  • the slice was defined with omitempty
  • the slice currently does not exist

A workaround in this particular case is to create the array in the patch instead of adding to the non-existing one. When creating the slice, existing values would be overwritten so this should only be used when it does not exist.

The following example shows both cases to consider while writing a patch for adding a value to a slice. This patch targets to add a file to the files slice of a KubeadmConfigTemplate which has omitempty set.

This patch requires the key .spec.template.spec.files to exist to succeed.

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
metadata:
  name: my-clusterclass
spec:
  ...
  patches:
  - name: add file
    definitions:
    - selector:
        apiVersion: bootstrap.cluster.x-k8s.io/v1beta2
        kind: KubeadmConfigTemplate
      jsonPatches:
      - op: add
        path: /spec/template/spec/files/-
        value:
          content: Some content.
          path: /some/file
---
apiVersion: bootstrap.cluster.x-k8s.io/v1beta2
kind: KubeadmConfigTemplate
metadata:
  name: "quick-start-default-worker-bootstraptemplate"
spec:
  template:
    spec:
      ...
      files:
      - content: Some other content
        path: /some/other/file

This patch would overwrite an existing slice at .spec.template.spec.files.

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
metadata:
  name: my-clusterclass
spec:
  ...
  patches:
  - name: add file
    definitions:
    - selector:
        apiVersion: bootstrap.cluster.x-k8s.io/v1beta2
        kind: KubeadmConfigTemplate
      jsonPatches:
      - op: add
        path: /spec/template/spec/files
        value:
        - content: Some content.
          path: /some/file
---
apiVersion: bootstrap.cluster.x-k8s.io/v1beta2
kind: KubeadmConfigTemplate
metadata:
  name: "quick-start-default-worker-bootstraptemplate"
spec:
  template:
    spec:
      ...

Changing a ClusterClass

Selecting a strategy

When planning a change to a ClusterClass, users should always take into consideration how those changes might impact the existing Clusters already using the ClusterClass, if any.

There are two strategies for defining how a ClusterClass change rolls out to existing Clusters:

  • Roll out ClusterClass changes to existing Cluster in a controlled/incremental fashion.
  • Roll out ClusterClass changes to all the existing Cluster immediately.

The first strategy is the recommended choice for people starting with ClusterClass; it requires the users to create a new ClusterClass with the expected changes, and then rebase each Cluster to use the newly created ClusterClass.

By splitting the change to the ClusterClass and its rollout to Clusters into separate steps the user will reduce the risk of introducing unexpected changes on existing Clusters, or at least limit the blast radius of those changes to a small number of Clusters already rebased (in fact it is similar to a canary deployment).

The second strategy listed above instead requires changing a ClusterClass “in place”, which can be simpler and faster than creating a new ClusterClass. However, this approach means that changes are immediately propagated to all the Clusters already using the modified ClusterClass. Any operation involving many Clusters at the same time has intrinsic risks, and it can impact heavily on the underlying infrastructure in case the operation triggers machine rollout across the entire fleet of Clusters.

However, regardless of which strategy you are choosing to implement your changes to a ClusterClass, please make sure to:

If instead you are interested in understanding more about which kind of
effects you should expect on the Clusters, or if you are interested in additional details about the internals of the topology reconciler you can start reading the notes in the Plan ClusterClass changes documentation or looking at the reference documentation at the end of this page.

Changing ClusterClass templates

Templates are an integral part of a ClusterClass, and thus the same considerations described in the previous paragraph apply. When changing a template referenced in a ClusterClass users should also always plan for how the change should be propagated to the existing Clusters and choose the strategy that best suits expectations.

According to the Cluster API operational practices, the recommended way for updating templates is by template rotation:

  • Create a new template
  • Update the template reference in the ClusterClass
  • Delete the old template

Also in case of changes to the ClusterClass templates, please make sure to:

You can learn more about this reading the notes in the Plan ClusterClass changes documentation or looking at the reference documentation at the end of this page.

Rebase

Rebasing is an operational practice for transitioning a Cluster from one ClusterClass to another, and the operation can be triggered by simply changing the value in Cluster.spec.topology.class.

Also in this case, please make sure to:

You can learn more about this reading the notes in the Plan ClusterClass changes documentation or looking at the reference documentation at the end of this page.

Compatibility Checks

When changing a ClusterClass, the system validates the required changes according to a set of compatibility rules to prevent changes which would lead to a non-functional Cluster, e.g. changing the InfrastructureProvider from AWS to Azure.

If the proposed changes are evaluated as dangerous, the operation is rejected.

Planning ClusterClass changes

Some general notes that can help you to understand what you should expect when planning your ClusterClass changes:

  • Users should expect the resources in a Cluster (e.g. MachineDeployments) to behave consistently no matter if a change is applied via a ClusterClass or directly as you do in a Cluster without a ClusterClass. In other words, if someone changes something on a KCP object triggering a control plane Machines rollout, you should expect the same to happen when the same change is applied to the KCP template in ClusterClass.

  • User should expect the Cluster topology to change consistently irrespective of how the change has been implemented inside the ClusterClass or applied to the ClusterClass. In other words, if you change a template field “in place”, or if you rotate the template referenced in the ClusterClass by pointing to a new template with the same field changed, or if you change the same field via a patch, the effects on the Cluster are the same.

See reference for more details.

Reference

Effects on the Clusters

The following table documents the effects each ClusterClass change can have on a Cluster; Similar considerations apply to changes introduced by changes in Cluster.Topology or by changes introduced by patches.

NOTE: for people used to operating Cluster API without Cluster Class, it could also help to keep in mind that the underlying objects like control plane and MachineDeployment act in the same way with and without a ClusterClass.

Changed fieldEffects on Clusters
infrastructure.refCorresponding InfrastructureCluster objects are updated (in-place update).
controlPlane.metadataIf labels/annotations are added, changed or deleted the ControlPlane objects are updated (in-place update).

In case of KCP, corresponding controlPlane Machines, KubeadmConfigs and InfrastructureMachines are updated in-place.
controlPlane.refCorresponding ControlPlane objects are updated (in-place update).
If updating ControlPlane objects implies changes in the spec, the corresponding ControlPlane Machines are updated accordingly (rollout).
controlPlane.machineInfrastructure.refIf the referenced template has changes only in metadata labels or annotations, the corresponding InfrastructureMachineTemplates are updated (in-place update).

If the referenced template has changes in the spec:
- Corresponding InfrastructureMachineTemplate are rotated (create new, delete old)
- Corresponding ControlPlane objects are updated with the reference to the newly created template (in-place update)
- The corresponding controlPlane Machines are updated accordingly (rollout).
controlPlane.nodeDrainTimeoutIf the value is changed the ControlPlane object is updated in-place.

In case of KCP, the change is propagated in-place to control plane Machines.
controlPlane.nodeVolumeDetachTimeoutIf the value is changed the ControlPlane object is updated in-place.

In case of KCP, the change is propagated in-place to control plane Machines.
controlPlane.nodeDeletionTimeoutIf the value is changed the ControlPlane object is updated in-place.

In case of KCP, the change is propagated in-place to control plane Machines.
workers.machineDeploymentsIf a new MachineDeploymentClass is added, no changes are triggered to the Clusters.
If an existing MachineDeploymentClass is changed, effect depends on the type of change (see below).
workers.machineDeployments[].template.metadataIf labels/annotations are added, changed or deleted the MachineDeployment objects are updated (in-place update) and corresponding worker Machines are updated (in-place).
workers.machineDeployments[].template.bootstrap.refIf the referenced template has changes only in metadata labels or annotations, the corresponding BootstrapTemplates are updated (in-place update).

If the referenced template has changes in the spec:
- Corresponding BootstrapTemplate are rotated (create new, delete old).
- Corresponding MachineDeployments objects are updated with the reference to the newly created template (in-place update).
- The corresponding worker machines are updated accordingly (rollout)
workers.machineDeployments[].template.infrastructure.refIf the referenced template has changes only in metadata labels or annotations, the corresponding InfrastructureMachineTemplates are updated (in-place update).

If the referenced template has changes in the spec:
- Corresponding InfrastructureMachineTemplate are rotated (create new, delete old).
- Corresponding MachineDeployments objects are updated with the reference to the newly created template (in-place update).
- The corresponding worker Machines are updated accordingly (rollout)
workers.machineDeployments[].template.nodeDrainTimeoutIf the value is changed the MachineDeployment is updated in-place.

The change is propagated in-place to the MachineDeployment Machine.
workers.machineDeployments[].template.nodeVolumeDetachTimeoutIf the value is changed the MachineDeployment is updated in-place.

The change is propagated in-place to the MachineDeployment Machine.
workers.machineDeployments[].template.nodeDeletionTimeoutIf the value is changed the MachineDeployment is updated in-place.

The change is propagated in-place to the MachineDeployment Machine.
workers.machineDeployments[].template.minReadySecondsIf the value is changed the MachineDeployment is updated in-place.

How the topology controller reconciles template fields

The topology reconciler enforces values defined in the ClusterClass templates into the topology owned objects in a Cluster.

More specifically, the topology controller uses Server Side Apply to write/patch topology owned objects; using SSA allows other controllers to co-author the generated objects, like e.g. adding info for subnets in CAPA.

A corollary of the behaviour described above is that it is technically possible to change fields in the object which are not derived from the templates and patches, but we advise against using the possibility or making ad-hoc changes in generated objects unless otherwise needed for a workaround. It is always preferable to improve ClusterClasses by supporting new Cluster variants in a reusable way.

Operating a managed Cluster

The spec.topology field added to the Cluster object as part of ClusterClass allows changes made on the Cluster to be propagated across all relevant objects. This means the Cluster object can be used as a single point of control for making changes to objects that are part of the Cluster, including the ControlPlane and MachineDeployments.

A managed Cluster can be used to:

Upgrade a Cluster

Using a managed topology the operation to upgrade a Kubernetes cluster is a one-touch operation. Let’s assume we have created a CAPD cluster with ClusterClass and specified Kubernetes v1.21.2 (as documented in the Quick Start guide). Specifying the version is done when running clusterctl generate cluster. Looking at the cluster, the version of the control plane and the MachineDeployments is v1.21.2.

> kubectl get kubeadmcontrolplane,machinedeployments
NAME                                                                              CLUSTER                   INITIALIZED   API SERVER AVAILABLE   REPLICAS   READY   UPDATED   UNAVAILABLE   AGE     VERSION
kubeadmcontrolplane.controlplane.cluster.x-k8s.io/clusterclass-quickstart-XXXX    clusterclass-quickstart   true          true                   1          1       1         0             2m21s   v1.21.2

NAME                                                                             CLUSTER                   REPLICAS   READY   UPDATED   UNAVAILABLE   PHASE     AGE     VERSION
machinedeployment.cluster.x-k8s.io/clusterclass-quickstart-linux-workers-XXXX    clusterclass-quickstart   1          1       1         0             Running   2m21s   v1.21.2

To update the Cluster the only change needed is to the version field under spec.topology in the Cluster object.

Change 1.21.2 to 1.22.0 as below.

kubectl patch cluster clusterclass-quickstart --type json --patch '[{"op": "replace", "path": "/spec/topology/version", "value": "v1.22.0"}]'

The patch will make the following change to the Cluster yaml:

   spec:
     topology:
      classRef:
        name: quick-start
+     version: v1.22.0
-     version: v1.21.2 

Important Note: A +2 minor Kubernetes version upgrade is not allowed in Cluster Topologies. This is to align with existing control plane providers, like KubeadmControlPlane provider, that limit a +2 minor version upgrade. Example: Upgrading from 1.21.2 to 1.23.0 is not allowed.

The upgrade will take some time to roll out as it will take place machine by machine with older versions of the machines only being removed after healthy newer versions come online.

To watch the update progress run:

watch kubectl get kubeadmcontrolplane,machinedeployments

After a few minutes the upgrade will be complete and the output will be similar to:

NAME                                                                              CLUSTER                   INITIALIZED   API SERVER AVAILABLE   REPLICAS   READY   UPDATED   UNAVAILABLE   AGE     VERSION
kubeadmcontrolplane.controlplane.cluster.x-k8s.io/clusterclass-quickstart-XXXX    clusterclass-quickstart   true          true                   1          1       1         0             7m29s   v1.22.0

NAME                                                                             CLUSTER                   REPLICAS   READY   UPDATED   UNAVAILABLE   PHASE     AGE     VERSION
machinedeployment.cluster.x-k8s.io/clusterclass-quickstart-linux-workers-XXXX    clusterclass-quickstart   1          1       1         0             Running   7m29s   v1.22.0

Scale a MachineDeployment

When using a managed topology scaling of MachineDeployments, both up and down, should be done through the Cluster topology.

Assume we have created a CAPD cluster with ClusterClass and Kubernetes v1.23.3 (as documented in the Quick Start guide). Initially we should have a MachineDeployment with 3 replicas. Running

kubectl get machinedeployments

Will give us:

NAME                                                            CLUSTER           REPLICAS   READY   UPDATED   UNAVAILABLE   PHASE     AGE   VERSION
machinedeployment.cluster.x-k8s.io/capi-quickstart-md-0-XXXX   capi-quickstart   3          3       3         0             Running   21m   v1.23.3

We can scale up or down this MachineDeployment through the Cluster object by changing the replicas field under /spec/topology/workers/machineDeployments/0/replicas The 0 in the path refers to the position of the target MachineDeployment in the list of our Cluster topology. As we only have one MachineDeployment we’re targeting the first item in the list under /spec/topology/workers/machineDeployments/.

To change this value with a patch:

kubectl patch cluster capi-quickstart --type json --patch '[{"op": "replace", "path": "/spec/topology/workers/machineDeployments/0/replicas",  "value": 1}]'

This patch will make the following changes on the Cluster yaml:

   spec:
     topology:
       workers:
         machineDeployments:
         - class: default-worker
           name: md-0
           metadata: {}
+          replicas: 1
-          replicas: 3

After a minute the MachineDeployment will have scaled down to 1 replica:

NAME                         CLUSTER           REPLICAS   READY   UPDATED   UNAVAILABLE   PHASE     AGE   VERSION
capi-quickstart-md-0-XXXXX  capi-quickstart   1          1       1         0             Running   25m   v1.23.3

As well as scaling a MachineDeployment, Cluster operators can edit the labels and annotations applied to a running MachineDeployment using the Cluster topology as a single point of control.

Add a MachineDeployment

MachineDeployments in a managed Cluster are defined in the Cluster’s topology. Cluster operators can add a MachineDeployment to a living Cluster by adding it to the cluster.spec.topology.workers.machineDeployments field.

Assume we have created a CAPD cluster with ClusterClass and Kubernetes v1.23.3 (as documented in the Quick Start guide). Initially we should have a single MachineDeployment with 3 replicas. Running

kubectl get machinedeployments

Will give us:

NAME                                                            CLUSTER           REPLICAS   READY   UPDATED   UNAVAILABLE   PHASE     AGE   VERSION
machinedeployment.cluster.x-k8s.io/capi-quickstart-md-0-XXXX   capi-quickstart   3          3       3         0             Running   21m   v1.23.3

A new MachineDeployment can be added to the Cluster by adding a new MachineDeployment spec under /spec/topology/workers/machineDeployments/. To do so we can patch our Cluster with:

kubectl patch cluster capi-quickstart --type json --patch '[{"op": "add", "path": "/spec/topology/workers/machineDeployments/-",  "value": {"name": "second-deployment", "replicas": 1, "class": "default-worker"} }]'

This patch will make the below changes on the Cluster yaml:

   spec:
     topology:
       workers:
         machineDeployments:
         - class: default-worker
           metadata: {}
           replicas: 3
           name: md-0
+        - class: default-worker
+          metadata: {}
+          replicas: 1
+          name: second-deployment

After a minute to scale the new MachineDeployment we get:

NAME                                      CLUSTER           REPLICAS   READY   UPDATED   UNAVAILABLE   PHASE     AGE   VERSION
capi-quickstart-md-0-XXXX                 capi-quickstart   1          1       1         0             Running   39m   v1.23.3
capi-quickstart-second-deployment-XXXX    capi-quickstart   1          1       1         0             Running   99s   v1.23.3

Our second deployment uses the same underlying MachineDeployment class default-worker as our initial deployment. In this case they will both have exactly the same underlying machine templates. In order to modify the templates MachineDeployments are based on take a look at Changing a ClusterClass.

A similar process as that described here - removing the MachineDeployment from cluster.spec.topology.workers.machineDeployments - can be used to delete a running MachineDeployment from an active Cluster.

Scale a ControlPlane

When using a managed topology scaling of ControlPlane Machines, where the Cluster is using a topology that includes ControlPlane MachineInfrastructure, should be done through the Cluster topology.

This is done by changing the ControlPlane replicas field at /spec/topology/controlPlane/replica in the Cluster object. The command is:

kubectl patch cluster capi-quickstart --type json --patch '[{"op": "replace", "path": "/spec/topology/controlPlane/replicas",  "value": 1}]'

This patch will make the below changes on the Cluster yaml:

   spec:
      topology:
        controlPlane:
          metadata: {}
+         replicas: 1
-         replicas: 3

As well as scaling a ControlPlane, Cluster operators can edit the labels and annotations applied to a running ControlPlane using the Cluster topology as a single point of control.

Use variables

A ClusterClass can use variables and patches in order to allow flexible customization of Clusters derived from a ClusterClass. Variable definition allows two or more Cluster topologies derived from the same ClusterClass to have different specs, with the differences controlled by variables in the Cluster topology.

Assume we have created a CAPD cluster with ClusterClass and Kubernetes v1.23.3 (as documented in the Quick Start guide). Our Cluster has a variable etcdImageTag as defined in the ClusterClass. The variable is not set on our Cluster. Some variables, depending on their definition in a ClusterClass, may need to be specified by the Cluster operator for every Cluster created using a given ClusterClass.

In order to specify the value of a variable all we have to do is set the value in the Cluster topology.

We can see the current unset variable with:

kubectl get cluster capi-quickstart -o jsonpath='{.spec.topology.variables[1]}'                                     

Which will return something like:

{"name":"etcdImageTag","value":""}

In order to run a different version of etcd in new ControlPlane machines - the part of the spec this variable sets - change the value using the below patch:

kubectl patch cluster capi-quickstart --type json --patch '[{"op": "replace", "path": "/spec/topology/variables/1/value",  "value": "3.5.0"}]'

Running the patch makes the following change to the Cluster yaml:

   spec:
     topology:
       variables:
       - name: imageRepository
         value: registry.k8s.io
       - name: etcdImageTag
         value: ""
       - name: coreDNSImageTag
+        value: "3.5.0"
-        value: ""

Retrieving the variable value from the Cluster object, with kubectl get cluster capi-quickstart -o jsonpath='{.spec.topology.variables[1]}' we can see:

{"name":"etcdImageTag","value":"3.5.0"}

Note: Changing the etcd version may have unintended impacts on a running Cluster. For safety the cluster should be reapplied after running the above variable patch.

Rebase a Cluster

To perform more significant changes using a Cluster as a single point of control, it may be necessary to change the ClusterClass that the Cluster is based on. This is done by changing the class referenced in /spec/topology/class.

To read more about changing an underlying class please refer to ClusterClass rebase.

Tips and tricks

Users should always aim at ensuring the stability of the Cluster and of the applications hosted on it while using spec.topology as a single point of control for making changes to the objects that are part of the Cluster.

Following recommendation apply:

  • If possible, avoid concurrent changes to control-plane and/or MachineDeployments to prevent excessive turnover on the underlying infrastructure or bottlenecks in the Cluster trying to move workloads from one machine to the other.
  • Keep machine labels and annotation stable, because changing those values requires machines rollouts; also, please note that machine labels and annotation are not propagated to Kubernetes nodes; see metadata propagation.
  • While upgrading a Cluster, if possible avoid any other concurrent change to the Cluster; please note that you can rely on version-aware patches to ensure the Cluster adapts to the new Kubernetes version in sync with the upgrade workflow.

For more details about how changes can affect a Cluster, please look at reference.

Upgrading Cluster API

There are some special considerations for ClusterClass regarding Cluster API upgrades when the upgrade includes a bump of the apiVersion of infrastructure, bootstrap or control plane provider CRDs.

The recommended approach is to first upgrade Cluster API and then update the apiVersions in the ClusterClass references afterwards. By following above steps, there won’t be any disruptions of the reconciliation as the Cluster topology controller is able to reconcile the Cluster even with the old apiVersions in the ClusterClass.

Note: The apiVersions in ClusterClass cannot be updated before Cluster API because the new apiVersions don’t exist in the management cluster before the Cluster API upgrade.

In general the Cluster topology controller always uses exactly the versions of the CRDs referenced in the ClusterClass. This means in the following example the Cluster topology controller will always use v1beta1 when reconciling/applying patches for the infrastructure ref, even if the DockerClusterTemplate already has a v1beta2 apiVersion.

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
metadata:
  name: quick-start
  namespace: default
spec:
  infrastructure:
    templateRef:
      apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
      kind: DockerClusterTemplate
...

Experimental Feature: Runtime SDK (alpha)

The Runtime SDK feature provides an extensibility mechanism that allows systems, products, and services built on top of Cluster API to hook into a workload cluster’s lifecycle.

Feature gate name: RuntimeSDK

Variable name to enable/disable the feature gate: EXP_RUNTIME_SDK

Additional documentation:

Implementing Runtime Extensions

Introduction

As a developer building systems on top of Cluster API, if you want to hook into the Cluster’s lifecycle via a Runtime Hook, you have to implement a Runtime Extension handling requests according to the OpenAPI specification for the Runtime Hook you are interested in.

Runtime Extensions by design are very powerful and flexible, however given that with great power comes great responsibility, a few key consideration should always be kept in mind (more details in the following sections):

  • Runtime Extensions are components that should be designed, written and deployed with great caution given that they can affect the proper functioning of the Cluster API runtime.
  • Cluster administrators should carefully vet any Runtime Extension registration, thus preventing malicious components from being added to the system.

Please note that following similar practices is already commonly accepted in the Kubernetes ecosystem for Kubernetes API server admission webhooks. Runtime Extensions share the same foundation and most of the same considerations/concerns apply.

Implementation

As mentioned above as a developer building systems on top of Cluster API, if you want to hook in the Cluster’s lifecycle via a Runtime Extension, you have to implement an HTTPS server handling a discovery request and a set of additional requests according to the OpenAPI specification for the Runtime Hook you are interested in.

The following shows a minimal example of a Runtime Extension server implementation:

package main

import (
	"context"
	"flag"
	"net/http"
	"os"

	"github.com/spf13/pflag"
	cliflag "k8s.io/component-base/cli/flag"
	"k8s.io/component-base/logs"
	logsv1 "k8s.io/component-base/logs/api/v1"
	"k8s.io/klog/v2"
	ctrl "sigs.k8s.io/controller-runtime"

	runtimehooksv1 "sigs.k8s.io/cluster-api/api/runtime/hooks/v1alpha1"
	runtimecatalog "sigs.k8s.io/cluster-api/exp/runtime/catalog"
	"sigs.k8s.io/cluster-api/exp/runtime/server"
)

var (
	// catalog contains all information about RuntimeHooks.
	catalog = runtimecatalog.New()

	// Flags.
	profilerAddress string
	webhookPort     int
	webhookCertDir  string
	logOptions      = logs.NewOptions()
)

func init() {
	// Adds to the catalog all the RuntimeHooks defined in cluster API.
	_ = runtimehooksv1.AddToCatalog(catalog)
}

// InitFlags initializes the flags.
func InitFlags(fs *pflag.FlagSet) {
	// Initialize logs flags using Kubernetes component-base machinery.
	logsv1.AddFlags(logOptions, fs)

	// Add test-extension specific flags
	fs.StringVar(&profilerAddress, "profiler-address", "",
		"Bind address to expose the pprof profiler (e.g. localhost:6060)")

	fs.IntVar(&webhookPort, "webhook-port", 9443,
		"Webhook Server port")

	fs.StringVar(&webhookCertDir, "webhook-cert-dir", "/tmp/k8s-webhook-server/serving-certs/",
		"Webhook cert dir.")
}

func main() {
	// Creates a logger to be used during the main func.
	setupLog := ctrl.Log.WithName("setup")

	// Initialize and parse command line flags.
	InitFlags(pflag.CommandLine)
	pflag.CommandLine.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
	pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
	// Set log level 2 as default.
	if err := pflag.CommandLine.Set("v", "2"); err != nil {
		setupLog.Error(err, "Failed to set default log level")
		os.Exit(1)
	}
	pflag.Parse()

	// Validates logs flags using Kubernetes component-base machinery and applies them
	if err := logsv1.ValidateAndApply(logOptions, nil); err != nil {
		setupLog.Error(err, "Unable to start extension")
		os.Exit(1)
	}

	pflag.CommandLine.VisitAll(func(flag *pflag.Flag) {
		klog.V(1).Infof("FLAG: --%s=%q", flag.Name, flag.Value)
	})

	// Add the klog logger in the context.
	ctrl.SetLogger(klog.Background())

	// Initialize the golang profiler server, if required.
	if profilerAddress != "" {
		klog.Infof("Profiler listening for requests at %s", profilerAddress)
		go func() {
			klog.Info(http.ListenAndServe(profilerAddress, nil))
		}()
	}

	// Create a http server for serving runtime extensions
	webhookServer, err := server.New(server.Options{
		Catalog: catalog,
		Port:    webhookPort,
		CertDir: webhookCertDir,
	})
	if err != nil {
		setupLog.Error(err, "Error creating webhook server")
		os.Exit(1)
	}

	// Register extension handlers.
	if err := webhookServer.AddExtensionHandler(server.ExtensionHandler{
		Hook:        runtimehooksv1.BeforeClusterCreate,
		Name:        "before-cluster-create",
		HandlerFunc: DoBeforeClusterCreate,
	}); err != nil {
		setupLog.Error(err, "Error adding handler")
		os.Exit(1)
	}
	if err := webhookServer.AddExtensionHandler(server.ExtensionHandler{
		Hook:        runtimehooksv1.BeforeClusterUpgrade,
		Name:        "before-cluster-upgrade",
		HandlerFunc: DoBeforeClusterUpgrade,
	}); err != nil {
		setupLog.Error(err, "Error adding handler")
		os.Exit(1)
	}

	// Setup a context listening for SIGINT.
	ctx := ctrl.SetupSignalHandler()

	// Start the https server.
	setupLog.Info("Starting Runtime Extension server")
	if err := webhookServer.Start(ctx); err != nil {
		setupLog.Error(err, "Error running webhook server")
		os.Exit(1)
	}
}

func DoBeforeClusterCreate(ctx context.Context, request *runtimehooksv1.BeforeClusterCreateRequest, response *runtimehooksv1.BeforeClusterCreateResponse) {
	log := ctrl.LoggerFrom(ctx)
	log.Info("BeforeClusterCreate is called")
	// Your implementation
}

func DoBeforeClusterUpgrade(ctx context.Context, request *runtimehooksv1.BeforeClusterUpgradeRequest, response *runtimehooksv1.BeforeClusterUpgradeResponse) {
	log := ctrl.LoggerFrom(ctx)
	log.Info("BeforeClusterUpgrade is called")
	// Your implementation
}

For a full example see our test extension.

Please note that a Runtime Extension server can serve multiple Runtime Hooks (in the example above BeforeClusterCreate and BeforeClusterUpgrade) at the same time. Each of them are handled at a different path, like the Kubernetes API server does for different API resources. The exact format of those paths is handled by the server automatically in accordance to the OpenAPI specification of the Runtime Hooks.

There is an additional Discovery endpoint which is automatically served by the Server. The Discovery endpoint returns a list of extension handlers to inform Cluster API which Runtime Hooks are implemented by this Runtime Extension server.

Please note that Cluster API is only able to enforce the correct request and response types as defined by a Runtime Hook version. Developers are fully responsible for all other elements of the design of a Runtime Extension implementation, including:

  • To choose which programming language to use; please note that Golang is the language of choice, and we are not planning to test or provide tooling and libraries for other languages. Nevertheless, given that we rely on Open API and plain HTTPS calls, other languages should just work but support will be provided at best effort.
  • To choose if a dedicated or a shared HTTPS Server is used for the Runtime Extension (it can be e.g. also used to serve a metric endpoint).

When using Golang the Runtime Extension developer can benefit from the following packages (provided by the sigs.k8s.io/cluster-api module) as shown in the example above:

  • api/runtime/hooks/v1alpha1 contains the Runtime Hook Golang API types, which are also used to generate the OpenAPI specification.
  • exp/runtime/catalog provides the Catalog object to register Runtime Hook definitions. The Catalog is then used by the server package to handle requests. Catalog is similar to the runtime.Scheme of the k8s.io/apimachinery/pkg/runtime package, but it is designed to store Runtime Hook registrations.
  • exp/runtime/server provides a Server object which makes it easy to implement a Runtime Extension server. The Server will automatically handle tasks like Marshalling/Unmarshalling requests and responses. A Runtime Extension developer only has to implement a strongly typed function that contains the actual logic.

Guidelines

While writing a Runtime Extension the following important guidelines must be considered:

Timeouts

Runtime Extension processing adds to reconcile durations of Cluster API controllers. They should respond to requests as quickly as possible, typically in milliseconds. Runtime Extension developers can decide how long the Cluster API Runtime should wait for a Runtime Extension to respond before treating the call as a failure (max is 30s) by returning the timeout during discovery. Of course a Runtime Extension can trigger long-running tasks in the background, but they shouldn’t block synchronously.

Availability

Runtime Extension failure could result in errors in handling the workload clusters lifecycle, and so the implementation should be robust, have proper error handling, avoid panics, etc. Failure policies can be set up to mitigate the negative impact of a Runtime Extension on the Cluster API Runtime, but this option can’t be used in all cases (see Error Management).

Blocking Hooks

A Runtime Hook can be defined as “blocking” - e.g. the BeforeClusterUpgrade hook allows a Runtime Extension to prevent the upgrade from starting. A Runtime Extension registered for the BeforeClusterUpgrade hook can block by returning a non-zero retryAfterSeconds value. Following consideration apply:

  • The system might decide to retry the same Runtime Extension even before the retryAfterSeconds period expires, e.g. due to other changes in the Cluster, so retryAfterSeconds should be considered as an approximate maximum time before the next reconcile.
  • If there is more than one Runtime Extension registered for the same Runtime Hook and more than one returns retryAfterSeconds, the shortest non-zero value will be used.
  • If there is more than one Runtime Extension registered for the same Runtime Hook and at least one returns retryAfterSeconds, all Runtime Extensions will be called again.

Detailed description of what “blocking” means for each specific Runtime Hooks is documented case by case in the hook-specific implementation documentation (e.g. Implementing Lifecycle Hook Runtime Extensions).

Side Effects

It is recommended that Runtime Extensions should avoid side effects if possible, which means they should operate only on the content of the request sent to them, and not make out-of-band changes. If side effects are required, rules defined in the following sections apply.

Idempotence

An idempotent Runtime Extension is able to succeed even in case it has already been completed before (the Runtime Extension checks current state and changes it only if necessary). This is necessary because a Runtime Extension may be called many times after it already succeeded because other Runtime Extensions for the same hook may not succeed in the same reconcile.

A practical example that explains why idempotence is relevant is the fact that extensions could be called more than once for the same lifecycle transition, e.g.

  • Two Runtime Extensions are registered for the BeforeClusterUpgrade hook.
  • Before a Cluster upgrade is started both extensions are called, but one of them temporarily blocks the operation by asking to retry after 30 seconds.
  • After 30 seconds the system retries the lifecycle transition, and both extensions are called again to re-evaluate if it is now possible to proceed with the Cluster upgrade.

Avoid dependencies

Each Runtime Extension should accomplish its task without depending on other Runtime Extensions. Introducing dependencies across Runtime Extensions makes the system fragile, and it is probably a consequence of poor “Separation of Concerns” between extensions.

Deterministic result

A deterministic Runtime Extension is implemented in such a way that given the same input it will always return the same output.

Some Runtime Hooks, e.g. like external patches, might explicitly request for corresponding Runtime Extensions to support this property. But we encourage developers to follow this pattern more generally given that it fits well with practices like unit testing and generally makes the entire system more predictable and easier to troubleshoot.

Error messages

RuntimeExtension authors should be aware that error messages might be surfaced as conditions in Kubernetes resources and recorded in Cluster API controller’s logs. As a consequence:

  • Error message must not contain any sensitive information.
  • Error message must be deterministic, and must avoid to including timestamps or values changing at every call.
  • Error message must not contain external errors when it’s not clear if those errors are deterministic (e.g. errors return from cloud APIs).

ExtensionConfig

To register your runtime extension apply the ExtensionConfig resource in the management cluster, including your CA certs, ClusterIP service associated with the app and namespace, and the target namespace for the given extension. Once created, the extension will detect the associated service and discover the associated Hooks. For clarification, you can check the status of the ExtensionConfig. Below is an example of ExtensionConfig -

apiVersion: runtime.cluster.x-k8s.io/v1beta2
kind: ExtensionConfig
metadata:
  annotations:
    runtime.cluster.x-k8s.io/inject-ca-from-secret: default/test-runtime-sdk-svc-cert
  name: test-runtime-sdk-extensionconfig
spec:
  clientConfig:
    service:
      name: test-runtime-sdk-svc
      namespace: default # Note: this assumes the test extension get deployed in the default namespace
      port: 443
  namespaceSelector:
    matchExpressions:
      - key: kubernetes.io/metadata.name
        operator: In
        values:
          - default # Note: this assumes the test extension is used by Cluster in the default namespace only

Settings

Settings can be added to the ExtensionConfig object in the form of a map with string keys and values. These settings are sent with each request to hooks registered by that ExtensionConfig. Extension developers can implement behavior in their extensions to alter behavior based on these settings. Settings should be well documented by extension developers so that ClusterClass authors can understand usage and expected behaviour.

Settings can be provided for individual external patches by providing them in the ClusterClass .spec.patches[*].external.settings. This can be used to overwrite settings at the ExtensionConfig level for that patch.

Error management

In case a Runtime Extension returns an error, the error will be handled according to the corresponding failure policy defined in the response of the Discovery call.

If the failure policy is Ignore the error is going to be recorded in the controller’s logs, but the processing will continue. However we recognize that this failure policy cannot be used in most of the use cases because Runtime Extension implementers want to ensure that the task implemented by an extension is completed before continuing with the cluster’s lifecycle.

If instead the failure policy is Fail the system will retry the operation until it passes. The following general considerations apply:

  • It is the responsibility of Cluster API components to surface Runtime Extension errors using conditions.
  • Operations will be retried with an exponential backoff or whenever the state of a Cluster changes (we are going to rely on controller runtime exponential backoff/watches).
  • If there is more than one Runtime Extension registered for the same Runtime Hook and at least one of them fails, all the registered Runtime Extension will be retried. See Idempotence

Additional considerations about errors that apply only to a specific Runtime Hook will be documented in the hook-specific implementation documentation.

Tips & tricks

Make sure to add the ExtensionConfig object to the YAML manifest used to deploy the runtime extensions (see Extensionsconfig for more details).

After you implemented and deployed a Runtime Extension you can manually test it by sending HTTP requests. This can be for example done via kubectl:

Via kubectl create --raw:

# Send a Discovery Request to the webhook-service in namespace default with protocol https on port 443:
kubectl create --raw '/api/v1/namespaces/default/services/https:webhook-service:443/proxy/hooks.runtime.cluster.x-k8s.io/v1alpha1/discovery' \
  -f <(echo '{"apiVersion":"hooks.runtime.cluster.x-k8s.io/v1alpha1","kind":"DiscoveryRequest"}') | jq

Via kubectl proxy and curl:

# Open a proxy with kubectl and then use curl to send the request
## First terminal:
kubectl proxy
## Second terminal:
curl -X 'POST' 'http://127.0.0.1:8001/api/v1/namespaces/default/services/https:webhook-service:443/proxy/hooks.runtime.cluster.x-k8s.io/v1alpha1/discovery' \
  -d '{"apiVersion":"hooks.runtime.cluster.x-k8s.io/v1alpha1","kind":"DiscoveryRequest"}' | jq

For more details about the API of the Runtime Extensions please see . For more details on proxy support please see Proxies in Kubernetes.

Implementing in-place update hooks

Introduction

The proposal for in-place updates in Cluster API introduced extensions allowing users to execute changes on existing machines without deleting the Machine and creating a new one.

Notably, the Cluster API user experience remains the same as of today no matter of the in-place update feature is enabled or not e.g. in order to trigger a MachineDeployment rollout, you have to rotate a template, etc.

Users should care ONLY about the desired state (as of today).

Cluster API is responsible to choose the best strategy to achieve desired state, and with the introduction of update extensions, Cluster API is expanding the set of tools that can be used to achieve the desired state.

If external update extensions can not cover the totality of the desired changes, CAPI will fall back to Cluster API’s default, immutable rollouts.

Cluster API will be also responsible to determine which Machine/MachineSet should be updated, as well as to handle rollout options like MaxSurge/MaxUnavailable. With this regard:

  • Machines updating in-place are considered not available, because in-place updates are always considered as potentially disruptive.
    • For control plane machines, if maxSurge is 1, a new machine must be created first, then as soon as there is “buffer” for in-place, in-place update can proceed.
      • KCP will not use in-place in case it will detect that it can impact health of the control plane.
    • For workers machines, if maxUnavailable is 0, a new machine must be created first, then as soon as there is “buffer” for in-place, in-place update can proceed.
      • When in-place is possible, the system should try to in-place update as many machines as possible. In practice, this means that maxSurge might not be fully used (it is used only for scale up by one if maxUnavailable=0).
    • No in-place updates are performed for workers machines when using rollout strategy OnDelete.

Guidelines

All guidelines defined in Implementing Runtime Extensions apply to the implementation of Runtime Extensions for in-place update hooks as well.

In summary, Runtime Extensions are components that should be designed, written and deployed with great caution given that they can affect the proper functioning of the Cluster API runtime. A poorly implemented Runtime Extension could potentially block updates.

Following recommendations are especially relevant:

Definitions

For additional details about the OpenAPI spec of the upgrade plan hooks, please download the runtime-sdk-openapi.yaml file and then open it from the Swagger UI.

CanUpdateMachine

This hook is called by KCP when performing the “can update in-place” for a control plane machine.

Example request:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: CanUpdateMachineRequest
settings: <Runtime Extension settings>
current:
  machine:
    apiVersion: cluster.x-k8s.io/v1beta2
    kind: Machine
    metadata:
      name: test-cluster
      namespace: test-ns
    spec:
      ...
  infrastructureMachine:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: VSphereMachine
    metadata:
      name: test-cluster
      namespace: test-ns
    spec:
      ...
  boostrapConfig:
    apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
    kind: KubeadmConfig
    metadata:
      name: test-cluster
      namespace: test-ns
    spec:
      ...
desired:
  machine:
    ...
  infrastructureMachine:
    ...
  boostrapConfig:
    ...

Note:

  • All the objects will have the latest API version known by Cluster API.
  • Only spec is provided, status fields are not included
  • In a future release, when registering more than one extension for the CanUpdateMachine will be supported, the current state will already include changes that can be handled in-place by other runtime extensions.

Example Response:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: CanUpdateMachineResponse
status: Success # or Failure
message: "error message if status == Failure"
machinePatch:
  patchType: JSONPatch
  patch: <JSON-patch>
infrastructureMachinePatch:
  ...
boostrapConfigPatch:
  ...

Note:

  • Extensions should return per-object patches to be applied on current objects to indicate which changes they can handle in-place.
  • Only fields in Machine/InfraMachine/BootstrapConfig spec have to be covered by patches
  • Patches must be in JSONPatch or JSONMergePatch format

CanUpdateMachineSet

This hook is called by the MachineDeployment controller when performing the “can update in-place” for all the Machines controlled by a MachineSet.

Example request:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: CanUpdateMachineSetRequest
settings: <Runtime Extension settings>
current:
  machineSet:
    apiVersion: cluster.x-k8s.io/v1beta2
    kind: MachineSet
    metadata:
      name: test-cluster
      namespace: test-ns
    spec:
      ...
  infrastructureMachineTemplate:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: VSphereMachineTemplate
    metadata:
      name: test-cluster
      namespace: test-ns
    spec:
      ...
  boostrapConfigTemplate:
    apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
    kind: KubeadmConfigTemplate
    metadata:
      name: test-cluster
      namespace: test-ns
    spec:
      ...
desired:
  machineSet:
    ...
  infrastructureMachineTemplate:
    ...
  boostrapConfigTemplate:
    ...

Note:

  • All the objects will have the latest API version known by Cluster API.
  • Only spec is provided, status fields are not included
  • In a future release, when registering more than one extension for the CanUpdateMachineSet will be supported, the current state will already include changes that can be handled in-place by other runtime extensions.

Example Response:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: CanUpdateMachineSetResponse
status: Success # or Failure
message: "error message if status == Failure"
machineSetPatch:
  patchType: JSONPatch
  patch: <JSON-patch>
infrastructureMachineTemplatePatch:
  ...
boostrapConfigTemplatePatch:
  ...

Note:

  • Extensions should return per-object patches to be applied on current objects to indicate which changes they can handle in-place.
  • Only fields in MachineSet/InfraMachineTemplate/BootstrapConfigTemplate spec.template.spec have to be covered by patches
  • Patches must be in JSONPatch or JSONMergePatch format

UpdateMachine

This hook is called by the Machine controller when performing the in-place updates for a Machine.

Example request:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: UpdateMachineRequest
settings: <Runtime Extension settings>
desired:
  machine:
    apiVersion: cluster.x-k8s.io/v1beta2
    kind: Machine
    metadata:
      name: test-cluster
      namespace: test-ns
    spec:
      ...
  infrastructureMachine:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: VSphereMachine
    metadata:
      name: test-cluster
      namespace: test-ns
    spec:
      ...
  boostrapConfig:
    apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
    kind: KubeadmConfig
    metadata:
      name: test-cluster
      namespace: test-ns
    spec:
      ...

Note:

  • Only desired is provided (the external updater extension should know current state of the Machine).
  • Only spec is provided, status fields are not included

Example Response:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: UpdateMachineResponse
status: Success # or Failure
message: "error message if status == Failure"
retryAfterSeconds: 10

Note:

  • The status of the update operation is determined by the CommonRetryResponse fields:
    • Status=Success + RetryAfterSeconds > 0: update is in progress
    • Status=Success + RetryAfterSeconds = 0: update completed successfully
    • Status=Failure: update failed

Implementing Lifecycle Hook Runtime Extensions

Introduction

The lifecycle hooks allow hooking into the Cluster lifecycle. The following diagram provides an overview:

Please see the corresponding CAEP as well as the proposal for Chained and efficient upgrades for additional background information.

Guidelines

All guidelines defined in Implementing Runtime Extensions apply to the implementation of Runtime Extensions for lifecycle hooks as well.

In summary, Runtime Extensions are components that should be designed, written and deployed with great caution given that they can affect the proper functioning of the Cluster API runtime. A poorly implemented Runtime Extension could potentially block lifecycle transitions from happening.

Following recommendations are especially relevant:

Definitions

For additional details about the OpenAPI spec of the lifecycle hooks, please download the runtime-sdk-openapi.yaml file and then open it from the Swagger UI.

BeforeClusterCreate

This hook is called after the Cluster object has been created by the user, immediately before all the objects which are part of a Cluster topology(*) are going to be created. Runtime Extension implementers can use this hook to determine/prepare add-ons for the Cluster and block the creation of those objects until everything is ready.

Example Request:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: BeforeClusterCreateRequest
settings: <Runtime Extension settings>
cluster:
  apiVersion: cluster.x-k8s.io/v1beta1
  kind: Cluster
  metadata:
   name: test-cluster
   namespace: test-ns
  spec:
   ...
  status:
   ...

Example Response:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: BeforeClusterCreateResponse
status: Success # or Failure
message: "error message if status == Failure"
retryAfterSeconds: 10

(*) The objects which are part of a Cluster topology are the infrastructure Cluster, the Control Plane, the MachineDeployments and the templates derived from the ClusterClass.

AfterControlPlaneInitialized

This hook is called after the Control Plane reports that the control plane is initialized, which means the API server can accept requests. This usually happens sometime during the first CP machine provisioning or immediately thereafter.

Runtime Extension implementers can use this hook to execute tasks, for example component installation on workload clusters, that are only possible once the Control Plane is available. This hook does not block any further changes to the Cluster.

Example Request:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: AfterControlPlaneInitializedRequest
settings: <Runtime Extension settings>
cluster:
  apiVersion: cluster.x-k8s.io/v1beta1
  kind: Cluster
  metadata:
   name: test-cluster
   namespace: test-ns
  spec:
   ...
  status:
   ...

Example Response:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: AfterControlPlaneInitializedResponse
status: Success # or Failure
message: "error message if status == Failure"

BeforeClusterUpgrade

This hook is called after the Cluster object has been updated with a new spec.topology.version by the user, and immediately before the new version is going to be propagated to the control plane (*). Runtime Extension implementers can use this hook to execute pre-upgrade add-on tasks and block upgrades of the ControlPlane and Workers.

(*) Under normal circumstances spec.topology.version gets propagated to the control plane immediately; however if previous upgrades or worker machine rollouts are still in progress, the system waits for those operations to complete before starting the new upgrade.

Note: While the upgrade is blocked changes made to the Cluster Topology will be delayed propagating to the underlying objects while the object is waiting for upgrade. Example: modifying ControlPlane/MachineDeployments (think scale up), or creating new MachineDeployments will be delayed until the target ControlPlane/MachineDeployment is ready to pick up the upgrade. This ensures that the ControlPlane and MachineDeployments do not perform a rollout prematurely while waiting to be rolled out again for the version upgrade (no double rollouts). This also ensures that any version specific changes are only pushed to the underlying objects also at the correct version.

Example Request:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: BeforeClusterUpgradeRequest
settings: <Runtime Extension settings>
cluster:
  apiVersion: cluster.x-k8s.io/v1beta1
  kind: Cluster
  metadata:
    name: test-cluster
    namespace: test-ns
  spec:
    ...
  status:
    ...
fromKubernetesVersion: "v1.30.0"
toKubernetesVersion: "v1.33.0"
controlPlaneUpgrades:
  - version: v1.31.0
  - version: v1.32.3
  - version: v1.33.0
workersUpgrades:
  - version: v1.32.3
  - version: v1.33.0

Note: The controlPlaneUpgrades and the workersUpgrades fields contain the intermediate steps to reach the target version, which is also included in the list.

Example Response:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: BeforeClusterUpgradeResponse
status: Success # or Failure
message: "error message if status == Failure"
retryAfterSeconds: 10

BeforeControlPlaneUpgrade

This hook is called before a new version is propagated to the control plane object, which happens as many times as defined by the upgrade plan.

Runtime Extension implementers can use this hook to execute pre-upgrade add-on tasks and block upgrades of the ControlPlane.

Note:

  • When an upgrade is starting, BeforeControlPlaneUpgrade will be called after BeforeClusterUpgrade is completed.
  • When an upgrade is in progress BeforeControlPlaneUpgrade will be called for each intermediate version that will be applied to the control plane (instead BeforeClusterUpgrade will be called only once at the beginning of the upgrade).

Example Request:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: BeforeControlPlaneUpgradeRequest
settings: <Runtime Extension settings>
cluster:
  apiVersion: cluster.x-k8s.io/v1beta1
  kind: Cluster
  metadata:
   name: test-cluster
   namespace: test-ns
  spec:
   ...
  status:
   ...
fromKubernetesVersion: "v1.30.0"
toKubernetesVersion: "v1.33.0"
controlPlaneUpgrades:
  - version: v1.31.0
  - version: v1.32.3
  - version: v1.33.0
workersUpgrades:
  - version: v1.32.3
  - version: v1.33.0

Note: The controlPlaneUpgrades and the workersUpgrades fields contain the intermediate steps to reach the target version, which is also included in the list.

Example Response:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: BeforeControlPlaneUpgradeResponse
status: Success # or Failure
message: "error message if status == Failure"
retryAfterSeconds: 10

AfterControlPlaneUpgrade

This hook is called after the control plane has been upgraded to the version specified in spec.topology.version or to an intermediate version in the upgrade plan and:

  • if workers upgrade can be skipped for this version and this is an intermediate version of an upgrade plan, immediately before calling the BeforeControlPlaneUpgrade hook for the next version in the upgrade plan.
  • if workers upgrade must be performed for this version, immediately before calling the BeforeWorkersUpgrade hook for the same version.
  • if the cluster does not have workers and this is the last version of an upgrade plan, immediately before calling the AfterClusterUpgrade hook.

Runtime Extension implementers can use this hook to execute post-upgrade add-on tasks and block upgrades to the next version of the control plane or to workers until everything is ready.

Note: While the MachineDeployments upgrade is blocked changes made to existing MachineDeployments and creating new MachineDeployments will be delayed while the object is waiting for upgrade. Example: modifying MachineDeployments (think scale up), or creating new MachineDeployments will be delayed until the target MachineDeployment is ready to pick up the upgrade. This ensures that the MachineDeployments do not perform a rollout prematurely while waiting to be rolled out again for the version upgrade (no double rollouts). This also ensures that any version specific changes are only pushed to the underlying objects also at the correct version.

Example Request:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: AfterControlPlaneUpgradeRequest
settings: <Runtime Extension settings>
cluster:
  apiVersion: cluster.x-k8s.io/v1beta1
  kind: Cluster
  metadata:
    name: test-cluster
    namespace: test-ns
  spec:
    ...
  status:
    ...
kubernetesVersion: "v1.30.0"
controlPlaneUpgrades:
  - version: v1.31.0
  - version: v1.32.3
  - version: v1.33.0
workersUpgrades:
  - version: v1.32.3
  - version: v1.33.0

Note: The controlPlaneUpgrades and the workersUpgrades fields contain the intermediate steps to reach the target version, which is also included in the list.

Example Response:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: AfterControlPlaneUpgradeResponse
status: Success # or Failure
message: "error message if status == Failure"
retryAfterSeconds: 10

BeforeWorkersUpgrade

This hook is called before a new version is propagated to workers. Runtime Extension implementers can use this hook to execute pre-upgrade add-on tasks and block upgrades of Workers.

Note:

  • This hook will be called only if workers upgrade must be performed for an intermediate version of a chained upgrade or when upgrading to the target spec.topology.version.

Example Request:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: BeforeWorkersUpgradeRequest
settings: <Runtime Extension settings>
cluster:
  apiVersion: cluster.x-k8s.io/v1beta1
  kind: Cluster
  metadata:
   name: test-cluster
   namespace: test-ns
  spec:
   ...
  status:
   ...
fromKubernetesVersion: "v1.30.0"
toKubernetesVersion: "v1.33.0"
controlPlaneUpgrades:
  - version: v1.31.0
  - version: v1.32.3
  - version: v1.33.0
workersUpgrades:
  - version: v1.32.3
  - version: v1.33.0

Note: The controlPlaneUpgrades and the workersUpgrades fields contain the intermediate steps to reach the target version, which is also included in the list.

Example Response:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: BeforeWorkersUpgradeResponse
status: Success # or Failure
message: "error message if status == Failure"
retryAfterSeconds: 10

AfterWorkersUpgrade

This hook is called after all the workers have been upgraded to the version specified in spec.topology.version or to an intermediate version in the upgrade plan, and:

  • if the upgrade plan is completed and the entire cluster is at spec.topology.version, immediately before calling the AfterClusterUpgrade hook.
  • if the upgrade plan is not complete and the entire cluster is now at one of the intermediate versions, immediately before calling BeforeControlPlaneUpgrade hook for the next intermediate step; in this case, the hook will ensure the control plane can’t to move to the next version in the upgrade plan until AfterWorkersUpgrade is completed.

Example Request:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: AfterWorkersUpgradeRequest
settings: <Runtime Extension settings>
cluster:
  apiVersion: cluster.x-k8s.io/v1beta1
  kind: Cluster
  metadata:
   name: test-cluster
   namespace: test-ns
  spec:
   ...
  status:
   ...
kubernetesVersion: "v1.30.0"
controlPlaneUpgrades:
  - version: v1.31.0
  - version: v1.32.3
  - version: v1.33.0
workersUpgrades:
  - version: v1.32.3
  - version: v1.33.0

Note: The controlPlaneUpgrades and the workersUpgrades fields contain the intermediate steps to reach the target version, which is also included in the list.

Example Response:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: AfterWorkersUpgradeResponse
status: Success # or Failure
message: "error message if status == Failure"
retryAfterSeconds: 10

AfterClusterUpgrade

This hook is called after the Cluster, control plane and workers have been upgraded to the version specified in spec.topology.version. Runtime Extensions implementers can use this hook to execute post-upgrade add-on tasks. This hook blocks new upgrades to start until it is completed.

Example Request:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: AfterClusterUpgradeRequest
settings: <Runtime Extension settings>
cluster:
  apiVersion: cluster.x-k8s.io/v1beta1
  kind: Cluster
  metadata:
   name: test-cluster
   namespace: test-ns
  spec:
   ...
  status:
   ...
kubernetesVersion: "v1.22.0"

Example Response:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: AfterClusterUpgradeResponse
status: Success # or Failure
message: "error message if status == Failure"
retryAfterSeconds: 10

BeforeClusterDelete

This hook is called after the Cluster deletion has been triggered by the user and immediately before the topology of the Cluster is going to be deleted. Runtime Extension implementers can use this hook to execute cleanup tasks for the add-ons and block deletion of the Cluster and descendant objects until everything is ready.

Example Request:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: BeforeClusterDeleteRequest
settings: <Runtime Extension settings>
cluster:
  apiVersion: cluster.x-k8s.io/v1beta1
  kind: Cluster
  metadata:
   name: test-cluster
   namespace: test-ns
  spec:
   ...
  status:
   ...

Example Response:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: BeforeClusterDeleteResponse
status: Success # or Failure
message: "error message if status == Failure"
retryAfterSeconds: 10

Implementing Topology Mutation Hook Runtime Extensions

Introduction

Three different hooks are called as part of Topology Mutation - two in the Cluster topology reconciler and one in the ClusterClass reconciler.

Cluster topology reconciliation

  • GeneratePatches: GeneratePatches is responsible for generating patches for the entire Cluster topology.
  • ValidateTopology: ValidateTopology is called after all patches have been applied and thus allow to validate the resulting objects.

ClusterClass reconciliation

  • DiscoverVariables: DiscoverVariables is responsible for providing variable definitions for a specific external patch.

Please see the corresponding CAEP for additional background information.

Guidelines

All guidelines defined in Implementing Runtime Extensions apply to the implementation of Runtime Extensions for topology mutation hooks as well.

In summary, Runtime Extensions are components that should be designed, written and deployed with great caution given that they can affect the proper functioning of the Cluster API runtime. A poorly implemented Runtime Extension could potentially block topology reconcile from happening.

Following recommendations are especially relevant:

Definitions

For additional details about the OpenAPI spec of the topology mutation hooks, please download the runtime-sdk-openapi.yaml file and then open it from the Swagger UI.

Inline vs. external patches

Inline patches have the following advantages:

  • Inline patches are easier when getting started with ClusterClass as they are built into the Cluster API core controller, no external component have to be developed and managed.

External patches have the following advantages:

  • External patches can be individually written, unit tested and released/versioned.
  • External patches can leverage the full feature set of a programming language and are thus not limited to the capabilities of JSON patches and Go templating.
  • External patches can use external data (e.g. from cloud APIs) during patch generation.
  • External patches can be easily reused across ClusterClasses.

External variable definitions

The DiscoverVariables hook can be used to supply variable definitions for use in external patches. These variable definitions are added to the status of any applicable ClusterClasses. Clusters using the ClusterClass can then set values for those variables.

External variable discovery in the ClusterClass

External variable definitions are discovered by calling the DiscoverVariables runtime hook. This hook is called from the ClusterClass reconciler. Once discovered the variable definitions are validated and stored in ClusterClass status.

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
# metadata
spec:
    # Inline variable definitions
    variables:
    # This variable is unique and can be accessed globally.
    - name: no-proxy
      required: true
      schema:
        openAPIV3Schema:
          type: string
          default: "internal.com"
          example: "internal.com"
          description: "comma-separated list of machine or domain names excluded from using the proxy."
    # This variable is also defined by an external DiscoverVariables hook.
    - name: http-proxy
      schema:
        openAPIV3Schema:
          type: string
          default: "proxy.example.com"
          example: "proxy.example.com"
          description: "proxy for http calls."
    # External patch definitions.
    patches:
    - name: lbImageRepository
      external:
          generatePatchesExtension: generate-patches.k8s-upgrade-with-runtimesdk
          validateTopologyExtension: validate-topology.k8s-upgrade-with-runtimesdk
          ## Call variable discovery for this patch.
          discoverVariablesExtension: discover-variables.k8s-upgrade-with-runtimesdk
status:
    # observedGeneration is used to check that the current version of the ClusterClass is the same as that when the Status was previously written.
    # if metadata.generation isn't the same as observedGeneration Cluster using the ClusterClass should not reconcile.
    observedGeneration: xx
    # variables contains a list of all variable definitions, both inline and from external patches, that belong to the ClusterClass.
    variables:
      - name: no-proxy
        definitions:
          - from: inline
            required: true
            schema:
              openAPIV3Schema:
                type: string
                default: "internal.com"
                example: "internal.com"
                description: "comma-separated list of machine or domain names excluded from using the proxy."
      - name: http-proxy
        # definitionsConflict is true if there are non-equal definitions for a variable.
        # Note: This conflict has to be resolved, until then corresponding Clusters are not reconciled.
        definitionsConflict: true
        definitions:
          - from: inline
            schema:
              openAPIV3Schema:
                type: string
                default: "proxy.example.com"
                example: "proxy.example.com"
                description: "proxy for http calls."
          - from: lbImageRepository
            schema:
              openAPIV3Schema:
                type: string
                default: "different.example.com"
                example: "different.example.com"
                description: "proxy for http calls."

Variable definition conflicts

Variable definitions can be inline in the ClusterClass or from any number of external DiscoverVariables hooks. The source of a variable definition is recorded in the from field in ClusterClass .status.variables. Variables that are defined by an external DiscoverVariables hook will have the name of the patch they are associated with as the value of from. Variables that are defined in the ClusterClass .spec.variables will have inline as the value of from. Note: inline is a reserved name for patches. It cannot be used as the name of an external patch to avoid conflicts.

If all variables that share a name have equivalent schemas the variable definitions are not in conflict. The CAPI components will consider variable definitions to be equivalent when they share a name and their schema is exactly equal. If variables are in conflict the VariablesReconciled will be set to false and the conflict has to be resolved. While there are variable conflicts, corresponding Clusters will not be reconciled.

Note: We enforce that variable conflicts have to be resolved by ClusterClass authors, so that defining Cluster topology is as simply as possible for end users.

Setting values for variables in the Cluster

Variables that are defined with external variable definitions can be set like regular variables in Cluster .spec.topology.variables.

apiVersion: cluster.x-k8s.io/v1beta2
kind: Cluster
#metadata 
spec:
    topology:
      variables:
        - name: no-proxy
          value: "internal.domain.com"
        - name: http-proxy
          value: http://proxy.example2.com:1234

Using one or multiple external patch extensions

Some considerations:

  • In general a single external patch extension is simpler than many, as only one extension then has to be built, deployed and managed.
  • A single extension also requires less HTTP round-trips between the CAPI controller and the extension(s).
  • With a single extension it is still possible to implement multiple logical features using different variables.
  • When implementing multiple logical features in one extension it’s recommended that they can be conditionally enabled/disabled via variables (either via certain values or by their existence).
  • Conway’s law might make it not feasible in large organizations to use a single extension. In those cases it’s important that boundaries between extensions are clearly defined.

Guidelines

For general Runtime Extension developer guidelines please refer to the guidelines in Implementing Runtime Extensions. This section outlines considerations specific to Topology Mutation hooks.

Patch extension guidelines

  • Input validation: An External Patch Extension must always validate its input, i.e. it must validate that all variables exist, have the right type and it must validate the kind and apiVersion of the templates which should be patched.
  • Timeouts: As External Patch Extensions are called during each Cluster topology reconciliation, they must respond as fast as possible (<=200ms) to avoid delaying individual reconciles and congestion.
  • Availability: An External Patch Extension must be always available, otherwise Cluster topologies won’t be reconciled anymore.
  • Side Effects: An External Patch Extension must not make out-of-band changes. If necessary external data can be retrieved, but be aware of performance impact.
  • Deterministic results: For a given request (a set of templates and variables) an External Patch Extension must always return the same response (a set of patches). Otherwise the Cluster topology will never reach a stable state.
  • Idempotence: An External Patch Extension must only return patches if changes to the templates are required, i.e. unnecessary patches when the template is already in the desired state must be avoided.
  • Avoid Dependencies: An External Patch Extension must be independent of other External Patch Extensions. However if dependencies cannot be avoided, it is possible to control the order in which patches are executed via the ClusterClass.
  • Error messages: For a given request (a set of templates and variables) an External Patch Extension must always return the same error message. Otherwise the system might become unstable due to controllers being overloaded by continuous changes to Kubernetes resources as these messages are reported as conditions. See error messages.

Variable discovery guidelines

  • Distinctive variable names: Names should be carefully chosen, and if possible generic names should be avoided. Using a generic name could lead to conflicts if the variables defined for this patch are used in combination with other patches providing variables with the same name.
  • Avoid breaking changes to variable definitions: Changing a variable definition can lead to problems on existing clusters because reconciliation will stop if variable values do not match the updated definition. When more than one variable with the same name is defined, changes to variable definitions can require explicit values for each patch. Updates to the variable definition should be carefully evaluated, and very well documented in extension release notes, so ClusterClass authors can evaluate impacts of changes before performing an upgrade.

Definitions

GeneratePatches

A GeneratePatches call generates patches for the entire Cluster topology. Accordingly the request contains all templates, the global variables and the template-specific variables. The response contains generated patches.

Example request:

  • Generating patches for a Cluster topology is done via a single call to allow External Patch Extensions a holistic view of the entire Cluster topology. Additionally this allows us to reduce the number of round-trips.
  • Each item in the request will contain the template as a raw object. Additionally information about where the template is used is provided via holderReference.
apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: GeneratePatchesRequest
settings: <Runtime Extension settings>
variables:
- name: <variable-name>
  value: <variable-value>
  ...
items:
- uid: 7091de79-e26c-4af5-8be3-071bc4b102c9
  holderReference:
    apiVersion: cluster.x-k8s.io/v1beta1
    kind: MachineDeployment
    namespace: default
    name: cluster-md1-xyz
    fieldPath: spec.template.spec.infrastructureRef
  object:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: AWSMachineTemplate
    spec:
    ...
  variables:
  - name: <variable-name>
    value: <variable-value>
    ...

Example Response:

  • The response contains patches instead of full objects to reduce the payload.
  • Templates in the request and patches in the response will be correlated via UIDs.
  • Like inline patches, external patches are only allowed to change fields in metadata.{labels,annotations}, spec.template.spec and spec.template.metadata.{labels,annotations} (see inline patches documentation for additional details).
  • Only fields below metadata.{labels,annotations}, spec.template.spec and spec.template.metadata can be patched. Note that patching metadata.{labels,annotations} makes only sense when another template will be originated from the template object linked in the ClusterClass (e.g. it instead makes sense patching VSphereMachineTemplate.metadata when this object is referenced from a MachineDeploymentClass because another VSphereMachineTemplate will be generated for each MachineDeployment using this class; instead it does not make sense patching KubeadmControlPlaneTemplate.metadata.labels because this field will be lost when generating the KubeadmControlPlane object for a Cluster).
apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: GeneratePatchesResponse
status: Success # or Failure
message: "error message if status == Failure"
items:
- uid: 7091de79-e26c-4af5-8be3-071bc4b102c9
  patchType: JSONPatch
  patch: <JSON-patch>

We are considering to introduce a library to facilitate development of External Patch Extensions. It would provide capabilities like:

  • Accessing builtin variables
  • Extracting certain templates from a GeneratePatches request (e.g. all bootstrap templates)

If you are interested in contributing to this library please reach out to the maintainer team or feel free to open an issue describing your idea or use case.

ValidateTopology

A ValidateTopology call validates the topology after all patches have been applied. The request contains all templates of the Cluster topology, the global variables and the template-specific variables. The response contains the result of the validation.

Example Request:

  • The request is the same as the GeneratePatches request except it doesn’t have uid fields. We don’t need them as we don’t have to correlate patches in the response.
apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: ValidateTopologyRequest
settings: <Runtime Extension settings>
variables:
- name: <variable-name>
  value: <variable-value>
  ...
items:
- holderReference:
    apiVersion: cluster.x-k8s.io/v1beta1
    kind: MachineDeployment
    namespace: default
    name: cluster-md1-xyz
    fieldPath: spec.template.spec.infrastructureRef
  object:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: AWSMachineTemplate
    spec:
    ...
  variables:
  - name: <variable-name>
    value: <variable-value>
    ...

Example Response:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: ValidateTopologyResponse
status: Success # or Failure
message: "error message if status == Failure"

DiscoverVariables

A DiscoverVariables call returns definitions for one or more variables.

Example Request:

  • The request is a simple call to the Runtime hook.
apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: DiscoverVariablesRequest
settings: <Runtime Extension settings>

Example Response:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: DiscoverVariablesResponse
status: Success # or Failure
message: ""
variables:
  - name: etcdImageTag 
    required: true
    schema:
      openAPIV3Schema:
        type: string
        default: "3.5.3-0" 
        example: "3.5.3-0"
        description: "etcdImageTag sets the tag for the etcd image."
  - name: preLoadImages
    required: false
    schema:
      openAPIV3Schema:
        default: []
        type: array
        items:
          type: string
        description: "preLoadImages sets the images for the Docker machines to preload."
  - name: podSecurityStandard
    required: false
    schema:
      openAPIV3Schema:
        type: object
        properties:
          enabled:
            type: boolean
            default: true
            description: "enabled enables the patches to enable Pod Security Standard via AdmissionConfiguration."
          enforce:
            type: string
            default: "baseline"
            description: "enforce sets the level for the enforce PodSecurityConfiguration mode. One of privileged, baseline, restricted."
          audit:
            type: string
            default: "restricted"
            description: "audit sets the level for the audit PodSecurityConfiguration mode. One of privileged, baseline, restricted."
          warn:
            type: string
            default: "restricted"
            description: "warn sets the level for the warn PodSecurityConfiguration mode. One of privileged, baseline, restricted."
...

Dealing with Cluster API upgrades with apiVersion bumps

There are some special considerations regarding Cluster API upgrades when the upgrade includes a bump of the apiVersion of infrastructure, bootstrap or control plane provider CRDs.

When calling external patches the Cluster topology controller is always sending the templates in the apiVersion of the references in the ClusterClass.

While inline patches are always referring to one specific apiVersion, external patch implementations are more flexible. They can be written in a way that they are able to handle multiple apiVersions of a CRD. This can be done by calculating patches differently depending on which apiVersion is received by the external patch implementation.

This allows users more flexibility during Cluster API upgrades:

Variant 1: External patch implementation supporting two apiVersions at the same time

  1. Update Cluster API
  2. Update the external patch implementation to be able to handle custom resources with the old and the new apiVersion
  3. Update the references in ClusterClasses to use the new apiVersion

Note In this variant it doesn’t matter if Cluster API or the external patch implementation is updated first.

Variant 2: Deploy an additional instance of the external patch implementation which can handle the new apiVersion

  1. Upgrade Cluster API
  2. Deploy the new external patch implementation which is able to handle the new apiVersion
  3. Update ClusterClasses to use the new apiVersion and the new external patch implementation
  4. Remove the old external patch implementation as it’s not used anymore

Note In this variant it doesn’t matter if Cluster API is updated or the new external patch implementation is deployed first.

Implementing Upgrade Plan Runtime Extensions

Introduction

The proposal for Chained and efficient upgrades introduced support for upgrading by more than one minor when working with Clusters using managed topologies.

According to the proposal, there are two ways to provide Cluster API the information required to compute the upgrade plan:

  • By setting the list of versions in the spec.kubernetesVersions field in the ClusterClass object.
  • By calling the runtime hook defined in the spec.upgrade field in the ClusterClass object.

This document defines the hook for the second option and provides recommendations on how to implement it.

Guidelines

All guidelines defined in Implementing Runtime Extensions apply to the implementation of Runtime Extensions for upgrade plan hooks as well.

In summary, Runtime Extensions are components that should be designed, written and deployed with great caution given that they can affect the proper functioning of the Cluster API runtime. A poorly implemented Runtime Extension could potentially block upgrades.

Following recommendations are especially relevant:

Definitions

For additional details about the OpenAPI spec of the upgrade plan hooks, please download the runtime-sdk-openapi.yaml file and then open it from the Swagger UI.

GenerateUpgradePlan

The GenerateUpgradePlan hook is called every time Cluster API is required to compute the upgrade plan.

Notably, during an upgrade, the upgrade plan is recomputed several times, ideally once each time the upgrade plan completes a step, but the number of calls might be higher depending on e.g. the duration of the upgrade.

Example Request:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: GenerateUpgradePlanRequest
settings: <Runtime Extension settings>
cluster:
  apiVersion: cluster.x-k8s.io/v1beta1
  kind: Cluster
  metadata:
    name: test-cluster
    namespace: test-ns
  spec:
    ...
  status:
    ...
fromControlPlaneKubernetesVersion: "v1.29.0"
fromWorkersKubernetesVersion: "v1.29.0"
toKubernetesVersion: "v1.33.0"

Example Response:

apiVersion: hooks.runtime.cluster.x-k8s.io/v1alpha1
kind: GenerateUpgradePlanResponse
status: Success # or Failure
message: "error message if status == Failure"
controlPlaneUpgrades:
- version: v1.30.0
- version: v1.31.0
- version: v1.32.3
- version: v1.33.0

Note: in this case the system will infer the list of intermediate version for workers from the list of control plane versions, taking care of performing the minimum number of workers upgrade by taking into account the Kubernetes version skew policy.

Implementers of this runtime extension can also address more sophisticated use cases by computing the response in different ways, e.g.

  • Go through more patch release for a minor if necessary, e.g., v1.30.0 -> v1.30.1 -> etc.

    ...
    controlPlaneUpgrades:
    - version: v1.30.0
    - version: v1.30.1
    - ...
    

Note: in this case the system will infer the list of intermediate version for workers from the list of control plane versions, taking care of performing the minimum number of workers upgrade by taking into account the Kubernetes version skew policy.

  • Force workers to upgrade to specific versions, e.g., force workers upgrade to v1.30.0 when doing v1.29.0 -> v1.32.3 (in this example, worker upgrade to 1.30.0 is not required by the Kubernetes version skew policy, so it would be skipped under normal circumstances).

    ...
    controlPlaneUpgrades:
    - version: v1.30.0
    - version: v1.31.0
    - version: v1.32.3
    workersUpgrades:
    - version: v1.30.0
    - version: v1.32.3
    

Note: in this case the system will take into consideration the provided workersUpgrades, and validated it is consistent with controlPlaneUpgrades and also compliant with the Kubernetes version skew policy.

  • Force workers to upgrade to all the intermediate steps (opt out from efficient upgrades).

    ...
    controlPlaneUpgrades:
    - version: v1.30.0
    - version: v1.31.0
    - version: v1.32.3
    workersUpgrades:
    - version: v1.30.0
    - version: v1.31.0
    - version: v1.32.3
    

Note: in this case the system will take into consideration the provided workersUpgrades, and validate it is consistent with controlPlaneUpgrades and also compliant with the Kubernetes version skew policy.

In all the cases above, the GenerateUpgradePlanResponse content must comply the following validation rules:

  • controlPlaneUpgrades is the list of version upgrade steps for the control plane; it must be always specified unless the control plane is already at the target version.

    • there should be at least one version for every minor between fromControlPlaneKubernetesVersion (excluded) and toKubernetesVersion (included).
    • each version must be:
      • greater than fromControlPlaneKubernetesVersion (or with a different build number)
      • greater than the previous version in the list (or with a different build number)
      • less or equal to toKubernetesVersion (or with a different build number)
      • the last version in the plan must be equal to toKubernetesVersion
  • workersUpgrades is the list of version upgrade steps for the workers.

    • In case the upgrade plan for workers will be left to empty, the system will automatically determine the minimal number of workers upgrade steps, thus minimizing impact on workloads and reducing the overall upgrade time.
    • If instead for any reason a custom upgrade plan for workers is required, workersUpgrades should be set and the following rules apply to each version in the list. More specifically, each version must be:
      • equal to fromControlPlaneKubernetesVersion or to one of the versions in the control plane upgrade plan.
      • greater than fromWorkersKubernetesVersion (or with a different build number)
      • greater than the previous version in the list (or with a different build number)
      • less or equal to the toKubernetesVersion (or with a different build number)
      • in case of versions with the same major/minor/patch version but different build number, also the order of those versions must be the same for control plane and worker upgrade plan.
      • the last version in the plan must be equal to toKubernetesVersion
      • the upgrade plan must have all the intermediate version which workers must go through to avoid breaking rules defining the max version skew between control plane and workers.

Deploy Runtime Extensions

Cluster API requires that each Runtime Extension must be deployed using an endpoint accessible from the Cluster API controllers. The recommended deployment model is to deploy a Runtime Extension in the management cluster by:

  • Packing the Runtime Extension in a container image.
  • Using a Kubernetes Deployment to run the above container inside the Management Cluster.
  • Using a Cluster IP Service to make the Runtime Extension instances accessible via a stable DNS name.
  • Using a cert-manager generated Certificate to protect the endpoint.
  • Register the Runtime Extension using ExtensionConfig.

For an example, please see our test extension which follows, as closely as possible, the kubebuilder setup used for controllers in Cluster API.

There are a set of important guidelines that must be considered while choosing the deployment method:

Availability

It is recommended that Runtime Extensions should leverage some form of load-balancing, to provide high availability and performance benefits. You can run multiple Runtime Extension servers behind a Kubernetes Service to leverage the load-balancing that services support.

Identity and access management

The security model for each Runtime Extension should be carefully defined, similar to any other application deployed in the Cluster. If the Runtime Extension requires access to the apiserver the deployment must use a dedicated service account with limited RBAC permission. Otherwise no service account should be used.

On top of that, the container image for the Runtime Extension should be carefully designed in order to avoid privilege escalation (e.g using distroless base images). The Pod spec in the Deployment manifest should enforce security best practices (e.g. do not use privileged pods).

Alternative deployments methods

Alternative deployment methods can be used as long as the HTTPs endpoint is accessible, like e.g.:

  • deploying the HTTPS Server as a part of another component, e.g. a controller.
  • deploying the HTTPS Server outside the Management Cluster.

In those cases recommendations about availability and identity and access management still apply.

Experimental Feature: Ignition Bootstrap Config (alpha)

The default configuration engine for bootstrapping workload cluster machines is cloud-init. Ignition is an alternative engine used by Linux distributions such as Flatcar Container Linux and Fedora CoreOS and therefore should be used when choosing an Ignition-based distribution as the underlying OS for workload clusters.

This guide explains how to deploy an AWS workload cluster using Ignition.

Prerequisites

  • kubectl installed locally
  • clusterawsadm installed locally - download from the releases page of the AWS provider
  • kind and Docker installed locally (when using kind to create a management cluster)

Configure a management cluster

Follow this section of the quick start guide to deploy a Kubernetes cluster or connect to an existing one.

Follow this section of the quick start guide to install clusterctl.

Initialize the management cluster

Before workload clusters can be deployed, Cluster API components must be deployed to the management cluster.

Initialize the management cluster:

export AWS_REGION=us-east-1
export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

# Workload clusters need to call the AWS API as part of their normal operation.
# The following command creates a CloudFormation stack which provisions the
# necessary IAM resources to be used by workload clusters.
clusterawsadm bootstrap iam create-cloudformation-stack

# The management cluster needs to call the AWS API in order to manage cloud
# resources for workload clusters. The following command tells clusterctl to
# store the AWS credentials provided before in a Kubernetes secret where they
# can be retrieved by the AWS provider running on the management cluster.
export AWS_B64ENCODED_CREDENTIALS=$(clusterawsadm bootstrap credentials encode-as-profile)

# Enable the feature gates controlling Ignition bootstrap.
export EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION=true # Used by the kubeadm bootstrap provider
export EXP_BOOTSTRAP_FORMAT_IGNITION=true # Used by the AWS provider

# Initialize the management cluster.
clusterctl init --infrastructure aws

Generate a workload cluster configuration

# Deploy the workload cluster in the following AWS region.
export AWS_REGION=us-east-1

# Authorize the following SSH public key on cluster nodes.
export AWS_SSH_KEY_NAME=my-key

# Ignition bootstrap data needs to be stored in an S3 bucket so that nodes can
# read them at boot time. Store Ignition bootstrap data in the following bucket.
export AWS_S3_BUCKET_NAME=my-bucket

# Set the EC2 machine size for controllers and workers.
export AWS_CONTROL_PLANE_MACHINE_TYPE=t3a.small
export AWS_NODE_MACHINE_TYPE=t3a.small

clusterctl generate cluster ignition-cluster \
    --from https://github.com/kubernetes-sigs/cluster-api-provider-aws/blob/main/templates/cluster-template-flatcar.yaml \
    --kubernetes-version v1.28.0 \
    --worker-machine-count 2 \
    > ignition-cluster.yaml

NOTE: Only certain Kubernetes versions have pre-built Kubernetes AMIs. See list of published pre-built Kubernetes AMIs.

Apply the workload cluster

kubectl apply -f ignition-cluster.yaml

Wait for the control plane of the workload cluster to become initialized:

kubectl get kubeadmcontrolplane ignition-cluster-control-plane

This could take a while. When the control plane is initialized, the INITIALIZED field should be true:

NAME                             CLUSTER            INITIALIZED   API SERVER AVAILABLE   REPLICAS   READY   UPDATED   UNAVAILABLE   AGE    VERSION
ignition-cluster-control-plane   ignition-cluster   true                                 1                  1         1             7m7s   v1.22.2

Connect to the workload cluster

Generate a kubeconfig for the workload cluster:

clusterctl get kubeconfig ignition-cluster > ./kubeconfig

Set kubectl to use the generated kubeconfig:

export KUBECONFIG=$(pwd)/kubeconfig

Verify connectivity with the workload cluster’s API server:

kubectl cluster-info

Sample output:

Kubernetes control plane is running at https://ignition-cluster-apiserver-284992524.us-east-1.elb.amazonaws.com:6443
CoreDNS is running at https://ignition-cluster-apiserver-284992524.us-east-1.elb.amazonaws.com:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

Deploy a CNI plugin

A CNI plugin must be deployed to the workload cluster for the cluster to become ready. We use Calico here, however other CNI plugins could be used, too.

kubectl apply -f https://docs.projectcalico.org/v3.20/manifests/calico.yaml

Ensure all cluster nodes become ready:

kubectl get nodes

Sample output:

NAME                                            STATUS   ROLES                  AGE   VERSION
ip-10-0-122-154.us-east-1.compute.internal   Ready    control-plane,master   14m   v1.22.2
ip-10-0-127-59.us-east-1.compute.internal    Ready    <none>                 13m   v1.22.2
ip-10-0-89-169.us-east-1.compute.internal    Ready    <none>                 13m   v1.22.2

Clean up

Delete the workload cluster (from a shell connected to the management cluster):

kubectl delete cluster ignition-cluster

Caveats

Supported infrastructure providers

Cluster API has multiple infrastructure providers which can be used to deploy workload clusters.

The following infrastructure providers already have Ignition support:

Ignition support will be added to more providers in the future.

Running multiple providers

Cluster API supports running multiple infrastructure/bootstrap/control plane providers on the same management cluster. It’s highly recommended to rely on clusterctl init command in this case. clusterctl will help ensure that all providers support the same API Version of Cluster API (contract).

Verification of CAPI artifacts

Requirements

You will need to have the following tools installed:

CAPI Images

Each release of the Cluster API project includes the following container images:

  • cluster-api-controller
  • kubeadm-bootstrap-controller
  • kubeadm-control-plane-controller
  • clusterctl

Verifying Image Signatures

All of the four images are hosted by registry.k8s.io. In order to verify the authenticity of the images, you can use cosign verify command with the appropriate image name and version:

$ cosign verify registry.k8s.io/cluster-api/cluster-api-controller:v1.5.0 --certificate-identity krel-trust@k8s-releng-prod.iam.gserviceaccount.com --certificate-oidc-issuer https://accounts.google.com | jq .
Verification for registry.k8s.io/cluster-api/cluster-api-controller:v1.5.0 --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - Existence of the claims in the transparency log was verified offline
  - The code-signing certificate was verified using trusted certificate authority certificates
[
  {
    "critical": {
      "identity": {
        "docker-reference": "registry.k8s.io/cluster-api/cluster-api-controller"
      },
      "image": {
        "docker-manifest-digest": "sha256:f34016d3a494f9544a16137c9bba49d8756c574a0a1baf96257903409ef82f77"
      },
      "type": "cosign container image signature"
    },
    "optional": {
      "1.3.6.1.4.1.57264.1.1": "https://accounts.google.com",
      "Bundle": {
        "SignedEntryTimestamp": "MEYCIQDtxr/v3uRl2QByVfYo1oopruADSaH3E4wThpmkibJs8gIhAIe0odbk99na5GBdYGjJ6IwpFzhlTlicgWOrsgxZH8LC",
        "Payload": {
          "body": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIzMDMzNzY0MTQwZmI2OTE5ZjRmNDg2MDgwMDZjYzY1ODU2M2RkNjE0NWExMzVhMzE5MmQyYTAzNjE1OTRjMTRlIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FUUNJQ3RtcGdHN3RDcXNDYlk0VlpXNyt6Rm5tYWYzdjV4OTEwcWxlWGppdTFvbkFpQS9JUUVSSDErdit1a0hrTURSVnZnN1hPdXdqTTN4REFOdEZyS3NUMHFzaUE9PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTTJha05EUVc1SFowRjNTVUpCWjBsVldqYzNUbGRSV1VacmQwNTVRMk13Y25GWWJIcHlXa3RyYURjMGQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcE5kMDU2U1RGTlZHTjNUa1JOTlZkb1kwNU5hazEzVG5wSk1VMVVZM2hPUkUwMVYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZ4VEdveFJsSmhLM2RZTUVNd0sxYzFTVlZWUW14UmRsWkNWM2xLWTFRcmFWaERjV01LWTA4d1prVmpNV2s0TVUxSFQwRk1lVXB2UXpGNk5TdHVaRGxFUnpaSGNFSmpOV0ZJYXpoU1QxaDBOV2h6U21wa1VVdFBRMEZhUVhkblowZE5UVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlYxTVRoMENqWjVWMWxNVlU5RVR5dEVjek52VVU1RFNsYzNZMUJWZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDFGQldVUldVakJTUVZGSUwwSkVXWGRPU1VWNVlUTktiR0pETVRCamJsWjZaRVZDY2s5SVRYUmpiVlp6V2xjMWJreFlRbmxpTWxGMVlWZEdkQXBNYldSNldsaEtNbUZYVG14WlYwNXFZak5XZFdSRE5XcGlNakIzUzFGWlMwdDNXVUpDUVVkRWRucEJRa0ZSVVdKaFNGSXdZMGhOTmt4NU9XaFpNazUyQ21SWE5UQmplVFZ1WWpJNWJtSkhWWFZaTWpsMFRVTnpSME5wYzBkQlVWRkNaemM0ZDBGUlowVklVWGRpWVVoU01HTklUVFpNZVRsb1dUSk9kbVJYTlRBS1kzazFibUl5T1c1aVIxVjFXVEk1ZEUxSlIwdENaMjl5UW1kRlJVRmtXalZCWjFGRFFraDNSV1ZuUWpSQlNGbEJNMVF3ZDJGellraEZWRXBxUjFJMFl3cHRWMk16UVhGS1MxaHlhbVZRU3pNdmFEUndlV2RET0hBM2J6UkJRVUZIU21wblMxQmlkMEZCUWtGTlFWSjZRa1pCYVVKSmJXeGxTWEFyTm05WlpVWm9DbWRFTTI1Uk5sazBSV2g2U25SVmMxRTRSSEJrWTFGeU5FSk1XRE41ZDBsb1FVdFhkV05tYmxCUk9GaExPWGRZYkVwcVNWQTBZMFpFT0c1blpIazRkV29LYldreGN6RkRTamczTW1zclRVRnZSME5EY1VkVFRUUTVRa0ZOUkVFeVkwRk5SMUZEVFVoaU9YRjBSbGQxT1VGUU1FSXpaR3RKVkVZNGVrazRZVEkxVUFwb2IwbFBVVlJLVWxKeGFsVmlUMkUyVnpOMlRVZEJOWFpKTlZkVVJqQkZjREZwTWtGT2QwbDNSVko0TW5ocWVtWjNjbmRPYmxoUVpEQjRjbmd3WWxoRENtUmpOV0Z4WWxsWlVsRXdMMWhSVVdONFRFVnRkVGwzUnpGRlYydFNNWE01VEdaUGVHZDNVMjRLTFMwdExTMUZUa1FnUTBWU1ZFbEdTVU5CVkVVdExTMHRMUW89In19fX0=",
          "integratedTime": 1690304684,
          "logIndex": 28719030,
          "logID": "c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"
        }
      },
      "Issuer": "https://accounts.google.com",
      "Subject": "krel-trust@k8s-releng-prod.iam.gserviceaccount.com",
      "org.kubernetes.kpromo.version": "kpromo-v4.0.3-5-ge99897c"
    }
  }
]

Diagnostics

Introduction

With CAPI v1.6 we introduced new flags to allow serving metrics, the pprof endpoint and an endpoint to dynamically change log levels securely in production.

This feature is enabled by default via:

          args:
            - "--diagnostics-address=${CAPI_DIAGNOSTICS_ADDRESS:=:8443}"

As soon as the feature is enabled the metrics endpoint is served via https and protected via authentication and authorization. This works the same way as metrics in core Kubernetes components: Metrics in Kubernetes.

To continue serving metrics via http the following configuration can be used:

          args:
            - "--diagnostics-address=localhost:8080"
            - "--insecure-diagnostics"

The same can be achieved via clusterctl:

export CAPI_DIAGNOSTICS_ADDRESS="localhost:8080"
export CAPI_INSECURE_DIAGNOSTICS="true"
clusterctl init ...

Note: If insecure serving is configured the pprof and log level endpoints are disabled for security reasons.

Scraping metrics

A ServiceAccount token is now required to scrape metrics. The corresponding ServiceAccount needs permissions on the /metrics path. This can be achieved e.g. by following the Kubernetes documentation.

via Prometheus

With the Prometheus Helm chart it is as easy as using the following config for the Prometheus job scraping the Cluster API controllers:

    scheme: https
    authorization:
      type: Bearer
      credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
    tls_config:
      ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      # The diagnostics endpoint is using a self-signed certificate, so we don't verify it.
      insecure_skip_verify: true

For more details please see our Prometheus development setup: Prometheus

Note: The Prometheus Helm chart deploys the required ClusterRole out-of-the-box.

via kubectl

First deploy the following RBAC configuration:

cat << EOT | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: default-metrics
rules:
- nonResourceURLs:
  - "/metrics"
  verbs:
  - get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: default-metrics
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: default-metrics
subjects:
- kind: ServiceAccount
  name: default
  namespace: default
EOT

Then let’s open a port-forward, create a ServiceAccount token and scrape the metrics:

# Terminal 1
kubectl -n capi-system port-forward deployments/capi-controller-manager 8443

# Terminal 2
TOKEN=$(kubectl create token default)
curl https://localhost:8443/metrics --header "Authorization: Bearer $TOKEN" -k

Collecting profiles

via Parca

Parca can be used to continuously scrape profiles from CAPI providers. For more details please see our Parca development setup: parca

via kubectl

First deploy the following RBAC configuration:

cat << EOT | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: default-pprof
rules:
- nonResourceURLs:
  - "/debug/pprof/*"
  verbs:
  - get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: default-pprof
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: default-pprof
subjects:
- kind: ServiceAccount
  name: default
  namespace: default
EOT

Then let’s open a port-forward, create a ServiceAccount token and scrape the profile:

# Terminal 1
kubectl -n capi-system port-forward deployments/capi-controller-manager 8443

# Terminal 2
TOKEN=$(kubectl create token default)

# Get a goroutine dump
curl "https://localhost:8443/debug/pprof/goroutine?debug=2" --header "Authorization: Bearer $TOKEN" -k > ./goroutine.txt

# Get a profile
curl "https://localhost:8443/debug/pprof/profile?seconds=10" --header "Authorization: Bearer $TOKEN" -k > ./profile.out
go tool pprof -http=:8080 ./profile.out

Changing the log level

via kubectl

First deploy the following RBAC configuration:

cat << EOT | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: default-loglevel
rules:
- nonResourceURLs:
  - "/debug/flags/v"
  verbs:
  - put
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: default-loglevel
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: default-loglevel
subjects:
- kind: ServiceAccount
  name: default
  namespace: default
EOT

Then let’s open a port-forward, create a ServiceAccount token and change the log level to 8:

# Terminal 1
kubectl -n capi-system port-forward deployments/capi-controller-manager 8443

# Terminal 2
TOKEN=$(kubectl create token default)
curl "https://localhost:8443/debug/flags/v" --header "Authorization: Bearer $TOKEN" -X PUT -d '8' -k

ClusterResourceSet (GA)

The ClusterResourceSet feature is introduced to provide a way to automatically apply a set of resources (such as CNI/CSI) defined by users to matching newly-created/existing clusters. ClusterResourceSet provides a basic solution for installing & managing resources, while for advanced use cases an addon provider must be used.

ClusterResourceSet is namespace-scoped, all resources and clusters referenced in the ClusterResourceSet spec need to be in the same namespace as the ClusterResourceSet.

More details on ClusterResourceSet can be found at: ClusterResourceSet CAEP

Example

Suppose you want to automatically install the relevant external cloud provider on all workload clusters. This can be accomplished by labeling the clusters with the specific cloud (e.g. AWS, GCP or OpenStack) and then creating a ClusterResourceSet for each. For example, you could have the following for OpenStack:

apiVersion: addons.cluster.x-k8s.io/v1beta2
kind: ClusterResourceSet
metadata:
  name: cloud-provider-openstack
  namespace: default
spec:
  strategy: Reconcile
  clusterSelector:
    matchLabels:
      cloud: openstack
  resources:
    - name: cloud-provider-openstack
      kind: ConfigMap
    - name: cloud-config
      kind: Secret

This ClusterResourceSet would apply the content of the Secret cloud-config and of the ConfigMap cloud-provider-openstack in all workload clusters with the label cloud=openstack. Suppose you have the file cloud.conf that should be included in the Secret and cloud-provider-openstack.yaml that should be in the ConfigMap. The Secret and ConfigMap can then be created in the following way:

kubectl create secret generic cloud-config --from-file=cloud.conf --type=addons.cluster.x-k8s.io/resource-set
kubectl create configmap cloud-provider-openstack --from-file=cloud-provider-openstack.yaml

Note that it is required that the Secret has the type addons.cluster.x-k8s.io/resource-set for it to be picked up.

Update from ApplyOnce to Reconcile

The strategy field is immutable so existing CRS can’t be updated directly. However, CAPI won’t delete the managed resources in the target cluster when the CRS is deleted. So if you want to start using the Reconcile strategy, delete your existing CRS and create it again with the updated strategy.

Security Guidelines

This section provides security guidelines useful to provision clusters which are secure by default to follow the secure defaults guidelines for cloud native apps.

Pod Security Standards

Pod Security Admission allows applying Pod Security Standards during creation of pods at the cluster level.

The flavor development-topology for the Docker provider used in Quick Start already includes a basic Pod Security Standard configuration. It is using ClusterClass variables and patches to inject the configuration.

Adding a basic Pod Security Standards configuration to a ClusterClass

By adding the following variables and patches Pod Security Standards can be added to every ClusterClass which references a Kubeadm based control plane.

Adding the variables to a ClusterClass

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
spec:
  variables:
  - name: podSecurityStandard
    required: false
    schema:
      openAPIV3Schema:
        type: object
        properties: 
          enabled: 
            type: boolean
            default: true
            description: "enabled enables the patches to enable Pod Security Standard via AdmissionConfiguration."
          enforce:
            type: string
            default: "baseline"
            description: "enforce sets the level for the enforce PodSecurityConfiguration mode. One of privileged, baseline, restricted."
            pattern: "privileged|baseline|restricted"
          audit:
            type: string
            default: "restricted"
            description: "audit sets the level for the audit PodSecurityConfiguration mode. One of privileged, baseline, restricted."
            pattern: "privileged|baseline|restricted"
          warn:
            type: string
            default: "restricted"
            description: "warn sets the level for the warn PodSecurityConfiguration mode. One of privileged, baseline, restricted."
            pattern: "privileged|baseline|restricted"
  ...
  • The version field in Pod Security Admission Config defaults to latest.
  • The kube-system namespace is exempt from Pod Security Standards enforcement, because it runs control-plane pods that need higher privileges.

Adding the patches to a ClusterClass

The following snippet contains the patch to be added to the ClusterClass.

Due to limitations of ClusterClass with patches there are two versions for this patch.

Use this patch if the following keys already exist inside the KubeadmControlPlaneTemplate referred by the ClusterClass:

  • .spec.template.spec.kubeadmConfigSpec.clusterConfiguration.apiServer.extraVolumes
  • .spec.template.spec.kubeadmConfigSpec.files
apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
spec:
  ...
  patches:
  - name: podSecurityStandard
    description: "Adds an admission configuration for PodSecurity to the kube-apiserver."
    definitions:
    - selector:
        apiVersion: controlplane.cluster.x-k8s.io/v1beta1
        kind: KubeadmControlPlaneTemplate
        matchResources:
          controlPlane: true
      jsonPatches:
      - op: add
        path: "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraArgs"
        value:
          admission-control-config-file: "/etc/kubernetes/kube-apiserver-admission-pss.yaml"
      - op: add
        path: "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraVolumes/-"
        value:
          name: admission-pss
          hostPath: /etc/kubernetes/kube-apiserver-admission-pss.yaml
          mountPath: /etc/kubernetes/kube-apiserver-admission-pss.yaml
          readOnly: true
          pathType: "File"
      - op: add
        path: "/spec/template/spec/kubeadmConfigSpec/files/-"
        valueFrom:
          template: |
            content: |
              apiVersion: apiserver.config.k8s.io/v1
              kind: AdmissionConfiguration
              plugins:
              - name: PodSecurity
                configuration:
                  apiVersion: pod-security.admission.config.k8s.io/v1{{ if semverCompare "< v1.25" .builtin.controlPlane.version }}beta1{{ end }}
                  kind: PodSecurityConfiguration
                  defaults:
                    enforce: "{{ .podSecurityStandard.enforce }}"
                    enforce-version: "latest"
                    audit: "{{ .podSecurityStandard.audit }}"
                    audit-version: "latest"
                    warn: "{{ .podSecurityStandard.warn }}"
                    warn-version: "latest"
                  exemptions:
                    usernames: []
                    runtimeClasses: []
                    namespaces: [kube-system]
            path: /etc/kubernetes/kube-apiserver-admission-pss.yaml
    enabledIf: "{{ .podSecurityStandard.enabled }}"
...

Use this patches if the following keys do not exist inside the KubeadmControlPlaneTemplate referred by the ClusterClass:

  • .spec.template.spec.kubeadmConfigSpec.clusterConfiguration.apiServer.extraVolumes
  • .spec.template.spec.kubeadmConfigSpec.files

Attention: Existing values inside the KubeadmControlPlaneTemplate at the mentioned keys will be replaced by this patch.

apiVersion: cluster.x-k8s.io/v1beta2
kind: ClusterClass
spec:
  ...
  patches:
  - name: podSecurityStandard
    description: "Adds an admission configuration for PodSecurity to the kube-apiserver."
    definitions:
    - selector:
        apiVersion: controlplane.cluster.x-k8s.io/v1beta1
        kind: KubeadmControlPlaneTemplate
        matchResources:
          controlPlane: true
      jsonPatches:
      - op: add
        path: "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraArgs"
        value:
          admission-control-config-file: "/etc/kubernetes/kube-apiserver-admission-pss.yaml"
      - op: add
        path: "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraVolumes"
        value:
        - name: admission-pss
          hostPath: /etc/kubernetes/kube-apiserver-admission-pss.yaml
          mountPath: /etc/kubernetes/kube-apiserver-admission-pss.yaml
          readOnly: true
          pathType: "File"
      - op: add
        path: "/spec/template/spec/kubeadmConfigSpec/files"
        valueFrom:
          template: |
            - content: |
                apiVersion: apiserver.config.k8s.io/v1
                kind: AdmissionConfiguration
                plugins:
                - name: PodSecurity
                  configuration:
                    apiVersion: pod-security.admission.config.k8s.io/v1{{ if semverCompare "< v1.25" .builtin.controlPlane.version }}beta1{{ end }}
                    kind: PodSecurityConfiguration
                    defaults:
                      enforce: "{{ .podSecurityStandard.enforce }}"
                      enforce-version: "latest"
                      audit: "{{ .podSecurityStandard.audit }}"
                      audit-version: "latest"
                      warn: "{{ .podSecurityStandard.warn }}"
                      warn-version: "latest"
                    exemptions:
                      usernames: []
                      runtimeClasses: []
                      namespaces: [kube-system]
              path: /etc/kubernetes/kube-apiserver-admission-pss.yaml
    enabledIf: "{{ .podSecurityStandard.enabled }}"
...

Create a secure Cluster using the ClusterClass

After adding the variables and patches the Pod Security Standards would be applied by default. It is also possible to disable this patch or configure different levels for the configuration using variables.

apiVersion: cluster.x-k8s.io/v1beta2
kind: Cluster
metadata:
  name: "my-cluster"
spec:
  ...
  topology:
    ...
    classRef:
      name: my-secure-cluster-class
    variables:
    - name: podSecurityStandard
      value: 
        enabled: true
        enforce: "restricted"

Security Guidelines for Cluster API Users

This document compiles security best practices for using Cluster API. These guidelines are based on the Cluster API Security Self-Assessment conducted by the Kubernetes SIG Security. We recommend that organizations adapt these guidelines to their specific infrastructure and security requirements to ensure safe operations.

Comprehensive auditing

To ensure comprehensive auditing, the following components require audit configuration:

  • Cluster-level Auditing

    • Auditing on the management cluster
    • API server auditing for all workload clusters
  • Node/VM-level Auditing

    • Audit KubeConfig files access that are located on the node
    • Audit access or edits to CA private keys and cert files located on the node
  • Cloud Provider Auditing

    • Cloud API auditing to log all actions performed using cloud credentials

After configuring these audit sources, centralize the logs using aggregation tools and implement real-time monitoring and alerting to detect suspicious activities and security incidents.

Use least privileges

To minimize security risks related to cloud provider access, create dedicated cloud credentials that have only the necessary permissions to manage the lifecycle of a cluster. Avoid using administrative or root accounts for Cluster API operations, and use separate credentials for different purposes such as management cluster versus workload clusters.

Limit access

Implement access restrictions to protect cluster infrastructure.

Control Plane Protection

Limit who can create pods on control plane nodes through multiple methods:

SSH Access

Disable or restrict SSH access to nodes in a cluster to prevent unauthorized modifications and access to sensitive files.

Second pair of eyes

Implement a review process where at least two people must approve privileged actions such as creating, deleting, or updating clusters. GitOps provides an effective way to enforce this requirement through pull request workflows, where changes to cluster configurations must be reviewed and approved by another team member before being merged and applied to the infrastructure.

Implement comprehensive alerting

Configure alerts in the centralized audit log system to detect security incidents and resource anomalies.

Security Event Monitoring

  • Alert when cluster API components are modified, restarted, or experience unexpected state changes
  • Monitor and alert on unauthorized changes to sensitive files on machine images
  • Alert on unexpected machine restarts or shutdowns
  • Monitor deletion or modification of Elastic Load Balancers (ELB) for API servers

Resource Activity Monitoring

  • Alert on all cloud resource creation, update, and deletion activities
  • Identify anomalous patterns such as mass resource creation or deletion
  • Monitor for resources created outside expected boundaries

Resource Limit Monitoring

  • Alert when the number of clusters approaches or exceeds defined soft limits
  • Monitor node creation rates and alert when approaching capacity limits
  • Track usage against cloud provider quotas and organizational limits
  • Alert on excessive API calls or resource creation requests

Cluster isolation and segregation

Implement multiple layers of isolation to prevent privilege escalation from workload clusters to management cluster.

Account/Subscription Separation

Separate workload clusters into different AWS accounts or Azure subscriptions, and use dedicated accounts for management cluster and production workloads. This approach provides a strong security boundary at the cloud provider level.

Network Boundaries

Separate workload and management clusters at the network level through VPC boundaries. Use dedicated VPC/VNet for each cluster type to prevent lateral movement between clusters.

Certificate Authority Isolation

Do not build a chain of trust for cluster CAs. Each cluster must have its own independent CA to ensure that workload cluster CA compromise does not provide access to the management cluster. See Kubernetes PKI certificates and requirements for best practices.

Prevent runtime updates

Implement controls to prevent tampering of machine images at runtime. Disable or restrict updates to machine images at runtime and prevent unauthorized modifications through SSH access restrictions. Following immutable infrastructure practices ensures that any changes require deploying new images rather than modifying running systems.

Overview of clusterctl

The clusterctl CLI tool handles the lifecycle of a Cluster API management cluster.

The clusterctl command line interface is specifically designed for providing a simple “day 1 experience” and a quick start with Cluster API. It automates fetching the YAML files defining provider components and installing them.

Additionally it encodes a set of best practices in managing providers, that helps the user in avoiding mis-configurations or in managing day 2 operations such as upgrades.

Below you can find a list of main clusterctl commands:

For the full list of clusterctl commands please refer to commands.

Avoiding GitHub rate limiting

While using providers hosted on GitHub, clusterctl is calling GitHub API which are rate limited; for normal usage free tier is enough but when using clusterctl extensively users might hit the rate limit.

To avoid rate limiting for the public repos set the GITHUB_TOKEN environment variable. To generate a token follow this documentation. The token only needs repo scope for clusterctl.

Per default clusterctl will use a go proxy to detect the available versions to prevent additional API calls to the GitHub API. It is possible to configure the go proxy url using the GOPROXY variable as for go itself (defaults to https://proxy.golang.org). To immediately fallback to the GitHub client and not use a go proxy, the environment variable could get set to GOPROXY=off or GOPROXY=direct. If a provider does not follow Go’s semantic versioning, clusterctl may fail when detecting the correct version. In such cases, disabling the go proxy functionality via GOPROXY=off should be considered.

Installing clusterctl

Instructions are available in the Quick Start.

clusterctl commands

CommandDescription
clusterctl alpha rolloutManages the rollout of Cluster API resources. For example: MachineDeployments.
clusterctl completionOutput shell completion code for the specified shell (bash or zsh).
clusterctl configDisplay clusterctl configuration.
clusterctl deleteDelete one or more providers from the management cluster.
clusterctl describe clusterDescribe workload clusters.
clusterctl generate clusterGenerate templates for creating workload clusters.
clusterctl generate providerGenerate templates for provider components.
clusterctl generate yamlProcess yaml using clusterctl’s yaml processor.
clusterctl get kubeconfigGets the kubeconfig file for accessing a workload cluster.
clusterctl helpHelp about any command.
clusterctl initInitialize a management cluster.
clusterctl init list-imagesLists the container images required for initializing the management cluster.
clusterctl convertEXPERIMENTAL: Convert Cluster API core resources (cluster.x-k8s.io) between API versions.
clusterctl moveMove Cluster API objects and all their dependencies between management clusters.
clusterctl upgrade planProvide a list of recommended target versions for upgrading Cluster API providers in a management cluster.
clusterctl upgrade applyApply new versions of Cluster API core and providers in a management cluster.
clusterctl versionPrint clusterctl version.

clusterctl init

The clusterctl init command installs the Cluster API components and transforms the Kubernetes cluster into a management cluster.

This document provides more detail on how clusterctl init works and on the supported options for customizing your management cluster.

Defining the management cluster

The clusterctl init command accepts in input a list of providers to install.

Automatically installed providers

The clusterctl init command automatically adds the cluster-api core provider, the kubeadm bootstrap provider, and the kubeadm control-plane provider to the list of providers to install. This allows users to use a concise command syntax for initializing a management cluster. For example, to get a fully operational management cluster with the aws infrastructure provider, the cluster-api core provider, the kubeadm bootstrap, and the kubeadm control-plane provider, use the command:

clusterctl init --infrastructure aws

Provider version

The clusterctl init command by default installs the latest version available for each selected provider.

Target namespace

The clusterctl init command by default installs each provider in the default target namespace defined by each provider, e.g. capi-system for the Cluster API core provider.

See the provider documentation for more details.

Provider repositories

To access provider specific information, such as the components YAML to be used for installing a provider, clusterctl init accesses the provider repositories, that are well-known places where the release assets for a provider are published.

Per default clusterctl will use a go proxy to detect the available versions to prevent additional API calls to the GitHub API. It is possible to configure the go proxy url using the GOPROXY variable as for go itself (defaults to https://proxy.golang.org). To immediately fallback to the GitHub client and not use a go proxy, the environment variable could get set to GOPROXY=off or GOPROXY=direct. If a provider does not follow Go’s semantic versioning, clusterctl may fail when detecting the correct version. In such cases, disabling the go proxy functionality via GOPROXY=off should be considered.

See clusterctl configuration for more info about provider repository configurations.

Variable substitution

Providers can use variables in the components YAML published in the provider’s repository.

During clusterctl init, those variables are replaced with environment variables or with variables read from the clusterctl configuration.

Additional information

When installing a provider, the clusterctl init command executes a set of steps to simplify the lifecycle management of the provider’s components.

  • All the provider’s components are labeled, so they can be easily identified in subsequent moments of the provider’s lifecycle, e.g. upgrades.
labels:
- clusterctl.cluster.x-k8s.io: ""
- cluster.x-k8s.io/provider: "<provider-name>"
  • An additional Provider object is created in the target namespace where the provider is installed. This object keeps track of the provider version, and other useful information for the inventory of the providers currently installed in the management cluster.

Cert-manager

Cluster API providers require a cert-manager version supporting the cert-manager.io/v1 API to be installed in the cluster.

While doing init, clusterctl checks if there is a version of cert-manager already installed. If not, clusterctl will install a default version (currently cert-manager v1.21.1). See clusterctl configuration for available options to customize this operation.

Avoiding GitHub rate limiting

Follow this

clusterctl generate cluster

The clusterctl generate cluster command returns a YAML template for creating a workload cluster.

For example

clusterctl generate cluster my-cluster --kubernetes-version v1.28.0 --control-plane-machine-count=3 --worker-machine-count=3 > my-cluster.yaml

Generates a YAML file named my-cluster.yaml with a predefined list of Cluster API objects; Cluster, Machines, Machine Deployments, etc. to be deployed in the current namespace (in case, use the --target-namespace flag to specify a different target namespace).

Then, the file can be modified using your editor of choice; when ready, run the following command to apply the cluster manifest.

kubectl apply -f my-cluster.yaml

Selecting the infrastructure provider to use

The clusterctl generate cluster command uses smart defaults in order to simplify the user experience; in the example above, it detects that there is only an aws infrastructure provider in the current management cluster and so it automatically selects a cluster template from the aws provider’s repository.

In case there is more than one infrastructure provider, the following syntax can be used to select which infrastructure provider to use for the workload cluster:

clusterctl generate cluster my-cluster --kubernetes-version v1.28.0 \
    --infrastructure aws > my-cluster.yaml

or

clusterctl generate cluster my-cluster --kubernetes-version v1.28.0 \
    --infrastructure aws:v0.4.1 > my-cluster.yaml

Flavors

The infrastructure provider authors can provide different types of cluster templates, or flavors; use the --flavor flag to specify which flavor to use; e.g.

clusterctl generate cluster my-cluster --kubernetes-version v1.28.0 \
    --flavor high-availability > my-cluster.yaml

Please refer to the providers documentation for more info about available flavors.

Alternative source for cluster templates

clusterctl uses the provider’s repository as a primary source for cluster templates; the following alternative sources for cluster templates can be used as well:

ConfigMaps

Use the --from-config-map flag to read cluster templates stored in a Kubernetes ConfigMap; e.g.

clusterctl generate cluster my-cluster --kubernetes-version v1.28.0 \
    --from-config-map my-templates > my-cluster.yaml

Also following flags are available --from-config-map-namespace (defaults to current namespace) and --from-config-map-key (defaults to template).

GitHub, raw template URL, local file system folder or standard input

Use the --from flag to read cluster templates stored in a GitHub repository, raw template URL, in a local file system folder, or from the standard input; e.g.

clusterctl generate cluster my-cluster --kubernetes-version v1.28.0 \
   --from https://github.com/my-org/my-repository/blob/main/my-template.yaml > my-cluster.yaml

or

clusterctl generate cluster my-cluster --kubernetes-version v1.28.0 \
   --from https://foo.bar/my-template.yaml > my-cluster.yaml

or

clusterctl generate cluster my-cluster --kubernetes-version v1.28.0 \
   --from ~/my-template.yaml > my-cluster.yaml

or

cat ~/my-template.yaml | clusterctl generate cluster my-cluster --kubernetes-version v1.28.0 \
    --from - > my-cluster.yaml

Variables

If the selected cluster template expects some environment variables, the user should ensure those variables are set in advance.

E.g. if the AWS_CREDENTIALS variable is expected for a cluster template targeting the aws infrastructure, you should ensure the corresponding environment variable to be set before executing clusterctl generate cluster.

Please refer to the providers documentation for more info about the required variables or use the clusterctl generate cluster --list-variables flag to get a list of variables names required by a cluster template.

The clusterctl configuration file can be used as alternative to environment variables.

clusterctl generate provider

Generate templates for provider components.

clusterctl fetches the provider components from the provider repository and performs variable substitution.

Variable values are either sourced from the clusterctl config file or from environment variables

Usage: clusterctl generate provider [flags]

Current usage of the command is as follows:

# Generates a yaml file for creating provider with variable values using
# components defined in the provider repository.
clusterctl generate provider --infrastructure aws

# Generates a yaml file for creating provider for a specific version with variable values using
# components defined in the provider repository.
clusterctl generate provider --infrastructure aws:v0.4.1

# Displays information about a specific infrastructure provider.
# If applicable, prints out the list of required environment variables.
clusterctl generate provider --infrastructure aws --describe

# Displays information about a specific version of the infrastructure provider.
clusterctl generate provider --infrastructure aws:v0.4.1 --describe

# Generates a yaml file for creating provider for a specific version.
# No variables will be processed and substituted using this flag
clusterctl generate provider --infrastructure aws:v0.4.1 --raw

clusterctl generate yaml

The clusterctl generate yaml command processes yaml using clusterctl’s yaml processor.

The intent of this command is to allow users who may have specific templates to leverage clusterctl’s yaml processor for variable substitution. For example, this command can be leveraged in local and CI scripts or for development purposes.

clusterctl ships with a simple yaml processor that performs variable substitution that takes into account default values. Under the hood, clusterctl’s yaml processor uses drone/envsubst to replace variables and uses the defaults if necessary.

Variable values are either sourced from the clusterctl config file or from environment variables.

Current usage of the command is as follows:

# Generates a configuration file with variable values using a template from a
# specific URL as well as a GitHub URL.
clusterctl generate yaml --from https://github.com/foo-org/foo-repository/blob/main/cluster-template.yaml

clusterctl generate yaml --from https://foo.bar/cluster-template.yaml

# Generates a configuration file with variable values using
# a template stored locally.
clusterctl generate yaml  --from ~/workspace/cluster-template.yaml

# Prints list of variables used in the local template
clusterctl generate yaml --from ~/workspace/cluster-template.yaml --list-variables

# Prints list of variables from template passed in via stdin
cat ~/workspace/cluster-template.yaml | clusterctl generate yaml --from - --list-variables

# Default behavior for this sub-command is to read from stdin.
# Generate configuration from stdin
cat ~/workspace/cluster-template.yaml | clusterctl generate yaml

clusterctl get kubeconfig

This command prints the kubeconfig of an existing workload cluster into stdout. This functionality is available in clusterctl v0.3.9 or newer.

Examples

Get the kubeconfig of a workload cluster named foo.

clusterctl get kubeconfig foo

Get the kubeconfig of a workload cluster named foo in the namespace bar

clusterctl get kubeconfig foo --namespace bar

Get the kubeconfig of a workload cluster named foo using a specific context bar

clusterctl get kubeconfig foo --kubeconfig-context bar

clusterctl describe cluster

The clusterctl describe cluster command provides an “at a glance” view of a Cluster API cluster designed to help the user in quickly understanding if there are problems and where.

For example clusterctl describe cluster capi-quickstart will provide an output similar to:

The “at a glance” view is based on the idea that clusterctl should avoid overloading the user with information, but instead surface problems, if any.

In practice, if you look at the ControlPlane node, you might notice that the underlying machines are grouped together, because all of them have the same state (Ready equal to True), so it is not necessary to repeat the same information three times.

If this is not the case, and machines have different states, the visualization is going to use different lines:

You might also notice that the visualization does not represent the infrastructure machine or the bootstrap object linked to a machine, unless their state differs from the machine’s state.

Customizing the visualization

By default, the visualization generated by clusterctl describe cluster hides details for the sake of simplicity and shortness. However, if required, the user can ask for showing all the detail:

By using --grouping=false, the user can force the visualization to show all the machines on separated lines, no matter if they have the same state or not:

By using the --echo flag, the user can force the visualization to show infrastructure machines and bootstrap objects linked to machines, no matter if they have the same state or not:

It is also possible to force the visualization to show all the conditions for an object (instead of showing only the ready condition). e.g. with --show-conditions KubeadmControlPlane you get:

Please note that this option is flexible, and you can pass a comma separated list of kind or kind/name for which the command should show all the object’s conditions (use ‘all’ to show conditions for everything).

clusterctl convert

Warning: This command is EXPERIMENTAL and may be removed in a future release!

The clusterctl convert command converts Cluster API resources between API versions.

Usage

clusterctl convert [SOURCE] [flags]

Examples

# Convert from file to stdout
clusterctl convert cluster.yaml

# Convert from stdin to stdout
cat cluster.yaml | clusterctl convert

# Save output to a file
clusterctl convert cluster.yaml --output converted-cluster.yaml

# Explicitly specify target version
clusterctl convert cluster.yaml --to-version v1beta2 --output converted-cluster.yaml

Flags

  • --output, -o: Output file path (default: stdout)
  • --to-version: Target API version for conversion (default: “v1beta2”)

Scope and Limitations

  • Only cluster.x-k8s.io resources are converted - Core CAPI resources like Cluster, MachineDeployment, Machine, etc.
  • Other CAPI API groups are passed through unchanged - Infrastructure, bootstrap, and control plane provider resources are not converted
  • ClusterClass patches are not converted - Manual intervention required for ClusterClass patch conversions
  • Field order may change - YAML field ordering is not preserved in the output
  • Comments are removed - YAML comments are stripped during conversion
  • API version references are dropped - Except for ClusterClass and external remediation references

clusterctl move

The clusterctl move command allows to move the Cluster API objects defining workload clusters, like e.g. Cluster, Machines, MachineDeployments, etc. from one management cluster to another management cluster.

You can use:

clusterctl move --to-kubeconfig="path-to-target-kubeconfig.yaml"

To move the Cluster API objects existing in the current namespace of the source management cluster; in case if you want to move the Cluster API objects defined in another namespace, you can use the --namespace flag.

The discovery mechanism for determining the objects to be moved is in the provider contract

Pivot

Pivoting is a process for moving the provider components and declared Cluster API resources from a source management cluster to a target management cluster.

This can now be achieved with the following procedure:

  1. Use clusterctl init to install the provider components into the target management cluster
  2. Use clusterctl move to move the cluster-api resources from a Source Management cluster to a Target Management cluster

Bootstrap & Pivot

The pivot process can be bounded with the creation of a temporary bootstrap cluster used to provision a target Management cluster.

This can now be achieved with the following procedure:

  1. Create a temporary bootstrap cluster, e.g. using kind or minikube
  2. Use clusterctl init to install the provider components
  3. Use clusterctl generate cluster ... | kubectl apply -f - to provision a target management cluster
  4. Wait for the target management cluster to be up and running
  5. Get the kubeconfig for the new target management cluster
  6. Use clusterctl init with the new cluster’s kubeconfig to install the provider components
  7. Use clusterctl move to move the Cluster API resources from the bootstrap cluster to the target management cluster
  8. Delete the bootstrap cluster

Note: It’s required to have at least one worker node to schedule Cluster API workloads (i.e. controllers). A cluster with a single control plane node won’t be sufficient due to the NoSchedule taint. If a worker node isn’t available, clusterctl init will timeout.

Dry run

With --dry-run option you can dry-run the move action by only printing logs without taking any actual actions. Use log level verbosity -v to see different levels of information.

clusterctl upgrade

The clusterctl upgrade command can be used to upgrade the version of the Cluster API providers (CRDs, controllers) installed into a management cluster.

upgrade plan

The clusterctl upgrade plan command can be used to identify possible targets for upgrades.

clusterctl upgrade plan

Produces an output similar to this:

Checking cert-manager version...
Cert-Manager will be upgraded from "v1.5.0" to "v1.5.3"

Checking new release availability...

Management group: capi-system/cluster-api, latest release available for the v1beta1 API Version of Cluster API (contract):

NAME                    NAMESPACE                           TYPE                     CURRENT VERSION   NEXT VERSION
bootstrap-kubeadm       capi-kubeadm-bootstrap-system       BootstrapProvider        v0.4.0           v1.0.0
control-plane-kubeadm   capi-kubeadm-control-plane-system   ControlPlaneProvider     v0.4.0           v1.0.0
cluster-api             capi-system                         CoreProvider             v0.4.0           v1.0.0
infrastructure-docker   capd-system                         InfrastructureProvider   v0.4.0           v1.0.0

You can now apply the upgrade by executing the following command:

   clusterctl upgrade apply --contract v1beta1

The output contains the latest release available for each Cluster API contract version. available at the moment.

upgrade apply

After choosing the desired option for the upgrade, you can run the following command to upgrade all the providers in the management cluster. This upgrades all the providers to the latest stable releases.

clusterctl upgrade apply --contract v1beta1

The upgrade process is composed by three steps:

  • Check the cert-manager version, and if necessary, upgrade it.
  • Delete the current version of the provider components, while preserving the namespace where the provider components are hosted and the provider’s CRDs.
  • Install the new version of the provider components.

Please note that clusterctl does not upgrade Cluster API objects (Clusters, MachineDeployments, Machine etc.); upgrading such objects are the responsibility of the provider’s controllers.

It is also possible to explicitly upgrade one or more components to specific versions.

clusterctl upgrade apply \
    --core cluster-api:v1.2.4 \
    --infrastructure docker:v1.2.4

clusterctl delete

The clusterctl delete command deletes the provider components from the management cluster.

The operation is designed to prevent accidental deletion of user created objects. For example:

clusterctl delete --infrastructure aws

This command deletes the AWS infrastructure provider components, while preserving the namespace where the provider components are hosted and the provider’s CRDs.

If you want to delete all the providers in a single operation, you can use the --all flag.

clusterctl delete --all

clusterctl completion

The clusterctl completion command outputs shell completion code for the specified shell (bash or zsh). The shell code must be evaluated to provide interactive completion of clusterctl commands.

Bash

To install bash-completion on macOS, use Homebrew:

brew install bash-completion

Once installed, bash_completion must be evaluated. This can be done by adding the following line to the ~/.bash_profile.

[[ -r "$(brew --prefix)/etc/profile.d/bash_completion.sh" ]] && . "$(brew --prefix)/etc/profile.d/bash_completion.sh"

If bash-completion is not installed on Linux, please install the ‘bash-completion’ package via your distribution’s package manager.

You now have to ensure that the clusterctl completion script gets sourced in all your shell sessions. There are multiple ways to achieve this:

  • Source the completion script in your ~/.bash_profile file:
    source <(clusterctl completion bash)
    
  • Add the completion script to the /usr/local/etc/bash_completion.d directory:
    clusterctl completion bash >/usr/local/etc/bash_completion.d/clusterctl
    

Zsh

The clusterctl completion script for Zsh can be generated with the command clusterctl completion zsh.

If shell completion is not already enabled in your environment you will need to enable it. You can execute the following once:

echo "autoload -U compinit; compinit" >> ~/.zshrc

To load completions for each session, execute once:

clusterctl completion zsh > "${fpath[1]}/_clusterctl"

You will need to start a new shell for this setup to take effect.

clusterctl alpha rollout

The clusterctl alpha rollout command manages the rollout of a Cluster API resource. It consists of several sub-commands which are documented below.

Restart

Use the restart sub-command to force an immediate rollout. Note that rollout refers to the replacement of existing machines with new machines using the desired rollout strategy (default: rolling update). For example, here the MachineDeployment my-md-0 will be immediately rolled out:

clusterctl alpha rollout restart machinedeployment/my-md-0

Pause/Resume

Use the pause sub-command to pause a Cluster API resource. The command is a NOP if the resource is already paused. Note that internally, this command sets the Paused field within the resource spec (e.g. MachineDeployment.Spec.Paused) to true.

clusterctl alpha rollout pause machinedeployment/my-md-0

Use the resume sub-command to resume a currently paused Cluster API resource. The command is a NOP if the resource is currently not paused.

clusterctl alpha rollout resume machinedeployment/my-md-0

clusterctl config repositories

Display the list of providers and their repository configurations.

clusterctl ships with a list of known providers; if necessary, edit $XDG_CONFIG_HOME/cluster-api/clusterctl.yaml file to add a new provider or to customize existing ones.

clusterctl help

Help provides help for any command in the application. Simply type clusterctl help [command] for full details.

clusterctl version

Print clusterctl version.

clusterctl init list-images

Lists the container images required for initializing the management cluster.

clusterctl Configuration File

The clusterctl config file is located at $XDG_CONFIG_HOME/cluster-api/clusterctl.yaml. It can be used to:

  • Customize the list of providers and provider repositories.
  • Provide configuration values to be used for variable substitution when installing providers or creating clusters.
  • Define image overrides for air-gapped environments.

Provider repositories

The clusterctl CLI is designed to work with providers implementing the clusterctl Provider Contract.

Each provider is expected to define a provider repository, a well-known place where release assets are published.

By default, clusterctl ships with providers sponsored by SIG Cluster Lifecycle. Use clusterctl config repositories to get a list of supported providers and their repository configuration.

Users can customize the list of available providers using the clusterctl configuration file, as shown in the following example:

providers:
  # add a custom provider
  - name: "my-infra-provider"
    url: "https://github.com/myorg/myrepo/releases/latest/infrastructure-components.yaml"
    type: "InfrastructureProvider"
  # override a pre-defined provider
  - name: "cluster-api"
    url: "https://github.com/myorg/myforkofclusterapi/releases/latest/core-components.yaml"
    type: "CoreProvider"
  # add a custom provider on a self-hosted GitLab (host should start with "gitlab.")
  - name: "my-other-infra-provider"
    url: "https://gitlab.example.com/api/v4/projects/myorg%2Fmyrepo/packages/generic/myrepo/v1.2.3/infrastructure-components.yaml"
    type: "InfrastructureProvider"
  # override a pre-defined provider on a self-hosted GitLab (host should start with "gitlab.")
  - name: "kubeadm"
    url: "https://gitlab.example.com/api/v4/projects/external-packages%2Fcluster-api/packages/generic/cluster-api/v1.1.3/bootstrap-components.yaml"
    type: "BootstrapProvider"

See provider contract for instructions about how to set up a provider repository.

Note: It is possible to use the ${HOME} and ${CLUSTERCTL_REPOSITORY_PATH} environment variables in url.

Variables

When installing a provider clusterctl reads a YAML file that is published in the provider repository. While executing this operation, clusterctl can substitute certain variables with the ones provided by the user.

The same mechanism also applies when clusterctl reads the cluster templates YAML published in the repository, e.g. when injecting the Kubernetes version to use, or the number of worker machines to create.

The user can provide values using OS environment variables, but it is also possible to add variables in the clusterctl config file:

# Values for environment variable substitution
AWS_B64ENCODED_CREDENTIALS: XXXXXXXX

The format of keys should always be UPPERCASE_WITH_UNDERSCORE for both OS environment variables and in the clusterctl config file (NOTE: this limitation derives from Viper, the library we are using internally to retrieve variables).

In case a variable is defined both in the config file and as an OS environment variable, the environment variable takes precedence.

Cert-Manager configuration

While doing init, clusterctl checks if there is a version of cert-manager already installed. If not, clusterctl will install a default version.

By default, cert-manager will be fetched from https://github.com/cert-manager/cert-manager/releases; however, if the user wants to use a different repository, it is possible to use the following configuration:

cert-manager:
  url: "/Users/foo/.config/cluster-api/dev-repository/cert-manager/latest/cert-manager.yaml"

Note: It is possible to use the ${HOME} and ${CLUSTERCTL_REPOSITORY_PATH} environment variables in url.

Similarly, it is possible to override the default version installed by clusterctl by configuring:

cert-manager:
  ...
  version: "v1.1.1"

For situations when resources are limited or the network is slow, the cert-manager wait time to be running can be customized by adding a field to the clusterctl config file, for example:

cert-manager:
  ...
  timeout: 15m

The value string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as “300ms”, “-1.5h” or “2h45m”. Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”.

If no value is specified, or the format is invalid, the default value of 10 minutes will be used.

Please note that the configuration above will be considered also when doing clusterctl upgrade plan or clusterctl upgrade apply.

For situations when you are using your own cert-manager installation, you can tell clusterctl init that cert-manager is already installed by adding a field to the clusterctl config file, for example:

cert-manager:
  ...
  externallyProvisioned: true
  timeout: 15m
  ...

If the externallyProvisioned flag is set, clusterctl will not install cert-manager but only test if it is proper working. If cert-manager is not working the test will be repeated until timeout expires; after that clusterctl int will stop and report an error.

Migrating to user-managed cert-manager

You may want to migrate to a user-managed cert-manager further down the line, after initialising cert-manager on the management cluster through clusterctl.

clusterctl looks for the label clusterctl.cluster.x-k8s.io/core=cert-manager on all api resources in the cert-manager namespace. If it finds the label, clusterctl will manage the cert-manager deployment. You can list all the resources with that label by running:

kubectl api-resources --verbs=list -o name | xargs -n 1 kubectl get --show-kind --ignore-not-found -A --selector=clusterctl.cluster.x-k8s.io/core=cert-manager

If you want to manage and install your own cert-manager, you’ll need to remove this label from all API resources.

Avoiding GitHub rate limiting

Follow this

Overrides Layer

clusterctl uses an overrides layer to read in injected provider components, cluster templates and metadata. By default, it reads the files from $XDG_CONFIG_HOME/cluster-api/overrides.

The directory structure under the overrides directory should follow the template:

<providerType-providerName>/<version>/<fileName>

For example,

├── bootstrap-kubeadm
│   └── v1.1.5
│       └── bootstrap-components.yaml
├── cluster-api
│   └── v1.1.5
│       └── core-components.yaml
├── control-plane-kubeadm
│   └── v1.1.5
│       └── control-plane-components.yaml
└── infrastructure-aws
    └── v0.5.0
            ├── cluster-template-dev.yaml
            └── infrastructure-components.yaml

For developers who want to generate the overrides layer, see Build artifacts locally.

Once these overrides are specified, clusterctl will use them instead of getting the values from the default or specified providers.

One example usage of the overrides layer is that it allows you to deploy clusters with custom templates that may not be available from the official provider repositories. For example, you can now do:

clusterctl generate cluster mycluster --flavor dev --infrastructure aws:v0.5.0 -v5

The -v5 provides verbose logging which will confirm the usage of the override file.

Using Override="cluster-template-dev.yaml" Provider="infrastructure-aws" Version="v0.5.0"

Another example, if you would like to deploy a custom version of CAPA, you can make changes to infrastructure-components.yaml in the overrides folder and run,

clusterctl init --infrastructure aws:v0.5.0 -v5
...
Using Override="infrastructure-components.yaml" Provider="infrastructure-aws" Version="v0.5.0"
...

If you prefer to have the overrides directory at a different location (e.g. /Users/foobar/workspace/dev-releases) you can specify the overrides directory in the clusterctl config file as

overridesFolder: /Users/foobar/workspace/dev-releases

Note: It is possible to use the ${HOME} and ${CLUSTERCTL_REPOSITORY_PATH} environment variables in overridesFolder.

Image overrides

When working in air-gapped environments, it’s necessary to alter the manifests to be installed in order to pull images from a local/custom image repository instead of public ones (e.g. gcr.io, or quay.io).

The clusterctl configuration file can be used to instruct clusterctl to override images automatically.

This can be achieved by adding an images configuration entry as shown in the example:

images:
  all:
    repository: myorg.io/local-repo

Please note that the image override feature allows for more fine-grained configuration, allowing to set image overrides for specific components, for example:

images:
  all:
    repository: myorg.io/local-repo
  cert-manager:
    tag: v1.5.3

In this example we are overriding the image repository for all the components and the image tag for all the images in the cert-manager component.

If required to alter only a specific image you can use:

images:
  all:
    repository: myorg.io/local-repo
  cert-manager/cert-manager-cainjector:
    tag: v1.5.3

Additionally, you can override the image name itself. This is useful when images have been mirrored with different names:

images:
  all:
    repository: myorg.io/local-repo
  cluster-api:
    name: mirrored-cluster-api-controller

This would transform registry.k8s.io/cluster-api/cluster-api-controller:v1.10.6 into myorg.io/local-repo/mirrored-cluster-api-controller:v1.10.6.

Or you can specify all three fields to completely override the image:

images:
  cluster-api:
    repository: myorg.io/local-repo
    name: mirrored-cluster-api-controller
    tag: v1.10.6

This would transform registry.k8s.io/cluster-api/cluster-api-controller:v1.8.0 into myorg.io/local-repo/mirrored-cluster-api-controller:v1.10.6, replacing both the image location and version.

Debugging/Logging

To have more verbose logs you can use the -v flag when running the clusterctl and set the level of the logging verbose with a positive integer number, ie. -v 3.

If you do not want to use the flag every time you issue a command you can set the environment variable CLUSTERCTL_LOG_LEVEL or set the variable in the clusterctl config file located by default at $XDG_CONFIG_HOME/cluster-api/clusterctl.yaml.

Skip checking for updates

clusterctl automatically checks for new versions every time it is used. If you do not want clusterctl to check for new updates you can set the environment variable CLUSTERCTL_DISABLE_VERSIONCHECK to "true" or set the variable in the clusterctl config file located by default at $XDG_CONFIG_HOME/cluster-api/clusterctl.yaml.

clusterctl for Developers

This document describes how to use clusterctl during the development workflow.

Prerequisites

  • A Cluster API development setup (go, git, kind v0.9 or newer, Docker v19.03 or newer etc.)
  • A local clone of the Cluster API GitHub repository
  • A local clone of the GitHub repositories for the providers you want to install

Build clusterctl

From the root of the local copy of Cluster API, you can build the clusterctl binary by running:

make clusterctl

The output of the build is saved in the bin/ folder; In order to use it you have to specify the full path, create an alias or copy it into a folder under your $PATH.

Use local artifacts

Clusterctl by default uses artifacts published in the providers repositories; during the development workflow you may want to use artifacts from your local workstation.

There are two options to do so:

  • Use the overrides layer, when you want to override a single published artifact with a local one.
  • Create a local repository, when you want to avoid using published artifacts and use the local ones instead.

If you want to create a local artifact, follow these instructions:

Build artifacts locally

In order to build artifacts for the CAPI core provider, the kubeadm bootstrap provider, the kubeadm control plane provider and the Docker infrastructure provider:

make docker-build REGISTRY=gcr.io/k8s-staging-cluster-api PULL_POLICY=IfNotPresent

Create a clusterctl-settings.json file

Next, create a clusterctl-settings.json file and place it in your local copy of Cluster API. This file will be used by create-local-repository.py. Here is an example:

{
  "providers": ["cluster-api","bootstrap-kubeadm","control-plane-kubeadm", "infrastructure-aws", "infrastructure-docker"],
  "provider_repos": ["../cluster-api-provider-aws"]
}

providers (Array[]String, default=[]): A list of the providers to enable. See available providers for more details.

provider_repos (Array[]String, default=[]): A list of paths to all the providers you want to use. Each provider must have a clusterctl-settings.json file describing how to build the provider assets.

Create the local repository

Run the create-local-repository hack from the root of the local copy of Cluster API:

cmd/clusterctl/hack/create-local-repository.py

The script reads from the source folders for the providers you want to install, builds the providers’ assets, and places them in a local repository folder located under $XDG_CONFIG_HOME/cluster-api/dev-repository/. Additionally, the command output provides you the clusterctl init command with all the necessary flags. The output should be similar to:

clusterctl local overrides generated from local repositories for the cluster-api, bootstrap-kubeadm, control-plane-kubeadm, infrastructure-docker, infrastructure-aws providers.
in order to use them, please run:

clusterctl init \
   --core cluster-api:v0.3.8 \
   --bootstrap kubeadm:v0.3.8 \
   --control-plane kubeadm:v0.3.8 \
   --infrastructure aws:v0.5.0 \
   --infrastructure docker:v0.3.8 \
   --config $XDG_CONFIG_HOME/cluster-api/dev-repository/config.yaml

As you might notice, the command is using the $XDG_CONFIG_HOME/cluster-api/dev-repository/config.yaml config file, containing all the required setting to make clusterctl use the local repository (it fallbacks to $HOME if $XDG_CONFIG_HOME is not set on your machine).

Available providers

The following providers are currently defined in the script:

  • cluster-api
  • bootstrap-kubeadm
  • control-plane-kubeadm
  • infrastructure-docker

More providers can be added by editing the clusterctl-settings.json in your local copy of Cluster API; please note that each provider_repo should have its own clusterctl-settings.json describing how to build the provider assets, e.g.

{
  "name": "infrastructure-aws",
  "config": {
    "componentsFile": "infrastructure-components.yaml",
    "nextVersion": "v0.5.0"
  }
}

Create a kind management cluster

kind can provide a Kubernetes cluster to be used as a management cluster. See Install and/or configure a Kubernetes cluster for more information.

Before running clusterctl init, you must ensure all the required images are available in the kind cluster.

This is always the case for images published in some image repository like Docker Hub or gcr.io, but it can’t be the case for images built locally; in this case, you can use kind load to move the images built locally. e.g.

kind load docker-image gcr.io/k8s-staging-cluster-api/cluster-api-controller-amd64:dev
kind load docker-image gcr.io/k8s-staging-cluster-api/kubeadm-bootstrap-controller-amd64:dev
kind load docker-image gcr.io/k8s-staging-cluster-api/kubeadm-control-plane-controller-amd64:dev
kind load docker-image gcr.io/k8s-staging-cluster-api/capd-manager-amd64:dev

to make the controller images available for the kubelet in the management cluster.

When the kind cluster is ready and all the required images are in place, run the clusterctl init command generated by the create-local-repository.py script.

Optionally, you may want to check if the components are running properly. The exact components are dependent on which providers you have initialized. Below is an example output with the Docker provider being installed.

kubectl get deploy -A | grep "cap\|cert"
capd-system                         capd-controller-manager                         1/1     1            1           25m
capi-kubeadm-bootstrap-system       capi-kubeadm-bootstrap-controller-manager       1/1     1            1           25m
capi-kubeadm-control-plane-system   capi-kubeadm-control-plane-controller-manager   1/1     1            1           25m
capi-system                         capi-controller-manager                         1/1     1            1           25m
cert-manager                        cert-manager                                    1/1     1            1           27m
cert-manager                        cert-manager-cainjector                         1/1     1            1           27m
cert-manager                        cert-manager-webhook                            1/1     1            1           27m

Additional Notes for the Docker Provider

Select the appropriate Kubernetes version

When selecting the --kubernetes-version, ensure that the kindest/node image is available.

For example, assuming that on docker hub there is no image for version vX.Y.Z, therefore creating a CAPD workload cluster with --kubernetes-version=vX.Y.Z will fail. See issue 3795 for more details.

Get the kubeconfig for the workload cluster when using Docker Desktop

For Docker Desktop on macOS, Linux or Windows use kind to retrieve the kubeconfig.

kind get kubeconfig --name capi-quickstart > capi-quickstart.kubeconfig

Docker Engine for Linux works with the default clusterctl approach.

clusterctl get kubeconfig capi-quickstart > capi-quickstart.kubeconfig

Fix kubeconfig when using Docker Desktop and clusterctl

When retrieving the kubeconfig using clusterctl with Docker Desktop on macOS or Windows or Docker Desktop (Docker Engine works fine) on Linux, you’ll need to take a few extra steps to get the kubeconfig for a workload cluster created with the Docker provider.

clusterctl get kubeconfig capi-quickstart > capi-quickstart.kubeconfig

To fix the kubeconfig run:

# Point the kubeconfig to the exposed port of the load balancer, rather than the inaccessible container IP.
sed -i -e "s/server:.*/server: https:\/\/$(docker port capi-quickstart-lb 6443/tcp | sed "s/0.0.0.0/127.0.0.1/")/g" ./capi-quickstart.kubeconfig

clusterctl Extensions with Plugins

You can extend clusterctl with plugins, similar to kubectl. Please refer to the kubectl plugin documentation for more information, as clusterctl plugins are implemented in the same way, with the exception of plugin distribution.

Installing clusterctl plugins

To install a clusterctl plugin, place the plugin’s executable file in any location on your PATH.

Writing clusterctl plugins

No plugin installation or pre-loading is required. Plugin executables inherit the environment from the clusterctl binary. A plugin determines the command it implements based on its name. For example, a plugin named clusterctl-foo provides the clusterctl foo command. The plugin executable should be installed in your PATH.

Example plugin

#!/bin/bash

# optional argument handling
if [[ "$1" == "version" ]]
then
echo "1.0.0"
exit 0
fi

# optional argument handling
if [[ "$1" == "example-env-var" ]]
then
    echo "$EXAMPLE_ENV_VAR"
    exit 0
fi

echo "I am a plugin named clusterctl-foo"

Using a plugin

To use a plugin, make the plugin executable:

sudo chmod +x ./clusterctl-foo

and place it anywhere in your PATH:

sudo mv ./clusterctl-foo /usr/local/bin

You may now invoke your plugin as a clusterctl command:

clusterctl foo
I am a plugin named clusterctl-foo

All args and flags are passed as-is to the executable:

clusterctl foo version
1.0.0

All environment variables are also passed as-is to the executable:

export EXAMPLE_ENV_VAR=example-value
clusterctl foo example-env-var
example-value
EXAMPLE_ENV_VAR=another-example-value clusterctl foo example-env-var
another-example-value

Additionally, the first argument that is passed to a plugin will always be the full path to the location where it was invoked ($0 would equal /usr/local/bin/clusterctl-foo in the example above).

Naming a plugin

A plugin determines the command path it implements based on its filename. Each sub-command in the path is separated by a dash (-). For example, a plugin for the command clusterctl foo bar baz would have the filename clusterctl-foo-bar-baz.

Developer Guide

Pieces of Cluster API

Cluster API is made up of many components, all of which need to be running for correct operation. For example, if you wanted to use Cluster API with AWS, you’d need to install both the cluster-api manager and the aws manager.

Cluster API includes a built-in provisioner, Docker, that’s suitable for using for testing and development. This guide will walk you through getting that daemon, known as CAPD, up and running.

Other providers may have additional steps you need to follow to get up and running.

Prerequisites

Docker

Iterating on the cluster API involves repeatedly building Docker containers. You’ll need the docker daemon v19.03 or newer available.

On MacOS systems using Lima is a viable alternative to Docker Desktop.

A Cluster

You’ll likely want an existing cluster as your management cluster. The easiest way to do this is with kind v0.9 or newer, as explained in the quick start.

Make sure your cluster is set as the default for kubectl. If it’s not, you will need to modify subsequent kubectl commands below.

A container registry

If you’re using kind, you’ll need a way to push your images to a registry so they can be pulled. You can instead side-load all images, but the registry workflow is lower-friction.

Most users test with GCR, but you could also use something like Docker Hub. If you choose not to use GCR, you’ll need to set the REGISTRY environment variable.

Kustomize

You’ll need to install kustomize. There is a version of kustomize built into kubectl, but it does not have all the features of kustomize v3 and will not work.

Kubebuilder

You’ll need to install kubebuilder.

Envsubst

You’ll need envsubst to handle variable substitution in manifests.

The GNU gettext version of envsubst does not support default values, so you must use the drone/envsubst version.

go install github.com/drone/envsubst/v2/cmd/envsubst@latest

Cert-Manager

You’ll need to deploy cert-manager components on your management cluster, using kubectl

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.21.1/cert-manager.yaml

Ensure the cert-manager webhook service is ready before creating the Cluster API components.

This can be done by following instructions for manual verification from the cert-manager web site. Note: make sure to follow instructions for the release of cert-manager you are installing.

Development

Option 1: Tilt

Tilt is a tool for quickly building, pushing, and reloading Docker containers as part of a Kubernetes deployment. Many of the Cluster API engineers use it for quick iteration. Please see our Tilt instructions to get started.

Option 2: The Old-fashioned way

# Build all the images
make docker-build

# Push images
make docker-push

# Apply the manifests
kustomize build config/default | ~/go/bin/envsubst | kubectl apply -f -
kustomize build bootstrap/kubeadm/config/default | ~/go/bin/envsubst | kubectl apply -f -
kustomize build controlplane/kubeadm/config/default | ~/go/bin/envsubst | kubectl apply -f -
kustomize build test/infrastructure/docker/config/default | ~/go/bin/envsubst | kubectl apply -f -

Testing

Cluster API has a number of test suites available for you to run. Please visit the testing page for more information on each suite.

That’s it!

Now you can create CAPI objects! To test another iteration, you’ll need to follow the steps to build, push, update the manifests, and apply.

Videos explaining CAPI architecture and code walkthroughs

CAPI components and architecture

Additional ClusterAPI KubeCon talks

Tutorials

Code walkthroughs

Let’s chat about …

We are currently hosting “Let’s chat about …” sessions where we are talking about topics relevant to contributors and users of the Cluster API project. For more details and an up-to-date list of recordings of past sessions please see Let’s chat about ….

CAPI e2e Deep Dive*

These are Deep-dive sessions with the CI team to investigate failing and flaking tests.

Developing “core” Cluster API

This section of the book is about developing “core” Cluster API.

With “core” Cluster API we refer to the common set of API and controllers that are required to run any Cluster API provider.

Please note that in the Cluster API code base, side by side of “core” Cluster API components there is also a limited number of in-tree providers:

  • Kubeadm bootstrap provider (CAPBK)
  • Kubeadm control plane provider (KCP)
  • Docker infrastructure provider (CAPD) - The Docker provider is not designed for production use and is intended for development & test only.

Please refer to Developing providers for documentation about in-tree providers (and out of tree providers too).

Developing Cluster API with Tilt

Overview

This document describes how to use kind and Tilt for a simplified workflow that offers easy deployments and rapid iterative builds.

Prerequisites

  1. Docker: v19.03 or newer (on MacOS e.g. via Lima)
  2. kind: v0.32.0 or newer
  3. Tilt: v0.33.18 or newer
  4. kustomize: provided via make kustomize
  5. helm: v3.7.1 or newer
  6. Clone the Cluster API repository locally
  7. Clone the provider(s) you want to deploy locally as well

Getting started

Create a kind cluster

This guide offers instructions for using the following CAPI infrastructure providers for running a development environment without using real machines or cloud resources:

  • CAPD - uses Docker containers as workload cluster nodes
  • CAPK - uses KubeVirt VMs as workload cluster nodes

CAPD is the default as it’s more lightweight and requires less setup. KubeVirt is useful when Docker isn’t suitable for whatever reason. Other infrastructure providers may be enabled as well (see below).

To create a kind cluster along with a local Docker registry and the correct mounts to run CAPD, run the following:

make kind-cluster

To create a kind cluster with CAPK, run the following:

make kind-cluster-kubevirt

You can see the status of the cluster with:

kubectl cluster-info --context kind-capi-test

Create a tilt-settings file

Next, create a tilt-settings.yaml file and place it in your local copy of cluster-api.

Here are some examples:

default_registry: gcr.io/your-project-name-here
enable_providers:
- docker
- kubeadm-bootstrap
- kubeadm-control-plane
enable_providers:
- kubevirt
- kubeadm-bootstrap
- kubeadm-control-plane
provider_repos:
# Path to a local clone of CAPK (replace with actual path)
- ../cluster-api-provider-kubevirt
kustomize_substitutions:
  # CAPK needs access to the containerd socket (replace with actual path)
  CRI_PATH: "/var/run/containerd/containerd.sock"
  KUBERNETES_VERSION: "v1.30.1"
  # An example - replace with an appropriate container disk image for the desired k8s version
  NODE_VM_IMAGE_TEMPLATE: "quay.io/capk/ubuntu-2204-container-disk:v1.30.1"
# Allow deploying CAPK workload clusters from the Tilt UI (optional)
template_dirs:
  kubevirt:
  - ../cluster-api-provider-kubevirt/templates

Other infrastructure providers may be added to the cluster using local clones and a configuration similar to the following:

default_registry: gcr.io/your-project-name-here
provider_repos:
- ../cluster-api-provider-aws
enable_providers:
- aws
- kubeadm-bootstrap
- kubeadm-control-plane

tilt-settings fields

allowed_contexts (Array, default=[]): A list of kubeconfig contexts Tilt is allowed to use. See the Tilt documentation on allow_k8s_contexts for more details.

default_registry (String, default=[]): The image registry to use if you need to push images. See the Tilt documentation for more details. Please note that, in case you are not using a local registry, this value is required; additionally, the Cluster API Tiltfile protects you from accidental push on gcr.io/k8s-staging-cluster-api.

build_engine (String, default=“docker”): The engine used to build images. Can either be docker or podman. NB: the default is dynamic and will be “podman” if the string “Podman Engine” is found in docker version (or in podman version if the command fails).

kind_cluster_name (String, default=“capi-test”): The name of the kind cluster to use when preloading images.

provider_repos (Array[]String, default=[]): A list of paths to all the providers you want to use. Each provider must have a tilt-provider.yaml or tilt-provider.json file describing how to build the provider.

enable_providers (Array[]String, default=[‘docker’]): A list of the providers to enable. See available providers for more details.

enable_core_provider (bool, default=true): By default, the core provider is enabled. This allows to disable it.

preload_images (bool, default=true): By default, images are preloaded into the kind cluster. This works on most platforms but can fail on Apple Silicon or Docker v29+. Set this to false to skip preloading and let the kubelet pull images on demand.

template_dirs (Map{String: Array[]String}, default={“docker”: [ “./test/infrastructure/docker/templates”]}): A map of providers to directories containing cluster templates. An example of the field is given below. See Deploying a workload cluster for how this is used.

template_dirs:
  docker:
  - ./test/infrastructure/docker/templates
  - <other-template-dir>
  azure:
  - <azure-template-dir>
  aws:
  - <aws-template-dir>
  gcp:
  - <gcp-template-dir>

kustomize_substitutions (Map{String: String}, default={}): An optional map of substitutions for ${}-style placeholders in the provider’s yaml. These substitutions are also used when deploying cluster templates. See Deploying a workload cluster.

Note: When running E2E tests locally using an existing cluster managed by Tilt, the following substitutions are required for successful tests:

kustomize_substitutions:
  CLUSTER_TOPOLOGY: "true"
  EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION: "true"
  EXP_RUNTIME_SDK: "true"
  EXP_MACHINE_SET_PREFLIGHT_CHECKS: "true"

For example, if the yaml contains ${AWS_B64ENCODED_CREDENTIALS}, you could do the following:

kustomize_substitutions:
  AWS_B64ENCODED_CREDENTIALS: "your credentials here"

An Azure Service Principal is needed for populating the controller manifests. This utilizes environment-based authentication.

  1. Save your Subscription ID
AZURE_SUBSCRIPTION_ID=$(az account show --query id --output tsv)
az account set --subscription $AZURE_SUBSCRIPTION_ID
  1. Set the Service Principal name
AZURE_SERVICE_PRINCIPAL_NAME=ServicePrincipalName
  1. Save your Tenant ID, Client ID, Client Secret
AZURE_TENANT_ID=$(az account show --query tenantId --output tsv)
AZURE_CLIENT_SECRET=$(az ad sp create-for-rbac --name http://$AZURE_SERVICE_PRINCIPAL_NAME --query password --output tsv)
AZURE_CLIENT_ID=$(az ad sp show --id http://$AZURE_SERVICE_PRINCIPAL_NAME --query appId --output tsv)

Add the output of the following as a section in your tilt-settings.yaml:

  cat <<EOF
  kustomize_substitutions:
     AZURE_SUBSCRIPTION_ID_B64: "$(echo "${AZURE_SUBSCRIPTION_ID}" | tr -d '\n' | base64 | tr -d '\n')"
     AZURE_TENANT_ID_B64: "$(echo "${AZURE_TENANT_ID}" | tr -d '\n' | base64 | tr -d '\n')"
     AZURE_CLIENT_SECRET_B64: "$(echo "${AZURE_CLIENT_SECRET}" | tr -d '\n' | base64 | tr -d '\n')"
     AZURE_CLIENT_ID_B64: "$(echo "${AZURE_CLIENT_ID}" | tr -d '\n' | base64 | tr -d '\n')"
  EOF
kustomize_substitutions:
  DO_B64ENCODED_CREDENTIALS: "your credentials here"

You can generate a base64 version of your GCP json credentials file using:

base64 -i ~/path/to/gcp/credentials.json
kustomize_substitutions:
  GCP_B64ENCODED_CREDENTIALS: "your credentials here"
kustomize_substitutions:
  VSPHERE_USERNAME: "administrator@vsphere.local"
  VSPHERE_PASSWORD: "Admin123"

deploy_observability ([string], default=[]): If set, installs on the dev cluster one of more observability tools. Important! This feature requires the helm command to be available in the user’s path.

Supported values are:

  • grafana*: To create dashboards and query loki, prometheus and tempo.
  • kube-state-metrics: For exposing metrics for Kubernetes and CAPI resources to prometheus.
  • loki: To receive and store logs.
  • metrics-server: To enable kubectl top node/pod.
  • prometheus*: For collecting metrics from Kubernetes.
  • alloy: For providing pod logs to loki.
  • parca*: For visualizing profiling data.
  • tempo: To store traces.
  • visualizer*: Visualize Cluster API resources for each cluster, provide quick access to the specs and status of any resource.
  • headlamp*: A Kubernetes web UI with the Cluster API plugin for browsing and managing CAPI resources.

*: Note: the UI will be accessible via a link in the tilt console

additional_kustomizations (map[string]string, default={}): If set, install the additional resources built using kustomize to the cluster. Example:

additional_kustomizations:
  capv-metrics: ../cluster-api-provider-vsphere/config/metrics

debug (Map{string: Map} default{}): A map of named configurations for the provider. The key is the name of the provider.

Supported settings:

  • port (int, default=0 (disabled)): If set to anything other than 0, then Tilt will run the provider with delve and port forward the delve server to localhost on the specified debug port. This can then be used with IDEs such as Visual Studio Code, Goland and IntelliJ.

  • continue (bool, default=true): By default, Tilt will run delve with --continue, such that any provider with debugging turned on will run normally unless specifically having a breakpoint entered. Change to false if you do not want the controller to start at all by default.

  • profiler_port (int, default=0 (disabled)): If set to anything other than 0, then Tilt will enable the profiler with --profiler-address and set up a port forward. A “profiler” link will be visible in the Tilt Web UI for the controller.

  • metrics_port (int, default=0 (disabled)): If set to anything other than 0, then Tilt will port forward to the default metrics port. A “metrics” link will be visible in the Tilt Web UI for the controller.

  • race_detector (bool, default=false) (Linux amd64 only): If enabled, Tilt will compile the specified controller with cgo and statically compile in the system glibc and enable the race detector. Currently, this is only supported when building on Linux amd64 systems. You must install glibc-static or have libc.a available for this to work.

    Example: Using the configuration below:

      debug:
        core:
          continue: false
          port: 30000
          profiler_port: 40000
          metrics_port: 40001
    
    Wiring up debuggers
    Visual Studio

    When using the example above, the core CAPI controller can be debugged in Visual Studio Code using the following launch configuration:

    {
      "version": "0.2.0",
      "configurations": [
        {
          "name": "Core CAPI Controller",
          "type": "go",
          "request": "attach",
          "mode": "remote",
          "remotePath": "",
          "port": 30000,
          "host": "127.0.0.1",
          "showLog": true,
          "trace": "log",
          "logOutput": "rpc"
        }
      ]
    }
    
    Goland / IntelliJ

    With the above example, you can configure a Go Remote run/debug configuration pointing at port 30000.


deploy_cert_manager (Boolean, default=true): Deploys cert-manager into the cluster for use for webhook registration.

trigger_mode (String, default=auto): Optional setting to configure if tilt should automatically rebuild on changes. Set to manual to disable auto-rebuilding and require users to trigger rebuilds of individual changed components through the UI.

extra_args (Object, default={}): A mapping of provider to additional arguments to pass to the main binary configured for this provider. Each item in the array will be passed in to the manager for the given provider.

Example:

extra_args:
  kubeadm-bootstrap:
  - --logging-format=json

With this config, the respective managers will be invoked with:

manager --logging-format=json

Create a kind cluster and run Tilt!

To create a pre-configured kind cluster (if you have not already done so) and launch your development environment, run

make tilt-up

This will open the command-line HUD as well as a web browser interface. You can monitor Tilt’s status in either location. After a brief amount of time, you should have a running development environment, and you should now be able to create a cluster. There are example worker cluster configs available. These can be customized for your specific needs.

Deploying a workload cluster

After your kind management cluster is up and running with Tilt, you can deploy a workload clusters in the Tilt web UI based off of YAML templates from the directories specified in the template_dirs field from the tilt-settings.yaml file (default ./test/infrastructure/docker/templates).

Templates should be named according to clusterctl conventions:

  • template files must be named cluster-template-{name}.yaml; those files will be accessible in the Tilt web UI under the label grouping {provider-label}.templates, i.e. CAPD.templates.
  • cluster class files must be named clusterclass-{name}.yaml; those file will be accessible in the Tilt web UI under the label grouping {provider-label}.clusterclasses, i.e. CAPD.clusterclasses.

By selecting one of those items in the Tilt web UI set of buttons will appear, allowing to create - with a dropdown for customizing variable substitutions - or delete clusters. Custom values for variable substitutions can be set using kustomize_substitutions in tilt-settings.yaml, e.g.

kustomize_substitutions:
  NAMESPACE: "default"
  KUBERNETES_VERSION: "v1.36.1"
  CONTROL_PLANE_MACHINE_COUNT: "1"
  WORKER_MACHINE_COUNT: "3"
# Note: kustomize substitutions expects the values to be strings. This can be achieved by wrapping the values in quotation marks.

Cleaning up your kind cluster and development environment

After stopping Tilt, you can clean up your kind cluster and development environment by running

make clean-kind

To remove all generated files, run

make clean

Note that you must run make clean or make clean-charts to fetch new versions of charts deployed using deploy_observability in tilt-settings.yaml.

Use of clusterctl

When the worker cluster has been created using tilt, clusterctl should not be used for management operations; this is because tilt doesn’t initialize providers on the management cluster like clusterctl init does, so some of the clusterctl commands like clusterctl config won’t work.

This limitation is an acceptable trade-off while executing fast dev-test iterations on controllers logic. If instead you are interested in testing clusterctl workflows, you should refer to the clusterctl developer instructions.

Available providers

The following providers are currently defined in the Tiltfile:

  • core: cluster-api itself
  • kubeadm-bootstrap: kubeadm bootstrap provider
  • kubeadm-control-plane: kubeadm control-plane provider
  • docker: Docker infrastructure provider
  • in-memory: In-memory infrastructure provider
  • test-extension: Runtime extension used by CAPI E2E tests

Additional providers can be added by following the procedure described in following paragraphs:

tilt-provider configuration

A provider must supply a tilt-provider.yaml file describing how to build it. Here is an example:

name: aws
config:
  image: "gcr.io/k8s-staging-cluster-api-aws/cluster-api-aws-controller"
  live_reload_deps: ["main.go", "go.mod", "go.sum", "api", "cmd", "controllers", "pkg"]
  label: CAPA

config fields

image: the image for this provider, as referenced in the kustomize files. This must match; otherwise, Tilt won’t build it.

live_reload_deps: a list of files/directories to watch. If any of them changes, Tilt rebuilds the manager binary for the provider and performs a live update of the running container.

version: allows to define the version to be used for the Provider CR. If empty, a default version will be used.

additional_docker_helper_commands (String, default=“”): Additional commands to be run in the helper image docker build. e.g.

RUN wget -qO- https://dl.k8s.io/v1.21.2/kubernetes-client-linux-amd64.tar.gz | tar xvz
RUN wget -qO- https://get.docker.com | sh

additional_docker_build_commands (String, default=“”): Additional commands to be appended to the dockerfile. The manager image will use docker-slim, so to download files, use additional_helper_image_commands. e.g.

COPY --from=tilt-helper /usr/bin/docker /usr/bin/docker
COPY --from=tilt-helper /go/kubernetes/client/bin/kubectl /usr/bin/kubectl

kustomize_folder (String, default=config/default): The folder where the kustomize file for a provider is defined; the path is relative to the provider root folder.

kustomize_options ([]String, default=[]): Options to be applied when running kustomize for generating the yaml manifest for a provider. e.g. "kustomize_options": [ "--load-restrictor=LoadRestrictionsNone" ]

apply_provider_yaml (Bool, default=true): Whether to apply the provider yaml. Set to false if your provider does not have a ./config folder or you do not want it to be applied in the cluster.

go_main (String, default=“main.go”): The go main file if not located at the root of the folder

label (String, default=provider name): The label to be used to group provider components in the tilt UI in tilt version >= v0.22.2 (see https://blog.tilt.dev/2021/08/09/resource-grouping.html); as a convention, provider abbreviation should be used (CAPD, KCP etc.).

additional_resources ([]string, default=[]): A list of paths to yaml file to be loaded into the tilt cluster; e.g. use this to deploy an ExtensionConfig object for a RuntimeExtension provider.

additional_uncategorized_resources ([]string, default=[]): A list of paths to yaml file to be loaded into the tilt cluster; e.g. use this to deploy CustomResourceDefinitions. The difference compared to additional_resources is that it is deployed as part of uncategorized and accordingly not re-created together with providers.

resource_deps ([]string, default=[]): A list of tilt resource names to be installed before the current provider; e.g. set this to [“capi_controller”] to ensure that this provider gets installed after Cluster API.

Customizing Tilt

If you need to customize Tilt’s behavior, you can create files in cluster-api’s tilt.d directory. This file is ignored by git so you can be assured that any files you place here will never be checked in to source control.

These files are included after the providers map has been defined and after all the helper function definitions. This is immediately before the “real work” happens.

Under the covers, a.k.a “the real work”

At a high level, the Tiltfile performs the following actions:

  1. Read tilt-settings.yaml
  2. Configure the allowed Kubernetes contexts
  3. Set the default registry
  4. Define the providers map
  5. Include user-defined Tilt files
  6. Deploy cert-manager
  7. Enable providers (core + what is listed in tilt-settings.yaml)
    1. Build the manager binary locally as a local_resource
    2. Invoke docker_build for the provider
    3. Invoke kustomize for the provider’s config/ directory

Live updates

Each provider in the providers map has a live_reload_deps list. This defines the files and/or directories that Tilt should monitor for changes. When a dependency is modified, Tilt rebuilds the provider’s manager binary on your local machine, copies the binary to the running container, and executes a restart script. This is significantly faster than rebuilding the container image for each change. It also helps keep the size of each development image as small as possible (the container images do not need the entire go toolchain, source code, module dependencies, etc.).

IDE support for Tiltfile

For IntelliJ, Syntax highlighting for the Tiltfile can be configured with a TextMate Bundle. For instructions, please see: Tiltfile TextMate Bundle.

For VSCode the Bazel plugin can be used, it provides syntax highlighting and auto-formatting. To enable it for Tiltfile a file association has to be configured via user settings:

"files.associations": {
  "Tiltfile": "starlark",
},

Using Podman

Podman can be used instead of Docker by following these actions:

  1. Enable the podman unix socket:
    • on Linux/systemd: systemctl --user enable --now podman.socket
    • on macOS: create a podman machine with podman machine init
  2. Set build_engine to podman in tilt-settings.yaml (optional, only if both Docker & podman are installed)
  3. Define the env variable DOCKER_HOST to the right socket:
    • on Linux/systemd: export DOCKER_HOST=unix:///run/user/$(id -u)/podman/podman.sock
    • on macOS: export DOCKER_HOST=$(podman machine inspect <machine> | jq -r '.[0].ConnectionInfo.PodmanSocket.Path') where <machine> is the podman machine name
  4. Run tilt up

NB: The socket defined by DOCKER_HOST is used only for the hack/tools/internal/tilt-prepare command, the image build is running the podman build/podman push commands.

Using Lima

Lima can be used instead of Docker Desktop. Please note that especially with CAPD the rootless template of Lima does not work.

The following command creates a working Lima machine for developing Cluster API with CAPD:

limactl start template://docker-rootful --name "docker" --tty=false \
  --set '.provision += {"mode":"system","script":"#!/bin/bash\nset -eux -o pipefail\ncat << EOF > \"/etc/sysctl.d/99-capi.conf\"\nfs.inotify.max_user_watches = 1048576\nfs.inotify.max_user_instances = 8192\nEOF\nsysctl -p \"/etc/sysctl.d/99-capi.conf\""}' \
  --set '.mounts[0] = {"location": "~", "writable": true}' \
  --memory 12 --cpus 10 --disk 64 \
  --vm-type vz --rosetta=true

After creating the Lima machine we need to set DOCKER_HOST to the correct path:

export DOCKER_HOST=$(limactl list "docker" --format 'unix://{{.Dir}}/sock/docker.sock')

Troubleshooting Tilt

Tilt is stuck

Sometimes tilt looks stuck when it’s waiting on connections.

Ensure that docker/podman is up and running and your kubernetes cluster is reachable.

Errors running tilt-prepare

failed to get current context from the KubeConfig file

  • Ensure the cluster in the default context is reachable by running kubectl cluster-info
  • Switch to the right context with kubectl config use-context
  • Ensure the context is allowed, see allowed_contexts field

Cannot connect to the Docker daemon

  • Ensure the docker daemon is running ;) or for podman see Using Podman
  • If a DOCKER_HOST is specified:
    • check that the DOCKER_HOST has the correct prefix (usually unix://)
    • ensure docker/podman is listening on $DOCKER_HOST using fuser / lsof / netstat -u

Errors pulling/pushing to the registry

connection refused / denied / not found

Ensure the default_registry field is a valid registry where you can pull and push images.

server gave HTTP response to HTTPS client

By default all registries except localhost:5000 are accessed via HTTPS.

If you run a HTTP registry you may have to configure the registry in docker/podman.

For example, in podman a localhost:5001 registry configuration should be declared in /etc/containers/registries.conf.d with this content:

[[registry]]
location = "localhost:5001"
insecure = true

NB: on macOS this configuration should be done in the podman machine by running podman machine ssh <machine>.

Errors loading images in kind

You may try manually to load images in kind by running:

kind load docker-image --name=<kind_cluster> <image>

image: "..." not present locally

If you are running podman, you may have hit this bug: https://github.com/kubernetes-sigs/kind/issues/2760

The workaround is to create a docker symlink to your podman executable and try to load the images again.

Repository Layout

This page covers the repository structure and details about the directories in Cluster API.

cluster-api
└───.github
└───api
└───bootstrap
└───cmd
│   │   clusterctl
└───config
└───controllers
└───controlplane
└───dev
└───docs
└───errors
└───exp
└───feature
└───hack
└───internal
└───logos
└───scripts
└───test
└───util
└───version
└───webhooks
└───main.go
└───Makefile

GitHub

~/.github

Contains GitHub workflow configuration and templates for Pull requests, bug reports etc.

API

~/api

This folder is used to store types and their related resources present in CAPI core. It includes things like API types, spec/status definitions, condition types, simple webhook implementation, autogenerated, deepcopy and conversion files. Some examples of Cluster API types defined in this package include Cluster, ClusterClass, Machine, MachineSet, MachineDeployment and MachineHealthCheck.

API folder has subfolders for each supported API version.

Bootstrap

~/bootstrap

This folder contains Cluster API bootstrap provider Kubeadm (CABPK) which is a reference implementation of a Cluster API bootstrap provider. This folder contains the types and controllers responsible for generating a cloud-init or ignition configuration to turn a Machine into a Kubernetes Node. It is built and deployed as an independent provider alongside the Cluster API controller manager.

ControlPlane

~/controlplane

This folder contains a reference implementation of a Cluster API Control Plane provider - KubeadmControlPlane. This package contains the API types and controllers required to instantiate and manage a Kubernetes control plane. It is built and deployed as an independent provider alongside the Cluster API controller manager.

Cluster API Provider Docker

~/test/infrastructure/docker

This folder contains a reference implementation of an infrastructure provider for the Cluster API project using Docker. This provider is intended for development purposes only.

Clusterctl CLI

~/cmd/clusterctl

This folder contains Clusterctl, a CLI that can be used to deploy Cluster API and providers, generate cluster manifests, read the status of a cluster, and much more.

Manifest Generation

~/config

This is a Kubernetes manifest folder containing application resource configuration as kustomize YAML definitions. These are generated from other folders in the repo using make generate-manifests

Some of the subfolders are:

  • ~/config/certmanager - It contains manifests like self-signed issuer CR and certificate CR useful for cert manager.

  • ~/config/crd - It contains CRDs generated from types defined in api folder

  • ~/config/manager - It contains manifest for the deployment of core Cluster API manager.

  • ~/config/rbac - Manifests for RBAC resources generated from kubebuilder markers defined in controllers.

  • ~/config/webhook - Manifest for webhooks generated from the markers defined in the web hook implementations present in api folder.

Note: Additional config containing manifests can be found in the packages for KubeadmControlPlane, KubeadmBootstrap and Cluster API Provider Docker.

Controllers

~/internal

This folder contains resources which are not meant to be used directly by users of Cluster API e.g. the implementation of controllers is present in ~/internal/controllers directory so that we can make changes in controller implementation without breaking users. This allows us to keep our api surface smaller and move faster.

~/controllers

This folder contains reconciler types which provide access to CAPI controllers present in ~/internal/controllers directory to our users. These types can be used by users to run any of the Cluster API controllers in an external program.

Documentation

~/docs

This folder is a place for proposals, developer release guidelines and the Cluster API book.

~/logos

Cluster API related logos and artwork

Tools

~/hack

This folder has scripts used for building, testing and developer workflow.

~/scripts

This folder consists of CI scripts related to setup, build and e2e tests. These are mostly called by CI jobs.

~/dev

This folder has example configuration for integrating Cluster API development with tools like IDEs.

Util, Feature and Errors

~/util

This folder contains utilities which are used across multiple CAPI package. These utils are also widely imported in provider implementations and by other users of CAPI.

~/feature

This package provides feature gate management used in Cluster API as well as providers. This implementation of feature gates is shared across all providers.

~/errors

This is a place for defining errors returned by CAPI. Error types defined here can be used by users of CAPI and the providers.

Experimental features

~/exp

This folder contains experimental features of CAPI. Experimental features are unreliable until they are promoted to the main repository. Each experimental feature is supposed to be present in a subfolder of ~/exp folder e.g. ClusterResourceSet is present inside ~/exp/addons folder. Historically, machine pool resources are not present in a sub-directory. Migrating them to a subfolder like ~/exp/machinepools is still pending as it can potentially break existing users who are relying on existing folder structure.

CRDs for experimental features are present outside ~/exp directory in ~/config folder. Also, these CRDs are deployed in the cluster irrespective of the feature gate value. These features can be enabled and disabled using feature gates supplied to the core Cluster API controller.

Webhooks

The api folder contains webhooks consisting of validators and defaults for many of the types in Cluster API.

~/internal/webhooks

This directory contains the implementation of some of the Cluster API webhooks. The internal implementation means that the methods supplied by this package cannot be imported by external code bases.

~/webhooks

This folder exposes the custom webhooks present in ~internal/webhooks to the users of CAPI.

Note: Additional webhook implementations can be found in the API packages for KubeadmControlPlane, KubeadmBootstrap and Cluster API Provider Docker.

Controllers

This section of the book provides an overview about “core” controllers in Cluster API.

Cluster Controller

The Cluster controller is responsible for reconciling the Cluster resource.

In order to allow Cluster provisioning on different type of infrastructure, The Cluster resource references an InfraCluster object, e.g. AWSCluster, GCPCluster etc.

The InfraCluster resource contract defines a set of rules a provider is expected to comply with in order to allow the expected interactions with the Cluster controller.

Among those rules:

Similarly, in order to support different solutions for control plane management, The Cluster resource references an ControlPlane object, e.g. KubeadmControlPlane, EKSControlPlane etc.

Among those rules:

Considering all the info above, the Cluster controller’s main responsibilities are:

  • Setting an OwnerReference on the infrastructure object referenced in Cluster.spec.infrastructureRef.
  • Setting an OwnerReference on the control plane object referenced in Cluster.spec.controlPlaneRef.
  • Keeping the Cluster’s status in sync with the InfraCluster and ControlPlane’s status.
  • If no ControlPlane object is referenced, create a kubeconfig secret for workload clusters.
  • Cleanup of all owned objects so that nothing is dangling after deletion.

Kubeconfig Secrets

In order to create a kubeconfig secret, it is required to have a certificate authority (CA) for the cluster.

If you are using the kubeadm bootstrap provider you do not have to provide any Cluster API secrets. It will generate all necessary CAs for you.

As alternative users can provide custom CA as described in Using Custom Certificates.

Last option, is to entirely bypass Cluster API kubeconfig generation by providing a kubeconfig secret formatted as described below.

Secret nameField nameContent
<cluster-name>-kubeconfigvaluebase64 encoded kubeconfig

Notes:

  • Also renewal of the above certificate should be taken care out of band.
  • This option does not prevent from providing a cluster CA which is required also for other purposes.

ClusterTopology Controller

The ClusterTopology controller reconciles the managed topology of a Cluster, as shown in the following diagram.

Its main responsibilities are to:

  1. Reconcile Clusters based on templates defined in a ClusterClass and managed topology.
  2. Create, update, delete managed topologies by continuously reconciling the topology managed resources.
  3. Reconcile Cluster-specific customizations of a ClusterClass

The high level workflow of ClusterTopology reconciliation is shown below.

Additional information

ClusterResourceSet Controller

The ClusterResourceSet provides a mechanism for applying resources - e.g. pods, deployments, daemonsets, secrets, configMaps - to a cluster once it is created.

Its main responsibility is to automatically apply a set of resources to newly-created and existing Clusters. Resources will be applied only once.

Additional information

MachineDeployment

A MachineDeployment orchestrates deployments over a fleet of MachineSets.

Its main responsibilities are:

  • Adopting matching MachineSets not assigned to a MachineDeployment
  • Adopting matching MachineSets not assigned to a Cluster
  • Managing the Machine deployment process
    • Scaling up new MachineSets when changes are made
    • Scaling down old MachineSets when newer MachineSets replace them
  • Updating the status of MachineDeployment objects

In-place propagation

Changes to the following fields of the MachineDeployment are propagated in-place to the MachineSet and do not trigger a full rollout:

  • .annotations
  • .spec.deletion.order
  • .spec.template.metadata.labels
  • .spec.template.metadata.annotations
  • .spec.template.spec.minReadySeconds
  • .spec.template.spec.deletion.nodeDrainTimeout
  • .spec.template.spec.deletion.nodeDeletionTimeout
  • .spec.template.spec.deletion.nodeVolumeDetachTimeout

Note: In cases where changes to any of these fields are paired with rollout causing changes, the new values are propagated only to the new MachineSet.

MachineSet

A MachineSet is an abstraction over Machines.

Its main responsibilities are:

  • Adopting unowned Machines that aren’t assigned to a MachineSet
  • Adopting unmanaged Machines that aren’t assigned a Cluster
  • Booting a group of N machines
    • Monitoring the status of those booted machines

In-place propagation

Changes to the following fields of MachineSet are propagated in-place to the Machine without needing a full rollout:

  • .spec.template.metadata.labels
  • .spec.template.metadata.annotations
  • .spec.template.spec.nodeDrainTimeout
  • .spec.template.spec.nodeDeletionTimeout
  • .spec.template.spec.nodeVolumeDetachTimeout

Changes to the following fields of MachineSet are propagated in-place to the InfrastructureMachine and BootstrapConfig:

  • .spec.template.metadata.labels
  • .spec.template.metadata.annotations

Note: Changes to these fields will not be propagated to Machines that are marked for deletion (example: because of scale down).

Machine Controller

The Machine controller is responsible for reconciling the Machine resource.

In order to allow Machine provisioning on different type of infrastructure, The Machine resource references an InfraMachine object, e.g. AWSMachine, GCMachine etc.

The InfraMachine resource contract defines a set of rules a provider is expected to comply with in order to allow the expected interactions with the Machine controller.

Among those rules:

  • InfraMachine MUST report a provider ID for the Machine
  • InfraMachine SHOULD take into account the failure domain where machines should be placed in
  • InfraMachine SHOULD surface machine’s addresses to help operators when troubleshooting issues
  • InfraMachine MUST report when Machine’s infrastructure is fully provisioned
  • InfraMachine SHOULD report conditions
  • InfraMachine SHOULD report terminal failures

Similarly, in order to support different machine bootstrappers, The Machine resource references a BootstrapConfig object, e.g. KubeadmBootstrapConfig etc.

The BootstrapConfig resource contract defines a set of rules a provider is expected to comply with in order to allow the expected interactions with the Machine controller.

Among those rules:

Considering all the info above, the Machine controller’s main responsibilities are:

  • Setting an OwnerReference on the infrastructure object referenced in Machine.spec.infrastructureRef.
  • Setting an OwnerReference on the bootstrap object referenced in Machine.spec.bootstrap.configRef.
  • Keeping the Machine’s status in sync with the InfraMachine and BootstrapConfig’s status.
    • Finding Kubernetes nodes matching the expected providerID in the workload cluster.
    • Setting NodeRefs to be able to associate machines and Kubernetes nodes.
    • Monitor Kubernetes nodes and propagate labels to them.
  • Cleanup of all owned objects so that nothing is dangling after deletion.
    • Drain nodes and wait for volumes being detached by CSI plugins.

After the machine controller sets the OwnerReferences on the associated objects, it waits for the bootstrap and infrastructure objects referenced by the machine to have the Status.initialization.dataSecretCreated field set to true. When the infrastructure object reports Status.initialization.provisioned, the machine controller will attempt to read its Spec.ProviderID and copy it into Machine.Spec.ProviderID.

The machine controller uses the kubeconfig for the new workload cluster to watch new nodes coming up. When a node appears with Node.Spec.ProviderID matching Machine.Spec.ProviderID, the machine controller transitions the associated machine into the Running state.

The following schema goes through machine phases and interactions with InfraMachine and BootstrapConfig happening at each step.

MachinePool Controller

📖 For conceptual information about MachinePools, when to use them, and how they compare to MachineDeployments, see the MachinePool Guide.

The MachinePool controller’s main responsibilities are:

  • Setting an OwnerReference on each MachinePool object to:
    • The associated Cluster object.
    • The associated BootstrapConfig object.
    • The associated InfrastructureMachinePool object.
  • Copy data from BootstrapConfig.Status.DataSecretName to MachinePool.Spec.Template.Spec.Bootstrap.DataSecretName if MachinePool.Spec.Template.Spec.Bootstrap.DataSecretName is empty.
  • Setting NodeRefs on MachinePool instances to be able to associate them with Kubernetes nodes.
  • Deleting Nodes in the target cluster when the associated MachinePool instance is deleted.
  • Keeping the MachinePool’s Status object up to date with the InfrastructureMachinePool’s Status object.
  • Finding Kubernetes nodes matching the expected providerIDs in the workload cluster.

After the machine pool controller sets the OwnerReferences on the associated objects, it waits for the bootstrap and infrastructure objects referenced by the machine to have the Status.Ready field set to true. When the infrastructure object is ready, the machine pool controller will attempt to read its Spec.ProviderIDList and copy it into MachinePool.Spec.ProviderIDList.

The machine pool controller uses the kubeconfig for the new workload cluster to watch new nodes coming up. When a node appears with a Node.Spec.ProviderID in MachinePool.Spec.ProviderIDList, the machine pool controller increments the number of ready replicas. When all replicas are ready and the infrastructure ref is also Ready, the machine pool controller marks the machine pool as Running.

Contracts

Cluster API

Cluster associations are made via labels.

Expected labels

whatlabelvaluemeaning
MachinePoolcluster.x-k8s.io/cluster-name<cluster-name>Identify a machine pool as belonging to a cluster with the name <cluster-name>

Bootstrap provider

The BootstrapConfig object must have a status object.

The CRD name must have the format produced by sigs.k8s.io/cluster-api/util/contract.CalculateCRDName(Group, Kind).

To override the bootstrap provider, a user (or external system) can directly set the MachinePool.Spec.Bootstrap.DataSecretName field. This will mark the machine as ready for bootstrapping and no bootstrap data secret name will be copied from the BootstrapConfig object.

Required status fields

The status object must have several fields defined:

  • ready - a boolean field indicating the bootstrap config data is generated and ready for use.
  • dataSecretName - a string field referencing the name of the secret that stores the generated bootstrap data.

Optional status fields

The status object may define several fields that do not affect functionality if missing:

  • failureReason - a string field explaining why a fatal error has occurred, if possible.
  • failureMessage - a string field that holds the message contained by the error.

Note: once any of failureReason or failureMessage surface on the machine pool who is referencing the bootstrap config object, they cannot be restored anymore (it is considered a terminal error; the only way to recover is to delete and recreate the machine pool).

Example:

kind: MyBootstrapProviderConfig
apiVersion: bootstrap.cluster.x-k8s.io/v1alpha3
status:
    ready: true
    dataSecretName: "MyBootstrapSecret"

Infrastructure provider

The InfrastructureMachinePool object must have both spec and status objects.

The CRD name must have the format produced by sigs.k8s.io/cluster-api/util/contract.CalculateCRDName(Group, Kind).

Required spec fields

The spec object must have at least one field defined:

  • providerIDList - the list of cloud provider IDs identifying the instances.

Required status fields

The status object must have at least one field defined:

  • ready - a boolean field indicating if the infrastructure is ready to be used or not.

Optional status fields

The status object may define several fields that do not affect functionality if missing:

  • failureReason - is a string that explains why a fatal error has occurred, if possible.
  • failureMessage - is a string that holds the message contained by the error.
  • infrastructureMachineKind - the kind of the InfraMachines. This should be set if the InfrastructureMachinePool plans to support MachinePool Machines.

Note: once any of failureReason or failureMessage surface on the machine pool who is referencing the InfrastructureMachinePool object, they cannot be restored anymore (it is considered a terminal error; the only way to recover is to delete and recreate the machine pool).

Note: Infrastructure providers can support MachinePool Machines by having the InfraMachinePool set the infrastructureMachineKind to the kind of their InfrastructureMachines. The InfrastructureMachinePool will be responsible for creating InfrastructureMachines as the MachinePool is scaled up, and the MachinePool controller will create Machines for each InfrastructureMachine and set the ownerRef. The InfrastructureMachinePool will be responsible for deleting the Machines as the MachinePool is scaled down in order for the Machine deletion workflow to function properly. In addition, the InfrastructureMachines must also have the following labels set by the InfrastructureMachinePool: cluster.x-k8s.io/cluster-name and cluster.x-k8s.io/pool-name. The MachinePoolNameLabel must also be formatted with capilabels.MustFormatValue() so that it will not exceed character limits.

Example

kind: MyMachinePool
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
spec:
    providerIDList:
      - cloud:////my-cloud-provider-id-0
      - cloud:////my-cloud-provider-id-1
status:
    ready: true
    infrastructureMachineKind: InfrastructureMachine

Externally Managed Autoscaler

A provider may implement an InfrastructureMachinePool that is externally managed by an autoscaler. For example, if you are using a Managed Kubernetes provider, it may include its own autoscaler solution. To indicate this to Cluster API, you would decorate the MachinePool object with the following annotation:

"cluster.x-k8s.io/replicas-managed-by": ""

Cluster API treats the annotation as a “boolean”, meaning that the presence of the annotation is sufficient to indicate external replica count management, with one exception: if the value is "false", then that indicates to Cluster API that replica enforcement is nominal, and managed by Cluster API.

Providers may choose to implement the cluster.x-k8s.io/replicas-managed-by annotation with different values (e.g., external-autoscaler, or karpenter) that may inform different provider-specific behaviors, but those values will have no effect upon Cluster API.

The effect upon Cluster API of this annotation is that during autoscaling events (initiated externally, not by Cluster API), when more or fewer MachinePool replicas are observed compared to the Spec.Replicas configuration, it will update its Status.Phase property to the value of "Scaling".

Example:

kind: MyMachinePool
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3
spec:
    providerIDList:
      - cloud:////my-cloud-provider-id-0
      - cloud:////my-cloud-provider-id-1
      - cloud:////my-cloud-provider-id-2
    replicas: 1
status:
    ready: true
    phase: Scaling
    infrastructureMachineKind: InfrastructureMachine

It is the provider’s responsibility to update Cluster API’s Spec.Replicas property to the value observed in the underlying infra environment as it changes in response to external autoscaling behaviors. Once that is done, and the number of providerID items is equal to the Spec.Replicas property, the MachinePools’s Status.Phase property will be set to Running by Cluster API.

Secrets

The machine pool controller will use a secret in the following format:

secret namefield namecontent
<cluster-name>-kubeconfigvaluebase64 encoded kubeconfig that is authenticated with the workload cluster

MachineHealthCheck

A MachineHealthCheck is responsible for remediating unhealthy Machines.

Its main responsibilities are:

  • Checking the health of Nodes in the workload clusters against a list of unhealthy conditions
  • Remediating Machine’s for Nodes determined to be unhealthy

Logging

The Cluster API project is committed to improving the SRE/developer experience when troubleshooting issues, and logging plays an important part in this goal.

In Cluster API we strive to follow three principles while implementing logging:

  • Logs are for SRE & developers, not for end users! Whenever an end user is required to read logs to understand what is happening in the system, most probably there is an opportunity for improvement of other observability in our API, like e.g. conditions and events.
  • Navigating logs should be easy: We should make sure that SREs/Developers can easily drill down logs while investigating issues, e.g. by allowing to search all the log entries for a specific Machine object, eventually across different controllers/reconciler logs.
  • Cluster API developers MUST use logs! As Cluster API contributors you are not only the ones that implement logs, but also the first users of them. Use it! Provide feedback!

Upstream Alignment

Kubernetes defines a set of logging conventions, as well as tools and libraries for logging.

Cluster API should align to those guidelines and use those tools as much as possible.

Continuous improvement

The foundational items of Cluster API logging are:

  • Support for structured logging in all the Cluster API controllers (see log format).
  • Using contextual logging (see contextual logging).
  • Adding a minimal set of key/value pairs in the logger at the beginning of each reconcile loop, so all the subsequent log entries will inherit them (see key value pairs).

Starting from the above foundations, then the long tail of small improvements will consist of following activities:

  • Improve consistency of additional key/value pairs added by single log entries (see key value pairs).
  • Improve log messages (see log messages).
  • Improve consistency of log levels (see log levels).

Log Format

Controllers MUST provide support for structured logging and for the JSON output format; quoting the Kubernetes documentation, these are the key elements of this approach:

  • Separate a log message from its arguments.
  • Treat log arguments as key-value pairs.
  • Be easily parsable and queryable.

Cluster API uses all the tooling provided by the Kubernetes community to implement structured logging: Klog, a logr wrapper that works with controller runtime, and other utils for exposing flags in the controller’s main.go.

Ideally, in a future release of Cluster API we will make JSON output format the default format for all the Cluster API controllers (currently the default is still text format).

Contextual logging

Contextual logging is the practice of using a log stored in the context across the entire chain of calls of a reconcile action. One of the main advantages of this approach is that key value pairs which are added to the logger at the beginning of the chain are then inherited by all the subsequent log entries created down the chain.

Contextual logging is also embedded in controller runtime; In Cluster API we use contextual logging via controller runtime’s LoggerFrom(ctx) and LoggerInto(ctx, log) primitives and this ensures that:

  • The logger passed to each reconcile call has a unique reconcileID, so all the logs being written during a single reconcile call can be easily identified (note: controller runtime also adds other useful key value pairs by default).
  • The logger has a key value pair identifying the objects being reconciled,e.g. a Machine Deployment, so all the logs impacting this object can be easily identified.

Cluster API developer MUST ensure that:

  • The logger has a set of key value pairs identifying the hierarchy of objects the object being reconciled belongs to, e.g. the Cluster a Machine Deployment belongs to, so it will be possible to drill down logs for related Cluster API objects while investigating issues.

Key/Value Pairs

One of the key elements of structured logging is key-value pairs.

Having consistent key value pairs is a requirement for ensuring readability and for providing support for searching and correlating lines across logs.

A set of good practices for defining key value pairs is defined in the Kubernetes Guidelines, and one of the above practices is really important for Cluster API developers

  • Developers MUST use klog.KObj or klog.KRef functions when logging key value pairs for Kubernetes objects, thus ensuring a key value pair representing a Kubernetes object is formatted consistently in all the logs.
  • Developers MUST use consistent log keys:
    • kinds should be written in upper camel case, e.g. MachineDeployment, MachineSet
      • Note: we cannot use lower camel case for kinds consistently because there is no way to automatically calculate the correct log key for provider CRDs like AWSCluster
    • all other keys should use lower camel case, e.g. resourceVersion, oldReplicas to align to Kubernetes log conventions

Please note that, in order to ensure logs can be easily searched it is important to ensure consistency for the following key value pairs (in order of importance):

  • Key value pairs identifying the object being reconciled, e.g. a MachineDeployment.
  • Key value pairs identifying the hierarchy of objects being reconciled, e.g. the Cluster a MachineDeployment belongs to.
  • Key value pairs identifying side effects on other objects, e.g. while reconciling a MachineDeployment, the controller creates a MachineSet.
  • Other Key value pairs.

Notably, over time in CAPI we are also standardizing usage of other key value pairs to improve consistency when reading logs, e.g.

  • key reason MUST be used when adding details about WHY a change happened.
  • key diff MUST be used when documenting the diff in an object that either lead to a change, or that is resulting from a change.

Log Messages

  • A Message MUST always start with a capital letter.
  • Period at the end of a message MUST be omitted.
  • Always prefer logging before the action, so in case of errors there will be an immediate, visual correlation between the action log and the corresponding error log; While logging before the action, log verbs should use the -ing form.
  • Ideally log messages should surface a different level of detail according to the target log level (see log levels for more details).
  • If Kubernetes resource name is used in log messages, it MUST be used as is, For example Reconciling DockerMachineTemplate
  • If an API field name is used in log messages, the entire path MUST be used and field names MUST capitalized like in the API (not as in the golang type). For example Waiting for spec.providerID to be set
  • If a log message is about a controlled or a referenced object, e.g. Machine controller performing an action on MachineSet, the message MUST contain the Kind of the controlled/referenced object and its namespace/name, for example Created MachineSet default/foo-bar
    • The controlled/referenced object MUST also be added as a key value pair (see guidelines above)

Log Levels

Kubernetes provides a set of recommendations for log levels; as a small integration on the above guidelines we would like to add:

  • Logs at the lower levels of verbosity (<=3) are meant to document “what happened” by describing how an object status is being changed by controller/reconcilers across subsequent reconciliations; as a rule of thumb, it is reasonable to assume that a person reading those logs has a deep knowledge of how the system works, but it should not be required for those persons to have knowledge of the codebase.
  • Logs at higher levels of verbosity (>=4) are meant to document “how it happened”, providing insight on thorny parts of the code; a person reading those logs usually has deep knowledge of the codebase.
  • Don’t use verbosity higher than 5.

We are using log level 2 as a default verbosity for all core Cluster API controllers as recommended by the Kubernetes guidelines.

Trade-offs

When developing logs there are operational trade-offs to take into account, e.g. verbosity vs space allocation, user readability vs machine readability, maintainability of the logs across the code base.

A reasonable approach for logging is to keep things simple and implement more log verbosity selectively and only on thorny parts of code. Over time, based on feedback from SRE/developers, more logs can be added to shed light where necessary.

Developing and testing logs

Our Tilt setup offers a batteries-included log suite based on alloy, Loki and Grafana.

We are working to continuously improving this experience, allowing Cluster API developers to use logs and improve them as part of their development process.

For the best experience exploring the logs using Tilt:

  1. Set --logging-format=json.
  2. Set a high log verbosity, e.g. v=5.
  3. Enable alloy, Loki, and Grafana under deploy_observability.

A minimal example of a tilt-settings.yaml file that deploys a ready-to-use logging suite looks like:

deploy_observability:
  - alloy
  - loki
  - grafana
enable_providers:
  - docker
  - kubeadm-bootstrap
  - kubeadm-control-plane
extra_args:
  core:
    - "--logging-format=json"
    - "--v=5"
  docker:
    - "--v=5"
    - "--logging-format=json"
  kubeadm-bootstrap:
    - "--v=5"
    - "--logging-format=json"
  kubeadm-control-plane:
    - "--v=5"
    - "--logging-format=json"

The above options can be combined with other settings from our Tilt setup. Once Tilt is up and running with these settings users will be able to browse logs using the Grafana Explore UI.

This will normally be available on localhost:3000. To explore logs from Loki, open the Explore interface for the DataSource ‘Loki’. This link should work as a shortcut with the default Tilt settings.

Example queries

In the Log browser the following queries can be used to browse logs by controller, and by specific Cluster API objects. For example:

{app="capi-controller-manager"} | json 

Will return logs from the capi-controller-manager which are parsed in json. Passing the query through the json parser allows filtering by key-value pairs that are part of nested json objects. For example .cluster.name becomes cluster_name.

{app="capi-controller-manager"} | json | Cluster_name="my-cluster"

Will return logs from the capi-controller-manager that are associated with the Cluster my-cluster.

{app="capi-controller-manager"} | json | Cluster_name="my-cluster" | v <= 2

Will return logs from the capi-controller-manager that are associated with the Cluster my-cluster with log level <= 2.

{app="capi-controller-manager"} | json | Cluster_name="my-cluster" reconcileID="6f6ad971-bdb6-4fa3-b803-xxxxxxxxxxxx"

Will return logs from the capi-controller-manager, associated with the Cluster my-cluster and the Reconcile ID 6f6ad971-bdb6-4fa3-b803-xxxxxxxxxxxx. Each reconcile loop will have a unique Reconcile ID.

{app="capi-controller-manager"} | json | Cluster_name="my-cluster" reconcileID="6f6ad971-bdb6-4fa3-b803-ef81c5c8f9d0" controller="cluster" | line_format "{{ .msg }}"

Will return logs from the capi-controller-manager, associated with the Cluster my-cluster and the Reconcile ID 6f6ad971-bdb6-4fa3-b803-xxxxxxxxxxxx it further selects only those logs which come from the Cluster controller. It will then format the logs so only the message is displayed.

{app=~"capd-controller-manager|capi-kubeadm-bootstrap-controller-manager|capi-kubeadm-control-plane-controller-manager"} | json | Cluster_name="my-cluster" Machine_name="my-cluster-linux-worker-1" | line_format "{{.controller}} {{.msg}}"

Will return the logs from four CAPI providers - the Core provider, Kubeadm Control Plane provider, Kubeadm Bootstrap provider and the Docker infrastructure provider. It filters by the cluster name and the machine name and then formats the log lines to show just the source controller and the message. This allows us to correlate logs and see actions taken by each of these four providers related to the machine my-cluster-linux-worker-1.

For more information on formatting and filtering logs using Grafana and Loki see:

What about providers

Cluster API providers are developed by independent teams, and each team is free to define their own processes and conventions.

However, given that SRE/developers looking at logs are often required to look both at logs from core CAPI and providers, we encourage providers to adopt and contribute to the guidelines defined in this document.

It is also worth noting that the foundational elements of the approach described in this document are easy to achieve by leveraging default Kubernetes tooling for logging.

Testing Cluster API

This document presents testing guidelines and conventions for Cluster API.

IMPORTANT: improving and maintaining this document is a collaborative effort, so we are encouraging constructive feedback and suggestions.

Unit tests

Unit tests focus on individual pieces of logic - a single func - and don’t require any additional services to execute. They should be fast and great for getting the first signal on the current implementation, but unit tests have the risk of allowing integration bugs to slip through.

In Cluster API most of the unit tests are developed using go test, gomega and the fakeclient; however using fakeclient is not suitable for all the use cases due to some limitations in how it is implemented. In some cases contributors will be required to use envtest. See the quick reference below for more details.

Mocking external APIs

In some cases when writing tests it is required to mock external API, e.g. etcd client API or the AWS SDK API.

This problem is usually well scoped in core Cluster API, and in most cases it is already solved by using fake implementations of the target API to be injected during tests.

Instead, mocking is much more relevant for infrastructure providers; in order to address the issue some providers can use simulators reproducing the behaviour of a real infrastructure providers (e.g CAPV); if this is not possible, a viable solution is to use mocks (e.g CAPA).

Generic providers

When writing tests core Cluster API contributors should ensure that the code works with any providers, and thus it is required to not use any specific provider implementation. Instead, the so-called generic providers e.g. “GenericInfrastructureCluster” should be used because they implement the plain Cluster API contract. This prevents tests from relying on assumptions that may not hold true in all cases.

Please note that in the long term we would like to improve the implementation of generic providers, centralizing the existing set of utilities scattered across the codebase, but while details of this work will be defined do not hesitate to reach out to reviewers and maintainers for guidance.

Integration tests

Integration tests are focused on testing the behavior of an entire controller or the interactions between two or more Cluster API controllers.

In Cluster API, integration tests are based on envtest and one or more controllers configured to run against the test cluster.

With this approach it is possible to interact with Cluster API almost like in a real environment, by creating/updating Kubernetes objects and waiting for the controllers to take action. See the quick reference below for more details.

Also in case of integration tests, considerations about mocking external APIs and usage of generic providers apply.

Fuzzing tests

Fuzzing tests automatically inject randomly generated inputs, often invalid or with unexpected values, into functions to discover vulnerabilities.

Two different types of fuzzing are currently being used on the Cluster API repository:

Fuzz testing for API conversion

Cluster API uses Kubernetes’ conversion-gen to automate the generation of functions to convert our API objects between versions. These conversion functions are tested using the FuzzTestFunc util in our conversion utils package. For more information about these conversions see the API conversion code walkthrough in our video walkthrough series.

OSS-Fuzz continuous fuzzing

Parts of the CAPI code base are continuously fuzzed through the OSS-Fuzz project. Issues found in these fuzzing tests are reported to Cluster API maintainers and surfaced in issues on the repo for resolution. To read more about the integration of Cluster API with OSS Fuzz see the 2022 Cluster API Fuzzing Report.

Test maintainability

Tests are an integral part of the project codebase.

Cluster API maintainers and all the contributors should be committed to help in ensuring that tests are easily maintainable, easily readable, well documented and consistent across the code base.

In light of continuing improving our practice around this ambitious goal, we are starting to introduce a shared set of:

  • Builders (sigs.k8s.io/cluster-api/util/test/builder), allowing to create test objects in a simple and consistent way.
  • Matchers (sigs.k8s.io/controller-runtime/pkg/envtest/komega), improving how we write test assertions.

Each contribution in growing this set of utilities or their adoption across the codebase is more than welcome!

Another consideration that can help in improving test maintainability is the idea of testing “by layers”; this idea could apply whenever we are testing “higher-level” functions that internally uses one or more “lower-level” functions; in order to avoid writing/maintaining redundant tests, whenever possible contributors should take care of testing only the logic that is implemented in the “higher-level” function, delegating the test function called internally to a “lower-level” set of unit tests.

A similar concern could be raised also in the case whenever there is overlap between unit tests and integration tests, but in this case the distinctive value of the two layers of testing is determined by how test are designed:

  • unit test are focused on code structure: func(input) = output, including edge case values, asserting error conditions etc.
  • integration test are user story driven: as a user, I want express some desired state using API objects, wait for the reconcilers to take action, check the new system state.

Running unit and integration tests

Run make test to execute all unit and integration tests.

Integration tests use the envtest test framework. The tests need to know the location of the executables called by the framework. The make test target installs these executables, and passes this location to the tests as an environment variable.

Test execution via IDE

Your IDE needs to know the location of the executables called by the framework, so that it can pass the location to the tests as an environment variable.

VSCode

The following files are an example configuration that integrates VSCode with the envtest framework. To use it, simply create the files in the .vscode directory in the repository, and restart VSCode.

settings.json
{
    "go.testEnvFile": "${workspaceFolder}/.vscode/test.env"
}
tasks.json
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "type": "shell",
            "label": "sigs.k8s.io/cluster-api: Prepare vscode to run envtest-based tests",
            "detail": "Install envtest and configure the vscode-go test environment.",
            "group": {
                "kind": "test",
                "isDefault": true
            },
            "command": [
                "echo $(make setup-envtest) > ${workspaceFolder}/.vscode/test.env",
            ],
            "presentation": {
                "echo": true,
                "reveal": "silent",
                "focus": true,
                "panel": "shared",
                "showReuseMessage": true,
                "clear": false
            },
            "runOptions": {
                "runOn": "folderOpen",
                "instanceLimit": 1,
            },
            "promptOnClose": true,
        }
    ]
}

The configuration works as follows: Whenever the project is opened in VSCode, a VSCode task runs that installs the executables, and writes the location to a file. A setting tells vscode-go to initialize the environment from this file.

End-to-end tests

The end-to-end tests are meant to verify the proper functioning of a Cluster API management cluster in an environment that resemble a real production environment.

The following guidelines should be followed when developing E2E tests:

See e2e development for more information on developing e2e tests for CAPI and external providers.

Running the end-to-end tests locally

Usually the e2e tests are executed by Prow, either pre-submit (on PRs) or periodically on certain branches (e.g. the default branch). Those jobs are defined in the kubernetes/test-infra repository in config/jobs/kubernetes-sigs/cluster-api. For development and debugging those tests can also be executed locally.

Prerequisites

make docker-build-e2e will build the images for all providers that will be needed for the e2e tests.

Test execution via ci-e2e.sh

To run a test locally via the command line, you should look at the Prow Job configuration for the test you want to run and then execute the same commands locally. For example to run pull-cluster-api-e2e-main just execute:

GINKGO_LABEL_FILTER="PR-Blocking" ./hack/scripts/ci/ci-e2e.sh

Test execution via make test-e2e

make test-e2e will run e2e tests by using whatever provider images already exist on disk. After running make docker-build-e2e at least once, make test-e2e can be used for a faster test run, if there are no provider code changes. If the provider code is changed, run make docker-build-e2e to update the images.

Test execution via IDE

It’s also possible to run the tests via an IDE which makes it easier to debug the test code by stepping through the code.

First, we have to make sure all prerequisites are fulfilled, i.e. all required images have been built (this also includes kind images). This can be done by executing the ./scripts/ci-e2e.sh script.

# Notes:
# * You can cancel the script as soon as it starts the actual test execution via `make test-e2e`.
# * If you want to run other tests (e.g. upgrade tests), make sure all required env variables are set (see the Prow Job config).
GINKGO_LABEL_FILTER="PR-Blocking" ./hack/scripts/ci/ci-e2e.sh

Now, the tests can be run in an IDE. The following describes how this can be done in IntelliJ IDEA and VS Code. It should work roughly the same way in all other IDEs. We assume the cluster-api repository has been checked out into /home/user/code/src/sigs.k8s.io/cluster-api.

IntelliJ

Create a new run configuration and fill in:

  • Test framework: gotest
  • Test kind: Package
  • Package path: sigs.k8s.io/cluster-api/test/e2e
  • Pattern: ^\QTestE2E\E$
  • Working directory: /home/user/code/src/sigs.k8s.io/cluster-api/test/e2e
  • Environment: ARTIFACTS=/home/user/code/src/sigs.k8s.io/cluster-api/_artifacts
  • Program arguments: -e2e.config=/home/user/code/src/sigs.k8s.io/cluster-api/test/e2e/config/docker.yaml -ginkgo.focus="\[PR-Blocking\]"

VS Code

Add the launch.json file in the .vscode folder in your repo:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Run e2e test",
            "type": "go",
            "request": "launch",
            "mode": "test",
            "program": "${workspaceRoot}/test/e2e/e2e_suite_test.go",
            "env": {
                "ARTIFACTS":"${workspaceRoot}/_artifacts"
            },
            "args": [
                "-e2e.config=${workspaceRoot}/test/e2e/config/docker.yaml",
                "-ginkgo.focus=\\[PR-Blocking\\]",
                "-ginkgo.v=true"
            ],
            "trace": "verbose",
            "buildFlags": "-tags 'e2e'",
            "showGlobalVariables": true
        }
    ]
}

Execute the run configuration with Debug.

Running specific tests

To run a subset of tests the GINKGO_LABEL_FILTER env variable can be set. See Ginkgo Spec Labels v2 for complete syntax documentation.

Each of these can be used to match tests, for example:

  • PR-Blocking => Sanity tests run before each PR merge
  • K8s-Upgrade => Tests which verify k8s component version upgrades on workload clusters
  • Conformance => Tests which run the k8s conformance suite on workload clusters
  • ClusterClass => Tests which use a ClusterClass to create a workload cluster
  • /When testing KCP.*/ => Tests which start with When testing KCP

For example: GINKGO_LABEL_FILTER="PR-Blocking" make test-e2e can be used to run the sanity E2E tests GINKGO_LABEL_FILTER="!K8s-Upgrade" make test-e2e can be used to skip the upgrade E2E tests

Further customization

The following env variables can be set to customize the test execution:

  • GINKGO_LABEL_FILTER to set ginkgo label filter (default empty - all tests)
  • GINKGO_NODES to set the number of ginkgo parallel nodes (default to 1)
  • E2E_CONF_FILE to set the e2e test config file (default to ${REPO_ROOT}/test/e2e/config/docker.yaml)
  • ARTIFACTS to set the folder where test artifact will be stored (default to ${REPO_ROOT}/_artifacts)
  • SKIP_RESOURCE_CLEANUP to skip resource cleanup at the end of the test (useful for problem investigation) (default to false)
  • USE_EXISTING_CLUSTER to use an existing management cluster instead of creating a new one for each test run (default to false)
  • GINKGO_NOCOLOR to turn off the ginkgo colored output (default to false)

Furthermore, it’s possible to overwrite all env variables specified in variables in test/e2e/config/docker.yaml.

Troubleshooting end-to-end tests

Analyzing logs

Logs of e2e tests can be analyzed with our development environment by pushing logs to Loki and then analyzing them via Grafana.

  1. Start the development environment as described in Developing Cluster API with Tilt.
    • Make sure to deploy Loki and Grafana via deploy_observability.
    • If you only want to see imported logs, don’t deploy alloy (via deploy_observability).
    • If you want to drop all logs from Loki, just delete the Loki Pod in the observability namespace.
  2. You can then import logs via the Import Logs button on the top right of the Loki resource page. Just click on the downwards arrow, enter either a ProwJob URL, a GCS path or a local folder and click on Import Logs. This will retrieve the logs and push them to Loki. Alternatively, the logs can be imported via:
    go run ./hack/tools/internal/log-push --log-path=<log-path>
    
    Examples for log paths:
    • ProwJob URL: https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/6189/pull-cluster-api-e2e-main/1496954690603061248
    • GCS path: gs://kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/6189/pull-cluster-api-e2e-main/1496954690603061248
    • Local folder: ./_artifacts
  3. Now the logs are available:
    • via Grafana
    • via Loki logcli
      logcli query '{app="capi-controller-manager"}' --timezone=UTC --from="2022-02-22T10:00:00Z"
      

As alternative to loki, JSON logs can be visualized with a human readable timestamp using jq:

  1. Browse the ProwJob artifacts and download the wanted logfile.

  2. Use jq to query the logs:

    cat manager.log \
      | grep -v "TLS handshake error" \
      | jq -r '(.ts / 1000 | todateiso8601) + " " + (. | tostring)'
    

    The (. | tostring) part could also be customized to only output parts of the JSON logline. E.g.:

    • (.err) to only output the error message part.
    • (.msg) to only output the message part.
    • (.controller + " " + .msg) to output the controller name and message part.

Known Issues

Building images on SELinux

Cluster API repositories use Moby Buildkit to speed up image builds. BuildKit does not currently work on SELinux.

Use sudo setenforce 0 to make SELinux permissive when running e2e tests.

Quick reference

envtest

envtest is a testing environment that is provided by the controller-runtime project. This environment spins up a local instance of etcd and the kube-apiserver. This allows tests to be executed in an environment very similar to a real environment.

Additionally, in Cluster API there is a set of utilities under [internal/envtest] that helps developers in setting up a envtest ready for Cluster API testing, and more specifically:

  • With the required CRDs already pre-configured.
  • With all the Cluster API webhook pre-configured, so there are enforced guarantees about the semantic accuracy of the test objects you are going to create.

This is an example of how to create an instance of envtest that can be shared across all the tests in a package; by convention, this code should be in a file named suite_test.go:

var (
	env *envtest.Environment
	ctx = ctrl.SetupSignalHandler()
)

func TestMain(m *testing.M) {
	// Setup envtest
	...

	// Run tests
	os.Exit(envtest.Run(ctx, envtest.RunInput{
		M:        m,
		SetupEnv: func(e *envtest.Environment) { env = e },
		SetupIndexes:     setupIndexes,
		SetupReconcilers: setupReconcilers,
	}))
}

Most notably, envtest provides not only a real API server to use during testing, but it offers the opportunity to configure one or more controllers to run against the test cluster, as well as creating informers index.

func TestMain(m *testing.M) {
	// Setup envtest
	setupReconcilers := func(ctx context.Context, mgr ctrl.Manager) {
		if err := (&MyReconciler{
			Client:  mgr.GetClient(),
			Log:     log.NullLogger{},
		}).SetupWithManager(mgr, controller.Options{MaxConcurrentReconciles: 1}); err != nil {
			panic(fmt.Sprintf("Failed to start the MyReconciler: %v", err))
		}
	}

	setupIndexes := func(ctx context.Context, mgr ctrl.Manager) {
		if err := index.AddDefaultIndexes(ctx, mgr); err != nil {
		panic(fmt.Sprintf("unable to setup index: %v", err))
	}
    
    // Run tests
	...
}

By combining pre-configured validation and mutating webhooks and reconcilers/indexes it is possible to use envtest for developing Cluster API integration tests that can mimic how the system behaves in real Cluster.

Please note that, because envtest uses a real kube-apiserver that is shared across many test cases, the developer should take care in ensuring each test runs in isolation from the others, by:

  • Creating objects in separated namespaces.
  • Avoiding object name conflict.

Developers should also be aware of the fact that the informers cache used to access the envtest depends on actual etcd watches/API calls for updates, and thus it could happen that after creating or deleting objects the cache takes a few milliseconds to get updated. This can lead to test flakes, and thus it always recommended to use patterns like create and wait or delete and wait; Cluster API env test provides a set of utils for this scope.

However, developers should be aware that in some ways, the test control plane will behave differently from “real” clusters, and that might have an impact on how you write tests.

One common example is garbage collection; because there are no controllers monitoring built-in resources, objects do not get deleted, even if an OwnerReference is set up; as a consequence, usually test implements code for cleaning up created objects.

This is an example of a test implementing those recommendations:

func TestAFunc(t *testing.T) {
	g := NewWithT(t)
	// Generate namespace with a random name starting with ns1; such namespace
	// will host test objects in isolation from other tests.
	ns1, err := env.CreateNamespace(ctx, "ns1")
	g.Expect(err).ToNot(HaveOccurred())
	defer func() {
		// Cleanup the test namespace
		g.Expect(env.DeleteNamespace(ctx, ns1)).To(Succeed())
	}()

	obj := &clusterv1.Cluster{
		ObjectMeta: metav1.ObjectMeta{
			Name:      "test",
			Namespace: ns1.Name, // Place test objects in the test namespace
		},
	}

	// Actual test code...
}

In case of object used in many test case within the same test, it is possible to leverage on Kubernetes GenerateName; For objects that are shared across sub-tests, ensure they are scoped within the test namespace and deep copied to avoid cross-test changes that may occur to the object.

func TestAFunc(t *testing.T) {
	g := NewWithT(t)
	// Generate namespace with a random name starting with ns1; such namespace
	// will host test objects in isolation from other tests.
	ns1, err := env.CreateNamespace(ctx, "ns1")
	g.Expect(err).ToNot(HaveOccurred())
	defer func() {
		// Cleanup the test namespace
		g.Expect(env.DeleteNamespace(ctx, ns1)).To(Succeed())
	}()

	obj := &clusterv1.Cluster{
		ObjectMeta: metav1.ObjectMeta{
			GenerateName: "test-",  // Instead of assigning a name, use GenerateName
			Namespace:    ns1.Name, // Place test objects in the test namespace
		},
	}

	t.Run("test case 1", func(t *testing.T) {
		g := NewWithT(t)
		// Deep copy the object in each test case, so we prevent side effects in case the object changes.
		// Additionally, thanks to GenerateName, the objects gets a new name for each test case.
		obj := obj.DeepCopy()

	    // Actual test case code...
	}
	t.Run("test case 2", func(t *testing.T) {
		g := NewWithT(t)
		obj := obj.DeepCopy()

	    // Actual test case code...
	}
	// More test cases.
}

fakeclient

fakeclient is another utility that is provided by the controller-runtime project. While this utility is really fast and simple to use because it does not require to spin-up an instance of etcd and kube-apiserver, the fakeclient comes with a set of limitations that could hamper the validity of a test, most notably:

  • it does not properly handle a set of fields which are common in the Kubernetes API objects (and Cluster API objects as well) like e.g. creationTimestamp, resourceVersion, generation, uid
  • fakeclient operations do not trigger defaulting or validation webhooks, so there are no enforced guarantees about the semantic accuracy of the test objects.
  • the fakeclient does not use a cache based on informers/API calls/etcd watches, so the test written in this way can’t help in surfacing race conditions related to how those components behave in real cluster.
  • there is no support for cache index/operations using cache indexes.

Accordingly, using fakeclient is not suitable for all the use cases, so in some cases contributors will be required to use envtest instead. In case of doubts about which one to use when writing tests, don’t hesitate to ask for guidance from project maintainers.

ginkgo

Ginkgo is a Go testing framework built to help you efficiently write expressive and comprehensive tests using Behavior-Driven Development (“BDD”) style.

While Ginkgo is widely used in the Kubernetes ecosystem, Cluster API maintainers found the lack of integration with the most used golang IDE somehow limiting, mostly because:

  • it makes interactive debugging of tests more difficult, since you can’t just run the test using the debugger directly
  • it makes it more difficult to only run a subset of tests, since you can’t just run or debug individual tests using an IDE, but you now need to run the tests using make or the ginkgo command line and override the focus to select individual tests

In Cluster API you MUST use ginkgo only for E2E tests, where it is required to leverage the support for running specs in parallel; in any case, developers MUST NOT use the table driven extension DSL (DescribeTable, Entry commands) which is considered unintuitive.

gomega

Gomega is a matcher/assertion library. It is usually paired with the Ginkgo BDD test framework, but it can be used with other test frameworks too.

More specifically, in order to use Gomega with go test you should

func TestFarmHasCow(t *testing.T) {
    g := NewWithT(t)
    g.Expect(f.HasCow()).To(BeTrue(), "Farm should have cow")
}

In Cluster API all the test MUST use Gomega assertions.

go test

go test testing provides support for automated testing of Go packages.

In Cluster API Unit and integration test MUST use go test.

Developing E2E tests

E2E tests are meant to verify the proper functioning of a Cluster API management cluster in an environment that resembles a real production environment.

The following guidelines should be followed when developing E2E tests:

The Cluster API test framework provides you a set of helper methods for getting your test in place quickly. The test E2E package provides examples of how this can be achieved and reusable test specs for the most common Cluster API use cases.

Prerequisites

Each E2E test requires a set of artifacts to be available:

  • Binaries & Docker images for Kubernetes, CNI, CRI & CSI
  • Manifests & Docker images for the Cluster API core components
  • Manifests & Docker images for the Cluster API infrastructure provider; in most cases machine images are also required (AMI, OVA etc.)
  • Credentials for the target infrastructure provider
  • Other support tools (e.g. kustomize, gsutil etc.)

The Cluster API test framework provides support for building and retrieving the manifest files for Cluster API core components and for the Cluster API infrastructure provider (see Setup).

For the remaining tasks you can find examples of how this can be implemented e.g. in CAPA E2E tests and CAPG E2E tests.

Setup

In order to run E2E tests it is required to create a Kubernetes cluster with a complete set of Cluster API providers installed. Setting up those elements is usually implemented in a BeforeSuite function, and it consists of two steps:

  • Defining an E2E config file
  • Creating the management cluster and installing providers

Defining an E2E config file

The E2E config file provides a convenient and flexible way to define common tasks for setting up a management cluster.

Using the config file it is possible to:

  • Define the list of providers to be installed in the management cluster. Most notably, for each provider it is possible to define:
    • One or more versions of the providers manifest (built from the sources, or pulled from a remote location).
    • A list of additional files to be added to the provider repository, to be used e.g. to provide cluster-templates.yaml files.
  • Define the list of variables to be used when doing clusterctl init or clusterctl generate cluster.
  • Define a list of intervals to be used in the test specs for defining timeouts for the wait and Eventually methods.
  • Define the list of images to be loaded in the management cluster (this is specific to management clusters based on kind).

An example E2E config file can be found here.

Creating the management cluster and installing providers

In order to run Cluster API E2E tests, you need a Kubernetes cluster. The NewKindClusterProvider gives you a type that can be used to create a local kind cluster and pre-load images into it. Existing clusters can be used if available.

Once you have a Kubernetes cluster, the InitManagementClusterAndWatchControllerLogs method provides a convenient way for installing providers.

This method:

  • Runs clusterctl init using the above local repository.
  • Waits for the providers controllers to be running.
  • Creates log watchers for all the providers

Writing test specs

A typical test spec is a sequence of:

  • Creating a namespace to host in isolation all the test objects.
  • Creating objects in the management cluster, wait for the corresponding infrastructure to be provisioned.
  • Exec operations like e.g. changing the Kubernetes version or clusterctl move, wait for the action to complete.
  • Delete objects in the management cluster, wait for the corresponding infrastructure to be terminated.

Creating Namespaces

The CreateNamespaceAndWatchEvents method provides a convenient way to create a namespace and setup watches for capturing namespaces events.

Creating objects

There are two possible approaches for creating objects in the management cluster:

  • Create object by object: create the Cluster object, then AwsCluster, Machines, AwsMachines etc.
  • Apply a cluster-templates.yaml file thus creating all the objects this file contains.

The first approach leverages the controller-runtime Client and gives you full control, but it comes with some drawbacks as well, because this method does not directly reflect real user workflows, and most importantly, the resulting tests are not as reusable with other infrastructure providers. (See writing portable tests).

We recommend using the ClusterTemplate method and the Apply method for creating objects in the cluster. This methods mimics the recommended user workflows, and it is based on cluster-templates.yaml files that can be provided via the E2E config file, and thus easily swappable when changing the target infrastructure provider.

After creating objects in the cluster, use the existing methods in the Cluster API test framework to discover which object were created in the cluster so your code can adapt to different cluster-templates.yaml files.

Once you have object references, the framework includes methods for waiting for the corresponding infrastructure to be provisioned, e.g. WaitForClusterToProvision, WaitForKubeadmControlPlaneMachinesToExist.

Exec operations

You can use Cluster API test framework methods to modify Cluster API objects, as a last option, use the controller-runtime Client.

The Cluster API test framework also includes methods for executing clusterctl operations, like e.g. the ClusterTemplate method, the ClusterctlMove method etc.. In order to improve observability, each clusterctl operation creates a detailed log.

After using clusterctl operations, you can rely on the Get and on the Wait methods defined in the Cluster API test framework to check if the operation completed successfully.

Naming the test spec

You can categorize the test with a custom label that can be used to filter a category of E2E tests to be run. Currently, the cluster-api codebase has these labels which are used to run a focused subset of tests.

Tear down

After a test completes/fails, it is required to:

  • Collect all the logs for the Cluster API controllers
  • Dump all the relevant Cluster API/Kubernetes objects
  • Cleanup all the infrastructure resources created during the test

Those tasks are usually implemented in the AfterSuite, and again the Cluster API test framework provides you useful methods for those tasks.

Please note that despite the fact that test specs are expected to delete objects in the management cluster and wait for the corresponding infrastructure to be terminated, it can happen that the test spec fails before starting object deletion or that objects deletion itself fails.

As a consequence, when scheduling/running a test suite, it is required to ensure all the generated resources are cleaned up. In Kubernetes, this is implemented by the boskos project.

Writing portable E2E tests

A portable E2E test is a test that can run with different infrastructure providers by simply changing the test configuration file.

The following recommendations should be followed to write portable E2E tests:

Cluster API conformance tests

As of today there is no a well-defined suite of E2E tests that can be used as a baseline for Cluster API conformance.

However, creating such a suite is something that can provide a huge value for the long term success of the project.

The test E2E package provides examples of how this can be achieved by implementing a set of reusable test specs for the most common Cluster API use cases.

Tuning Controller

When tuning controllers, both for scalability, performance or for reducing their footprint, following suggestions can make your work simpler and much more effective.

  • You need the right tools for the job: without logs, metrics, traces and profiles tuning is hardly possible. Also, given that tuning is an iterative work, having a setup that allows you to experiment and improve quickly could be a huge boost in your work.
  • Only optimize if there is clear evidence of an issue. This evidence is key for you to measure success and it can provide the necessary context for developing, validating, reviewing and approving the fix. On the contrary, optimizing without evidence can be not worth the effort or even make things worse.

Tooling for controller tuning in CAPI

Cluster API provides a full stack of tools for tuning its own controllers as well as controllers for all providers if developed using controller runtime. As a bonus, most of this tooling can be used with any other controller runtime based controllers.

With tilt, you can easily deploy a full observability stack with Grafana, Loki, alloy, Prometheus, kube-state-metrics, Parca and Tempo.

All tools are preconfigured, and most notably kube-state-metrics already collects CAPI metrics and Grafana is configured with a set of dashboards that we used in previous rounds of CAPI tuning. Overall, the CAPI dev environment offers a considerable amount of expertise, free to use and to improve for the entire community. We highly recommend to invest time in looking into those tools, learn and provide feedback.

Additionally, Cluster API includes CAPD with support for both Docker and in-memory backend. Both allow you to quickly create development clusters with the limited resources available on a developer workstation, however:

  • CAPD with docker backend gives you a fully functional cluster running in containers; scalability and performance are limited by the size of your machine.
  • CAPD with the inmemory backend gives you a fake cluster running in memory; you can scale more easily but the clusters do not support any Kubernetes feature other than what is strictly required for CAPI, CABPK and KCP to work.

Analyzing metrics, traces and profiles

Tuning controllers and finding performance bottlenecks can vary depending on the issues you are dealing with, so please consider following guidelines as collection of suggestions, not as a strict process to follow.

Before looking at data, it usually helps to have a clear understanding of:

  • What are the requirements and constraints of the use case you are looking at, e.g.:

    • Use a management cluster with X cpu, Y memory
    • Create X cluster, with concurrency Y
    • Each cluster must have X CP nodes, Y workers
  • What does it mean for you if the system is working well, e.g.:

    • All machines should be provisioned in less than X minutes
    • All controllers should reconcile in less than Y ms
    • All controllers should allocate less than Z Gb memory

Once you know the scenario you are looking at and what you are tuning for, you can finally look at data, but given that the amount of data available could be overwhelming, you probably need a strategy to navigate all the available metrics, traces, etc. .

Among the many possible strategies, one usually very effective is to look at the KPIs you are aiming for, and then, if the current system performance is not good enough, start looking at other metrics trying to identify the biggest factor that is impacting the results. Usually by removing a single, performance bottleneck the behaviour of the system changes in a significant way; after that you can decide if the performance is now good enough or you need another round of tuning.

Let’s try to make this more clear by using an example, machine provisioning time is degrading when running CAPI at scale (machine provisioning time can be seen in the Cluster API Performance dashboard).

When running at scale, one of the first things to take care of is the client-go rate limiting, which is a mechanism built inside client-go that prevents a Kubernetes client from being accidentally too aggressive to the API server. However this mechanism can also limit the performance of a controller when it actually requires to make many calls to the API server.

So one of the first data point to look at is the rate limiting metrics; given that upstream CR doesn’t have metric for that we can only look for logs containing “client-side throttling” via Loki (Note: this link should be open while tilt is running).

If rate limiting is not your issue, then you can look at the controller’s work queue. In an healthy system reconcile events are continuously queued, processed and removed from the queue. If the system is slowing down at scale, it could be that some controllers are struggling to keep up with the events being added in the queue, thus leading to slowness in reconciling the desired state.

So then the next step after looking at rate limiting metrics, is to look at the “work queue depth” panel in the Controller-Runtime dashboard.

Assuming that one controller is struggling with its own work queue, the next step is to look at why this is happening. It might be that the average duration of each reconcile is high for some reason. This can be checked in the “Reconcile Duration by Controller” panel in the Controller-Runtime dashboard.

If this is the case, then it is time to start looking at traces, looking for the longer spans in average (or total). Unfortunately traces are not yet implemented in Cluster API, so alternative approaches must be used, like looking at condition transitions or at logs to figure out what the slowest operations are.

And so on.

Please note that there are also cases where CAPI controllers are just idle waiting for something else to happen on the infrastructure side. In this case investigating bottlenecks requires access to a different set of metrics. Similar considerations apply if the issue is slowness of the API server or of the network.

Runtime tuning options

Cluster API offers a set of options that can be set on the controller deployment at runtime, without the need of changing the CAPI code.

  • Client-go rate limiting; by increasing the client-go rate limits we allow a controller to make more API server calls per second (--kube-api-qps) or to have a bigger burst to handle spikes (--kube-api-burst). Please note that these settings must be increased carefully, because being too aggressive on the API server might lead to different kind of problems.

  • Controller concurrency (e.g. via --kubeadmcontrolplane-concurrency); by increasing the number of concurrent reconcile loops for each controller it is possible to help the system in keeping the work queue clean, and thus reconciling to the desired state faster. Also in this case, trade-offs should be considered, because by increasing concurrency not only the controller footprint is going to increase, but also the number of API server calls is likely going to increase (see previous point).

  • Resync period (--sync-period); this setting defines the interval after which reconcile events for all current objects will be triggered. Historically this value in Cluster API is much lower than the default in controller runtime (10m vs. 10h). This has some advantages, because e.g. it is a fallback in case controller struggle to pick up events from external infrastructure. But it also has impact at scale when a controller gets a sudden spike of events at every resync period. This can be mitigated by increasing the resync period.

As a general rule, you should tune those parameters only if you have evidence supported by data that you are hitting a bottleneck of the system. Similarly, another sample of data should be analyzed after tuning the parameter to check the effects of the change.

Improving code for better performance

Performance is usually a moving target, because things can change due the evolution of the use cases, of the user needs, of the codebase and of all the dependencies Cluster API relies on, starting from Kubernetes and the infrastructure we are using.

That means that no matter of the huge effort that has been put into making CAPI performant, more work will be required to preserve the current state or to improve performance.

Also in this case, most of the considerations really depend on the issue your are dealing with, but some suggestions are worth to be considered for the majority of the use cases.

The best optimization that can be done is to avoid any work at all for controllers. E.g instead of re-queuing every few seconds when a controller is waiting for something to happen, which leads to the controller to do some work to check if something changed in the system, it is always better to watch for events, so the controller is going to do the work only once when it is actually required. When implementing watches, non-relevant changes should be filtered out whenever possible.

Same considerations apply also for the actual reconcile implementation, if you can avoid API server calls or expensive computations under certain conditions, it is always better and faster than any optimization you can do to that code.

However, when work from the controllers is required, it is necessary to make sure that expensive operations are limited as much as possible.

A common example for an expensive operation is the generation of private keys for certificates, or the creation of a Kubernetes client, but the most frequent expensive operations that each controller does are API server calls.

Luckily controller runtime does a great job in helping to address this by providing a delegating client per default that reads from a cache that is maintained by client-go shared informers. This is a huge boost of performance (microseconds vs. seconds) that everyone gets at the cost of some memory allocation and the need of considering stale reads when writing code.

As a rule of thumbs it is always better to deal with stale reads/memory consumption than disabling caching. Even if stale reads could be a concern under certain circumstances, e.g when reading an object right after it has been created.

Also, please be aware that some API server read operations are not cached by default, e.g. reads for unstructured objects, but you can enable caching for those operations when creating the controller runtime client.

But at some point some API server calls must be done, either uncached reads or write operations.

When looking at unchached reads, some operation are more expensive than others, e.g. a list call with a label selector degrades according to the number of object in the same namespace and the number of the items in the result set.

Whenever possible, you should avoid uncached list calls, or make sure they happen only once in a reconcile loop and possibly only under specific circumstances.

When looking at write operations, you can rely on some best practices developed in CAPI. Like for example use a defer call to patch the object with the patch helper to make a single write at the end of the reconcile loop (and only if there are actual changes).

In order to complete this overview, there is another category of operations that can slow down CAPI controllers, which are network calls to other services like e.g. the infrastructure provider.

Some general recommendations apply also in those cases, like e.g re-using long lived clients instead of continuously re-creating new ones, leverage on async callback and watches whenever possible vs. continuously checking for status, etc. .

Support running multiple instances of the same provider

Up until v1alpha3, the need of supporting multiple credentials was addressed by running multiple instances of the same provider, each one with its own set of credentials while watching different namespaces.

However, running multiple instances of the same provider proved to be complicated for several reasons:

  • Complexity in packaging providers: CustomResourceDefinitions (CRD) are global resources, these may have a reference to a service that can be used to convert between CRD versions (conversion webhooks). Only one of these services should be running at any given time, this requirement led us to previously split the webhooks code to a different deployment and namespace.
  • Complexity in deploying providers, due to the requirement to ensure consistency of the management cluster, e.g. controllers watching the same namespaces.
  • The introduction of the concept of management groups in clusterctl, with impacts on the user experience/documentation.
  • Complexity in managing co-existence of different versions of the same provider while there could be only one version of CRDs and webhooks. Please note that this constraint generates a risk, because some version of the provider de-facto were forced to run with CRDs and webhooks deployed from a different version.

Nevertheless, we want to make it possible for users to choose to deploy multiple instances of the same providers, in case the above limitations/extra complexity are acceptable for them.

In order to make it possible for users to deploy multiple instances of the Cluster API controller following flags are provided:

  • Providers MUST support the --namespace flag in their controllers.
  • Providers MUST support the --watch-filter flag in their controllers.

Developing Cluster API providers

This section of the book is about developing Cluster API providers.

Getting Started

This is a getting started guide to demonstrate how to develop a new Cluster API provider.

The guide focus on setting up a new project for implementing the provider and creating:

  • API types and corresponding CustomResourceDefinition (CRD).
  • Webhooks, responsible to default and validate above resources.
  • Controllers, responsible of reconciling above resources.

We will use kubebuilder to create an example infrastructure provider; for more information on kubebuilder and CRDs in general we highly recommend reading the Kubebuilder Book. Much of the information here was adapted directly from it.

Also worth to notice that suggestion in this guide are only intended to help first time provider implementers to get started, but this is not an exhaustive guide of all the intricacies of developing Kubernetes controllers. Please refer to the Kubebuilder Book and to Cluster API videos and tutorials for more information.

If you already know how kubebuilder works, if you know how to write Kubernetes controllers, or if you are planning to use something different than kubebuilder to develop your own Cluster API provider, you can skip this guide entirely.

Prerequisites

tl;dr

# Install kubectl
brew install kubernetes-cli

# Install kustomize
brew install kustomize

# Install Kubebuilder
brew install kubebuilder
# Install kubectl
KUBECTL_VERSION=$(curl -sfL https://dl.k8s.io/release/stable.txt)
curl -fLO https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl

# Install kustomize
curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh"  | bash
chmod +x ./kustomize && sudo mv ./kustomize /usr/local/bin/kustomize

# Install Kubebuilder
curl -sLo kubebuilder https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH)
chmod +x ./kubebuilder && sudo mv ./kubebuilder /usr/local/bin/kubebuilder

Repository Naming

The naming convention for new Cluster API provider repositories is generally of the form cluster-api-provider-${env}, where ${env} is a, possibly short, name for the environment in question. For example cluster-api-provider-gcp is an implementation for the Google Cloud Platform, and cluster-api-provider-aws is one for Amazon Web Services. Note that an environment may refer to a cloud, bare metal, virtual machines, or any other infrastructure hosting Kubernetes. Finally, a single environment may include more than one variant. So for example, cluster-api-provider-aws may include both an implementation based on EC2 as well as one based on their hosted EKS solution.

For the purposes of this guide we will create an infrastructure provider for a service named mailgun. Therefore the name of the repository will be cluster-api-provider-mailgun.

Please note that other naming conventions/best practices applies, e.g. for API types (continue to this guide to get more info).

A note on Acronyms

Because these names end up being so long, developers of Cluster API frequently refer to providers by acronyms. Cluster API itself becomes CAPI, pronounced “Cappy.” cluster-api-provider-aws is CAPA, pronounced “KappA.” cluster-api-provider-gcp is CAPG, pronounced “Cap Gee,” and so on.

Initialize a repository and the provider’s API types

Create a repository

mkdir -p src/sigs.k8s.io/cluster-api-provider-mailgun
cd src/sigs.k8s.io/cluster-api-provider-mailgun
git init

You’ll then need to set up go modules

go mod init github.com/liztio/cluster-api-provider-mailgun
go: creating new go.mod: module github.com/liztio/cluster-api-provider-mailgun

Generate controller scaffolding

kubebuilder init --domain cluster.x-k8s.io

kubebuilder init will create the basic repository layout, including a simple containerized manager. It will also initialize the external go libraries that will be required to build your project.

A few considerations about --domain cluster.x-k8s.io:

Every Kubernetes resource has a Group, Version and Kind that uniquely identifies it.

The resource Group is similar to package in a language; it disambiguates different APIs that may happen to have identically named Kinds. Groups often contain a domain name, such as k8s.io. The domain for Cluster API resources is cluster.x-k8s.io, and infrastructure providers generally use infrastructure.cluster.x-k8s.io.

Commit your changes so far:

git add .
git commit -m "Generate scaffolding."

Generate API types for Clusters and Machines

A Cluster API infrastructure provider usually has two main API types, one modeling the infrastructure to get the Cluster working (e.g. LoadBalancer), and one modeling the infrastructure for one machine/VM.

When creating an API, the resource Kind should be the name of the objects we’ll be creating and modifying. In this case it’s MailgunMachine and MailgunCluster.

The resource Version defines the stability of the API and its backward compatibility guarantees. Examples include v1alpha1, v1beta1, v1, etc. and are governed by the Kubernetes API Deprecation Policy 1. Your provider should expect to abide by the same policies.

Also, please note that the API version of Cluster API and the version of your provider do not need to be in sync. Instead, prefer choosing a version that matches the stability of the provider API and its backward compatibility guarantees.

Once Kind and Version, are defined, you can run.

kubebuilder create api --group infrastructure --version v1alpha1 --kind MailgunCluster
kubebuilder create api --group infrastructure --version v1alpha1 --kind MailgunMachine

Here you will be asked if you want to generate resources and corresponding reconciler in the controller. You’ll want both of them (you are going to need them later in the guide):

Create Resource under pkg/apis [y/n]?
y
Create Controller under pkg/controller [y/n]?
y

And regenerate the CRDs:

make manifests

Commit your changes

git add .
git commit -m "Generate Cluster and Machine resources."

Apply further customizations

The cluster API CRDs should be further customized, please refer to provider contracts.


  1. https://kubernetes.io/docs/reference/using-api/deprecation-policy/

Implementing your API types

The API generated by Kubebuilder is just a shell. Your actual API will likely have more fields defined on it.

Kubernetes has a lot of conventions and requirements around API design. The Kubebuilder docs have some helpful hints on how to design your types.

Let’s take a look at what was generated for us:

// MailgunClusterSpec defines the desired state of MailgunCluster
type MailgunClusterSpec struct {
	// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
	// Important: Run "make" to regenerate code after modifying this file
}

// MailgunClusterStatus defines the observed state of MailgunCluster
type MailgunClusterStatus struct {
	// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
	// Important: Run "make" to regenerate code after modifying this file
}

Our API is based on Mailgun, so you’re going to have some email based fields:

type Priority string

const (
	// PriorityUrgent means do this right away
	PriorityUrgent = Priority("Urgent")

	// PriorityUrgent means do this immediately
	PriorityExtremelyUrgent = Priority("ExtremelyUrgent")

	// PriorityBusinessCritical means you absolutely need to do this now
	PriorityBusinessCritical = Priority("BusinessCritical")
)

// MailgunClusterSpec defines the desired state of MailgunCluster
type MailgunClusterSpec struct {
  // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
	// Important: Run "make" to regenerate code after modifying this file
	
	// Priority is how quickly you need this cluster
	Priority Priority `json:"priority"`
	// Request is where you ask extra nicely
	Request string `json:"request"`
	// Requester is the email of the person sending the request
	Requester string `json:"requester"`
}

// MailgunClusterStatus defines the observed state of MailgunCluster
type MailgunClusterStatus struct {
	// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
	// Important: Run "make" to regenerate code after modifying this file

	// MessageID is set to the message ID from Mailgun when our message has been sent
	MessageID *string `json:"response"`
}

As the comments request, run make manager manifests to regenerate some of the generated data files afterwards.

git add .
git commit -m "Added cluster types"

Registering APIs in the scheme

To enable clients to encode and decode your API, your types must be able to be registered within a scheme.

By default, Kubebuilder will provide you with a scheme builder (likely in api/v1alpha1/groupversion_info.go) like:

import (
	"k8s.io/apimachinery/pkg/runtime/schema"
	"sigs.k8s.io/controller-runtime/pkg/scheme"
)

var (
	// GroupVersion is group version used to register these objects.
	GroupVersion = schema.GroupVersion{Group: "infrastructure.cluster.x-k8s.io", Version: "v1alpha1"}

	// SchemeBuilder is used to add go types to the GroupVersionKind scheme.
	SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}

	// AddToScheme adds the types in this group-version to the given scheme.
	AddToScheme = SchemeBuilder.AddToScheme
)

and scheme registration (likely in api/v1alpha1/*_types.go) that looks like:

func init() {
	SchemeBuilder.Register(&MailgunCluster{}, &MailgunClusterList{})
}

This pattern introduces a dependency on controller-runtime to your API types, which is discouraged for API packages as it makes it more difficult for consumers of your API to import your API types. In general, you should minimise the imports within the API folder of your package to allow your API types to be imported cleanly into other projects.

To mitigate this, use the following schemebuilder pattern:

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
)

var (
	// GroupVersion is group version used to register these objects.
	GroupVersion = schema.GroupVersion{Group: "infrastructure.cluster.x-k8s.io", Version: "v1alpha1"}

	// SchemeBuilder is used to add go types to the GroupVersionKind scheme.
	schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)

	// AddToScheme adds the types in this group-version to the given scheme.
	AddToScheme = schemeBuilder.AddToScheme

	objectTypes = []runtime.Object{}
)

func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(GroupVersion, objectTypes...)
	metav1.AddToGroupVersion(scheme, GroupVersion)
	return nil
}

and register types as below:

func init() {
	objectTypes = append(objectTypes, &MailgunCluster{}, &MailgunClusterList{})
}

This pattern reduces the number of dependencies being introduced into the API package within your project.

Webhooks

The webhooks in our mailgun provider are offered through tools in Controller Runtime and Controller Tools, which are the building blocks Kubebuilder relies on.

At high level, in order to add webhooks to the mailgun provider it is required to implement interfaces defined in Controller Runtime, while generation of manifests for the corresponding MutatingWebhookConfiguration and ValidatingWebhookConfiguration can be done using Controller Tools via Makefile targets generated by Kubebuilder.

Before taking a look at this in detail, let’s get an overview of the types of web hooks supported by Controller Runtime.

Validating webhooks

Validating webhooks are an implementation of a Kubernetes validating webhook.

A validating webhook allows developers to test whether values supplied by users are valid. e.g. the Cluster webhook ensures the Infrastructure reference supplied at the Cluster’s .spec.infrastructureRef is in the same namespace as the Cluster itself and rejects the object creation or update if not.

Defaulting webhooks

Defaulting webhooks are an implementation of a Kubernetes mutating webhook.

A defaulting webhook allows developers to set default values for a type before they are placed in etcd, the Kubernetes data store. e.g. the Cluster webhook will set the Infrastructure reference namespace to equal the Cluster namespace if .spec.infrastructureRef.namespace is empty.

Conversion webhooks

Conversion webhooks are also an implementation of a Kubernetes mutating webhook.

Conversion webhooks are what allow Cluster API to work with multiple API version of the same API type. It does this by converting the incoming version to a Hub version which is used internally by the controllers. To read more about conversion see the Kubebuilder documentation

For a walkthrough on implementing conversion webhooks see the video in the Developer Guide

Implementing webhooks with Controller Runtime, Controller Tools and Kubebuilder

The Kubebuilder book provide detailed description about how to implement interfaces defined in Controller Runtime for each of the above webhook types.

Webhook manifests instead are generated by Controller Tools via Makefile targets implemented by Kubebuilder.

In order to do so, it is required to add tags to API types in the codebase. Below, for example, are the tags on the the Cluster webhook:


// +kubebuilder:webhook:verbs=create;update;delete,path=/validate-cluster-x-k8s-io-v1beta1-cluster,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=cluster.x-k8s.io,resources=clusters,versions=v1beta1,name=validation.cluster.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1
// +kubebuilder:webhook:verbs=create;update,path=/mutate-cluster-x-k8s-io-v1beta1-cluster,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=cluster.x-k8s.io,resources=clusters,versions=v1beta1,name=default.cluster.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1

// Cluster implements a validating and defaulting webhook for Cluster.
type Cluster struct {
    Client client.Reader
}

A detailed guide on the purpose of each of these tags is here.

Controllers and Reconciliation

Right now, you can create objects with your API types, but those objects don’t make any impact on your mailgun infrastructure. Let’s fix that by implementing controllers and reconciliation for your API objects.

From the kubebuilder book:

Controllers are the core of Kubernetes, and of any operator.

It’s a controller’s job to ensure that, for any given object, the actual state of the world (both the cluster state, and potentially external state like running containers for Kubelet or loadbalancers for a cloud provider) matches the desired state in the object. Each controller focuses on one root Kind, but may interact with other Kinds.

We call this process reconciling.

Also in this case, controllers and reconcilers generated by Kubebuilder are just a shell. It is up to you to fill it with the actual implementation.

Let’s see the Code

Kubebuilder has created our first controller in controllers/mailguncluster_controller.go. Let’s take a look at what got generated:

// MailgunClusterReconciler reconciles a MailgunCluster object
type MailgunClusterReconciler struct {
	client.Client
	Scheme *runtime.Scheme
}

// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=mailgunclusters,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=mailgunclusters/status,verbs=get;update;patch

func (r *MailgunClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
	_ = logf.FromContext(ctx)

	// TODO(user): your logic here

	return ctrl.Result{}, nil
}

RBAC Roles

Before looking at (add) your logic here, lets focus for a moment on the markers before the Reconcile func.

The // +kubebuilder... lines tell kubebuilder to generate RBAC roles so the manager we’re writing can access its own managed resources. These should already exist in controllers/mailguncluster_controller.go:

// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=mailgunclusters,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=mailgunclusters/status,verbs=get;update;patch

We also need to add rules that will let it retrieve (but not modify) Cluster objects. So we’ll add another annotation for that, right below the other lines:

// +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=clusters;clusters/status,verbs=get;list;watch

If any resource sets another resource as the owner with blockOwnerDeletion set, additional RBAC to update finalizers on the owner resource is required:

// +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=clusters/finalizers,verbs=update

Make sure to add this/these annotation to MailgunClusterReconciler.

Also, for our MailgunMachineReconciler, access to Cluster API Machine object is needed, so you must add this annotation in controllers/mailgunmachine_controller.go:

// +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=machines;machines/status,verbs=get;list;watch

Regenerate the RBAC roles after you are done:

make manifests

Reconciliation

Let’s focus on the MailgunClusterReconciler struct first.

First, a word of warning: no guarantees are made about parallel access, both on one machine or multiple machines. That means you should not store any important state in memory: if you need it, write it into a Kubernetes object and store it.

We’re going to be sending mail, so let’s add a few extra fields:

// MailgunClusterReconciler reconciles a MailgunCluster object
type MailgunClusterReconciler struct {
	client.Client
	Scheme *runtime.Scheme
	Mailgun   mailgun.Mailgun
	Recipient string
}

Now it’s time for our Reconcile function. Reconcile is only passed a name, not an object, so let’s retrieve ours.

Here’s a naive example:

func (r *MailgunClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
	ctx := context.Background()
	_ = ctrl.LoggerFrom(ctx)

	var cluster infrav1.MailgunCluster
	if err := r.Get(ctx, req.NamespacedName, &cluster); err != nil {
		return ctrl.Result{}, err
	}

	return ctrl.Result{}, nil
}

By returning an error, you request that our controller will get Reconcile() called again. That may not always be what you want - what if the object’s been deleted? So let’s check that:

    var mailgunCluster infrav1.MailgunCluster
    if err := r.Get(ctx, req.NamespacedName, &mailgunCluster); err != nil {
        // 	import apierrors "k8s.io/apimachinery/pkg/api/errors"
        if apierrors.IsNotFound(err) {
            return ctrl.Result{}, nil
        }
        return ctrl.Result{}, err
    }

Now that we have our own cluster object (MailGunCluster) that represents all the infrastructure provider specific details for our cluster, we also need to retrieve the upstream Cluster object that is defined by Cluster API itself. Luckily, cluster API provides a helper for us.

First, you’ll need to import the cluster-api package into our project if you haven’t done so yet:

# In your Mailgun repository's root directory
go get sigs.k8s.io/cluster-api
go mod tidy

Now we can add in a call to the GetOwnerCluster function to retrieve the cluster object:

    // import sigs.k8s.io/cluster-api/util
    cluster, err := util.GetOwnerCluster(ctx, r.Client, mailgunCluster.ObjectMeta)
    if err != nil {
        return ctrl.Result{}, err
    }

If our cluster was just created, the Cluster API controller may not have set the ownership reference on our object yet, so we’ll have to return here and wait to do more with our cluster object until then. We can leave a log message noting that we’re waiting for the main Cluster API controller to set the ownership reference. Here’s what our Reconcile() function looks like now:

func (r *MailgunClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    // We change the _ to `log` since we're going to log something now
    log = ctrl.LoggerFrom(ctx)

    var mailgunCluster infrav1.MailgunCluster
    if err := r.Get(ctx, req.NamespacedName, &mailgunCluster); err != nil {
        // import apierrors "k8s.io/apimachinery/pkg/api/errors"
        if apierrors.IsNotFound(err) {
            return ctrl.Result{}, nil
        }
        return ctrl.Result{}, err
    }

    // import sigs.k8s.io/cluster-api/util
    cluster, err := util.GetOwnerCluster(ctx, r.Client, mailgunCluster.ObjectMeta)
    if err != nil {
        return ctrl.Result{}, err
    }

	if cluster == nil {
		log.Info("Waiting for Cluster Controller to set OwnerRef on MailGunCluster")
		return ctrl.Result{}, nil
	}

The fun part

More Documentation: The Kubebuilder Book has some excellent documentation on many things, including how to write good controllers!

Now that you have all the objects you care about, it’s time to do something with them! This is where your provider really comes into its own. In our case, let’s try sending some mail:

subject := fmt.Sprintf("[%s] New Cluster %s requested", mailgunCluster.Spec.Priority, cluster.Name)
body := fmt.Sprintf("Hello! One cluster please.\n\n%s\n", mailgunCluster.Spec.Request)

msg := r.mailgun.NewMessage(mailgunCluster.Spec.Requester, subject, body, r.Recipient)
_, _, err = r.Mailgun.Send(msg)
if err != nil {
    return ctrl.Result{}, err
}

Idempotency

But wait, this isn’t quite right. Reconcile() gets called periodically for updates, and any time any updates are made. That would mean we’re potentially sending an email every few minutes! This is an important thing about controllers: they need to be idempotent. This means a controller must be able to repeat actions on the same inputs without changing the effect of those actions.

So in our case, we’ll store the result of sending a message, and then check to see if we’ve sent one before.

    if mailgunCluster.Status.MessageID != nil {
        // We already sent a message, so skip reconciliation
        return ctrl.Result{}, nil
    }
    
    subject := fmt.Sprintf("[%s] New Cluster %s requested", mailgunCluster.Spec.Priority, cluster.Name)
    body := fmt.Sprintf("Hello! One cluster please.\n\n%s\n", mailgunCluster.Spec.Request)
    
    msg := r.Mailgun.NewMessage(mailgunCluster.Spec.Requester, subject, body, r.Recipient)
    _, msgID, err := r.Mailgun.Send(msg)
    if err != nil {
        return ctrl.Result{}, err
    }
    
    // patch from sigs.k8s.io/cluster-api/util/patch
    helper, err := patch.NewHelper(&mailgunCluster, r.Client)
    if err != nil {
        return ctrl.Result{}, err
    }
    mailgunCluster.Status.MessageID = &msgID
    if err := helper.Patch(ctx, &mailgunCluster); err != nil {
        return ctrl.Result{}, errors.Wrapf(err, "couldn't patch cluster %q", mailgunCluster.Name)
    }
    
    return ctrl.Result{}, nil

A note about the status

Usually, the Status field should only be values that can be computed from existing state. Things like whether a machine is running can be retrieved from an API, and cluster status can be queried by a healthcheck. The message ID is ephemeral, so it should properly go in the Spec part of the object. Anything that can’t be recreated, either with some sort of deterministic generation method or by querying/observing actual state, needs to be in Spec. This is to support proper disaster recovery of resources. If you have a backup of your cluster and you want to restore it, Kubernetes doesn’t let you restore both spec & status together.

We use the MessageID as a Status here to illustrate how one might issue status updates in a real application.

Update main.go

Since you added fields to the MailgunClusterReconciler, it is now required to update main.go to set those fields when our reconciler is initialized.

Right now, it probably looks like this:

    if err = (&controllers.MailgunClusterReconciler{
        Client: mgr.GetClient(),
        Scheme: mgr.GetScheme(),
    }).SetupWithManager(mgr); err != nil {
        setupLog.Error(err, "Unable to create controller", "controller", "MailgunCluster")
        os.Exit(1)
    }

Let’s add our configuration. We’re going to use environment variables for this:

    domain := os.Getenv("MAILGUN_DOMAIN")
    if domain == "" {
        setupLog.Info("missing required env MAILGUN_DOMAIN")
        os.Exit(1)
    }
    
    apiKey := os.Getenv("MAILGUN_API_KEY")
    if apiKey == "" {
        setupLog.Info("missing required env MAILGUN_API_KEY")
        os.Exit(1)
    }
    
    recipient := os.Getenv("MAIL_RECIPIENT")
    if recipient == "" {
        setupLog.Info("missing required env MAIL_RECIPIENT")
        os.Exit(1)
    }
    
    mg := mailgun.NewMailgun(domain, apiKey)
    
    if err = (&controllers.MailgunClusterReconciler{
        Client:    mgr.GetClient(),
        Scheme: mgr.GetScheme(),
        Mailgun:   mg,
        Recipient: recipient,
    }).SetupWithManager(mgr); err != nil {
        setupLog.Error(err, "Unable to create controller", "controller", "MailgunCluster")
        os.Exit(1)
    }

If you have some other state, you’ll want to initialize it here!

Configure the controller manifest

kubebuilder generates most of the YAML you’ll need to deploy your controller into Kubernetes by using a Deployment. You just need to modify it to add the MAILGUN_DOMAIN, MAILGUN_API_KEY and MAIL_RECIPIENT environment variables introduced in the previous steps.

First, let’s add our environment variables as a patch to the manager yaml.

config/manager/manager_config.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: controller-manager
  namespace: system
spec:
  template:
    spec:
      containers:
      - name: manager
        env:
        - name: MAILGUN_API_KEY
          valueFrom:
            secretKeyRef:
              name: mailgun-secret
              key: api_key
        - name: MAILGUN_DOMAIN
          valueFrom:
            configMapKeyRef:
              name: mailgun-config
              key: mailgun_domain
        - name: MAIL_RECIPIENT
          valueFrom:
            configMapKeyRef:
              name: mailgun-config
              key: mail_recipient

And then, we have to add that patch to config/kustomization.yaml:

patches:
- path: manager_image_patch.yaml
- path: manager_config.yaml

As you might have noticed, we are reading variable values from a ConfigMap and a Secret.

You now have to add those to the manifest, but how to inject configuration in production? The convention many Cluster-API projects use is environment variables.

config/manager/credentials.yaml

---
apiVersion: v1
kind: Secret
metadata:
  name: mailgun-config
  namespace: system
type: Opaque
stringData:
  api_key: ${MAILGUN_API_KEY}
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: mailgun-config
  namespace: system
data:
  mailgun_domain: ${MAILGUN_DOMAIN}
  mail_recipient: ${MAILGUN_RECIPIENT}

And add this to config/manager/kustomization.yaml

resources:
- manager.yaml
- credentials.yaml

You can now (hopefully) generate your yaml!

kustomize build config/default

EnvSubst

A tool like direnv can be used to help manage environment variables.

kustomize does not handle replacing those ${VARIABLES} with actual values. For that, we use envsubst.

You’ll need to have those environment variables (MAILGUN_API_KEY, MAILGUN_DOMAIN, MAILGUN_RECIPIENT) in your environment when you generate the final yaml file.

Change Makefile to include the call to envsubst:

-	$(KUSTOMIZE) build config/default | kubectl apply -f -
+	$(KUSTOMIZE) build config/default | envsubst | kubectl apply -f -

To generate the manifests, call envsubst in line, like so:

kustomize build config/default | envsubst

Or to build and deploy the CRDs and manifests directly:

make install deploy

Building, Running, Testing

Docker Image Name

The IMG variable is used to build the Docker image and push it to a registry. The default value is controller:latest, which is a local image. You can change it to a remote image if you want to push it to a registry.

make docker-push IMG=ghcr.io/your-org/your-repo:dev

Deployment

Cluster API

Before you can deploy the infrastructure controller, you’ll need to deploy Cluster API itself to the management cluster.

Follow the quick start guide up to and including the step of creating the management cluster. We will proceed presuming you created a cluster with kind and initalized cluster-api with clusterctl init.

Check the status of the manager to make sure it’s running properly:

kubectl describe -n capi-system pod | grep -A 5 Conditions
Conditions:
  Type                        Status
  PodReadyToStartContainers   True
  Initialized                 True
  Ready                       True
  ContainersReady             True

Your provider

In this guide, we are building an infrastructure provider. We must tell cluster-api and its developer tooling which type of provider it is. Edit config/default/kustomization.yaml and add the following common label. The prefix infrastructure- is used to detect the provider type.

labels:
- includeSelectors: true
  pairs:
    cluster.x-k8s.io/provider: infrastructure-mailgun

If you’re using kind for your management cluster, you can use the following command to build and push your image to the kind cluster’s local registry. We need to use the IMG variable to override the default controller:latest image name with a specific version like controller:0.1 to avoid having kubernetes try to pull the latest version of controller from docker hub.

cd cluster-api-provider-mailgun

# Build the Docker image
make docker-build IMG=controller:dev

# Load the Docker image into the kind cluster
kind load docker-image controller:dev

Now you can apply your provider as well:

cd cluster-api-provider-mailgun

# Install CRD and controller to current kubectl context
make install deploy IMG=controller:dev

kubectl describe -n cluster-api-provider-mailgun-system pod | grep -A 5 Conditions
Conditions:
  Type                        Status
  PodReadyToStartContainers   True 
  Initialized                 True 
  Ready                       True 
  ContainersReady             True 

Tiltfile

Cluster API development requires a lot of iteration, and the “build, tag, push, update deployment” workflow can be very tedious. Tilt makes this process much simpler by watching for updates, then automatically building and deploying them.

See Developing Cluster API with Tilt on all details how to develop both Cluster API and your provider at the same time. In short, you need to perform these steps for a basic Tilt-based development environment:

  • Create file tilt-provider.yaml in your provider directory:
name: mailgun
config:
  image: controller:latest # change to remote image name if desired
  label: CAPM
  live_reload_deps: ["main.go", "go.mod", "go.sum", "api", "controllers", "pkg"]
  go_main: cmd/main.go # kubebuilder puts main.go under the cmd directory
  • Create file tilt-settings.yaml in the cluster-api directory:
default_registry: "" # change if you use a remote image registry
provider_repos:
  # This refers to your provider directory and loads settings
  # from `tilt-provider.yaml`
  - ../cluster-api-provider-mailgun
enable_providers:
  - mailgun
  • Bring tilt up by using the make tilt-up command in the cluster-api directory. This will ensure tilt is set up correctly to use a local registry for your image. You may need to make tilt-clean before this if you’ve been using tilt with other providers.
cd cluster-api
make tilt-up
  • Run tilt up in the cluster-api folder

You can then use Tilt to watch the container logs.

On any changed file in the listed places (live_reload_deps and those watched inside cluster-api repo), Tilt will build and deploy again. In the regular case of a changed file, only your controller’s binary gets rebuilt, copied into the running container, and the process restarted. This is much faster than a full re-build and re-deployment of a Docker image and restart of the Kubernetes pod.

You best watch the Kubernetes pods with something like k9s -A or watch kubectl get pod -A. Particularly in case your provider implementation crashes, Tilt has no chance to deploy any code changes into the container since it might be crash-looping indefinitely. In such a case – which you will notice in the log output – terminate Tilt (hit Ctrl+C) and start it again to deploy the Docker image from scratch.

Your first Cluster

Let’s try our cluster out. We’ll make some simple YAML:

apiVersion: cluster.x-k8s.io/v1beta2
kind: Cluster
metadata:
  name: hello-mailgun
spec:
  clusterNetwork:
    pods:
      cidrBlocks: ["192.168.0.0/16"]
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    kind: MailgunCluster
    name: hello-mailgun
---
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha1
kind: MailgunCluster
metadata:
  name: hello-mailgun
spec:
  priority: "ExtremelyUrgent"
  request: "Please make me a cluster, with sugar on top?"
  requester: "cluster-admin@example.com"

We apply it as normal with kubectl apply -f <filename>.yaml.

If all goes well, you should be getting an email to the address you configured when you set up your management cluster:

Conclusion

Obviously, this is only the first step. We need to implement our Machine object too, and log events, handle updates, and many more things.

Hopefully you feel empowered to go out and create your own provider now. The world is your Kubernetes-based oyster!

Provider contract

The Cluster API contract defines a set of rules a provider is expected to comply with in order to interact with Cluster API. Those rules can be in the form of CustomResourceDefinition (CRD) fields and/or expected behaviors to be implemented.

Different rules apply to each provider type and for each different resource that is expected to interact with “core” Cluster API.

See Cluster API release vs contract versions for info about current and supported contract versions.

Additional rules must be considered for a provider to work with the clusterctl CLI.

Improving and contributing to the contract

The definition of the contract between Cluster API and providers may be changed in future versions of Cluster API. The Cluster API maintainers welcome feedback and contributions to the contract in order to improve how it’s defined, its clarity and visibility to provider implementers and its suitability across the different kinds of Cluster API providers. To provide feedback or open a discussion about the provider contract please open an issue on the Cluster API repo or add an item to the agenda in the Cluster API community meeting.

Contract rules for InfraCluster

Infrastructure providers SHOULD implement an InfraCluster resource using Kubernetes’ CustomResourceDefinition (CRD).

The goal of an InfraCluster resource is to supply whatever prerequisites (in term of infrastructure) are necessary for running machines. Examples might include networking, load balancers, firewall rules, and so on.

The InfraCluster resource will be referenced by one of the Cluster API core resources, Cluster.

The Cluster’s controller will be responsible to coordinate operations of the InfraCluster, and the interaction between the Cluster’s controller and the InfraCluster resource is based on the contract rules defined in this page.

Once contract rules are satisfied by an InfraCluster implementation, other implementation details could be addressed according to the specific needs (Cluster API is not prescriptive).

Nevertheless, it is always recommended to take a look at Cluster API controllers, in-tree providers, other providers and use them as a reference implementation (unless custom solutions are required in order to address very specific needs).

In order to facilitate the initial design for each InfraCluster resource, a few implementation best practices and infrastructure Provider Security Guidance are explicitly called out in dedicated pages.

Rules (contract version v1beta2)

Note:

  • All resources refers to all the provider’s resources “core” Cluster API interacts with; In the context of this page: InfraCluster, InfraClusterTemplate and corresponding list types

All resources: scope

All resources MUST be namespace-scoped.

All resources: TypeMeta and ObjectMeta field

All resources MUST have the standard Kubernetes TypeMeta and ObjectMeta fields.

All resources: APIVersion field value

In Kubernetes APIVersion is a combination of API group and version. Special consideration MUST applies to both API group and version for all the resources Cluster API interacts with.

All resources: API group

The domain for Cluster API resources is cluster.x-k8s.io, and infrastructure providers under the Kubernetes SIGS org generally use infrastructure.cluster.x-k8s.io as API group.

If your provider uses a different API group, you MUST grant full read/write RBAC permissions for resources in your API group to the Cluster API core controllers. If any resource sets another resource as the owner with blockOwnerDeletion set, additional RBAC to update finalizers on the owner resource is required. The canonical way to do so is via a ClusterRole resource with the aggregation label cluster.x-k8s.io/aggregate-to-manager: "true".

The following is an example ClusterRole for a FooCluster resource in the infrastructure.foo.com API group:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
    name: capi-foo-clusters
    labels:
      cluster.x-k8s.io/aggregate-to-manager: "true"
rules:
- apiGroups:
    - infrastructure.foo.com
  resources:
    - fooclusters
  verbs:
    - create
    - delete
    - get
    - list
    - patch
    - update
    - watch
- apiGroups:
    - infrastructure.foo.com
  resources:
    - fooclustertemplates
  verbs:
    - get
    - list
    - patch
    - update
    - watch

Note: The write permissions allow the Cluster controller to set owner references and labels on the InfraCluster resources; write permissions are not used for general mutations of InfraCluster resources, unless specifically required (e.g. when using ClusterClass and managed topologies).

All resources: version

The resource Version defines the stability of the API and its backward compatibility guarantees. Examples include v1alpha1, v1beta1, v1, etc. and are governed by the Kubernetes API Deprecation Policy.

Your provider SHOULD abide by the same policies.

Note: The version of your provider does not need to be in sync with the version of core Cluster API resources. Instead, prefer choosing a version that matches the stability of the provider API and its backward compatibility guarantees.

Additionally:

Providers MUST set cluster.x-k8s.io/<version> label on the InfraCluster Custom Resource Definitions.

The label is a map from a Cluster API contract version to your Custom Resource Definition versions. The value is an underscore-delimited (_) list of versions. Each value MUST point to an available version in your CRD Spec.

The label allows Cluster API controllers to perform automatic conversions for object references, the controllers will pick the last available version in the list if multiple versions are found.

To apply the label to CRDs it’s possible to use labels in your kustomization.yaml file, usually in config/crd:

labels:
- pairs:
    cluster.x-k8s.io/v1beta1: v1beta1
    cluster.x-k8s.io/v1beta2: v1beta2

An example of this is in the Kubeadm Bootstrap provider.

InfraCluster, InfraClusterList resource definition

You MUST define a InfraCluster resource. The InfraCluster resource name must have the format produced by sigs.k8s.io/cluster-api/util/contract.CalculateCRDName(Group, Kind).

Note: Cluster API is using such a naming convention to avoid an expensive CRD lookup operation when looking for labels from the CRD definition of the InfraCluster resource.

It is a generally applied convention to use names in the format ${env}Cluster, where ${env} is a, possibly short, name for the environment in question. For example GCPCluster is an implementation for the Google Cloud Platform, and AWSCluster is one for Amazon Web Services.

// +kubebuilder:object:root=true
// +kubebuilder:resource:path=fooclusters,shortName=foocl,scope=Namespaced,categories=cluster-api
// +kubebuilder:storageversion
// +kubebuilder:subresource:status

// FooCluster is the Schema for fooclusters.
type FooCluster struct {
    metav1.TypeMeta `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`
    Spec FooClusterSpec `json:"spec,omitempty"`
    Status FooClusterStatus `json:"status,omitempty"`
}

type FooClusterSpec struct {
    // See other rules for more details about mandatory/optional fields in InfraCluster spec.
    // Other fields SHOULD be added based on the needs of your provider.
}

type FooClusterStatus struct {
    // See other rules for more details about mandatory/optional fields in InfraCluster status.
    // Other fields SHOULD be added based on the needs of your provider.
}

For each InfraCluster resource, you MUST also add the corresponding list resource. The list resource MUST be named as <InfraCluster>List.

// +kubebuilder:object:root=true

// FooClusterList contains a list of fooclusters.
type FooClusterList struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ListMeta `json:"metadata,omitempty"`
    Items           []FooCluster `json:"items"`
}

InfraCluster: control plane endpoint

Each Cluster needs a control plane endpoint to sit in front of control plane machines. Control plane endpoint can be provided in three ways in Cluster API: by the users, by the control plane provider or by the infrastructure provider.

In case you are developing an infrastructure provider which is responsible to provide a control plane endpoint for each Cluster, the host and port of the generated control plane endpoint MUST surface on spec.controlPlaneEndpoint in the InfraCluster resource.

type FooClusterSpec struct {
    // controlPlaneEndpoint represents the endpoint used to communicate with the control plane.
    // +optional
    ControlPlaneEndpoint APIEndpoint `json:"controlPlaneEndpoint,omitempty,omitzero"`
    
    // See other rules for more details about mandatory/optional fields in InfraCluster spec.
    // Other fields SHOULD be added based on the needs of your provider.
}

// APIEndpoint represents a reachable Kubernetes API endpoint.
// +kubebuilder:validation:MinProperties=1
type APIEndpoint struct {
    // host is the hostname on which the API server is serving.
    // +optional
    // +kubebuilder:validation:MinLength=1
    // +kubebuilder:validation:MaxLength=512
    Host string `json:"host,omitempty"`

    // port is the port on which the API server is serving.
    // +optional
    // +kubebuilder:validation:Minimum=1
    // +kubebuilder:validation:Maximum=65535
    Port int32 `json:"port,omitempty"`
}

Once spec.controlPlaneEndpoint is set on the InfraCluster resource and the [InfraCluster initialization completed], the Cluster controller will surface this info in Cluster’s spec.controlPlaneEndpoint.

If instead you are developing an infrastructure provider which is NOT responsible to provide a control plane endpoint, the implementer should exit reconciliation until it sees Cluster’s spec.controlPlaneEndpoint populated.

InfraCluster: failure domains

In case you are developing an infrastructure provider which has a notion of failure domains where machines should be placed in, the list of available failure domains MUST surface on status.failureDomains in the InfraCluster resource.

type FooClusterStatus struct {
    // failureDomains is a list of failure domain objects synced from the infrastructure provider.
    // +optional
    // +listType=map
    // +listMapKey=name
    // +kubebuilder:validation:MinItems=1
    // +kubebuilder:validation:MaxItems=100
    FailureDomains []clusterv1.FailureDomain `json:"failureDomains,omitempty"`
    
    // See other rules for more details about mandatory/optional fields in InfraCluster status.
    // Other fields SHOULD be added based on the needs of your provider.
}

FailureDomain is defined as:

  • name string: the name of the failure domain (must be unique)
  • controlPlane *bool: indicates if failure domain is appropriate for running control plane instances.
  • attributes map[string]string: arbitrary attributes for users to apply to a failure domain.

Once status.failureDomains is set on the InfraCluster resource and the [InfraCluster initialization completed], the Cluster controller will surface this info in Cluster’s status.failureDomains.

InfraCluster: initialization completed

Each InfraCluster MUST report when Machine’s infrastructure is fully provisioned (initialization) by setting status.initialization.provisioned in the InfraCluster resource.

type FooClusterStatus struct {
    // initialization provides observations of the FooCluster initialization process.
    // NOTE: Fields in this struct are part of the Cluster API contract and are used to orchestrate initial Cluster provisioning.
    // +optional
    Initialization FooClusterInitializationStatus `json:"initialization,omitempty,omitzero"`
    
    // See other rules for more details about mandatory/optional fields in InfraCluster status.
    // Other fields SHOULD be added based on the needs of your provider.
}

// FooClusterInitializationStatus provides observations of the FooCluster initialization process.
// +kubebuilder:validation:MinProperties=1
type FooClusterInitializationStatus struct {
	// provisioned is true when the infrastructure provider reports that the Cluster's infrastructure is fully provisioned.
	// NOTE: this field is part of the Cluster API contract, and it is used to orchestrate initial Cluster provisioning.
	// +optional
	Provisioned *bool `json:"provisioned,omitempty"`
}

Once status.initialization.provisioned is set the Cluster “core” controller will bubble up this info in Cluster’s status.initialization.infrastructureProvisioned; if defined, also InfraCluster’s spec.controlPlaneEndpoint and status.failureDomains will be surfaced on Cluster’s corresponding fields at the same time.

InfraCluster: conditions

According to Kubernetes API Conventions, Conditions provide a standard mechanism for higher-level status reporting from a controller.

Providers implementers SHOULD implement status.conditions for their InfraCluster resource. In case conditions are implemented on a InfraCluster resource, Cluster API will only consider conditions providing the following information:

  • type (required)
  • status (required, one of True, False, Unknown)
  • reason (optional, if omitted a default one will be used)
  • message (optional, if omitted an empty message will be used)
  • lastTransitionTime (optional, if omitted time.Now will be used)
  • observedGeneration (optional, if omitted the generation of the InfraCluster resource will be used)

Other fields will be ignored.

If a condition with type Ready exist, such condition will be mirrored in Cluster’s InfrastructureReady condition.

Please note that the Ready condition is expected to surface the status of the InfraCluster during its own entire lifecycle, including initial provisioning, the final deletion process, and the period in between these two moments.

See Improving status in CAPI resources for more context.

InfraCluster: terminal failures

Starting from the v1beta2 contract version, there is no more special treatment for provider’s terminal failures within Cluster API.

In case necessary, “terminal failures” should be surfaced using conditions, with a well documented type/reason; it is up to consumers to treat them accordingly.

See Improving status in CAPI resources for more context.

InfraClusterTemplate, InfraClusterTemplateList resource definition

For a given InfraCluster resource, you should also add a corresponding InfraClusterTemplate resources in order to use it in ClusterClasses. The template resource MUST be named as <InfraCluster>Template.

// +kubebuilder:object:root=true
// +kubebuilder:resource:path=fooclustertemplates,scope=Namespaced,categories=cluster-api
// +kubebuilder:storageversion

// FooClusterTemplate is the Schema for the fooclustertemplates API.
type FooClusterTemplate struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec FooClusterTemplateSpec `json:"spec,omitempty"`
}

type FooClusterTemplateSpec struct {
    Template FooClusterTemplateResource `json:"template"`
}

type FooClusterTemplateResource struct {
    // Standard object's metadata.
    // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
    // +optional
    ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"`
    Spec FooClusterSpec `json:"spec"`
}

NOTE: in this example InfraClusterTemplate’s spec.template.spec embeds FooClusterSpec from InfraCluster. This might not always be the best choice depending of if/how InfraCluster’s spec fields applies to many clusters vs only one.

For each InfraClusterTemplate resource, you MUST also add the corresponding list resource. The list resource MUST be named as <InfraClusterTemplate>List.

// +kubebuilder:object:root=true

// FooClusterTemplateList contains a list of FooClusterTemplates.
type FooClusterTemplateList struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ListMeta `json:"metadata,omitempty"`
    Items           []FooClusterTemplate `json:"items"`
}

Externally managed infrastructure

In some cases, users might be required (or choose to) manage infrastructure out of band and run CAPI on top of already existing infrastructure.

In order to support this use case, the InfraCluster controller SHOULD skip reconciliation of InfraCluster resources with the cluster.x-k8s.io/managed-by: "<name-of-system>" label, and not update the resource or its status in any way.

Please note that when the cluster infrastructure is externally managed, it is responsibility of external management system to abide to the following contract rules:

  • [InfraCluster control plane endpoint]
  • [InfraCluster failure domains]
  • [InfraCluster initialization completed]
  • [InfraCluster terminal failures]

See the externally managed infrastructure proposal for more detail about this use case.

Multi tenancy

Multi tenancy in Cluster API defines the capability of an infrastructure provider to manage different credentials, each one of them corresponding to an infrastructure tenant.

See infrastructure Provider Security Guidance for considerations about cloud provider credential management.

Please also note that Cluster API does not support running multiples instances of the same provider, which someone can assume an alternative solution to implement multi tenancy; same applies to the clusterctl CLI.

See Support running multiple instances of the same provider for more context.

However, if you want to make it possible for users to run multiples instances of your provider, your controller’s SHOULD:

  • support the --namespace flag.
  • support the --watch-filter flag.

Please, read carefully the page linked above to fully understand implications and risks related to this option.

Clusterctl support

The clusterctl command is designed to work with all the providers compliant with the rules defined in the clusterctl provider contract.

InfraCluster: pausing

Providers SHOULD implement the pause behaviour for every object with a reconciliation loop. This is done by checking if spec.paused is set on the Cluster object and by checking for the cluster.x-k8s.io/paused annotation on the InfraCluster object.

If implementing the pause behavior, providers SHOULD surface the paused status of an object using the Paused condition: Status.Conditions[Paused].

Typical InfraCluster reconciliation workflow

A cluster infrastructure provider must respond to changes to its InfraCluster resources. This process is typically called reconciliation. The provider must watch for new, updated, and deleted resources and respond accordingly.

As a reference you can look at the following workflow to understand how the typical reconciliation workflow is implemented in InfraCluster controllers:

Normal resource

  1. If the resource is externally managed, exit the reconciliation
    1. The ResourceIsNotExternallyManaged predicate can be used to prevent reconciling externally managed resources
  2. If the resource does not have a Cluster owner, exit the reconciliation
    1. The Cluster API Cluster reconciler populates this based on the value in the Cluster’s spec.infrastructureRef field.
  3. Add the provider-specific finalizer, if needed
  4. Reconcile provider-specific cluster infrastructure
    1. If any errors are encountered, exit the reconciliation
  5. If the provider created a load balancer for the control plane, record its hostname or IP in spec.controlPlaneEndpoint
  6. Set status.infrastructure.provisioned to true
  7. Set status.failureDomains based on available provider failure domains (optional)
  8. Patch the resource to persist changes

Deleted resource

  1. If the resource has a Cluster owner
    1. Perform deletion of provider-specific cluster infrastructure
    2. If any errors are encountered, exit the reconciliation
  2. Remove the provider-specific finalizer from the resource
  3. Patch the resource to persist changes

Contract rules for InfraMachine

Infrastructure providers SHOULD implement an InfraMachine resource using Kubernetes’ CustomResourceDefinition (CRD).

The goal of an InfraMachine resource is to manage the lifecycle of a provider-specific machine instances. These may be physical or virtual instances, and they represent the infrastructure for Kubernetes nodes.

The InfraMachine resource will be referenced by one of the Cluster API core resources, Machine.

The Machine’s controller will be responsible to coordinate operations of the InfraMachine, and the interaction between the Machine’s controller and the InfraMachine resource is based on the contract rules defined in this page.

Once contract rules are satisfied by an InfraMachine implementation, other implementation details could be addressed according to the specific needs (Cluster API is not prescriptive).

Nevertheless, it is always recommended to take a look at Cluster API controllers, in-tree providers, other providers and use them as a reference implementation (unless custom solutions are required in order to address very specific needs).

In order to facilitate the initial design for each InfraMachine resource, a few implementation best practices and infrastructure Provider Security Guidance are explicitly called out in dedicated pages.

Rules (contract version v1beta2)

Note:

  • All resources refers to all the provider’s resources “core” Cluster API interacts with; In the context of this page: InfraMachine, InfraMachineTemplate and corresponding list types

All resources: scope

All resources MUST be namespace-scoped.

All resources: TypeMeta and ObjectMeta field

All resources MUST have the standard Kubernetes TypeMeta and ObjectMeta fields.

All resources: APIVersion field value

In Kubernetes APIVersion is a combination of API group and version. Special consideration MUST applies to both API group and version for all the resources Cluster API interacts with.

All resources: API group

The domain for Cluster API resources is cluster.x-k8s.io, and infrastructure providers under the Kubernetes SIGS org generally use infrastructure.cluster.x-k8s.io as API group.

If your provider uses a different API group, you MUST grant full read/write RBAC permissions for resources in your API group to the Cluster API core controllers. If any resource sets another resource as the owner with blockOwnerDeletion set, additional RBAC to update finalizers on the owner resource is required. The canonical way to do so is via a ClusterRole resource with the aggregation label cluster.x-k8s.io/aggregate-to-manager: "true".

The following is an example ClusterRole for a FooMachine resource in the infrastructure.foo.com API group:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
    name: capi-foo-clusters
    labels:
      cluster.x-k8s.io/aggregate-to-manager: "true"
rules:
- apiGroups:
    - infrastructure.foo.com
  resources:
    - foomachines
    - foomachinetemplates
  verbs:
    - create
    - delete
    - get
    - list
    - patch
    - update
    - watch

Note: The write permissions are required because Cluster API manages InfraMachines generated from InfraMachineTemplates; when using ClusterClass and managed topologies, also InfraMachineTemplates are managed directly by Cluster API.

All resources: version

The resource Version defines the stability of the API and its backward compatibility guarantees. Examples include v1alpha1, v1beta1, v1, etc. and are governed by the Kubernetes API Deprecation Policy.

Your provider SHOULD abide by the same policies.

Note: The version of your provider does not need to be in sync with the version of core Cluster API resources. Instead, prefer choosing a version that matches the stability of the provider API and its backward compatibility guarantees.

Additionally:

Providers MUST set cluster.x-k8s.io/<version> label on the InfraMachine Custom Resource Definitions.

The label is a map from a Cluster API contract version to your Custom Resource Definition versions. The value is an underscore-delimited (_) list of versions. Each value MUST point to an available version in your CRD Spec.

The label allows Cluster API controllers to perform automatic conversions for object references, the controllers will pick the last available version in the list if multiple versions are found.

To apply the label to CRDs it’s possible to use labels in your kustomization.yaml file, usually in config/crd:

labels:
- pairs:
    cluster.x-k8s.io/v1beta1: v1beta1
    cluster.x-k8s.io/v1beta2: v1beta2

An example of this is in the Kubeadm Bootstrap provider.

InfraMachine, InfraMachineList resource definition

You MUST define a InfraMachine resource. The InfraMachine resource name must have the format produced by sigs.k8s.io/cluster-api/util/contract.CalculateCRDName(Group, Kind).

Note: Cluster API is using such a naming convention to avoid an expensive CRD lookup operation when looking for labels from the CRD definition of the InfraMachine resource.

It is a generally applied convention to use names in the format ${env}Machine, where ${env} is a, possibly short, name for the environment in question. For example GCPMachine is an implementation for the Google Cloud Platform, and AWSMachine is one for Amazon Web Services.

// +kubebuilder:object:root=true
// +kubebuilder:resource:path=foomachines,shortName=foom,scope=Namespaced,categories=cluster-api
// +kubebuilder:storageversion
// +kubebuilder:subresource:status

// FooMachine is the Schema for foomachines.
type FooMachine struct {
    metav1.TypeMeta `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`
    Spec FooMachineSpec `json:"spec,omitempty"`
    Status FooMachineStatus `json:"status,omitempty"`
}

type FooMachineSpec struct {
    // See other rules for more details about mandatory/optional fields in InfraMachine spec.
    // Other fields SHOULD be added based on the needs of your provider.
}

type FooMachineStatus struct {
    // See other rules for more details about mandatory/optional fields in InfraMachine status.
    // Other fields SHOULD be added based on the needs of your provider.
}

For each InfraMachine resource, you MUST also add the corresponding list resource. The list resource MUST be named as <InfraMachine>List.

// +kubebuilder:object:root=true

// FooMachineList contains a list of foomachines.
type FooMachineList struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ListMeta `json:"metadata,omitempty"`
    Items           []FooMachine `json:"items"`
}

InfraMachine: provider ID

Each Machine needs a provider ID to identify the Kubernetes Node that runs on the machine. Node’s Provider id MUST surface on spec.providerID in the InfraMachine resource.

type FooMachineSpec struct {
    // providerID must match the provider ID as seen on the node object corresponding to this machine.
	// For Kubernetes Nodes running on the Foo provider, this value is set by the corresponding CPI component 
	// and it has the format docker:////<vm-name>. 
    // +optional
	// +kubebuilder:validation:MinLength=1
	// +kubebuilder:validation:MaxLength=512
	ProviderID string `json:"providerID,omitempty"`
    
    // See other rules for more details about mandatory/optional fields in InfraMachine spec.
    // Other fields SHOULD be added based on the needs of your provider.
}

NOTE: To align with API conventions, we recommend since the v1beta2 contract that the ProviderID field should be of type string (it was *string before). Both are compatible with the v1beta2 contract though. Once spec.providerID is set on the InfraMachine resource and the [InfraMachine initialization completed], the Cluster controller will surface this info in Machine’s spec.providerID.

InfraMachine: failure domain

In case you are developing an infrastructure provider which has a notion of failure domains where machines should be placed in, the InfraMachine resource MUST comply to the value that exists in the spec.failureDomain field of the Machine (in other words, the InfraMachine MUST be placed in the failure domain specified at Machine level).

Also, InfraMachine providers are allowed to surface the failure domain where the machine is actually placed by implementing the status.failureDomain field; this info, if present, will then surface at Machine level in a corresponding field (also in status).

type FooMachineStatus struct {
    // failureDomain is the unique identifier of the failure domain where this Machine has been placed in.
    // +optional
    // +kubebuilder:validation:MinLength=1
    // +kubebuilder:validation:MaxLength=256
    FailureDomain string `json:"failureDomain,omitempty"`

    // See other rules for more details about mandatory/optional fields in InfraMachineStatus.
    // Other fields SHOULD be added based on the needs of your provider.
}

InfraMachine: addresses

Infrastructure provider have the opportunity to surface machines addresses on the InfraMachine resource; this information won’t be used by core Cluster API controller, but it is really useful for operator troubleshooting issues on machines.

In case you want to surface machine’s addresses, you MUST surface them in status.addresses in the InfraMachine resource.

type FooMachineStatus struct {
    // addresses contains the associated addresses for the machine.
    // +optional
    Addresses []clusterv1.MachineAddress `json:"addresses,omitempty"`

    // See other rules for more details about mandatory/optional fields in InfraMachine status.
    // Other fields SHOULD be added based on the needs of your provider.
}

Each MachineAddress must have a type; accepted types are Hostname, ExternalIP, InternalIP, ExternalDNS or InternalDNS.

Once status.addresses is set on the InfraMachine resource and the [InfraMachine initialization completed], the Machine controller will surface this info in Machine’s status.addresses.

InfraMachine: initialization completed

Each InfraMachine MUST report when Machine’s infrastructure is fully provisioned (initialization) by setting status.initialization.provisioned in the InfraMachine resource.

type FooMachineStatus struct {
    // initialization provides observations of the FooMachine initialization process.
    // NOTE: Fields in this struct are part of the Cluster API contract and are used to orchestrate initial Machine provisioning.
    // +optional
    Initialization FooMachineInitializationStatus `json:"initialization,omitempty,omitzero"`
    
    // See other rules for more details about mandatory/optional fields in InfraMachine status.
    // Other fields SHOULD be added based on the needs of your provider.
}

// FooMachineInitializationStatus provides observations of the FooMachine initialization process.
// +kubebuilder:validation:MinProperties=1
type FooMachineInitializationStatus struct {
	// provisioned is true when the infrastructure provider reports that the Machine's infrastructure is fully provisioned.
	// NOTE: this field is part of the Cluster API contract, and it is used to orchestrate initial Machine provisioning.
	// +optional
	Provisioned *bool `json:"provisioned,omitempty"`
}

Once status.initialization.provisioned is set the Machine “core” controller will bubble up this info in Machine’s status.initialization.infrastructureProvisioned; also InfraMachine’s spec.providerID, status.failureDomain and status.addresses will be surfaced on Machine’s corresponding fields at the same time.

InfraMachine: conditions

According to Kubernetes API Conventions, Conditions provide a standard mechanism for higher-level status reporting from a controller.

Providers implementers SHOULD implement status.conditions for their InfraMachine resource. In case conditions are implemented on a InfraMachine resource, Cluster API will only consider conditions providing the following information:

  • type (required)
  • status (required, one of True, False, Unknown)
  • reason (optional, if omitted a default one will be used)
  • message (optional, if omitted an empty message will be used)
  • lastTransitionTime (optional, if omitted time.Now will be used)
  • observedGeneration (optional, if omitted the generation of the InfraMachine resource will be used)

Other fields will be ignored.

If a condition with type Ready exist, such condition will be mirrored in Machine’s InfrastructureReady condition.

Please note that the Ready condition is expected to surface the status of the InfraMachine during its own entire lifecycle, including initial provisioning, the final deletion process, and the period in between these two moments.

See Improving status in CAPI resources for more context.

InfraMachine: interruptible

In case the Machine is backed by a non-guaranteed instance, e.g. a spot instance on a cloud provider, infrastructure providers can surface this by setting status.interruptible to true in the InfraMachine resource.

type FooMachineStatus struct {
    // interruptible reports that this machine can be interrupted.
    // +optional
    Interruptible *bool `json:"interruptible,omitempty"`

    // See other rules for more details about mandatory/optional fields in InfraMachine status.
    // Other fields SHOULD be added based on the needs of your provider.
}

Once status.interruptible is set to true, the Machine controller will add the cluster.x-k8s.io/interruptible label to the corresponding Node; this can then be used, for example, by a DaemonSet dedicated to gracefully handling the termination of workloads running on interruptible instances.

InfraMachine: terminal failures

Starting from the v1beta2 contract version, there is no more special treatment for provider’s terminal failures within Cluster API.

In case necessary, “terminal failures” should be surfaced using conditions, with a well documented type/reason; it is up to consumers to treat them accordingly.

See Improving status in CAPI resources for more context.

InfraMachine: support for in-place changes

In case you are developing an infrastructure provider with support for in-place updates of the Machine infrastructure, you should consider following recommendations during implementation.

  • The Update Extension is the component responsible for orchestrating in-place changes on Machines. Accordingly, the InfraMachine controller should ignore in-place changes. As alternative the InfraMachine controller must orchestrate those changes with the Update Extension (e.g. the Update Extension must report change progress).
  • It might be useful to start thinking about the InfraMachine API surface as a set of fields with one of the following behaviors:
    • “Immutable” fields that can only be changed by performing a rollout.
    • “Mutable” fields that will be “reconciled” by the Update Extension.
    • Fields written back to spec by the infra provider (e.g. ProviderID).
  • The validation webhook for the InfraMachine CR should allow changes to “mutable” fields; in case an infra provider wants to allow this change selectively, e.g. only when applied by core CAPI, please reach out to maintainers to discuss options.
  • Please note that the above field classification do not apply to the InfraMachineTemplate object.

See Proposal.

InfraMachineTemplate, InfraMachineTemplateList resource definition

For a given InfraMachine resource, you MUST also add a corresponding InfraMachineTemplate resources in order to use it when defining set of machines, e.g. MachineDeployments.

The template resource MUST be named as <InfraMachine>Template.

// +kubebuilder:object:root=true
// +kubebuilder:resource:path=foomachinetemplates,scope=Namespaced,categories=cluster-api
// +kubebuilder:storageversion

// FooMachineTemplate is the Schema for the foomachinetemplates API.
type FooMachineTemplate struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec FooMachineTemplateSpec `json:"spec,omitempty"`
}

type FooMachineTemplateSpec struct {
    Template FooMachineTemplateResource `json:"template"`
}

type FooMachineTemplateResource struct {
    // Standard object's metadata.
    // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
    // +optional
    ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"`
    Spec FooMachineSpec `json:"spec"`
}

NOTE: in this example InfraMachineTemplate’s spec.template.spec embeds FooMachineSpec from InfraMachine. This might not always be the best choice depending of if/how InfraMachine’s spec fields applies to many machines vs only one.

For each InfraMachineTemplate resource, you MUST also add the corresponding list resource. The list resource MUST be named as <InfraMachineTemplate>List.

// +kubebuilder:object:root=true

// FooMachineTemplateList contains a list of FooMachineTemplates.
type FooMachineTemplateList struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ListMeta `json:"metadata,omitempty"`
    Items           []FooMachineTemplate `json:"items"`
}

InfraMachineTemplate: support for SSA dry run

When Cluster API’s topology controller is trying to identify differences between templates defined in a ClusterClass and the current Cluster topology, it is required to run Server Side Apply (SSA) dry run call.

However, in case you immutability checks for your InfraMachineTemplate, this can lead the SSA dry run call to errors.

In order to avoid this InfraMachineTemplate MUST specifically implement support for SSA dry run calls from the topology controller.

The implementation requires to use controller runtime’s Validator.

This will allow to skip the immutability check only when the topology controller is dry running while preserving the validation behavior for all other cases.

See the DevMachineTemplate webhook as a reference for a compatible implementation.

Multi tenancy

Multi tenancy in Cluster API defines the capability of an infrastructure provider to manage different credentials, each one of them corresponding to an infrastructure tenant.

See infrastructure Provider Security Guidance for considerations about cloud provider credential management.

Please also note that Cluster API does not support running multiples instances of the same provider, which someone can assume an alternative solution to implement multi tenancy; same applies to the clusterctl CLI.

See Support running multiple instances of the same provider for more context.

However, if you want to make it possible for users to run multiples instances of your provider, your controller’s SHOULD:

  • support the --namespace flag.
  • support the --watch-filter flag.

Please, read carefully the page linked above to fully understand implications and risks related to this option.

Clusterctl support

The clusterctl command is designed to work with all the providers compliant with the rules defined in the clusterctl provider contract.

InfraMachine: pausing

Providers SHOULD implement the pause behaviour for every object with a reconciliation loop. This is done by checking if spec.paused is set on the Cluster object and by checking for the cluster.x-k8s.io/paused annotation on the InfraMachine object.

If implementing the pause behavior, providers SHOULD surface the paused status of an object using the Paused condition: Status.Conditions[Paused].

InfraMachineTemplate: support cluster autoscaling from zero

As described in the enhancement Opt-in Autoscaling from Zero, providers may implement the capacity and nodeInfo fields in machine templates to inform the cluster autoscaler about the resources available on that machine type, the architecture, and the operating system it runs.

Building on the FooMachineTemplate example from above, this shows the addition of a status and capacity field:

import corev1 "k8s.io/api/core/v1"

// FooMachineTemplate is the Schema for the foomachinetemplates API.
type FooMachineTemplate struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec   FooMachineTemplateSpec `json:"spec,omitempty"`
    Status FooMachineTemplateStatus `json:"status,omitempty"`
}

// FooMachineTemplateStatus defines the observed state of FooMachineTemplate.
type FooMachineTemplateStatus struct {
	// Capacity defines the resource capacity for this machine.
	// This value is used for autoscaling from zero operations as defined in:
	// https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20210310-opt-in-autoscaling-from-zero.md
	// +optional
	Capacity corev1.ResourceList `json:"capacity,omitempty"`
	// +optional
	NodeInfo NodeInfo `json:"nodeInfo,omitempty,omitzero"`
}

// Architecture represents the CPU architecture of the node.
// Its underlying type is a string and its value can be any of amd64, arm64, s390x, ppc64le.
// +kubebuilder:validation:Enum=amd64;arm64;s390x;ppc64le
// +enum
type Architecture string

// Example architecture constants defined for better readability and maintainability.
const (
    ArchitectureAmd64 Architecture = "amd64"
    ArchitectureArm64 Architecture = "arm64"
    ArchitectureS390x Architecture = "s390x"
    ArchitecturePpc64le Architecture = "ppc64le"
)

// NodeInfo contains information about the node's architecture and operating system.
// +kubebuilder:validation:MinProperties=1
type NodeInfo struct {
    // architecture is the CPU architecture of the node. 
    // Its underlying type is a string and its value can be any of amd64, arm64, s390x, ppc64le.
    // +optional
    Architecture Architecture `json:"architecture,omitempty"`
    // operatingSystem is a string representing the operating system of the node.
    // This may be a string like 'linux' or 'windows'.
    // +optional
    OperatingSystem string `json:"operatingSystem,omitempty"`
}

When rendered to a manifest, the machine template status capacity field representing an amd64 linux instance with 500 megabytes of RAM, 1 CPU core, and 1 NVidia GPU should look like this:

status:
  capacity:
    memory: 500mb
    cpu: "1"
    nvidia.com/gpu: "1"
   nodeInfo:
    architecture: amd64
    operatingSystem: linux

If the information in the nodeInfo field is not available, the result of the autoscaling from zero operation will depend on the cluster autoscaler implementation. For example, the Cluster API implementation of the Kubernetes Cluster Autoscaler will assume the host is running either the architecture set in the CAPI_SCALE_ZERO_DEFAULT_ARCH environment variable of the cluster autoscaler pod environment, or the amd64 architecture and Linux operating system as default values.

See autoscaling.

Typical InfraMachine reconciliation workflow

A machine infrastructure provider must respond to changes to its InfraMachine resources. This process is typically called reconciliation. The provider must watch for new, updated, and deleted resources and respond accordingly.

As a reference you can look at the following workflow to understand how the typical reconciliation workflow is implemented in InfraMachine controllers:

Normal resource

  1. If the resource does not have a Machine owner, exit the reconciliation
    1. The Cluster API Machine reconciler populates this based on the value in the Machines’s spec.infrastructureRef field
  2. If the Cluster to which this resource belongs cannot be found, exit the reconciliation
  3. Add the provider-specific finalizer, if needed
  4. If the associated Cluster’s status.infrastructureReady is false, exit the reconciliation
    1. Note: This check should not be blocking any further delete reconciliation flows.
    2. Note: This check should only be performed after appropriate owner references (if any) are updated.
  5. If the associated Machine’s spec.bootstrap.dataSecretName is nil, exit the reconciliation
  6. Reconcile provider-specific machine infrastructure
    1. If this is a control plane machine, register the instance with the provider’s control plane load balancer (optional)
  7. Set spec.providerID to the provider-specific identifier for the provider’s machine instance
  8. Set status.infrastructure.provisioned to true
  9. Set status.addresses to the provider-specific set of instance addresses (optional)
  10. Set status.failureDomain to the provider-specific failure domain the instance is running in (optional)
  11. Patch the resource to persist changes

Deleted resource

  1. If the resource has a Machine owner
    1. Perform deletion of provider-specific machine infrastructure
    2. If this is a control plane machine, deregister the instance from the provider’s control plane load balancer (optional)
    3. If any errors are encountered, exit the reconciliation
  2. Remove the provider-specific finalizer from the resource
  3. Patch the resource to persist changes

Contract rules for InfraMachinePool

Infrastructure providers CAN OPTIONALLY implement an InfraMachinePool resource using Kubernetes’ CustomResourceDefinition (CRD).

The goal of an InfraMachinePool is to manage the lifecycle of a provider-specific pool of machines using a provider specific service (like Auto Scaling groups in AWS & Virtual Machine Scale Sets in Azure).

The machines in the pool may be physical or virtual instances (although most likely virtual), and they represent the infrastructure for Kubernetes nodes.

The InfraMachinePool resource will be referenced by one of the Cluster API core resources, MachinePool.

The core MachinePool’s controller is responsible to coordinate operations of the MachinePool with the InfraMachinePool. The operations are coordinated via the contract rules defined in this page.

Once contract rules are satisfied by an InfraMachinePool implementation, other implementation details could be addressed according to the specific needs (Cluster API is not prescriptive).

Nevertheless, it is always recommended to take a look at Cluster API controllers, in-tree providers, other providers and use them as a reference implementation (unless custom solutions are required in order to address very specific needs).

Rules (contract version v1beta2)

Note:

  • All resources refers to all the provider’s resources “core” Cluster API interacts with; In the context of this page: InfraMachinePool, InfraMachinePoolTemplate and corresponding list types

All resources: scope

All resources MUST be namespace-scoped.

All resources: TypeMeta and ObjectMeta field

All resources MUST have the standard Kubernetes TypeMeta and ObjectMeta fields.

All resources: APIVersion field value

In Kubernetes APIVersion is a combination of API group and version. Special consideration MUST apply to both API group and version for all the resources Cluster API interacts with.

All resources: API group

The domain for Cluster API resources is cluster.x-k8s.io, and infrastructure providers under the Kubernetes SIGS org generally use infrastructure.cluster.x-k8s.io as API group.

If your provider uses a different API group, you MUST grant full read/write RBAC permissions for resources in your API group to the Cluster API core controllers. If any resource sets another resource as the owner with blockOwnerDeletion set, additional RBAC to update finalizers on the owner resource is required. The canonical way to do so is via a ClusterRole resource with the [aggregation label] cluster.x-k8s.io/aggregate-to-manager: "true".

The following is an example ClusterRole for a FooMachinePool resource in the infrastructure.foo.com API group:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
    name: capi-foo-clusters
    labels:
      cluster.x-k8s.io/aggregate-to-manager: "true"
rules:
- apiGroups:
    - infrastructure.foo.com
  resources:
    - foomachinepools
    - foomachinepooltemplates
  verbs:
    - create
    - delete
    - get
    - list
    - patch
    - update
    - watch

Note: The write permissions are required because Cluster API manages InfraMachinePools generated from InfraMachinePoolTemplates; when using ClusterClass and managed topologies, also InfraMachinePoolTemplates are managed directly by Cluster API.

All resources: version

The resource Version defines the stability of the API and its backward compatibility guarantees. Examples include v1alpha1, v1beta1, v1, etc. and are governed by the [Kubernetes API Deprecation Policy].

Your provider SHOULD abide by the same policies.

Note: The version of your provider does not need to be in sync with the version of core Cluster API resources. Instead, prefer choosing a version that matches the stability of the provider API and its backward compatibility guarantees.

Additionally:

Providers MUST set cluster.x-k8s.io/<version> label on the InfraMachinePool Custom Resource Definitions.

The label is a map from a Cluster API contract version to your Custom Resource Definition versions. The value is an underscore-delimited (_) list of versions. Each value MUST point to an available version in your CRD Spec.

The label allows Cluster API controllers to perform automatic conversions for object references, the controllers will pick the last available version in the list if multiple versions are found.

To apply the label to CRDs it’s possible to use labels in your kustomization.yaml file, usually in config/crd:

labels:
- pairs:
    cluster.x-k8s.io/v1beta1: v1beta1
    cluster.x-k8s.io/v1beta2: v1beta2

An example of this is in the AWS infrastructure provider.

InfraMachinePool, InfraMachinePoolList resource definition

You MUST define a InfraMachinePool resource if you provider supports MachinePools. The InfraMachinePool CRD name must have the format produced by sigs.k8s.io/cluster-api/util/contract.CalculateCRDName(Group, Kind).

Note: Cluster API is using such a naming convention to avoid an expensive CRD lookup operation when looking for labels from the CRD definition of the InfraMachinePool resource.

It is a generally applied convention to use names in the format ${env}MachinePool, where ${env} is a, possibly short, name for the environment in question. For example AWSMachinePool is an implementation for Amazon Web Services, and AzureMachinePool is one for Azure.

// +kubebuilder:object:root=true
// +kubebuilder:resource:path=foomachinepools,shortName=foomp,scope=Namespaced,categories=cluster-api
// +kubebuilder:storageversion
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of FooMachinePool"

// FooMachinePool is the Schema for foomachinepools.
type FooMachinePool struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`
    Spec FooMachinePoolSpec `json:"spec,omitempty"`
    Status FooMachinePoolStatus `json:"status,omitempty"`
}

type FooMachinePoolSpec struct {
    // See other rules for more details about mandatory/optional fields in InfraMachinePool spec.
    // Other fields SHOULD be added based on the needs of your provider.
}

type FooMachinePoolStatus struct {
    // See other rules for more details about mandatory/optional fields in InfraMachinePool status.
    // Other fields SHOULD be added based on the needs of your provider.
}

For each InfraMachinePool resource, you MUST also add the corresponding list resource. The list resource MUST be named as <InfraMachinePool>List.

// +kubebuilder:object:root=true

// FooMachinePoolList contains a list of foomachinepools.
type FooMachinePoolList struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ListMeta `json:"metadata,omitempty"`
    Items           []FooMachinePool `json:"items"`
}

InfraMachinePool: instances

Each InfraMachinePool MAY specify a status field that is used to report information about each replica within the machine pool. This field is not used by core CAPI. It is purely informational and is used as convenient way for a user to get details of the replicas in the machine pool, such as their provider id and ip addresses.

If you implement this then create a status.instances field that is a slice of a struct type that contains the information you want to store and be made available to the users.

type FooMachinePoolStatus struct {
    // Instances contains the status for each instance in the pool
    // +optional
    Instances []FooMachinePoolInstanceStatus `json:"instances,omitempty"`
    
    // See other rules for more details about mandatory/optional fields in InfraMachinePool status.
    // Other fields SHOULD be added based on the needs of your provider.
}

// FooMachinePoolInstanceStatus contains instance status information about a FooMachinePool.
type FooMachinePoolInstanceStatus struct {
    // Addresses contains the associated addresses for the machine.
    // +optional
    Addresses []clusterv1.MachineAddress `json:"addresses,omitempty"`

    // InstanceName is the identification of the Machine Instance within the Machine Pool
    InstanceName string `json:"instanceName,omitempty"`

    // ProviderID is the provider identification of the Machine Pool Instance
    // +optional
    ProviderID *string `json:"providerID,omitempty"`

    // Version defines the Kubernetes version for the Machine Instance
    // +optional
    Version *string `json:"version,omitempty"`

    // Ready denotes that the machine is ready
    // +optional
    Ready bool `json:"ready"`
}

MachinePoolMachines support

A provider can opt-in to MachinePool Machines (MPM). With MPM machines all the replicas in a MachinePool are represented by a Machine & InfraMachine. This enables core CAPI to perform common operations on single machines (and their Nodes), such as draining a node before scale down, integration with Cluster Autoscaler and also MachineHealthChecks.

If you want to adopt MPM then you MUST have an status.infrastructureMachineKind field and the fields value must be set to the resource kind that represents the replicas in the pool. This is usually the resource kind name for the providers InfraMachine. For example, for the AWS provider the value would be set to AWSMachine.

By opting in, the infra provider is expected to create a InfraMachine for every replica in the pool. The lifecycle of these InfraMachines must be managed so that when scale up or scale down happens, the list of InfraMachines is kept up to date.

type FooMachinePoolStatus struct {
    // InfrastructureMachineKind is the kind of the infrastructure resources behind MachinePool Machines.
    // +optional
    InfrastructureMachineKind string `json:"infrastructureMachineKind,omitempty"`
   
    // See other rules for more details about mandatory/optional fields in InfraMachinePool status.
    // Other fields SHOULD be added based on the needs of your provider.
}

Note: not all InfraMachinePool implementations support MPM as it depends on whether the infrastructure service underpinning the InfraMachinePool supports operations being performed against single machines. For example, in CAPA AWSManagedMachinePool is used to represent an “EKS managed node group” and as a “managed” service you are expected to NOT perform operations against single nodes.

For further information see the proposal.

InfraMachinePool: providerID

Each InfraMachinePool MAY specify a provider ID on spec.providerID that can be used to identify the infrastructure resource that implements the InfraMachinePool.

This field isn’t used by core CAPI. Its main purpose is purely informational to the user to surface the infrastructures identifier for the InfraMachinePool. For example, for AWSMachinePool this would be the ASG identifier.

type FooMachinePoolSpec struct {
    // providerID is the identification ID of the FooMachinePool.
    // +optional
    // +kubebuilder:validation:MinLength=1
    // +kubebuilder:validation:MaxLength=512
    ProviderID string `json:"providerID,omitempty"`
    
    // See other rules for more details about mandatory/optional fields in InfraMachinePool spec.
    // Other fields SHOULD be added based on the needs of your provider.
}

NOTE: To align with API conventions, we recommend since the v1beta2 contract that the ProviderID field should be of type string.

InfraMachinePool: providerIDList

Each InfraMachinePool MUST supply a list of the identification IDs of the machine instances managed by the machine pool by storing these in spec.providerIDList.

type FooMachinePoolSpec struct {
    // ProviderIDList is the list of identification IDs of machine instances managed by this Machine Pool
    // +optional
    // +listType=atomic
    // +kubebuilder:validation:MaxItems=10000
    // +kubebuilder:validation:items:MinLength=1
    // +kubebuilder:validation:items:MaxLength=512
    ProviderIDList []string `json:"providerIDList,omitempty"`
    
    // See other rules for more details about mandatory/optional fields in InfraMachinePool spec.
    // Other fields SHOULD be added based on the needs of your provider.
}

Cluster API uses this list to determine the status of the machine pool and to know when replicas have been deleted, at which point the Node will be deleted. Therefore, the list MUST be kept up to date.

InfraMachinePool: initialization completed

Each InfraMachinePool MUST report when the MachinePool’s infrastructure is fully provisioned (initialization) by setting status.initialization.provisioned in the InfraMachinePool resource.

type FooMachinePoolStatus struct {
    // initialization provides observations of the FooMachinePool initialization process.
    // +optional
    Initialization FooMachinePoolInitializationStatus `json:"initialization,omitempty,omitzero"`
    
    // See other rules for more details about mandatory/optional fields in InfraMachinePool status.
    // Other fields SHOULD be added based on the needs of your provider.
}

// FooMachinePoolInitializationStatus provides observations of the FooMachinePool initialization process.
// +kubebuilder:validation:MinProperties=1
type FooMachinePoolInitializationStatus struct {
    // provisioned is true when the infrastructure provider reports that the MachinePool's infrastructure is fully provisioned.
    // +optional
    Provisioned *bool `json:"provisioned,omitempty"`
}

Once status.initialization.provisioned is set, the MachinePool “core” controller will bubble this info in the MachinePool’s status.initialization.infrastructureProvisioned; also InfraMachinePools’s spec.providerIDList and status.replicas will be surfaced on MachinePool’s corresponding fields at the same time.

InfraMachinePool: pausing

Providers SHOULD implement the pause behaviour for every object with a reconciliation loop. This is done by checking if spec.paused is set on the Cluster object and by checking for the cluster.x-k8s.io/paused annotation on the InfraMachinePool object. Preferably, the utility sigs.k8s.io/cluster-api/util/annotations.IsPaused(cluster, infraMachinePool) SHOULD be used.

If implementing the pause behaviour, providers SHOULD surface the paused status of an object using the Paused condition: Status.Conditions[Paused].

InfraMachinePool: conditions

According to Kubernetes API Conventions, Conditions provide a standard mechanism for higher-level status reporting from a controller.

Providers implementers SHOULD implement status.conditions for their InfraMachinePool resource. In case conditions are implemented on a InfraMachinePool resource, Cluster API will only consider conditions providing the following information:

  • type (required)
  • status (required, one of True, False, Unknown)
  • reason (optional, if omitted a default one will be used)
  • message (optional, if omitted an empty message will be used)
  • lastTransitionTime (optional, if omitted time.Now will be used)
  • observedGeneration (optional, if omitted the generation of the InfraMachinePool resource will be used)

Other fields will be ignored.

If a condition with type Ready exist, such condition will be mirrored in MachinePool’s InfrastructureReady condition (not implemented yet).

Please note that the Ready condition is expected to surface the status of the InfraMachinePool during its own entire lifecycle, including initial provisioning, the final deletion process, and the period in between these two moments.

See Improving status in CAPI resources for more context.

InfraMachinePool: replicas

Provider implementers MUST implement status.replicas to report the most recently observed number of machine instances in the pool. For example, in AWS this would be the number of replicas in a Auto Scaling group (ASG).

type FooMachinePoolStatus struct {
    // Replicas is the most recently observed number of replicas.
    // +optional
    Replicas int32 `json:"replicas"`
    
    // See other rules for more details about mandatory/optional fields in InfraMachinePool status.
    // Other fields SHOULD be added based on the needs of your provider.
}

The value from this field is surfaced via the MachinePool’s status.replicas field.

InfraMachinePool: terminal failures

Starting from the v1beta2 contract version, there is no more special treatment for provider’s terminal failures within Cluster API.

In case necessary, “terminal failures” should be surfaced using conditions, with a well documented type/reason; it is up to consumers to treat them accordingly.

See Improving status in CAPI resources for more context.

InfraMachinePoolTemplate, InfraMachineTemplatePoolList resource definition

For a given InfraMachinePool resource, you SHOULD also add a corresponding InfraMachinePoolTemplate resource in order to use it in ClusterClasses. The template resource MUST be name <InfraMachinePool>Template.

// +kubebuilder:object:root=true
// +kubebuilder:resource:path=foomachinepooltemplates,scope=Namespaced,categories=cluster-api
// +kubebuilder:storageversion

// FooMachinePoolTemplate is the Schema for the foomachinepooltemplates API.
type FooMachinePoolTemplate struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec FooMachinePoolTemplateSpec `json:"spec,omitempty"`
}

type FooMachinePoolTemplateSpec struct {
    Template FooMachinePooleTemplateResource `json:"template"`
}

type FooMachinePoolTemplateResource struct {
    // Standard object's metadata.
    // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
    // +optional
    ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"`
    Spec FooMachinePoolSpec `json:"spec"`
}

NOTE: in this example spec.template.spec embeds FooMachinePoolSpec from MachinePool. This might not always be the best choice depending of if/how InfraMachinePools spec fields applies to many machine pools vs only one.

For each InfraMachinePoolTemplate resource, you MUST also add the corresponding list resource. The list resource MUST be named as <InfraMachinePoolTemplate>List.

// +kubebuilder:object:root=true

// FooMachinePoolTemplateList contains a list of FooMachinePoolTemplates.
type FooMachinePoolTemplateList struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ListMeta `json:"metadata,omitempty"`
    Items           []FooMachinePoolTemplate `json:"items"`
}

InfraMachinePoolTemplate: support for SSA dry run

When Cluster API’s topology controller is trying to identify differences between templates defined in a ClusterClass and the current Cluster topology, it is required to run [Server Side Apply] (SSA) dry run call.

However, in case you have immutability checks for your InfraMachinePoolTemplate, this can lead the SSA dry run call to error.

In order to avoid this InfraMachinePoolTemplate MUST specifically implement support for SSA dry run calls from the topology controller.

The implementation requires to use controller runtime’s CustomValidator, available since version v0.12.3.

This will allow to skip the immutability check only when the topology controller is dry running while preserving the validation behavior for all other cases.

Multi tenancy

Multi tenancy in Cluster API defines the capability of an infrastructure provider to manage different credentials, each one of them corresponding to an infrastructure tenant.

See infrastructure Provider Security Guidance for considerations about cloud provider credential management.

Please also note that Cluster API does not support running multiples instances of the same provider, which someone can assume an alternative solution to implement multi tenancy; same applies to the clusterctl CLI.

See Support running multiple instances of the same provider for more context.

However, if you want to make it possible for users to run multiples instances of your provider, your controller’s SHOULD:

  • support the --namespace flag.
  • support the --watch-filter flag.

Please, read carefully the page linked above to fully understand implications and risks related to this option.

Clusterctl support

The clusterctl command is designed to work with all the providers compliant with the rules defined in the clusterctl provider contract.

Contract rules for BootstrapConfig

Bootstrap providers SHOULD implement a BootstrapConfig resource using Kubernetes’ CustomResourceDefinition (CRD).

The goal of a BootstrapConfig resource is to generates bootstrap data that is used to bootstrap a Kubernetes node. These may be e.g. cloud-init scripts.

The BootstrapConfig resource will be referenced by one of the Cluster API core resources, Machine.

The Machine’s controller will be responsible to coordinate operations of the BootstrapConfig, and the interaction between the Machine’s controller and the BootstrapConfig resource is based on the contract rules defined in this page.

Once contract rules are satisfied by a BootstrapConfig implementation, other implementation details could be addressed according to the specific needs (Cluster API is not prescriptive).

Nevertheless, it is always recommended to take a look at Cluster API controllers, in-tree providers, other providers and use them as a reference implementation (unless custom solutions are required in order to address very specific needs).

In order to facilitate the initial design for each BootstrapConfig resource, a few implementation best practices are explicitly called out in dedicated pages.

Rules (contract version v1beta2)

Note:

  • All resources refers to all the provider’s resources “core” Cluster API interacts with; In the context of this page: BootstrapConfig, BootstrapConfigTemplate and corresponding list types

All resources: scope

All resources MUST be namespace-scoped.

All resources: TypeMeta and ObjectMeta field

All resources MUST have the standard Kubernetes TypeMeta and ObjectMeta fields.

All resources: APIVersion field value

In Kubernetes APIVersion is a combination of API group and version. Special consideration MUST applies to both API group and version for all the resources Cluster API interacts with.

All resources: API group

The domain for Cluster API resources is cluster.x-k8s.io, and bootstrap providers under the Kubernetes SIGS org generally use bootstrap.cluster.x-k8s.io as API group.

If your provider uses a different API group, you MUST grant full read/write RBAC permissions for resources in your API group to the Cluster API core controllers. If any resource sets another resource as the owner with blockOwnerDeletion set, additional RBAC to update finalizers on the owner resource is required. The canonical way to do so is via a ClusterRole resource with the aggregation label cluster.x-k8s.io/aggregate-to-manager: "true".

The following is an example ClusterRole for a FooConfig resource in the bootstrap.foo.com API group:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
    name: capi-foo-clusters
    labels:
      cluster.x-k8s.io/aggregate-to-manager: "true"
rules:
- apiGroups:
    - bootstrap.foo.com
  resources:
    - fooconfig
    - fooconfigtemplates
  verbs:
    - create
    - delete
    - get
    - list
    - patch
    - update
    - watch

Note: The write permissions are required because Cluster API manages BootstrapConfig generated from BootstrapConfigTemplates; when using ClusterClass and managed topologies, also BootstrapConfigTemplates are managed directly by Cluster API.

All resources: version

The resource Version defines the stability of the API and its backward compatibility guarantees. Examples include v1alpha1, v1beta1, v1, etc. and are governed by the Kubernetes API Deprecation Policy.

Your provider SHOULD abide by the same policies.

Note: The version of your provider does not need to be in sync with the version of core Cluster API resources. Instead, prefer choosing a version that matches the stability of the provider API and its backward compatibility guarantees.

Additionally:

Providers MUST set cluster.x-k8s.io/<version> label on the BootstrapConfig Custom Resource Definitions.

The label is a map from a Cluster API contract version to your Custom Resource Definition versions. The value is an underscore-delimited (_) list of versions. Each value MUST point to an available version in your CRD Spec.

The label allows Cluster API controllers to perform automatic conversions for object references, the controllers will pick the last available version in the list if multiple versions are found.

To apply the label to CRDs it’s possible to use labels in your kustomization.yaml file, usually in config/crd:

labels:
- pairs:
    cluster.x-k8s.io/v1beta1: v1beta1
    cluster.x-k8s.io/v1beta2: v1beta2

An example of this is in the Kubeadm Bootstrap provider.

BootstrapConfig, BootstrapConfigList resource definition

You MUST define a BootstrapConfig resource. The BootstrapConfig resource name must have the format produced by sigs.k8s.io/cluster-api/util/contract.CalculateCRDName(Group, Kind).

Note: Cluster API is using such a naming convention to avoid an expensive CRD lookup operation when looking for labels from the CRD definition of the BootstrapConfig resource.

It is a generally applied convention to use names in the format ${env}Config, where ${env} is a, possibly short, name for the bootstrapper in question. For example KubeadmConfig is an implementation for kubeadm.

// +kubebuilder:object:root=true
// +kubebuilder:resource:path=fooconfig,scope=Namespaced,categories=cluster-api
// +kubebuilder:storageversion
// +kubebuilder:subresource:status

// FooConfig is the Schema for fooconfig.
type FooConfig struct {
    metav1.TypeMeta `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`
    Spec FooConfigSpec `json:"spec,omitempty"`
    Status FooConfigStatus `json:"status,omitempty"`
}

type FooConfigSpec struct {
    // See other rules for more details about mandatory/optional fields in BootstrapConfig spec.
    // Other fields SHOULD be added based on the needs of your provider.
}

type FooConfigStatus struct {
    // See other rules for more details about mandatory/optional fields in BootstrapConfig status.
    // Other fields SHOULD be added based on the needs of your provider.
}

For each BootstrapConfig resource, you MUST also add the corresponding list resource. The list resource MUST be named as <BootstrapConfig>List.

// +kubebuilder:object:root=true

// FooConfigList contains a list of fooconfig.
type FooConfigList struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ListMeta `json:"metadata,omitempty"`
    Items           []FooConfig `json:"items"`
}

BootstrapConfig: data secret

Each BootstrapConfig MUST store generated bootstrap data into a Kubernetes Secret and surface the secret name in .status.dataSecretName.

type FooConfigStatus struct {
    // dataSecretName is the name of the secret that stores the bootstrap data script.
    // +optional
    // +kubebuilder:validation:MinLength=1
    // +kubebuilder:validation:MaxLength=253
    DataSecretName string `json:"dataSecretName,omitempty"`

    // See other rules for more details about mandatory/optional fields in BootstrapConfig status.
    // Other fields SHOULD be added based on the needs of your provider.
}

The Secret containing bootstrap data must:

  1. Use the API resource’s status.dataSecretName for its name
  2. Have the label cluster.x-k8s.io/cluster-name set to the name of the cluster
  3. Have a controller owner reference to the API resource
  4. Have a single key, value, containing the bootstrap data

Note: because the dataSecretName is part of status, this value must be deterministically recreatable from the data in the Cluster, Machine, and/or bootstrap resource. If the name is randomly generated, it is not always possible to move the resource and its associated secret from one management cluster to another.

When the Secret is created its name MUST surface in the status.dataSecretName field of the BootstrapConfig resource; the Machine controller will surface this info in Machine’s spec.boostrap.dataSecretName when BootstrapConfig: initialization completed.

BootstrapConfig: initialization completed

Each BootstrapConfig MUST report when the bootstrap data secret is fully provisioned (initialization) by setting status.initialization.dataSecretCreated in the BootstrapConfig resource.

type FooConfigStatus struct {
    // initialization provides observations of the FooConfig initialization process.
    // NOTE: Fields in this struct are part of the Cluster API contract and are used to orchestrate initial Machine provisioning.
    // +optional
    Initialization FooConfigInitializationStatus `json:"initialization,omitempty,omitzero"`
    
    // See other rules for more details about mandatory/optional fields in BootstrapConfig status.
    // Other fields SHOULD be added based on the needs of your provider.
}

// FooConfigInitializationStatus provides observations of the FooConfig initialization process.
// +kubebuilder:validation:MinProperties=1
type FooConfigInitializationStatus struct {
    // dataSecretCreated is true when the Machine's boostrap secret is created.
    // NOTE: this field is part of the Cluster API contract, and it is used to orchestrate initial Machine provisioning.
    // +optional
    DataSecretCreated *bool `json:"dataSecretCreated,omitempty"`
}

Once status.initialization.dataSecretCreated the Machine “core” controller will bubble up this info in Machine’s status.initialization.bootstrapDataSecretCreated; also BootstrapConfig’s status.dataSecretName will be surfaced on Machine’s corresponding fields at the same time.

BootstrapConfig: conditions

According to Kubernetes API Conventions, Conditions provide a standard mechanism for higher-level status reporting from a controller.

Providers implementers SHOULD implement status.conditions for their BootstrapConfig resource. In case conditions are implemented on a BootstrapConfig resource, Cluster API will only consider conditions providing the following information:

  • type (required)
  • status (required, one of True, False, Unknown)
  • reason (optional, if omitted a default one will be used)
  • message (optional, if omitted an empty message will be used)
  • lastTransitionTime (optional, if omitted time.Now will be used)
  • observedGeneration (optional, if omitted the generation of the BootstrapConfig resource will be used)

Other fields will be ignored.

If a condition with type Ready exist, such condition will be mirrored in Machine’s BootstrapConfigReady condition.

Please note that the Ready condition is expected to surface the status of the BootstrapConfig during its own entire lifecycle, including initial provisioning, but not limited to that.

See Improving status in CAPI resources for more context.

BootstrapConfig: terminal failures

Starting from the v1beta2 contract version, there is no more special treatment for provider’s terminal failures within Cluster API.

In case necessary, “terminal failures” should be surfaced using conditions, with a well documented type/reason; it is up to consumers to treat them accordingly.

See Improving status in CAPI resources for more context.

BootstrapConfig: support for in-place changes

In case you are developing an bootstrap config provider with support for in-place updates of the Machine configuration, you should consider following recommendations during implementation.

  • The Update Extension is the component responsible for orchestrating in-place changes on Machines. Accordingly, the BootstrapConfig controller should ignore in-place changes and do not re-generate the bootstrap config.
  • It might be useful to start thinking about the BootstrapConfig API surface as a set of fields with one of the following behaviors:
    • “Immutable” fields that can only be changed by performing a rollout.
    • “Mutable” fields that will be “reconciled” by the Update Extension.
  • The validation webhook for the BootstrapConfig CR should allow changes to “mutable” fields; in case a bootstrap config provider wants to allow this change selectively, e.g. only when applied by core CAPI, please reach out to maintainers to discuss options.
  • Please note that the above field classification do not apply to the BootstrapConfigTemplate object.

See Proposal.

BootstrapConfigTemplate, BootstrapConfigTemplateList resource definition

For a given BootstrapConfig resource, you MUST also add a corresponding BootstrapConfigTemplate resources in order to use it when defining set of machines, e.g. MachineDeployments.

The template resource MUST be named as <BootstrapConfig>Template.

// +kubebuilder:object:root=true
// +kubebuilder:resource:path=fooconfigtemplates,scope=Namespaced,categories=cluster-api
// +kubebuilder:storageversion

// FooConfigTemplate is the Schema for the fooconfigtemplates API.
type FooConfigTemplate struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec FooConfigTemplateSpec `json:"spec,omitempty"`
}

type FooConfigTemplateSpec struct {
    Template FooConfigTemplateResource `json:"template"`
}

type FooConfigTemplateResource struct {
    // Standard object's metadata.
    // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
    // +optional
    ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"`
    Spec FooConfigSpec `json:"spec"`
}

NOTE: in this example BootstrapConfigTemplate’s spec.template.spec embeds FooConfigSpec from BootstrapConfig. This might not always be the best choice depending of if/how BootstrapConfig’s spec fields applies to many machines vs only one.

For each BootstrapConfigTemplate resource, you MUST also add the corresponding list resource. The list resource MUST be named as <BootstrapConfigTemplate>List.

// +kubebuilder:object:root=true

// FooConfigTemplateList contains a list of FooConfigTemplates.
type FooConfigTemplateList struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ListMeta `json:"metadata,omitempty"`
    Items           []FooConfigTemplate `json:"items"`
}

BootstrapConfigTemplate: support for SSA dry run

When Cluster API’s topology controller is trying to identify differences between templates defined in a ClusterClass and the current Cluster topology, it is required to run Server Side Apply (SSA) dry run call.

However, in case you immutability checks for your BootstrapConfigTemplate, this can lead the SSA dry run call to errors.

In order to avoid this BootstrapConfigTemplate MUST specifically implement support for SSA dry run calls from the topology controller.

The implementation requires to use controller runtime’s Validator.

This will allow to skip the immutability check only when the topology controller is dry running while preserving the validation behavior for all other cases.

See the DevMachineTemplate webhook as a reference for a compatible implementation.

Sentinel file

A bootstrap provider’s bootstrap data must create /run/cluster-api/bootstrap-success.complete (or C:\run\cluster-api\bootstrap-success.complete for Windows machines) upon successful bootstrapping of a Kubernetes node. This allows infrastructure providers to detect and act on bootstrap failures.

Taint Nodes at creation

A bootstrap provider can optionally taint worker nodes at creation with node.cluster.x-k8s.io/uninitialized:NoSchedule. This taint is used to prevent workloads to be scheduled on Nodes before the node is initialized by Cluster API. As of today the Node initialization consists of syncing labels from Machines to Nodes. Once the labels have been initially synced the taint is removed from the Node.

Support for running multiple instances

Cluster API does not support running multiples instances of the same provider, which someone can assume an alternative solution to implement multi tenancy; same applies to the clusterctl CLI.

See Support running multiple instances of the same provider for more context.

However, if you want to make it possible for users to run multiples instances of your provider, your controller’s SHOULD:

  • support the --namespace flag.
  • support the --watch-filter flag.

Please, read carefully the page linked above to fully understand implications and risks related to this option.

Clusterctl support

The clusterctl command is designed to work with all the providers compliant with the rules defined in the clusterctl provider contract.

BootstrapConfig: pausing

Providers SHOULD implement the pause behaviour for every object with a reconciliation loop. This is done by checking if spec.paused is set on the Cluster object and by checking for the cluster.x-k8s.io/paused annotation on the BootstrapConfig object.

If implementing the pause behavior, providers SHOULD surface the paused status of an object using the Paused condition: Status.Conditions[Paused].

Typical BootstrapConfig reconciliation workflow

A bootstrap provider must respond to changes to its BootstrapConfig resources. This process is typically called reconciliation. The provider must watch for new, updated, and deleted resources and respond accordingly.

As a reference you can look at the following workflow to understand how the typical reconciliation workflow is implemented in BootstrapConfig controllers:

Behavior

A bootstrap provider must respond to changes to its bootstrap resources. This process is typically called reconciliation. The provider must watch for new, updated, and deleted resources and respond accordingly.

The following diagram shows the typical logic for a bootstrap provider:

  1. If the resource does not have a Machine owner, exit the reconciliation
    1. The Cluster API Machine reconciler populates this based on the value in the Machine’s spec.bootstrap.configRef field.
  2. If the Cluster to which this resource belongs cannot be found, exit the reconciliation
  3. Deterministically generate the name for the bootstrap data secret
  4. Try to retrieve the Secret with the name from the previous step
    1. If it does not exist, generate bootstrap data and create the Secret
  5. Set status.dataSecretName to the generated name
  6. Set status.initialization.dataSecretCreated to true
  7. Patch the resource to persist changes

Contract rules for ControlPlane

Control plane providers MUST implement a ControlPlane resource using Kubernetes’ CustomResourceDefinition (CRD).

The goal of a ControlPlane resource is to instantiate a Kubernetes control plane; a Kubernetes control plane at least contains the following components:

  • Kubernetes API Server
  • Kubernetes Controller Manager
  • Kubernetes Scheduler
  • etcd (if not externally managed)

Optional control plane components are

  • Cloud controller manager
  • Cluster DNS (e.g. CoreDNS)
  • Service proxy (e.g. kube-proxy)

Instead, CNI should be left to users to apply once the control plane is instantiated.

The ControlPlane resource will be referenced by one of the Cluster API core resources, Cluster.

The Cluster’s controller will be responsible to coordinate operations of the ControlPlane, and the interaction between the Cluster’s controller and the ControlPlane resource is based on the contract rules defined in this page.

Once contract rules are satisfied by a ControlPlane implementation, other implementation details could be addressed according to the specific needs (Cluster API is not prescriptive).

Nevertheless, it is always recommended to take a look at Cluster API controllers, in-tree providers, other providers and use them as a reference implementation (unless custom solutions are required in order to address very specific needs).

In order to facilitate the initial design for each ControlPlane resource, a few implementation best practices are explicitly called out in dedicated pages.

On top of that special consideration MUST be done to ensure security around private key material required to create and run the Kubernetes control plane.

Rules (contract version v1beta2)

RuleMandatoryNote
All resources: scopeYes
All resources: TypeMeta and ObjectMetafieldYes
All resources: APIVersion field valueYes
ControlPlane, ControlPlaneList resource definitionYes
ControlPlane: endpointNoMandatory if control plane endpoint is not provided by other means.
ControlPlane: replicasNoMandatory if control plane has a notion of number of instances.
ControlPlane: versionNoMandatory if control plane allows direct management of the Kubernetes version in use; Mandatory for cluster class support.
ControlPlane: machinesNoMandatory if control plane instances are represented with a set of Cluster API Machines.
ControlPlane: rolloutAfterNo
ControlPlane: initialization completedYes
ControlPlane: in-place updatesNoOnly supported for control plane providers with control plane machines
ControlPlane: conditionsNo
ControlPlane: terminal failuresNo
ControlPlaneTemplate, ControlPlaneTemplateList resource definitionNoMandatory for ClusterClasses support
Cluster kubeconfig managementYes
Cluster certificate managementNo
Machine placementNo
Metadata propagationNo
MinReadySeconds and UpToDate propagationNo
Support for running multiple instancesNoMandatory for clusterctl CLI support
Clusterctl supportNoMandatory for clusterctl CLI support
ControlPlane: pausingNo

All resources: scope

All resources MUST be namespace-scoped.

All resources: TypeMeta and ObjectMeta field

All resources MUST have the standard Kubernetes TypeMeta and ObjectMeta fields.

All resources: APIVersion field value

In Kubernetes APIVersion is a combination of API group and version. Special consideration MUST applies to both API group and version for all the resources Cluster API interacts with.

All resources: API group

The domain for Cluster API resources is cluster.x-k8s.io, and control plane providers under the Kubernetes SIGS org generally use controlplane.cluster.x-k8s.io as API group.

If your provider uses a different API group, you MUST grant full read/write RBAC permissions for resources in your API group to the Cluster API core controllers. If any resource sets another resource as the owner with blockOwnerDeletion set, additional RBAC to update finalizers on the owner resource is required. The canonical way to do so is via a ClusterRole resource with the aggregation label cluster.x-k8s.io/aggregate-to-manager: "true".

The following is an example ClusterRole for a FooControlPlane resource in the controlplane.foo.com API group:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
    name: capi-foo-controlplane
    labels:
      cluster.x-k8s.io/aggregate-to-manager: "true"
rules:
- apiGroups:
    - controlplane.foo.com
  resources:
    - foocontrolplanes
  verbs:
    - create
    - delete
    - get
    - list
    - patch
    - update
    - watch
- apiGroups:
    - controlplane.foo.com
  resources:
    - foocontrolplanetemplates
  verbs:
    - get
    - list
    - patch
    - update
    - watch

Note: The write permissions allow the Cluster controller to set owner references and labels on the ControlPlane resources; write permissions are not used for general mutations of ControlPlane resources, unless specifically required (e.g. when using ClusterClass and managed topologies).

All resources: version

The resource Version defines the stability of the API and its backward compatibility guarantees. Examples include v1alpha1, v1beta1, v1, etc. and are governed by the Kubernetes API Deprecation Policy.

Your provider SHOULD abide by the same policies.

Note: The version of your provider does not need to be in sync with the version of core Cluster API resources. Instead, prefer choosing a version that matches the stability of the provider API and its backward compatibility guarantees.

Additionally:

Providers MUST set cluster.x-k8s.io/<version> label on the InfraCluster Custom Resource Definitions.

The label is a map from a Cluster API contract version to your Custom Resource Definition versions. The value is an underscore-delimited (_) list of versions. Each value MUST point to an available version in your CRD Spec.

The label allows Cluster API controllers to perform automatic conversions for object references, the controllers will pick the last available version in the list if multiple versions are found.

To apply the label to CRDs it’s possible to use labels in your kustomization.yaml file, usually in config/crd:

labels:
- pairs:
    cluster.x-k8s.io/v1beta1: v1beta1
    cluster.x-k8s.io/v1beta2: v1beta2

An example of this is in the Kubeadm Bootstrap provider.

ControlPlane, ControlPlaneList resource definition

You MUST define a ControlPlane resource. The ControlPlane resource name must have the format produced by sigs.k8s.io/cluster-api/util/contract.CalculateCRDName(Group, Kind).

Note: Cluster API is using such a naming convention to avoid an expensive CRD lookup operation when looking for labels from the CRD definition of the ControlPlane resource.

It is a generally applied convention to use names in the format ${env}ControlPlane, where ${env} is a, possibly short, name for the control plane implementation in question. For example KubeadmControlPlane is an implementation of a control plane using kubeadm as a bootstrapper tool.

// +kubebuilder:object:root=true
// +kubebuilder:resource:path=foocontrolplanes,shortName=foocp,scope=Namespaced,categories=cluster-api
// +kubebuilder:storageversion
// +kubebuilder:subresource:status

// FooControlPlane is the Schema for foocontrolplanes.
type FooControlPlane struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`
    Spec FooControlPlaneSpec `json:"spec,omitempty"`
    Status FooControlPlaneStatus `json:"status,omitempty"`
}

type FooControlPlaneSpec struct {
    // See other rules for more details about mandatory/optional fields in ControlPlane spec.
    // Other fields SHOULD be added based on the needs of your provider.
}

type FooControlPlaneStatus struct {
    // See other rules for more details about mandatory/optional fields in ControlPlane status.
    // Other fields SHOULD be added based on the needs of your provider.
}

For each ControlPlane resource, you MUST also add the corresponding list resource. The list resource MUST be named as <ControlPlane>List.

// +kubebuilder:object:root=true

// FooControlPlaneList contains a list of foocontrolplanes.
type FooControlPlaneList struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ListMeta `json:"metadata,omitempty"`
    Items           []FooControlPlane `json:"items"`
}

ControlPlane: endpoint

Each Cluster needs a control plane endpoint to sit in front of control plane machines. Control plane endpoint can be provided in three ways in Cluster API: by the users, by the control plane provider or by the infrastructure provider.

In case you are developing a control plane provider which is responsible to provide a control plane endpoint for each Cluster, the host and port of the generated control plane endpoint MUST surface on spec.controlPlaneEndpoint in the ControlPlane resource.

type FooControlPlaneSpec struct {
    // controlPlaneEndpoint represents the endpoint used to communicate with the control plane.
    // +optional
    ControlPlaneEndpoint APIEndpoint `json:"controlPlaneEndpoint,omitempty,omitzero"`
    
    // See other rules for more details about mandatory/optional fields in ControlPlane spec.
    // Other fields SHOULD be added based on the needs of your provider.
}

// APIEndpoint represents a reachable Kubernetes API endpoint.
// +kubebuilder:validation:MinProperties=1
type APIEndpoint struct {
    // host is the hostname on which the API server is serving.
    // +optional
    // +kubebuilder:validation:MinLength=1
    // +kubebuilder:validation:MaxLength=512
    Host string `json:"host,omitempty"`

    // port is the port on which the API server is serving.
    // +optional
    // +kubebuilder:validation:Minimum=1
    // +kubebuilder:validation:Maximum=65535
    Port int32 `json:"port,omitempty"`
}

Once spec.controlPlaneEndpoint is set on the ControlPlane resource and the ControlPlane: initialization completed, the Cluster controller will surface this info in Cluster’s spec.controlPlaneEndpoint.

If instead you are developing a control plane provider which is NOT responsible to provide a control plane endpoint, the implementer should exit reconciliation until it sees Cluster’s spec.controlPlaneEndpoint populated.

ControlPlane: replicas

In case you are developing a control plane provider which allows control of the number of replicas of the Kubernetes control plane instances in your control plane, following fields MUST be implemented in the ControlPlane spec.

type FooControlPlaneSpec struct {
    // replicas represent the number of desired replicas.
    // This is a pointer to distinguish between explicit zero and not specified.
    // +optional
    Replicas *int32 `json:"replicas,omitempty"`
    
    // See other rules for more details about mandatory/optional fields in ControlPlane spec.
    // Other fields SHOULD be added based on the needs of your provider.
}

Following fields MUST be implemented in the ControlPlane status.

type FooControlPlaneStatus struct {
    // selector is the label selector in string format to avoid introspection
    // by clients, and is used to provide the CRD-based integration for the
    // scale subresource and additional integrations for things like kubectl
    // describe. The string will be in the same format as the query-param syntax.
    // More info about label selectors: http://kubernetes.io/docs/user-guide/labels#label-selectors
    // +optional
    Selector string `json:"selector,omitempty"`

    // replicas is the total number of machines targeted by this control plane
    // (their labels match the selector).
    // +optional
    Replicas *int32 `json:"replicas,omitempty"`

    // readyReplicas is the number of ready replicas for this ControlPlane. A machine is considered ready when Machine's Ready condition is true.
    // +optional
    ReadyReplicas *int32 `json:"readyReplicas,omitempty"`

    // availableReplicas is the number of available replicas for this ControlPlane. A machine is considered available when Machine's Available condition is true.
    // +optional
    AvailableReplicas *int32 `json:"availableReplicas,omitempty"`

    // upToDateReplicas is the number of up-to-date replicas targeted by this ControlPlane. A machine is considered available when Machine's  UpToDate condition is true.
    // +optional
    UpToDateReplicas *int32 `json:"upToDateReplicas,omitempty"`

    // See other rules for more details about mandatory/optional fields in ControlPlane status.
    // Other fields SHOULD be added based on the needs of your provider.
}

As you might have already noticed from the status.selector field, the ControlPlane custom resource definition MUST support the scale subresource with the following signature:

scale:
  labelSelectorPath: .status.selector
  specReplicasPath: .spec.replicas
  statusReplicasPath: .status.replicas
status: {}

More information about the scale subresource can be found in the Kubernetes documentation.

ControlPlane: version

In case you are developing a control plane provider which allows control of the version of the Kubernetes control plane instances in your control plane, following fields MUST be implemented in the ControlPlane spec.

type FooControlPlaneSpec struct {
    // version defines the desired Kubernetes version for the control plane. 
    // The value must be a valid semantic version; also if the value provided by the user does not start with the v prefix, it
    // must be added.
    // +required
    // +kubebuilder:validation:MinLength=1
    // +kubebuilder:validation:MaxLength=256
    Version string `json:"version"`
    
    // See other rules for more details about mandatory/optional fields in ControlPlane spec.
    // Other fields SHOULD be added based on the needs of your provider.
}

ControlPlane providers MUST report version information in the ControlPlane status by implementing at least one of the following fields.

status.versions is the preferred source of truth for surfacing control plane versions. Entries in this list MUST be ordered from the older to the newer version. Each entry MUST include a valid semantic version and if control of the number of replicas is supported the number of replicas at that version must be set as well.

type FooControlPlaneStatus struct {
    // versions is the aggregated Kubernetes versions in this control plane.
    // +optional
    // +listType=map
    // +listMapKey=version
    // +kubebuilder:validation:MinItems=1
    // +kubebuilder:validation:MaxItems=100
    Versions []clusterv1.StatusVersion `json:"versions,omitempty"`

    // See other rules for more details about mandatory/optional fields in ControlPlane status.
    // Other fields SHOULD be added based on the needs of your provider.
}

status.version can be used as an alternative or as a fallback mechanism, but support for this field will be removed in the next Cluster API contract version.

type FooControlPlaneStatus struct {
    // version represents the minimum Kubernetes version for the control plane machines
    // in the cluster.
    //
    // Deprecated: This field is deprecated and is going to be removed in a future API version.
    // Please use status.versions instead.
    // +optional
    // +kubebuilder:validation:MinLength=1
    // +kubebuilder:validation:MaxLength=256
    Version string `json:"version,omitempty"`
    
    // See other rules for more details about mandatory/optional fields in ControlPlane status.
    // Other fields SHOULD be added based on the needs of your provider.
}

NOTE: To align with API conventions, we recommend since the v1beta2 contract that the Version field should be of type string (it was *string before). Both are compatible with the v1beta2 contract though. NOTE: The minimum Kubernetes version, and more specifically the API server version, will be used to determine when a control plane is fully upgraded and for enforcing Kubernetes version skew policies when a Cluster derived from a ClusterClass is managed by the Topology controller.

ControlPlane: machines

In case you are developing a control plane provider which uses a Cluster API Machine object to represent each control plane instance, the providers MUST set the cluster.x-k8s.io/control-plane label with an empty value on the created Machines.

Additionally following the fields MUST be implemented in the ControlPlane spec.

type FooControlPlaneSpec struct {
    // machineTemplate contains information about how machines
    // should be shaped when creating or updating a control plane.
    // +required
    MachineTemplate FooControlPlaneMachineTemplate `json:"machineTemplate"`
    
    // See other rules for more details about mandatory/optional fields in ControlPlane spec.
    // Other fields SHOULD be added based on the needs of your provider.
}

type FooControlPlaneMachineTemplate struct {
    // metadata is the standard object's metadata.
    // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
    // +optional
    ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"`

    // spec defines the spec for Machines of the control plane.
    // +optional
    Spec FooControlPlaneMachineTemplateSpec `json:"spec,omitempty,omitzero"`
}

type FooControlPlaneMachineTemplateSpec struct {
	// infrastructureRef is a required reference to a custom infra machine template resource
	// offered by an infrastructure provider.
	// +required
	InfrastructureRef clusterv1.ContractVersionedObjectReference `json:"infrastructureRef"`

	// deletion contains configuration options for Machine deletion.
	// +optional
	Deletion FooControlPlaneMachineTemplateDeletionSpec `json:"deletion,omitempty,omitzero"`
}

// FooControlPlaneMachineTemplateDeletionSpec contains configuration options for Machine deletion.
// +kubebuilder:validation:MinProperties=1
type FooControlPlaneMachineTemplateDeletionSpec struct {
    // nodeDrainTimeoutSeconds is the total amount of time that the controller will spend on draining a controlplane node
    // The default value is 0, meaning that the node can be drained without any time limitations.
	// NOTE: nodeDrainTimeoutSeconds is different from `kubectl drain --timeout`
    // +optional
    // +kubebuilder:validation:Minimum=0
    NodeDrainTimeoutSeconds *int32 `json:"nodeDrainTimeoutSeconds,omitempty"`
    
    // nodeVolumeDetachTimeoutSeconds is the total amount of time that the controller will spend on waiting for all volumes
    // to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
    // +optional
    // +kubebuilder:validation:Minimum=0
    NodeVolumeDetachTimeoutSeconds *int32 `json:"nodeVolumeDetachTimeoutSeconds,omitempty"`
    
    // nodeDeletionTimeoutSeconds defines how long the machine controller will attempt to delete the Node that the Machine
    // hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely.
    // If no value is provided, the default value for this property of the Machine resource will be used.
    // +optional
    // +kubebuilder:validation:Minimum=0
    NodeDeletionTimeoutSeconds *int32 `json:"nodeDeletionTimeoutSeconds,omitempty"`
  
    // Other fields SHOULD be added based on the needs of your provider.
}

Please note that some of the above fields (metadata, nodeDrainTimeoutSeconds, nodeVolumeDetachTimeoutSeconds, nodeDeletionTimeoutSeconds) must be propagated to machines without triggering rollouts. See In place propagation of changes affecting Kubernetes objects only as well as Metadata propagation for more details.

In case you are developing a control plane provider that allows definition of machine readiness gates, you SHOULD also implement the following spec.machineTemplate.spec field.

type FooControlPlaneMachineTemplateSpec struct {
    // readinessGates specifies additional conditions to include when evaluating Machine Ready condition.
    //
    // This field can be used e.g. by Cluster API control plane providers to extend the semantic of the
    // Ready condition for the Machine they control, like the kubeadm control provider adding ReadinessGates
    // for the APIServerPodHealthy, SchedulerPodHealthy conditions, etc.
    //
    // Another example are external controllers, e.g. responsible to install special software/hardware on the Machines;
    // they can include the status of those components with a new condition and add this condition to ReadinessGates.
    //
    // NOTE: This field is considered only for computing v1beta2 conditions.
    // NOTE: In case readinessGates conditions start with the APIServer, ControllerManager, Scheduler prefix, and all those
    // readiness gates condition are reporting the same message, when computing the Machine's Ready condition those
    // readinessGates will be replaced by a single entry reporting "Control plane components: " + message.
    // This helps to improve readability of conditions bubbling up to the Machine's owner resource / to the Cluster).
    // +optional
    // +listType=map
    // +listMapKey=conditionType
    // +kubebuilder:validation:MinItems=1
    // +kubebuilder:validation:MaxItems=32
    ReadinessGates []clusterv1.MachineReadinessGate `json:"readinessGates,omitempty"`

    // See other rules for more details about mandatory/optional fields in ControlPlane spec.
    // Other fields SHOULD be added based on the needs of your provider.
}

NOTE: In the v1beta1 contract the readinessGates field was located directly in the spec.machineTemplate field.

In case you are developing a control plane provider that allows definition of machine taints, you SHOULD also implement the following spec.machineTemplate.spec field.

type FooControlPlaneMachineTemplateSpec struct {
	// taints are the node taints that Cluster API will manage.
	// This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes,
	// e.g. the node controller might add the node.kubernetes.io/not-ready taint.
	// Only those taints defined in this list will be added or removed by core Cluster API controllers.
	//
	// There can be at most 64 taints.
	// A pod would have to tolerate all existing taints to run on the corresponding node.
	//
	// NOTE: This list is implemented as a "map" type, meaning that individual elements can be managed by different owners.
	// +optional
	// +listType=map
	// +listMapKey=key
	// +listMapKey=effect
	// +kubebuilder:validation:MinItems=1
	// +kubebuilder:validation:MaxItems=64
	Taints []clusterv1.MachineTaint `json:"taints,omitempty"`

    // See other rules for more details about mandatory/optional fields in ControlPlane spec.
    // Other fields SHOULD be added based on the needs of your provider.
}

In case you are developing a control plane provider where control plane instances uses a Cluster API Machine object to represent each control plane instance, but those instances do not show up as a Kubernetes node (for example, managed control plane providers for AKS, EKS, GKE etc), you SHOULD also implement the following status field.

type FooControlPlaneStatus struct {
    // externalManagedControlPlane is a bool that should be set to true if the Node objects do not exist in the cluster.
    // +optional
    ExternalManagedControlPlane *bool `json:"externalManagedControlPlane,omitempty"`

    // See other rules for more details about mandatory/optional fields in ControlPlane status.
    // Other fields SHOULD be added based on the needs of your provider.
}

NOTE: To align with API conventions, we recommend since the v1beta2 contract that the ExternalManagedControlPlane field should be of type *bool (it was bool before). Both are compatible with the v1beta2 contract though.

Please note that by representing each control plane instance as Cluster API machine, each control plane instance can benefit from several Cluster API behaviours, for example:

  • Machine provisioning workflow (in coordination with an InfraMachine and a BootstrapConfig of your choice)
  • Machine health checking
  • Machine drain and wait for volume detach during deletion

ControlPlane: rolloutAfter

In case you are developing a control plane provider which supports scheduled rollout via the rolloutAfter field, following fields MUST be implemented in the ControlPlane spec.

type FooControlPlaneSpec struct {
    // rollout allows you to configure the behaviour of rolling updates to the control plane.
    // +optional
    Rollout FooControlPlaneRolloutSpec `json:"rollout,omitempty,omitzero"`
	
    // See other rules for more details about mandatory/optional fields in ControlPlane status.
    // Other fields SHOULD be added based on the needs of your provider.
}

// +kubebuilder:validation:MinProperties=1
type FooControlPlaneRolloutSpec struct {
    // after is a field to indicate a rollout should be performed
    // after the specified time even if no changes have been made to the
    // FooControlPlane.
    // Example: In the YAML the time can be specified in the RFC3339 format.
    // To specify the rolloutAfter target as March 9, 2023, at 9 am UTC
    // use "2023-03-09T09:00:00Z".
    // +optional
    After metav1.Time `json:"after,omitempty,omitzero"`
}

ControlPlane: initialization completed

Each ControlPlane MUST report when the Kubernetes control plane is initialized; usually a control plane is considered initialized when it can accept requests, no matter if this happens before the control plane is fully provisioned or not.

For example, in a highly available Kubernetes control plane with three instances of each component, usually the control plane can be considered initialized after the first instance is up and running.

A ControlPlane reports when it is initialized by setting status.initialization.controlPlaneInitialized.

type FooControlPlaneStatus struct {
    // initialization provides observations of the FooControlPlane initialization process.
    // NOTE: Fields in this struct are part of the Cluster API contract and are used to orchestrate initial Cluster provisioning.
    // +optional
    Initialization FooControlPlaneInitializationStatus `json:"initialization,omitempty,omitzero"`
    
    // See other rules for more details about mandatory/optional fields in ControlPlane status.
    // Other fields SHOULD be added based on the needs of your provider.
}

// FooControlPlaneInitializationStatus provides observations of the FooControlPlane initialization process.
// +kubebuilder:validation:MinProperties=1
type FooControlPlaneInitializationStatus struct {
    // controlPlaneInitialized is true when the control plane provider reports that the Kubernetes control plane is initialized; 
    // usually a control plane is considered initialized when it can accept requests, no matter if this happens before 
    // the control plane is fully provisioned or not.
    // NOTE: this field is part of the Cluster API contract, and it is used to orchestrate initial Cluster provisioning.
    // +optional
    ControlPlaneInitialized *bool `json:"controlPlaneInitialized,omitempty"`
}

Once status.initialization.controlPlaneInitialized is set the Cluster “core” controller will bubble up this info in Cluster’s status.initialization.controlPlaneInitialized field and in the ControlPlaneInitialized condition.

If defined, also ControlPlane’s spec.controlPlaneEndpoint will be surfaced on Cluster’s corresponding fields at the same time.

ControlPlane: in-place updates

In case a control plane provider would like to provide support for in-place updates, please check the proposal.

Supporting in-place updates requires:

  • implementing the call for the registered CanUpdateMachine hook when performing the “can update in-place” decision.
  • when it is decided to perform the in-place decision:
    • the machine spec must be updated to the desired state, as well as the spec for the corresponding infrastructure machine and bootstrap config
    • while updating those objects also the in-place-updates.internal.cluster.x-k8s.io/update-in-progress annotation must be set
    • once all objects are updated the UpdateMachine hook must be set as pending on the machine object

After above steps are completed, the machine controller will take over and complete the in-place upgrade.

ControlPlane: conditions

According to Kubernetes API Conventions, Conditions provide a standard mechanism for higher-level status reporting from a controller.

Providers implementers SHOULD implement status.conditions for their ControlPlane resource. In case conditions are implemented on a ControlPlane resource, Cluster API will only consider conditions providing the following information:

  • type (required)
  • status (required, one of True, False, Unknown)
  • reason (optional, if omitted a default one will be used)
  • message (optional, if omitted an empty message will be used)
  • lastTransitionTime (optional, if omitted time.Now will be used)
  • observedGeneration (optional, if omitted the generation of the ControlPlane resource will be used)

Other fields will be ignored.

If a condition with type Available exist, such condition will be mirrored in Cluster’s ControlPlaneAvailable condition.

The Available condition is expected to properly represents the fact that a ControlPlane can be operational even if there is a certain degree of not readiness / disruption in the system, or if lifecycle operations are happening.

Last, but not least, in order to ensure a consistent users experience, it is also recommended to consider aligning also other ControlPlane conditions to conditions existing on other Cluster API objects.

For example KubeadmControlPlane implements the following conditions on top of the Available defined by this contract: CertificatesAvailable, EtcdClusterAvailable, MachinesReady, MachinesUpToDate, RollingOut, ScalingUp, ScalingDown, Remediating, Deleting, Paused.

Most notably, If RollingOut, ScalingUp, ScalingDown conditions are implemented, the Cluster controller is going to read them to compute a Cluster level RollingOut, ScalingUp, ScalingDown condition including all the scalable resources.

See Improving status in CAPI resources for more context.

ControlPlane: terminal failures

Starting from the v1beta2 contract version, there is no more special treatment for provider’s terminal failures within Cluster API.

In case necessary, “terminal failures” should be surfaced using conditions, with a well documented type/reason; it is up to consumers to treat them accordingly.

See Improving status in CAPI resources for more context.

ControlPlaneTemplate, ControlPlaneTemplateList resource definition

For a given ControlPlane resource, you should also add a corresponding ControlPlaneTemplate resources in order to use it in ClusterClasses. The template resource MUST be named as <ControlPlane>Template.

// +kubebuilder:object:root=true
// +kubebuilder:resource:path=foocontrolplanetemplates,scope=Namespaced,categories=cluster-api
// +kubebuilder:storageversion

// FooControlPlaneTemplate is the Schema for the fooclustertemplates API.
type FooControlPlaneTemplate struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec FooControlPlaneTemplateSpec `json:"spec,omitempty"`
}

type FooControlPlaneTemplateSpec struct {
    Template FooControlPlaneTemplateResource `json:"template"`
}

type FooControlPlaneTemplateResource struct {
    // Standard object's metadata.
    // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
    // +optional
    ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"`
    Spec FooControlPlaneSpec `json:"spec"`
}

NOTE: in this example ControlPlaneTemplate’s spec.template.spec embeds FooControlPlaneSpec from ControlPlane. This might not always be the best choice depending of if/how ControlPlane’s spec fields applies to many clusters vs only one.

For each ControlPlaneTemplate resource, you MUST also add the corresponding list resource. The list resource MUST be named as <ControlPlaneTemplate>List.

// +kubebuilder:object:root=true

// FooControlPlaneTemplateList contains a list of FooControlPlaneTemplates.
type FooControlPlaneTemplateList struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ListMeta `json:"metadata,omitempty"`
    Items           []FooControlPlaneTemplate `json:"items"`
}

Cluster kubeconfig management

Control Plane providers are expected to create and maintain a Kubeconfig secret for Cluster API to gain access to the workload cluster.

Such secret might be used also by operators to gain initial access to the cluster, but this secret MUST not be shared with other users or applications build on top of Cluster API. Instead, follow instruction in Certificate Management to create custom certificates for additional users or other applications.

The kubeconfig secret MUST:

  • Be created in the same namespace where the Cluster exists
  • Be named <cluster>-kubeconfig
  • Have type cluster.x-k8s.io/secret
  • Be labelled with the key-pair cluster.x-k8s.io/cluster-name=${CLUSTER_NAME}. Note: this label is required for the secret to be retrievable in the cache used by CAPI managers.
  • Have the base64 encoded kubeconfig in the field called value

Important! If a control plane provider uses client certificates for authentication in these Kubeconfigs, the client certificate MUST be kept with a reasonably short expiration period and periodically regenerated to keep a valid set of credentials available. As an example, the Kubeadm Control Plane provider uses a year of validity and refreshes the certificate after 6 months.

Cluster certificate management

Control Plane providers are expected to create and maintain all the certificates required to create and run a Kubernetes cluster.

Cluster certificates MUST be stored as a secrets:

  • In the same namespace where the Cluster exists
  • Following a naming convention <cluster>-<certificate>; common certificate names are ca, etcd, proxy, sa
  • Have type cluster.x-k8s.io/secret
  • Be labelled with the key-pair cluster.x-k8s.io/cluster-name=${CLUSTER_NAME}. Note: this label is required for the secret to be retrievable in the cache used by CAPI managers.

See Certificate Management for more context.

Machine placement

Control Plane providers are expected to place machines in failure domains defined in Cluster’s status.failureDomains field.

More specifically, Control Plane should be spread across failure domains specifically flagged to host control plane machines.

Metadata propagation

Cluster API defines rules to propagate metadata (labels and annotations) across the hierarchies of objects, down to Machines and nodes.

In order to ensure a nice and consistent user experience across the entire Cluster, also ControlPlane providers are expected to implement similar propagation rules for control plane machines.

See. Metadata propagation rules for more details about how metadata should be propagated across the hierarchy of Cluster API objects (use KubeadmControlPlane as a reference).

Also, please note that metadata MUST be propagated to control plane instances machines without triggering rollouts. See In place propagation of changes affecting Kubernetes objects only for more details.

See. Label and Annotations Sync Between Machines and underlying Kubernetes Nodes for more details about how metadata are propagated to Kubernetes Nodes.

MinReadySeconds and UpToDate propagation

Support for running multiple instances

Cluster API does not support running multiples instances of the same provider, which someone can assume an alternative solution to implement multi tenancy; same applies to the clusterctl CLI.

See Support running multiple instances of the same provider for more context.

However, if you want to make it possible for users to run multiples instances of your provider, your controller’s SHOULD:

  • support the --namespace flag.
  • support the --watch-filter flag.

Please, read carefully the page linked above to fully understand implications and risks related to this option.

Clusterctl support

The clusterctl command is designed to work with all the providers compliant with the rules defined in the [clusterctl provider contract].

ControlPlane: pausing

Providers SHOULD implement the pause behaviour for every object with a reconciliation loop. This is done by checking if spec.paused is set on the Cluster object and by checking for the cluster.x-k8s.io/paused annotation on the ControlPlane object.

If implementing the pause behavior, providers SHOULD surface the paused status of an object using the Paused condition: Status.Conditions[Paused].

Typical ControlPlane reconciliation workflow

A control plane provider must respond to changes to its ControlPlane resources. This process is typically called reconciliation. The provider must watch for new, updated, and deleted resources and respond accordingly.

As a reference you can look at the following workflow to understand how the typical reconciliation workflow is implemented in ControlPlane controllers:

clusterctl Provider Contract (contract version v1beta2)

The clusterctl command is designed to work with all the providers compliant with the following rules.

Provider Repositories

Each provider MUST define a provider repository, that is a well-known place where the release assets for a provider are published.

The provider repository MUST contain the following files:

  • The metadata YAML
  • The components YAML

Additionally, the provider repository SHOULD contain the following files:

  • Workload cluster templates

Optionally, the provider repository can include the following files:

  • ClusterClass definitions

Adding a provider to clusterctl

As a Cluster API project, we always have been more than happy to give visibility to all the open source CAPI providers by allowing provider’s maintainers to add their own project to the pre-defined list of provider shipped with clusterctl.

This is the process to add a new provider to the pre-defined list of providers shipped with clusterctl:

  • As soon as possible, create an issue to the Cluster API repository declaring the intent to add a new provider; each provider must have a unique name & type in the pre-defined list of providers shipped with clusterctl; the provider’s name must be declared in the issue above and abide to the following naming convention:
    • The name must consist of lower case alphanumeric characters or ‘-’, and must start and end with an alphanumeric character. If the name includes upper case alphanumeric characters, clusterctl enforces it lower case it.
    • The name length should not exceed 63 characters.
    • For providers not in the kubernetes-sigs org, in order to prevent conflicts the clusterctl name must be prefixed with the provider’s GitHub org name followed by - (see note below).
  • Create a PR making the necessary changes to clusterctl and the Cluster API book, e.g. #9798, 9720.

The Cluster API maintainers will review issues/PRs for adding new providers. If the PR merges before code freeze deadline for the next Cluster API minor release, changes will be included in the release, otherwise in the next minor release. Maintainers will also consider if possible/convenient to backport to the current Cluster API minor release branch to include it in the next patch release.

Creating a provider repository on GitHub

You can use a GitHub release to package your provider artifacts for other people to use.

A GitHub release can be used as a provider repository if:

  • The release tag is a valid semantic version number
  • The components YAML, the metadata YAML and eventually the workload cluster templates are included into the release assets.

See the GitHub docs for more information about how to create a release.

Per default clusterctl will use a go proxy to detect the available versions to prevent additional API calls to the GitHub API. It is possible to configure the go proxy url using the GOPROXY variable as for go itself (defaults to https://proxy.golang.org). To immediately fallback to the GitHub client and not use a go proxy, the environment variable could get set to GOPROXY=off or GOPROXY=direct. If a provider does not follow Go’s semantic versioning, clusterctl may fail when detecting the correct version. In such cases, disabling the go proxy functionality via GOPROXY=off should be considered.

Creating a provider repository on GitLab

You can use a GitLab generic packages for provider artifacts.

A provider url should be in the form https://{host}/api/v4/projects/{projectSlug}/packages/generic/{packageName}/{defaultVersion}/{componentsPath}, where:

  • {host} should start with gitlab. (gitlab.com, gitlab.example.org, …)
  • {projectSlug} is either a project id (42) or escaped full path (myorg%2Fmyrepo)
  • {defaultVersion} is a valid semantic version number
  • The components YAML, the metadata YAML and eventually the workload cluster templates are included into the same package version

See the GitLab docs for more information about how to create a generic package.

If you are hosting a private Gitlab repository, you can use a personal access token or project access token to access the provider artifacts by adding the gitlab-access-token variable to the clusterctl configuration in order to authenticate against the GitLab API.

This can be used in conjunction with GitLabracadabra to avoid direct internet access from clusterctl, and use GitLab as artifacts repository. For example, for the core provider:

  • Use the following action file:

    external-packages/cluster-api:
      packages_enabled: true
      package_mirrors:
      - github:
          full_name: kubernetes-sigs/cluster-api
          tags:
          - v1.2.3
          assets:
          - clusterctl-linux-amd64
          - core-components.yaml
          - bootstrap-components.yaml
          - control-plane-components.yaml
          - metadata.yaml
    
  • Use the following clusterctl configuration:

    providers:
      # override a pre-defined provider on a self-host GitLab
      - name: "cluster-api"
        url: "https://gitlab.example.com/api/v4/projects/external-packages%2Fcluster-api/packages/generic/cluster-api/v1.2.3/core-components.yaml"
        type: "CoreProvider"
    

Limitation: Provider artifacts hosted on GitLab don’t support getting all versions. As a consequence, you need to set version explicitly for upgrades.

Creating a local provider repository

clusterctl supports reading from a repository defined on the local file system.

A local repository can be defined by creating a <provider-label> folder with a <version> sub-folder for each hosted release; the sub-folder name MUST be a valid semantic version number. e.g.

~/local-repository/infrastructure-aws/v0.5.2

Each version sub-folder MUST contain the corresponding components YAML, the metadata YAML and eventually the workload cluster templates.

Metadata YAML

The provider is required to generate a metadata YAML file and publish it to the provider’s repository.

The metadata YAML file documents the release series of each provider and maps each release series to an API Version of Cluster API (contract).

For example, for Cluster API:

apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3
kind: Metadata
releaseSeries:
- major: 0
  minor: 3
  contract: v1alpha3
- major: 0
  minor: 2
  contract: v1alpha2

Validation Rules

Starting from clusterctl v1.11, the metadata YAML file is subject to strict validation to ensure consistency and prevent configuration errors. The following validation rules are enforced:

  1. apiVersion: Must be set to clusterctl.cluster.x-k8s.io/v1alpha3

    • This ensures compatibility with the current clusterctl metadata format
  2. kind: Must be set to Metadata

    • This identifies the resource type correctly
  3. releaseSeries: Must contain at least one entry

    • This ensures providers properly document their version compatibility

These validation rules help catch configuration issues early and provide clear error messages to assist in troubleshooting.

Components YAML

The provider is required to generate a components YAML file and publish it to the provider’s repository. This file is a single YAML with all the components required for installing the provider itself (CRDs, Controller, RBAC etc.).

The following rules apply:

Naming conventions

It is strongly recommended that:

  • Core providers release a file called core-components.yaml
  • Infrastructure providers release a file called infrastructure-components.yaml
  • Bootstrap providers release a file called bootstrap-components.yaml
  • Control plane providers release a file called control-plane-components.yaml
  • IPAM providers release a file called ipam-components.yaml
  • Runtime extensions providers release a file called runtime-extension-components.yaml
  • Add-on providers release a file called addon-components.yaml

Target namespace

The instance components should contain one Namespace object, which will be used as the default target namespace when creating the provider components.

All the objects in the components YAML MUST belong to the target namespace, with the exception of objects that are not namespaced, like ClusterRoles/ClusterRoleBinding and CRD objects.

Controllers & Watching namespace

Each provider is expected to deploy controllers/runtime extension server using a Deployment.

While defining the Deployment Spec, the container that executes the controller/runtime extension server binary MUST be called manager.

For controllers only, the manager MUST support a --namespace flag for specifying the namespace where the controller will look for objects to reconcile; however, clusterctl will always install providers watching for all namespaces (--namespace=""); for more details see support for multiple instances for more context.

While defining Pods for Deployments, canonical names should be used for images.

Variables

The components YAML can contain environment variables matching the format ${VAR}; it is highly recommended to prefix the variable name with the provider name e.g. ${AWS_CREDENTIALS}

clusterctl uses the library drone/envsubst to perform variable substitution.

# If `VAR` is not set or empty, the default value is used. This is true for
# all the following formats.
${VAR:=default}
${VAR=default}
${VAR:-default}

Other functions such as substring replacement are also supported by the library. See drone/envsubst for more information.

Additionally, each provider should create user facing documentation with the list of required variables and with all the additional notes that are required to assist the user in defining the value for each variable.

Labels

The components YAML components should be labeled with cluster.x-k8s.io/provider and the name of the provider. This will enable an easier transition from kubectl apply to clusterctl.

As a reference you can consider the labels applied to the following providers.

Provider NameLabel
CAPIcluster.x-k8s.io/provider=cluster-api
CABPKcluster.x-k8s.io/provider=bootstrap-kubeadm
CABPMcluster.x-k8s.io/provider=bootstrap-microk8s
CABPKK3Scluster.x-k8s.io/provider=bootstrap-kubekey-k3s
CABPK0Scluster.x-k8s.io/provider=bootstrap-k0smotron
CACPKcluster.x-k8s.io/provider=control-plane-kubeadm
CACPMcluster.x-k8s.io/provider=control-plane-microk8s
CACPNcluster.x-k8s.io/provider=control-plane-nested
CACPKK3Scluster.x-k8s.io/provider=control-plane-kubekey-k3s
CACPK0Scluster.x-k8s.io/provider=control-plane-k0smotron
CAPAcluster.x-k8s.io/provider=infrastructure-aws
CAPBcluster.x-k8s.io/provider=infrastructure-byoh
CAPCcluster.x-k8s.io/provider=infrastructure-cloudstack
CAPCScluster.x-k8s.io/provider=infrastructure-cloudscale-ch-cloudscale
CAPDcluster.x-k8s.io/provider=infrastructure-docker
CAPDOcluster.x-k8s.io/provider=infrastructure-digitalocean
CAPGcluster.x-k8s.io/provider=infrastructure-gcp
CAPHcluster.x-k8s.io/provider=infrastructure-hetzner
CAPHWcluster.x-k8s.io/provider=infrastructure-huawei
CAPIBMcluster.x-k8s.io/provider=infrastructure-ibmcloud
CAPKKcluster.x-k8s.io/provider=infrastructure-kubekey
CAPKcluster.x-k8s.io/provider=infrastructure-kubevirt
CAPM3cluster.x-k8s.io/provider=infrastructure-metal3
CAPMScluster.x-k8s.io/provider=infrastructure-metal-stack
CAPNcluster.x-k8s.io/provider=infrastructure-nested
CAPONEcluster.x-k8s.io/provider=infrastructure-opennebula
CAPOcluster.x-k8s.io/provider=infrastructure-openstack
CAPOCIcluster.x-k8s.io/provider=infrastructure-oci
CAPScluster.x-k8s.io/provider=infrastructure-scaleway
CAPTcluster.x-k8s.io/provider=infrastructure-tinkerbell
CAPVcluster.x-k8s.io/provider=infrastructure-vsphere
CAPVCcluster.x-k8s.io/provider=infrastructure-vcluster
CAPVCDcluster.x-k8s.io/provider=infrastructure-vcd
CAPXcluster.x-k8s.io/provider=infrastructure-nutanix
CAPZcluster.x-k8s.io/provider=infrastructure-azure
CAPOSCcluster.x-k8s.io/provider=infrastructure-outscale
CAPK0Scluster.x-k8s.io/provider=infrastructure-k0smotron
CAIPAMICcluster.x-k8s.io/provider=ipam-in-cluster
CAIPAMXcluster.x-k8s.io/provider=ipam-nutanix
CAIPAM3cluster.x-k8s.io/provider=ipam-metal3
CAREXcluster.x-k8s.io/provider=runtime-extensions-nutanix

Workload cluster templates

An infrastructure provider could publish a cluster templates file to be used by clusterctl generate cluster. This is single YAML with all the objects required to create a new workload cluster.

With ClusterClass enabled it is possible to have cluster templates with managed topologies. Cluster templates with managed topologies require only the cluster object in the template and a corresponding ClusterClass definition.

The following rules apply:

Naming conventions

Cluster templates MUST be stored in the same location as the component YAML and follow this naming convention:

  1. The default cluster template should be named cluster-template.yaml.
  2. Additional cluster template should be named cluster-template-{flavor}.yaml. e.g cluster-template-prod.yaml

{flavor} is the name the user can pass to the clusterctl generate cluster --flavor flag to identify the specific template to use.

Each provider SHOULD create user facing documentation with the list of available cluster templates.

Target namespace

The cluster template YAML MUST assume the target namespace already exists.

All the objects in the cluster template YAML MUST be deployed in the same namespace.

Variables

The cluster templates YAML can also contain environment variables (as can the components YAML).

Additionally, each provider should create user facing documentation with the list of required variables and with all the additional notes that are required to assist the user in defining the value for each variable.

Common variables

The clusterctl generate cluster command allows user to set a small set of common variables via CLI flags or command arguments.

Templates writers should use the common variables to ensure consistency across providers and a simpler user experience (if compared to the usage of OS environment variables or the clusterctl config file).

CLI flagVariable nameNote
--target-namespace${NAMESPACE}The namespace where the workload cluster should be deployed
--kubernetes-version${KUBERNETES_VERSION}The Kubernetes version to use for the workload cluster
--controlplane-machine-count${CONTROL_PLANE_MACHINE_COUNT}The number of control plane machines to be added to the workload cluster
--worker-machine-count${WORKER_MACHINE_COUNT}The number of worker machines to be added to the workload cluster

Additionally, the value of the command argument to clusterctl generate cluster <cluster-name> (<cluster-name> in this case), will be applied to every occurrence of the ${ CLUSTER_NAME } variable.

ClusterClass definitions

An infrastructure provider could publish a ClusterClass definition file to be used by clusterctl generate cluster that will be used along with the workload cluster templates. This is a single YAML with all the objects required that make up the ClusterClass.

The following rules apply:

Naming conventions

ClusterClass definitions MUST be stored in the same location as the component YAML and follow this naming convention:

  1. The ClusterClass definition should be named clusterclass-{ClusterClass-name}.yaml, e.g clusterclass-prod.yaml.

{ClusterClass-name} is the name of the ClusterClass that is referenced from the Cluster.spec.topology.class field in the Cluster template; Cluster template files using a ClusterClass are usually simpler because they are no longer required to have all the templates.

Additionally, namespace of the ClusterClass can differ from the Cluster. This requires specifying Cluster.spec.topology.classNamespace field in the Cluster template; Cluster template may define classNamespace as classNamespace: ${CLUSTER_CLASS_NAMESPACE:=""}, which would allow to optionally specify namespace of the referred ClusterClass via env. Empty or missing value is uses Cluster namespace by default.

Each provider should create user facing documentation with the list of available ClusterClass definitions.

Target namespace

The ClusterClass definition YAML MUST assume the target namespace already exists.

The references in the ClusterClass definition should NOT specify a namespace.

It is recommended that none of the objects in the ClusterClass YAML should specify a namespace.

Even if technically possible, it is strongly recommended that none of the objects in the ClusterClass definitions are shared across multiple definitions; this helps in preventing changing an object inadvertently impacting many ClusterClasses, and consequently, all the Clusters using those ClusterClasses.

Variables

Currently the ClusterClass definitions SHOULD NOT have any environment variables in them.

ClusterClass definitions files should not use variable substitution, given that ClusterClass and managed topologies provide an alternative model for variable definition.

Note

A ClusterClass definition is automatically included in the output of clusterctl generate cluster if the cluster template uses a managed topology and a ClusterClass with the same name does not already exists in the Cluster.

OwnerReferences chain

Each provider is responsible to ensure that all the providers resources (like e.g. VSphereCluster, VSphereMachine, VSphereVM etc. for the vsphere provider) MUST have a Metadata.OwnerReferences entry that links directly or indirectly to a Cluster object.

Please note that all the provider specific resources that are referenced by the Cluster API core objects will get the OwnerReference set by the Cluster API core controllers, e.g.:

  • The Cluster controller ensures that all the objects referenced in Cluster.Spec.InfrastructureRef get an OwnerReference that links directly to the corresponding Cluster.
  • The Machine controller ensures that all the objects referenced in Machine.Spec.InfrastructureRef get an OwnerReference that links to the corresponding Machine, and the Machine is linked to the Cluster through its own OwnerReference chain.

That means that, practically speaking, provider implementers are responsible for ensuring that the OwnerReferences are set only for objects that are not directly referenced by Cluster API core objects, e.g.:

  • All the VSphereVM instances should get an OwnerReference that links to the corresponding VSphereMachine, and the VSphereMachine is linked to the Cluster through its own OwnerReference chain.

Additional notes

Components YAML transformations

Provider authors should be aware of the following transformations that clusterctl applies during component installation:

  • Variable substitution;
  • Enforcement of target namespace:
    • The name of the namespace object is set;
    • The namespace field of all the objects is set (with exception of cluster wide objects like e.g. ClusterRoles);
  • All components are labeled;

Cluster template transformations

Provider authors should be aware of the following transformations that clusterctl applies during components installation:

  • Variable substitution;
  • Enforcement of target namespace:
    • The namespace field of all the objects are set;

The clusterctl command requires that both the components YAML and the cluster templates contain all the required objects.

If, for any reason, the provider authors/YAML designers decide not to comply with this recommendation and e.g. to

  • implement links to external objects from a component YAML (e.g. secrets, aggregated ClusterRoles NOT included in the component YAML)
  • implement link to external objects from a cluster template (e.g. secrets, configMaps NOT included in the cluster template)

The provider authors/YAML designers should be aware that it is their responsibility to ensure the proper functioning of clusterctl when using non-compliant component YAML or cluster templates.

Move

Provider authors should be aware that clusterctl move command implements a discovery mechanism that considers:

  • All the Kind defined in one of the CRDs installed by clusterctl using clusterctl init (identified via the clusterctl.cluster.x-k8s.io label); For each CRD, discovery collects:
    • All the objects from the namespace being moved only if the CRD scope is Namespaced.
    • All the objects if the CRD scope is Cluster.
  • All the ConfigMap objects from the namespace being moved.
  • All the Secret objects from the namespace being moved and from the namespaces where infrastructure providers are installed.

After completing discovery, clusterctl move moves to the target cluster only the objects discovered in the previous phase that are compliant with one of the following rules:

  • The object is directly or indirectly linked to a Cluster object (linked through the OwnerReference chain).
  • The object is a secret containing a user provided certificate (linked to a Cluster object via a naming convention).
  • The object is directly or indirectly linked to a ClusterResourceSet object (through the OwnerReference chain).
  • The object is directly or indirectly linked to another object with the clusterctl.cluster.x-k8s.io/move-hierarchy label, e.g. the infrastructure Provider ClusterIdentity objects (linked through the OwnerReference chain).
  • The object has the clusterctl.cluster.x-k8s.io/move label or the clusterctl.cluster.x-k8s.io/move-hierarchy label, e.g. the CPI config secret.

Note. clusterctl.cluster.x-k8s.io/move and clusterctl.cluster.x-k8s.io/move-hierarchy labels could be applied to single objects or at the CRD level (the label applies to all the objects).

Please note that during move:

  • Namespaced objects, if not existing in the target cluster, are created.
  • Namespaced objects, if already existing in the target cluster, are updated.
  • Namespaced objects are removed from the source cluster.
  • Global objects, if not existing in the target cluster, are created.
  • Global objects, if already existing in the target cluster, are not updated.
  • Global objects are not removed from the source cluster.
  • Namespaced objects which are part of an owner chain that starts with a global object (e.g. a secret containing credentials for an infrastructure Provider ClusterIdentity) are treated as Global objects.

If moving some of excluded object is required, the provider authors should create documentation describing the exact move sequence to be executed by the user.

Additionally, provider authors should be aware that clusterctl move assumes all the provider’s Controllers respect the Cluster.spec.paused field. If a provider needs to perform extra work in response to a cluster being paused, clusterctl move can be blocked from creating any resources on the destination management cluster by annotating any resource to be moved with clusterctl.cluster.x-k8s.io/block-move.

IPAM Provider Specification

Overview

The IPAM provider is responsible for handling the IP addresses for the machines in a cluster.

IPAM providers are optional when using Cluster API. Infrastructure providers need to implement explicit support to be usable in conjunction with IPAM providers.

Data Types

An IPAM provider must define one or more API types for IP address pools using Kubernetes’ CustomResourceDefinition (CRD). The types:

  1. Must belong to an API group served by the Kubernetes apiserver
  2. Must be implemented as a CustomResourceDefinition. The CRD name must have the format produced by sigs.k8s.io/cluster-api/util/contract.CalculateCRDName(Group, Kind).
  3. Must have the standard Kubernetes “type metadata” and “object metadata”
  4. Should have a status.conditions field with the following:
    1. A Ready condition to represent the overall operational state of the component. It can be based on the summary of more detailed conditions existing on the same object, e.g. instanceReady, SecurityGroupsReady conditions.

Behaviour

IPAM providers must handle any IPAddressClaim resources that reference IP address pools that are managed by the provider and create an IPAddress resource for it. IPAddressClaims are usually created by infrastructure providers.

IPAM Provider

An IPAM provider must watch for new, updated and deleted IPAddressClaims that reference an IP address pool that is manged by the provider in their spec.poolRef field.

Normal IPAddressClaim

  1. If the IPAddressClaim does not reference a pool managed by the provider in it’s spec.poolRef, abort the reconciliation.
  2. If the related Cluster is paused, abort reconciliation
    1. The related Cluster is referenced using the spec.clusterName field or a cluster.x-k8s.io/cluster-name label (the latter is deprecated).
    2. If the paused field is empty and the cluster.x-k8s.io/paused annotation is not present, reconciliation can continue.
    3. If the referenced cluster is not found, abort reconciliation.
    4. If the referenced cluster has spec.paused set or a cluster.x-k8s.io/paused annotation, skip reconciliation
  3. Add any required provider-specific finalziers (you probably need one)
  4. Allocate an IP address for the claim
  5. Create an IPAddress object
    1. It should have the same name as the claim.
    2. It must have a owner reference with controller: true and blockOwnerDeletion: true to the Claim
    3. It must have a owner reference with controller: false and blockOwnerDeletion: true to the referenced Pool
    4. It should have a Finalizer that prevents accidental deletion, e.g. ipam.cluster.x-k8s.io/protect-address.
  6. Set the status.addressRef on the IPAddressClaim to the created IPAddress

Deleted IPAddressClaim

  1. If the related Cluster is paused, abort reconciliation (see 2. above)
  2. Deallocate the IP address
  3. Delete the IPAddress object
    1. Remove any Finalizers that were set to prevent deletion
  4. Remove the Finalizer from the claim

Clusterctl Move

In order for Pools to be moved alongside clusters, they need to have a cluster.x-k8s.io/cluster-name label.

Infrastructure Provider

In order to consume IP addresses from an IP address pool, an IPAddressClaim resource needs to be created, which will then be fulfilled with an IPAddress resource. Since the IPAddressClaim needs to reference an IP pool, you’ll need to add a property to your infrastructure Machine that allows to specify the pool.

  1. Create an IPAddressClaim
    1. The spec.poolRef must reference the pool you want to use
    2. It should have an owner reference to the infrastructure Machine (or the intermediate resource) it is created for (required to support clusterctl move). The reference should have controller: true and blockOwnerDeletion: true set.
    3. It’s spec.clusterName field should be set (or it should have a cluster.x-k8s.io/cluster-name label)
    4. Ideally it’s name is derived from the infrastructure Machine’s name
  2. Wait until an IP is allocated, ideally by watching the IPAddressClaim and waiting for status.addressRef to be set
  3. Fetch the IPAddress resource which contains the allocated address

When the infrastructure Machine is deleted, the claim should be deleted as well. The infrastructure Machine deletion should be blocked until the claim is deleted (handled by the API server if the owner relation is set up correctly).

Best practices

Implementation best practices

Cluster API doesn’t define strict rules about how providers should implement controllers.

However, some best practice are worth to notice:

  • Infrastructure objects (e.g. load balancers, VMs etc) generated by the Infra providers SHOULD adopt a naming convention that directly links to the Kubernetes resource that originated those objects. Please note that in most cases external constraints might impact this decision, like e.g.

    • Differences in naming conversions from Kubernetes CRDs and the target infrastructure
    • The fact that the InfraCluster Kubernetes CRD is namespace-scoped while target infrastructure might have different approaches to grouping resources
  • Naming convention above should not be used and advertised as a contract to build on top. Instead more robust mechanism MUST always be provided and used for identifying objects, like tagging or labeling. Please note that this is necessary not only to prevent issues in case Cluster API changes default naming strategies for the Kubernetes objects generated by core controllers, but also to handle use cases where users intentionally influence Cluster API naming strategies.

  • Cluster API offers a great development environment based on Tilt, which can be easily extended to work with any provider. Use it! See Rapid iterative development with Tilt

  • Cluster API defines a set of best practices and standards that, if adopted, could speed up provider development and improve consistency with core Cluster API. See:

  • Cluster API implements a test framework that, if adopted, could help in ensuring the quality of the provider. See:

  • While standard security practices for developing Kubernetes controllers apply, it is important to recognize that given that infrastructure provider deal with cloud credentials and cloud infrastructure, there are additional critical security concern that must be addressed to ensure secure operations. See:

Infrastructure Provider Security Guidance

There are several critical areas that any infrastructure provider implementer must address to ensure secure operations. These include:

  • Management of cloud credentials assigned to the infrastructure provider, including setting quotas and rate limiting.
  • Ensuring secure access to VMs for troubleshooting, with proper authentication methods.
  • Controlling manual operations performed on cloud infrastructure targeted by the provider.
  • Housekeeping of the cloud infrastructure, ensuring timely cleanup and garbage collection of unused resources.
  • Securing Machine’s bootstrap data ensuring protection of oversensitive data that might be included in it.

The following list outlines high-level security recommendations. It is a community-maintained resource, and everyone’s contributions are essential to continuously improve and adapt these best practices. Each provider implementer is responsible for translating these recommendations to fit the context of their specific cloud provider:

  1. Credentials Management: Ensure credentials used by Cluster API are least privileged. Apply access control to Cluster API controller namespaces, restricting unauthorized access to cloud administrators only.

  2. Two-Factor Authentication (2FA): Implement 2FA for all maintainer accounts on GitHub. For any privileged actions (e.g., image building or updates to machine images), follow the “second pair of eyes” principle to ensure review and oversight.

  3. Short-lived Credentials: Use short-lived credentials that are automatically renewed via node-level attestation mechanisms, minimizing the risk of credential misuse.

  4. Rate Limiting for Cloud Resources: Implement rate limits for the creation, deletion, and updating of cloud resources, protecting against potential abuse or accidental overload.

  5. Resource Housekeeping: Any cloud resource not linked to a cluster after a fixed configurable period, created by cloud credentials, should be automatically deleted or marked for garbage collection to avoid resource sprawl.

  6. Securing Machine’s bootstrap data: Bootstrap data are usually stored in machine’s metadata, and they might contain sensitive data, like e.g. Cluster secrets, user credentials, ssh certificates etc. It is important to ensure protection of this metadata, or if not possible, to clean it up immediately after machine bootstrap.

Version migration

The following pages provide an overview of relevant changes between versions of Cluster API and their direct successors. These guides are intended to assist maintainers of other providers and consumers of the Go API in upgrading from one version of Cluster API to a subsequent version.

For older versions please refer to Older Cluster API documentation versions

Cluster API v1.12 compared to v1.13

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

Any feedback or contributions to improve following documentation is welcome!

Go version

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

Dependencies

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

Graduation

  • Both the PriorityQueue and the ReconcilerRateLimiting feature gate graduated to beta and are enabled by default
    • Starting from this release ReconcilerRateLimiting feature also requires PriorityQueue to be enabled.
    • The same constraint has been backported on the CAPI 1.12 branch starting from v1.12.4 in order to ensure that ReconcilerRateLimiting works consistently with controller runtime exponential backoff.

Implemented proposal

The following proposal have been implemented in the Cluster API v1.12 release:

API Changes

Cluster

  • The new spec.topology.controlPlane.rollout.taints, spec.topology.workers.machineDeployments[].taints and spec.topology.workers.machinePools[].taints fields has been added
  • The new spec.topology.controlPlane.rollout.after and spec.topology.workers.machineDeployments[].rollout.after fields has been added

Machine

  • The new status.failureDomain field has been added.
  • The new NodeKubeadmLabelsAndTaintsSet condition has been added for Machines managed by KCP

ClusterClass

  • The new spec.controlPlane.rollout.taints, spec.workers.machineDeployments[].taints and spec.workers.machinePools[].taints fields has been added

KubeadmConfig

  • The new spec.diskSetup.partitions.diskLayout field has been added

KubeadmConfigTemplate

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

KubeadmControlPlane

  • The new spec.machineTemplate.taints field has been added
  • KubeadmControlPlane spec.kubeadmConfigSpec has been aligned to changes in the KubeadmConfig spec struct

KubeadmControlPlaneTemplate

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

Runtime hooks Changes

  • Following hook messages are now using v1beta2 Cluster type instead of the deprecated v1beta1 Cluster type.

    • BeforeClusterCreateRequest
    • AfterControlPlaneInitializedRequest
    • BeforeClusterUpgradeRequest
    • BeforeControlPlaneUpgradeRequest
    • AfterControlPlaneUpgradeRequest
    • BeforeWorkersUpgradeRequest
    • AfterWorkersUpgradeRequest
    • AfterClusterUpgradeRequest
    • BeforeClusterDeleteRequest
  • The DiscoverVariablesResponse hook message are now using v1beta2 ClusterClassVariable type instead of the deprecated v1beta1 ClusterClassVariable type.

  • The Builtins type used for computing variables lists in the GeneratePatchesRequest and the ValidateTopologyRequest hook messages is now using a custom ObjectMeta type instead of the deprecated v1beta1 ObjectMeta type.

Cluster API Contract changes

  • A new, optional rule has been added to the bootstrap config contract and the infra machine provider contract, defining what is required for implementing support for in-place changes.
  • A new, optional rule has been added to the control plane contract, defining what is required for implementing support for taints.
  • A new, optional rule has been added to the control plane contract, defining what is required for implementing support for rolloutAfter.
  • Clarification about expectations about consistency between metadata.yaml versions and cluster.x-k8s.io/<version> label on provider’s CRDs has been added to the clusterctl contract and to contract for all the provider types.

Deprecation

The following API types are now deprecated (you should use corresponding Dev* API types)

  • DockerCluster and DockerClusterTemplate
  • DockerMachine and DockerMachineTemplate
  • DockerMachinePool and DockerMachinePoolTemplate

Removals

  • Remove deprecated --enable-crd-storage-version-migration flag for clusterctl upgrade and corresponding provider CRD storage version migration code
  • The deprecated --disable-grouping flag for clusterctl describe cluster has been removed.
  • The deprecated ClusterCache.GetClientCertificatePrivateKey method has been removed.
  • The deprecated --cluster-concurrency CABPK command-line flag has been removed
  • Remove deprecated util/topology.ShouldSkipImmutabilityChecks (use util/topology.IsDryRunRequest instead)
  • Removed deprecated util/version.ParseMajorMinorPatch (use semver.Parse instead)
  • Removed deprecated util/version.ParseMajorMinorPatchTolerant (use semver.ParseTolerant instead)

Suggested changes for providers

  • A new conversion.MarshalDataUnsafeNoCopy func was introduced. The difference to conversion.MarshalData is that it mutates the passed in source object before marshaling to avoid additional memory allocations. Usually this is fine because this func is used at the end of ConvertFrom methods. Accordingly, we recommend to start using this new func, except if it’s not safe in your circumstances.
  • If you are developing a control plane provider with support for machines, please consider adding spec.machineTemplate.spec.taints (see contract)
  • Cluster API bumped the default values of --kube-api-qps & --kube-api-burst to 100/200 in CAPI-13317. You might want to consider doing the same.

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 April 2027 (instead of the original August 2026)
  • Starting from the CAPI release when v1beta1 removal will happen, tentatively April 2027, 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.
  • All the status.deprecated fields will be removed tentatively in April 2027.
  • Compatibility support for the v1beta1 version of the Cluster API contract will be removed tentatively in April 2027
  • Removal of Docker* API types will happen in a future version (as soon as possible)
    • NOTE: CAPD is considered a test provider, API deprecation guarantee do not apply

Cluster API v1.13 compared to v1.14

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

Any feedback or contributions to improve following documentation is welcome!

Go version

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

Dependencies

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

Graduation

  • No feature flags has been graduated in this release

Implemented proposal

API Changes

Cluster

  • The new status.controlPlane.versions and status.workers.versions fields has been added
  • The new status.controlPlane.upgradePlan and status.workers.upgradePlan fields has been added

MachineDeployment

  • The new status.versions field has been added

MachineSet

  • The new status.versions field has been added

MachinePool

  • The new status.versions field has been added

Machine

  • The new status.deletion.waitForPreDrainHookStartTime and status.deletion.waitForPreTerminateHookStartTime fields has been added

KubeadmConfig

  • The new spec.files[].contentFormat field has been added

KubeadmConfigTemplate

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

KubeadmControlPlane

  • KubeadmControlPlane spec.kubeadmConfigSpec has been aligned to changes in the KubeadmConfig spec struct
  • The new status.versions field has been added, the existing status.version has been deprecated

KubeadmControlPlaneTemplate

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

Runtime hooks Changes

  • Please note that since CAPI-13813 errors returned from Runtime Extensions might be surfaced in conditions. Accordingly, please ensure that the error messages are deterministic to avoid infinite reconciles. This change was done because we realized that errors reported by Runtime Extensions are a crucial feedback mechanism to users and its too cumbersome for users to search in controller logs for errors.

Cluster API Contract changes

  • All contracts: document necessary RBAC rules for enabling usage of the OwnerReferencesPermissionEnforcement admission controller.
  • Control plane contract:
    • Introduce optional contract field status.versions for control plane providers which allows control of the version.
    • The optional contract field status.version has been deprecated

Deprecation

  • Control plane contract:
    • The optional contract field status.version has been deprecated; the new optional contract field status.versions must be used instead.
  • The following functions and types have been deprecated, please use ClusterCache or inline them instead:
    • controllers/remote.NewClusterClient
    • controllers/remote.RESTConfig
    • controllers/remote.ClusterClientGetter
    • controllers/remote/fake.NewClusterClient
  • The util/record package has been deprecated, please use controller runtime mgr.GetEventRecorderFor instead.

Removals

  • No removal in this release

Suggested changes for providers

  • Providers implementers should read the code organization proposal and take into account:
    • Different level of guarantees provided by different go modules
    • New guidelines for bumping go versions
  • It is highly recommended to start planning for future removals described in following paragraphs

Removals scheduled for future releases

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

Important:

  • The v1beta1 API version in core Cluster API, CABPK and KCP is on track to be unserved in CAPI v1.16. All the consumers of this API version should migrate to v1beta2 ASAP.
    • Utils for the Cluster API v1beta1 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 will be removed as a next step.
    • All the status.deprecated fields existing in v1beta2 types (used for v1beta1 down conversions) types will be removed as a next step.
  • Support for the Cluster API v1beta1 contract versions is on track to be dropped in CAPI v1.16. Provider should start implementing the v1beta2 contract ASAP.
  • Removal of Docker* API resources will happen in CAPI v1.15. All the consumers of these API resources should migrate to Dev* API resources ASAP.

Cluster API v1.14 compared to v1.15

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

Any feedback or contributions to improve following documentation is welcome!

Go version

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

Dependencies

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

Graduation

  • Both the PriorityQueue and the ReconcilerRateLimiting feature gate graduated to GA

Implemented proposal

API Changes

Cluster

Machine

ClusterClass

KubeadmConfig

KubeadmConfigTemplate

KubeadmControlPlane

KubeadmControlPlaneTemplate

Runtime hooks Changes

=

Cluster API Contract changes

Deprecation

  • Both the PriorityQueue and ReconcilerRateLimiting features are now GA so their corresponding feature gates are deprecated and will be removed in the v1.17 release.

Removals

  • The deprecated GA feature gate MachineWaitForVolumeDetachConsiderVolumeAttachments has been removed
  • The following functions and types have been removed, please use ClusterCache or inline them instead:
    • controllers/remote.NewClusterClient
    • controllers/remote.RESTConfig
    • controllers/remote.ClusterClientGetter
    • controllers/remote/fake.NewClusterClient
  • The util/record package has been removed, please use controller runtime mgr.GetEventRecorderFor instead.

Suggested changes for providers

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 April 2027 (instead of the original August 2026)
  • Starting from the CAPI release when v1beta1 removal will happen, tentatively April 2027, 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.
  • All the status.deprecated fields will be removed tentatively in April 2027.
  • Compatibility support for the v1beta1 version of the Cluster API contract will be removed tentatively in April 2027
  • Removal of Docker* API types will happen in a future version (as soon as possible)
    • NOTE: CAPD is considered a test provider, API deprecation guarantee do not apply

Troubleshooting

Troubleshooting Quick Start with Docker (CAPD)

This guide assumes you’ve completed the apply the workload cluster section of the Quick Start using Docker.

When running clusterctl describe cluster capi-quickstart to verify the created resources, we expect the output to be similar to this (note: this is before installing the Calico CNI).

NAME                                                           READY  SEVERITY  REASON                       SINCE  MESSAGE
Cluster/capi-quickstart                                        True                                          46m
├─ClusterInfrastructure - DockerCluster/capi-quickstart-94r9d  True                                          48m
├─ControlPlane - KubeadmControlPlane/capi-quickstart-6487w     True                                          46m
│ └─3 Machines...                                              True                                          47m    See capi-quickstart-6487w-d5lkp, capi-quickstart-6487w-mpmkq, ...
└─Workers
  └─MachineDeployment/capi-quickstart-md-0-d6dn6               False  Warning   WaitingForAvailableMachines  48m    Minimum availability requires 3 replicas, current 0 available
    └─3 Machines...                                            True                                          47m    See capi-quickstart-md-0-d6dn6-584ff97cb7-kr7bj, capi-quickstart-md-0-d6dn6-584ff97cb7-s6cbf, ...

Machines should be started, but Workers are not because Calico isn’t installed yet. You should be able to see the containers running with docker ps --all and they should not be restarting.

If you notice Machines are failing to start/restarting your output might look similar to this:

clusterctl describe cluster capi-quickstart
NAME                                                           READY  SEVERITY  REASON                       SINCE  MESSAGE
Cluster/capi-quickstart                                        False  Warning   ScalingUp                    57s    Scaling up control plane to 3 replicas (actual 2)
├─ClusterInfrastructure - DockerCluster/capi-quickstart-n5w87  True                                          110s
├─ControlPlane - KubeadmControlPlane/capi-quickstart-6587k     False  Warning   ScalingUp                    57s    Scaling up control plane to 3 replicas (actual 2)
│ ├─Machine/capi-quickstart-6587k-fgc6m                        True                                          81s
│ └─Machine/capi-quickstart-6587k-xtvnz                        False  Warning   BootstrapFailed              52s    1 of 2 completed
└─Workers
  └─MachineDeployment/capi-quickstart-md-0-5whtj               False  Warning   WaitingForAvailableMachines  110s   Minimum availability requires 3 replicas, current 0 available
    └─3 Machines...                                            False  Info      Bootstrapping                77s    See capi-quickstart-md-0-5whtj-5d8c9746c9-f8sw8, capi-quickstart-md-0-5whtj-5d8c9746c9-hzxc2, ...

In the example above we can see that the Machine capi-quickstart-6587k-xtvnz has failed to start. The reason provided is BootstrapFailed.

To investigate why a machine fails to start you can inspect the conditions of the objects using clusterctl describe --show-conditions all cluster capi-quickstart. You can get more detailed information about the status of the machines using kubectl describe machines.

To inspect the underlying infrastructure - in this case Docker containers acting as Machines - you can access the logs using docker logs <MACHINE-NAME>. For example:

docker logs capi-quickstart-6587k-xtvnz
(...)
Failed to create control group inotify object: Too many open files
Failed to allocate manager object: Too many open files
[!!!!!!] Failed to allocate manager object.
Exiting PID 1...

To resolve this specific error please read Cluster API with Docker - “too many open files”.

Node bootstrap failures when using CABPK with cloud-init

Failures during Node bootstrapping can have a lot of different causes. For example, Cluster API resources might be misconfigured or there might be problems with the network. The following steps describe how bootstrap failures can be troubleshooted systematically.

  1. Access the Node via ssh.
  2. Take a look at cloud-init logs via less /var/log/cloud-init-output.log or journalctl -u cloud-init --since "1 day ago". (Note: cloud-init persists logs of the commands it executes (like kubeadm) only after they have returned.)
  3. It might also be helpful to take a look at journalctl --since "1 day ago".
  4. If you see that kubeadm times out waiting for the static Pods to come up, take a look at:
    1. containerd: crictl ps -a, crictl logs, journalctl -u containerd
    2. Kubelet: journalctl -u kubelet --since "1 day ago" (Note: it might be helpful to increase the Kubelet log level by e.g. setting --v=8 via systemctl edit --full kubelet && systemctl restart kubelet)
  5. If Node bootstrapping consistently fails and the kubeadm logs are not verbose enough, the kubeadm verbosity can be increased via KubeadmConfigSpec.Verbosity.

Labeling nodes with reserved labels such as node-role.kubernetes.io fails with kubeadm error during bootstrap

Self-assigning Node labels such as node-role.kubernetes.io using the kubelet --node-labels flag (see kubeletExtraArgs in the CABPK examples) is not possible due to a security measure imposed by the NodeRestriction admission controller that kubeadm enables by default.

Assigning such labels to Nodes must be done after the bootstrap process has completed:

kubectl label nodes <name> node-role.kubernetes.io/worker=""

For convenience, here is an example one-liner to do this post installation

# Kubernetes 1.19 (kubeadm 1.19 sets only the node-role.kubernetes.io/master label)
kubectl get nodes --no-headers -l '!node-role.kubernetes.io/master' -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}' | xargs -I{} kubectl label node {} node-role.kubernetes.io/worker=''
# Kubernetes >= 1.20 (kubeadm >= 1.20 sets the node-role.kubernetes.io/control-plane label)
kubectl get nodes --no-headers -l '!node-role.kubernetes.io/control-plane' -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}' | xargs -I{} kubectl label node {} node-role.kubernetes.io/worker=''

Cluster API with Docker - common issues with docker -

When provisioning workload clusters using Cluster API with the Docker infrastructure provider, provisioning might be stuck:

  1. if there are stopped containers on your machine from previous runs. Clean unused containers with docker rm -f .

  2. if the Docker space on your disk is being exhausted

Cluster API with Docker - “too many open files”

When creating many nodes using Cluster API and Docker infrastructure, either by creating large Clusters or a number of small Clusters, the OS may run into inotify limits which prevent new nodes from being provisioned. If the error Failed to create inotify object: Too many open files is present in the logs of the Docker Infrastructure provider this limit is being hit.

On Linux this issue can be resolved by increasing the inotify watch limits with:

sysctl fs.inotify.max_user_watches=1048576
sysctl fs.inotify.max_user_instances=8192

Newly created clusters should be able to take advantage of the increased limits.

MacOS and Docker Desktop - “too many open files”

This error was also observed in Docker Desktop 4.3 and 4.4 on MacOS. It can be resolved by updating to Docker Desktop for Mac 4.5 or using a version lower than 4.3.

The upstream issue for this error is closed as of the release of Docker 4.5.0

Note: The below workaround is not recommended unless upgrade or downgrade cannot be performed.

If using a version of Docker Desktop for Mac 4.3 or 4.4, the following workaround can be used:

Increase the maximum inotify file watch settings in the Docker Desktop VM:

  1. Enter the Docker Desktop VM
nc -U ~/Library/Containers/com.docker.docker/Data/debug-shell.sock
  1. Increase the inotify limits using sysctl
sysctl fs.inotify.max_user_watches=1048576
sysctl fs.inotify.max_user_instances=8192
  1. Exit the Docker Desktop VM
exit

Failed clusterctl init - ‘failed to get cert-manager object’

When using older versions of Cluster API 0.4 and 1.0 releases - 0.4.6, 1.0.3 and older respectively - Cert Manager may not be downloadable due to a change in the repository location. This will cause clusterctl init to fail with the error:

clusterctl init --infrastructure docker
Fetching providers
Installing cert-manager Version="v1.11.0"
Error: action failed after 10 attempts: failed to get cert-manager object /, Kind=, /: Object 'Kind' is missing in 'unstructured object has no kind'

This error was fixed in more recent Cluster API releases on the 0.4 and 1.0 release branches. The simplest way to resolve the issue is to upgrade to a newer version of Cluster API for a given release. For who need to continue using an older release it is possible to override the repository used by clusterctl init in the clusterctl config file. The default location of this file is in $XDG_CONFIG_HOME/cluster-api/clusterctl.yaml.

To do so add the following to the file:

cert-manager:
  url: "https://github.com/cert-manager/cert-manager/releases/latest/cert-manager.yaml"

Alternatively a Cert Manager yaml file can be placed in the clusterctl overrides layer which is by default in $XDG_CONFIG_HOME/cluster-api/overrides. A Cert Manager yaml file can be placed at e.g. $XDG_CONFIG_HOME/cluster-api/overrides/cert-manager/v1.11.0/cert-manager.yaml

More information on the clusterctl config file can be found at its page in the book

Failed clusterctl upgrade apply - ‘failed to update cert-manager component’

Upgrading Cert Manager may fail due to a breaking change introduced in Cert Manager release v1.6. An upgrade using clusterctl is affected when:

  • using clusterctl in version v1.1.4 or a more recent version.
  • Cert Manager lower than version v1.0.0 did run in the management cluster (which was shipped in Cluster API until including v0.3.14).

This will cause clusterctl upgrade apply to fail with the error:

clusterctl upgrade apply
Checking cert-manager version...
Deleting cert-manager Version="v1.5.3"
Installing cert-manager Version="v1.7.2"
Error: action failed after 10 attempts: failed to update cert-manager component apiextensions.k8s.io/v1, Kind=CustomResourceDefinition, /certificaterequests.cert-manager.io: CustomResourceDefinition.apiextensions.k8s.io "certificaterequests.cert-manager.io" is invalid: status.storedVersions[0]: Invalid value: "v1alpha2": must appear in spec.versions

The Cert Manager maintainers provide documentation to migrate the deprecated API Resources to the new storage versions to mitigate the issue.

More information about the change in Cert Manager can be found at their upgrade notes from v1.5 to v1.6.

Clusterctl failing to start providers due to outdated image overrides

clusterctl allows users to configure image overrides via the clusterctl config file. However, when the image override is pinning a provider image to a specific version, it could happen that this conflicts with clusterctl behavior of picking the latest version of a provider.

E.g., if you are pinning KCP images to version v1.0.2 but then clusterctl init fetches yamls for version v1.1.0 or greater KCP will fail to start with the following error:

invalid argument "ClusterTopology=false,KubeadmBootstrapFormatIgnition=false" for "--feature-gates" flag: unrecognized feature gate: KubeadmBootstrapFormatIgnition

In order to solve this problem you should specify the version of the provider you are installing by appending a version tag to the provider name:

clusterctl init -b kubeadm:v1.0.2 -c kubeadm:v1.0.2 --core cluster-api:v1.0.2 -i docker:v1.0.2

Even if slightly verbose, pinning the version provides a better control over what is installed, as usually required in an enterprise environment, especially if you rely on an internal repository with a separated software supply chain or a custom versioning schema.

Managed Cluster and co-authored slices

As documented in #6320 managed topologies assumes a slice to be either authored from templates or by the users/the infrastructure controllers.

In cases the slice is instead co-authored (templates provide some info, the infrastructure controller fills in other info) this can lead to infinite reconcile.

A solution to this problem is being investigated, but in the meantime you should avoid co-authored slices.

Failed to removed fields from lists using Server Side Apply

The Cluster API projects is continuously improving its API, including improving the support for Server Side Apply, which allows for a more granular ownership of list items.

However, when transitioning from atomic lists to map lists, there are edge cases not supported and this can lead to a SSA patches failing to remove an item in a list.

Note: the issue only occurs in a very specific scenario, most of the users are not affected (e.g. client-side apply or “continuous” SSA with GitOps tools works as expected)

Example of fields transitioned from atomic lists to map lists are e.g.

  • cluster.spec.topology.variables
  • cluster.spec.topology.workers.machineDeployments

In case you face this issue, please use kubectl edit or kubectl apply with client-side apply to remove the item from the list; after the item is removed everything should work as expected.

See comment for more details.

kubeadm join fails after upgrading to Kubernetes patch releases

When upgrading a cluster to any of the following Kubernetes patch releases, kubeadm join completes but the control plane rollout gets stuck because the API server cannot proxy requests to the kubelet:

  • v1.36.1
  • v1.35.5
  • v1.34.8
  • v1.33.12

Cause: These releases include a kubeadm security improvement (kubernetes/kubernetes#138957) that reduces the scope of the API server’s kubelet client credentials. A dedicated ClusterRoleBinding named kubeadm:apiserver-kubelet-client is now required, binding the API server’s certificate CN (kube-apiserver-kubelet-client) to the system:kubelet-api-admin ClusterRole.

Without this binding, the API server cannot proxy or exec to kubelets on nodes with the new certificates. KCP logs will show errors similar to:

unable to upgrade connection: Forbidden (user=kube-apiserver-kubelet-client,
verb=create, resource=nodes, subresource(s)=[proxy])

CAPI releases prior to v1.11.11, v1.12.8, and v1.13.2 do not create this binding during upgrades, causing the control plane rollout to get stuck.

Fix: Before upgrading Kubernetes to the above patch versions, upgrade CAPI to one of the following releases which include the corresponding fix (cluster-api#13664):

  • v1.13.2 or later
  • v1.12.8 or later
  • v1.11.11 or later

If you are already in a broken state and cannot upgrade CAPI first, manually create the missing ClusterRoleBinding on the workload cluster:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kubeadm:apiserver-kubelet-client
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:kubelet-api-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: kube-apiserver-kubelet-client

After applying this manifest to the workload cluster, retry the upgrade.

Reference

This section contains various resources that define the Cluster API project.

API Reference

Cluster API currently exposes the following APIs:

Following pages provide additional documentation to better understand and use Cluster API types.

Supported Labels

LabelNoteManaged byApplies to
cluster.x-k8s.io/cluster-nameIt is set on machines linked to a cluster and external objects(bootstrap and infrastructure providers).UserMachines
cluster.x-k8s.io/control-planeIt is set on machines or related objects that are part of a control plane.Cluster APIMachines
cluster.x-k8s.io/control-plane-nameIt is set on machines if they’re controlled by a control plane. The value of this label may be a hash if the control plane name is longer than 63 characters.Cluster APIMachines
cluster.x-k8s.io/deployment-nameIt is set on machines if they’re controlled by a MachineDeployment.Cluster APIMachines
cluster.x-k8s.io/drainIf set with the value “skip” on a Pod in the workload cluster, the Pod will not be evicted during Node drain.UserPods (workload cluster)
cluster.x-k8s.io/interruptibleIt is used to mark the nodes that run on interruptible instances.UserNodes (workload cluster)
cluster.x-k8s.io/pool-nameIt is set on machines if they’re controlled by a MachinePool.Cluster APIMachines
cluster.x-k8s.io/providerIt is set on components in the provider manifest. The label allows one to easily identify all the components belonging to a provider. The clusterctl tool uses this label for implementing provider’s lifecycle operations.UserProvider Components
cluster.x-k8s.io/set-nameIt is set on machines if they’re controlled by MachineSet. The value of this label may be a hash if the MachineSet name is longer than 63 characters.Cluster APIMachines
cluster.x-k8s.io/watch-filterIt can be applied to any Cluster API object. Controllers which allow for selective reconciliation may check this label and proceed with reconciliation of the object only if this label and a configured value is present.Cluster APIAll Cluster API objects
machine-template-hashIt is applied to Machines in a MachineDeployment containing the hash of the template.Cluster APIMachines
topology.cluster.x-k8s.io/deployment-nameIt is set on the generated MachineDeployment objects to track the name of the MachineDeployment topology it represents.Cluster APIMachineDeployments
topology.cluster.x-k8s.io/ownedIt is set on all the object which are managed as part of a ClusterTopology.Cluster APIClusterTopology objects

Supported Annotations

AnnotationNoteManaged ByApplies to
before-upgrade.hook.cluster.cluster.x-k8s.ioIt specifies the prefix we search each annotation for during the before-upgrade lifecycle hook to block propagating the new version to the control plane. These hooks will prevent propagation of changes made to the Cluster Topology to the underlying objects.UserClusters
cluster.x-k8s.io/annotations-from-machineIt is set on nodes to track the annotations that originated from machines.Cluster APINodes (workload cluster)
cluster.x-k8s.io/cloned-from-groupkindIt is the annotation that stores the group-kind of the template from which the current resource has been cloned from.Cluster APIAll Cluster API objects cloned from a template
cluster.x-k8s.io/cloned-from-nameIt is the annotation that stores the name of the template from which the current resource has been cloned from.Cluster APIAll Cluster API objects cloned from a template
cluster.x-k8s.io/cluster-nameIt is set on nodes identifying the name of the cluster the node belongs to.Cluster APINodes (workload cluster)
cluster.x-k8s.io/cluster-namespaceIt is set on nodes identifying the namespace of the cluster the node belongs to.Cluster APINodes (workload cluster)
cluster.x-k8s.io/delete-machineIt marks control plane and worker nodes that will be given priority for deletion when KCP or a MachineSet scales down. It is given top priority on all delete policies.UserMachines
cluster.x-k8s.io/disable-machine-createIt can be used to signal a MachineSet to stop creating new machines. It is utilized in the OnDelete MachineDeploymentStrategy to allow the MachineDeployment controller to scale down older MachineSets when Machines are deleted and add the new replicas to the latest MachineSet.Cluster APIMachineSets
cluster.x-k8s.io/labels-from-machineIt is set on nodes to track the labels that originated from machines.Cluster APINodes (workload cluster)
cluster.x-k8s.io/managed-byIt can be applied to InfraCluster resources to signify that some external system is managing the cluster infrastructure. Provider InfraCluster controllers will ignore resources with this annotation. An external controller must fulfill the contract of the InfraCluster resource. External infrastructure providers should ensure that the annotation, once set, cannot be removed.UserInfraClusters
cluster.x-k8s.io/machineIt is set on nodes identifying the machine the node belongs to.Cluster APINodes (workload cluster)
cluster.x-k8s.io/owner-kindIt is set on nodes identifying the machine’s owner kind the node belongs to.Cluster APINodes (workload cluster)
cluster.x-k8s.io/owner-nameIt is set on nodes identifying the machine’s owner name the node belongs to.Cluster APINodes (workload cluster)
cluster.x-k8s.io/pausedIt can be applied to any Cluster API object to prevent a controller from processing a resource. Controllers working with Cluster API objects must check the existence of this annotation on the reconciled object.UserAll Cluster API objects
cluster.x-k8s.io/remediate-machineIt can be applied to a machine to manually mark it for remediation by MachineHealthCheck reconciler.UserMachines
cluster.x-k8s.io/replicas-managed-byIt can be applied to MachinePool resources to signify that some external system is managing infrastructure scaling for that pool. See the MachinePool documentation for more details.Infrastructure ProvidersMachinePools
cluster.x-k8s.io/skip-remediationIt is used to mark the machines that should not be considered for remediation by MachineHealthCheck reconciler.UserMachines
clusterctl.cluster.x-k8s.io/block-moveBlockMoveAnnotation prevents the cluster move operation from starting if it is defined on at least one of the objects in scope. Provider controllers are expected to set the annotation on resources that cannot be instantaneously paused and remove the annotation when the resource has been actually paused.ProvidersAll Cluster API objects
clusterctl.cluster.x-k8s.io/delete-for-moveDeleteForMoveAnnotation will be set to objects that are going to be deleted from the source cluster after being moved to the target cluster during the clusterctl move operation. It will help any validation webhook to take decision based on it.Cluster APIAll Cluster API objects
clusterctl.cluster.x-k8s.io/skip-crd-name-preflight-checkCan be placed on provider CRDs, so that clusterctl doesn’t emit an error if the CRD doesn’t comply with Cluster APIs naming scheme. Only CRDs that are referenced by core Cluster API CRDs have to comply with the naming scheme.ProvidersCRDs
controlplane.cluster.x-k8s.io/remediation-forIt is a machine annotation that links a new machine to the unhealthy machine it is replacing.Cluster APIMachines
controlplane.cluster.x-k8s.io/remediation-in-progressIt is a KCP annotation that tracks that the system is in between having deleted an unhealthy machine and recreating its replacement.Cluster APIKubeadmControlPlanes
controlplane.cluster.x-k8s.io/skip-corednsIt explicitly skips reconciling CoreDNS if set.UserKubeadmControlPlanes
controlplane.cluster.x-k8s.io/skip-kube-proxyIt explicitly skips reconciling kube-proxy if set.UserKubeadmControlPlanes
crd-migration.cluster.x-k8s.io/observed-generationIt indicates on a CRD for which generation CRD migration is completed.Cluster APICustomResourceDefinitions
machine.cluster.x-k8s.io/certificates-expiryIt captures the expiry date of the machine certificates in RFC3339 format. It is used to trigger rollout of control plane machines before certificates expire. It can be set on BootstrapConfig and Machine objects. The value set on Machine object takes precedence. The annotation is only used by control plane machines.Cluster API/UserBootstrapConfigs, Machines
machine.cluster.x-k8s.io/exclude-node-drainingIt explicitly skips node draining if set.UserMachines
machine.cluster.x-k8s.io/exclude-wait-for-node-volume-detachIt explicitly skips the waiting for node volume detaching if set.UserMachines
machinedeployment.clusters.x-k8s.io/desired-replicasIt is the desired replicas for a machine deployment recorded as an annotation in its machine sets. Helps in separating scaling events from the rollout process and for determining if the new machine set for a deployment is really saturated.Cluster APIMachineSets
machinedeployment.clusters.x-k8s.io/max-replicasIt is the maximum replicas a deployment can have at a given point, which is machinedeployment.spec.replicas + maxSurge. Used by the underlying machine sets to estimate their proportions in case the deployment has surge replicas.Cluster APIMachineSets
machinedeployment.clusters.x-k8s.io/revisionIt is the revision annotation of a machine deployment’s machine sets which records its rollout sequence.Cluster APIMachineSets
machineset.cluster.x-k8s.io/skip-preflight-checksIt can be applied on MachineDeployment, MachineSet and corresponding BootstrapConfigTemplate resources to specify a comma-separated list of preflight checks that should be skipped during MachineSet reconciliation. Supported preflight checks are: All, KubeadmVersionSkew, KubernetesVersionSkew, ControlPlaneIsStable.UserMachineDeployments, MachineSets, BootstrapConfigTemplates
pre-drain.delete.hook.machine.cluster.x-k8s.ioIt specifies the prefix we search each annotation for during the pre-drain.delete lifecycle hook to pause reconciliation of deletion. These hooks will prevent removal of draining the associated node until all are removed.UserMachines
pre-terminate.delete.hook.machine.cluster.x-k8s.ioIt specifies the prefix we search each annotation for during the pre-terminate.delete lifecycle hook to pause reconciliation of deletion. These hooks will prevent removal of an instance from an infrastructure provider until all are removed.UserMachines
topology.cluster.x-k8s.io/defer-upgradeIt can be used to defer the Kubernetes upgrade of a single MachineDeployment topology. If the annotation is set on a MachineDeployment topology in Cluster.spec.topology.workers, the Kubernetes upgrade for this MachineDeployment topology is deferred. It doesn’t affect other MachineDeployment topologies.Cluster APIMachineDeployments in Cluster.topology
topology.cluster.x-k8s.io/dry-runIt is an annotation that gets set on objects by the topology controller only during a server side dry run apply operation. It is used for validating update webhooks for objects which get updated by template rotation (e.g. InfrastructureMachineTemplate). When the annotation is set and the admission request is a dry run, the webhook should deny validation due to immutability. By that the request will succeed (without any changes to the actual object because it is a dry run) and the topology controller will receive the resulting object.Cluster APITemplate rotation objects
topology.cluster.x-k8s.io/hold-upgrade-sequenceIt can be used to hold the entire MachineDeployment upgrade sequence. If the annotation is set on a MachineDeployment topology in Cluster.spec.topology.workers, the Kubernetes upgrade for this MachineDeployment topology and all subsequent ones is deferred.Cluster APIMachineDeployments in Cluster.topology
topology.cluster.x-k8s.io/upgrade-concurrencyIt can be used to configure the maximum concurrency while upgrading MachineDeployments of a classy Cluster. It is set as a top level annotation on the Cluster object. The value should be >= 1. If unspecified the upgrade concurrency will default to 1.Cluster APIClusters
unsafe.topology.cluster.x-k8s.io/disable-update-class-name-checkIt can be used to disable the webhook check on update that disallows a pre-existing Cluster to be populated with Topology information and Class.UserClusters
unsafe.topology.cluster.x-k8s.io/disable-update-version-checkIt can be used to disable the webhook checks on update that disallows updating the .topology.spec.version on certain conditions.UserClusters

Internal Annotations

Following annotation are used by CAPI internally.

AnnotationNoteApplies to
in-place-updates.internal.cluster.x-k8s.io/acknowledge-moveThis annotation is added by the MD controller to a MachineSet when it acknowledges a machine pending acknowledge after being moved from an oldMSMachineSet
in-place-updates.internal.cluster.x-k8s.io/move-machines-to-machinesetThis annotation is added by the MD controller to the oldMS when it should scale down by moving machines that can be updated in-place to the newMS instead of deleting them.MachineSet
in-place-updates.internal.cluster.x-k8s.io/pending-acknowledge-moveThis annotation is by the MS controller to a machine when being moved from the oldMS to the newMSMachine
in-place-updates.internal.cluster.x-k8s.io/receive-machines-from-machinesetsThis annotation is added by the MD controller to the newMS when it should receive replicas from an oldMSMachineSet
in-place-updates.internal.cluster.x-k8s.io/update-in-progressThis annotation is added to machines by the controller owning the Machine when in-place update is startedMachine
topology.internal.cluster.x-k8s.io/upgrade-stepThis is an annotation used by the topology controller to a cluster to track upgrade steps.Clusters

CustomResourceDefinitions relationships

There are many resources that appear in the Cluster API. In this section, we use diagrams to illustrate the most common relationships between Cluster API resources.

Control plane machines relationships

Worker machines relationships

ClusterClass relationships

Metadata propagation

Cluster API controllers implement consistent metadata (labels & annotations) propagation across the core API resources. This behaviour tries to be consistent with Kubernetes apps/v1 Deployment and ReplicaSet. New providers should behave accordingly fitting within the following pattern:

Cluster Topology

ControlPlaneTopology labels are labels and annotations are continuously propagated to ControlPlane top-level labels and annotations and ControlPlane MachineTemplate labels and annotations.

  • .spec.topology.controlPlane.metadata.labels => ControlPlane.labels, ControlPlane.spec.machineTemplate.metadata.labels
  • .spec.topology.controlPlane.metadata.annotations => ControlPlane.annotations, ControlPlane.spec.machineTemplate.metadata.annotations

MachineDeploymentTopology labels and annotations are continuously propagated to MachineDeployment top-level labels and annotations and MachineDeployment MachineTemplate labels and annotations.

  • .spec.topology.machineDeployments[i].metadata.labels => MachineDeployment.labels, MachineDeployment.spec.template.metadata.labels
  • .spec.topology.machineDeployments[i].metadata.annotations => MachineDeployment.annotations, MachineDeployment.spec.template.metadata.annotations

ClusterClass

ControlPlaneClass labels are labels and annotations are continuously propagated to ControlPlane top-level labels and annotations and ControlPlane MachineTemplate labels and annotations.

  • .spec.controlPlane.metadata.labels => ControlPlane.labels, ControlPlane.spec.machineTemplate.metadata.labels
  • .spec.controlPlane.metadata.annotations => ControlPlane.annotations, ControlPlane.spec.machineTemplate.metadata.annotations Note: ControlPlaneTopology labels and annotations take precedence over ControlPlaneClass labels and annotations.

MachineDeploymentClass labels and annotations are continuously propagated to MachineDeployment top-level labels and annotations and MachineDeployment MachineTemplate labels and annotations.

  • .spec.workers.machineDeployments[i].template.metadata.labels => MachineDeployment.labels, MachineDeployment.spec.template.metadata.labels
  • .spec.worker.machineDeployments[i].template.metadata.annotations => MachineDeployment.annotations, MachineDeployment.spec.template.metadata.annotations Note: MachineDeploymentTopology labels and annotations take precedence over MachineDeploymentClass labels and annotations.

KubeadmControlPlane

Top-level labels and annotations do not propagate at all.

  • .labels => Not propagated.
  • .annotations => Not propagated.

MachineTemplate labels and annotations continuously propagate to new and existing Machines, InfraMachines and BootstrapConfigs.

  • .spec.machineTemplate.metadata.labels => Machine.labels, InfraMachine.labels, BootstrapConfig.labels
  • .spec.machineTemplate.metadata.annotations => Machine.annotations, InfraMachine.annotations, BootstrapConfig.annotations

MachineDeployment

Top-level labels do not propagate at all. Top-level annotations continuously propagate to MachineSets top-level annotations.

  • .labels => Not propagated.
  • .annotations => MachineSet.annotations

Template labels continuously propagate to MachineSets top-level and MachineSets template metadata. Template annotations continuously propagate to MachineSets template metadata.

  • .spec.template.metadata.labels => MachineSet.labels, MachineSet.spec.template.metadata.labels
  • .spec.template.metadata.annotations => MachineSet.spec.template.metadata.annotations

MachineSet

Top-level labels and annotations do not propagate at all.

  • .labels => Not propagated.
  • .annotations => Not propagated.

Template labels and annotations continuously propagate to new and existing Machines, InfraMachines and BootstrapConfigs.

  • .spec.template.metadata.labels => Machine.labels, InfraMachine.labels, BootstrapConfig.labels
  • .spec.template.metadata.annotations => Machine.annotations, InfraMachine.annotations, BootstrapConfig.annotations

Machine

Top-level labels and annotations that meet a specific criteria are propagated to the Node labels and annotations.

  • .labels.[label-meets-criteria] => Node.labels
  • .annotations.[annotation-meets-criteria] => Node.annotations

Labels that meet at least one of the following criteria are always propagated to the Node:

  • Has node-role.kubernetes.io as prefix.
  • Belongs to node-restriction.kubernetes.io domain.
  • Belongs to node.cluster.x-k8s.io domain.

In addition, any labels that match at least one of the regexes provided by the --additional-sync-machine-labels flag on the manager will be synced from the Machine to the Node.

Annotations that meet at least one of the following criteria are always propagated to the Node:

  • Belongs to node.cluster.x-k8s.io domain

In addition, any annotations that match at least one of the regexes provided by the --additional-sync-machine-annotations flag on the manager will be synced from the Machine to the Node.

Patches

While this is not technically metadata propagation, it is worth to notice that when using Cluster API managed topologies, by using patches it is also possible to manage labels and annotations in resources that are originated from templates linked to the ClusterClass. More specifically:

Patches for ControlPlaneTemplates, InfraClusterTemplates, MachinePoolTemplates and BootstrapConfigTemplates (only if referenced from a MachinePool class):

  • Changes to .spec.template.metadata.{labels|annotations} will be reflected in .metadata.{labels|annotations} of the corresponding generated object. e.g. KubeadmControlPlaneTemplate.spec.template.metadata.labels –> KubeadmControlPlane.metadata.labels

Patches for InfraMachineTemplates, BootstrapConfigTemplates (except when referenced from a MachinePool)

  • Changes to .metadata.{labels|annotations} will be reflected in .metadata.{labels|annotations} of the corresponding generated template. e.g. VSphereMachineTemplate.metadata.labels –> VSphereMachineTemplate.metadata.labels
  • Changes to .spec.template.metadata.{labels|annotations} will be reflected in .spec.template.metadata.{labels|annotations} of the corresponding generated template. e.g. VSphereMachineTemplate.spec.template.metadata.labels –> VSphereMachineTemplate.spec.template.metadata.labels

Taint propagation

Cluster API controllers implement consistent taint propagation across Cluster API resources and from Machines to corresponding Kubernetes Node in the workload cluster. Note: To enable this feature it is required to set the MachineTaintPropagation feature gate to true.

See the proposal Propagating taints from Cluster API to Nodes for more information.

When using Cluster API managed topologies, taint can be set both on ClusterClass or on the Cluster object; the propagation of the taints is summarized in the following table and picture:

ClusterClassClusterResult on ControlPlane, MachineDeployment, MachinePools
SetSetCluster taints (ClusterClass taints are ignored)
SetNot setClusterClass taints
Not setSetCluster taints
Not setNot setNo taints from ClusterClass or Cluster

Taint set on ControlPlane, MachineDeployment (MachineSet) resources are propagated in-place, without triggering a rollout, to the controlled Machines.

Taint set on the Machine resource are propagated to the corresponding Kubernetes Node in the workload cluster. This operation is performed according to the propagation rule defined for each taint on the Machine object:

  • Always:

    • These taints are supposed to be set on the Node object as long as it is defined on its parent core CAPI object.
    • Example: Nodes where only GPU related workload should run
    • Reconciliation behavior:
      • Always taint added to the machine or exists during initialization: reconciliation will add the taint to the node.
      • Always taint removed from machine: reconciliation will remove the taint from the node, if it did add it in the past.
      • Always taint not changed: reconciliation takes care that the taint still exists on the node.
  • OnInitialization

    • These taints are supposed to be set once by Cluster API on a Node object.
    • Example: Ensure that no workload gets scheduled to a Node unless the taint got removed to e.g. install a GPU driver before allowing workload.
    • Cluster API should once set the taint on the Node and not add it again if it got removed.

Taint propagation for MachinePools resources is not implemented yet.

Please note that:

  • Taints with a key of node.cluster.x-k8s.io/uninitialized or node.cluster.x-k8s.io/outdated-revision cannot be set by users (these taints are managed by Cluster API and providers).
  • Taints with the key prefix node.kubernetes.io/ cannot be set by users, except node.kubernetes.io/out-of-service (these taints are managed by the node controller or the kubelet).
  • Taints with the key prefix node.cloudprovider.kubernetes.io/ cannot be set by users (these taints are either managed by the kubelet or by a cloud-controller-manager’s node-lifecycle-controller)
  • The taint node-role.kubernetes.io/control-plane cannot be set by users on worker nodes.
  • The taint node-role.kubernetes.io/master cannot be set by users (deprecated since 1.24)

Notes for the Kubeadm bootstrap provider

If using the kubeadm bootstrap provider, taints can also be added by setting init/joinConfiguration.nodeRegistration.taints.

Adding taints with this approach is almost equivalent to adding an OnInitialization taint on the Machine resource.

The following table describe available options depending on where taints are set or not set [1].

MachineCABPKResult
SetSetCABPK and Machine taints, on same key + effect use the value from the Machine defined taint
SetNot setCABPK default [2] and Machine taints, on same key + effect use the value from the Machine defined taint
Setempty / []Machine taints
Not setSetCABPK taints
Not setNot setCABPK default [2] taint
Not setempty / []no taints

[1]: If the taint are not set on the Machine, CAPBK preserve the same behaviour existing before the implementation of this feature. [2]: Per default kubeadm adds the taint node-role.kubernetes.io/control-plane:NoSchedule to control plane nodes.

Owner References

Cluster API uses Kubernetes owner references to track relationships between objects. These references are used for Kubernetes garbage collection, which is also used for Cluster deletion in CAPI. They are also used in places where the ownership hierarchy is important, for example when using clusterctl move.

CAPI uses owner references in an opinionated way. The following guidelines should be considered:

  1. Objects should always be created with an owner reference to prevent leaking objects. Initial ownerReferences can be
    replaced later where another object is a more appropriate owner.
  2. Owner references should be re-reconciled if they are lost for an object. This is required as some tools - e.g. velero - may delete owner references on objects.
  3. Owner references should be kept to the most recent apiVersion.
    • This ensures garbage collection still works after an old apiVersion is no longer served.
  4. Owner references should not be added unless required.
    • Multiple owner references on a single object should be exceptional.

Owner reference relationships in Cluster API

The below tables map out the a reference for ownership relationships for the objects in a Cluster API cluster. The tables are identical for classy and non-classy clusters.

Providers may implement their own ownership relationships which may or may not map directly to the below tables. These owner references are almost all tested in an end-to-end test. Lack of testing is noted where this is not the case. CAPI Providers can take advantage of the e2e test framework to ensure their owner references are predictable, documented and stable.

Kubernetes core types

typeOwnerControllerNote
SecretKubeadmControlPlaneyesFor cluster certificates
SecretKubeadmConfigyesFor bootstrap secrets
SecretClusterResourceSetnoWhen referenced by CRS. Not tested in e2e.
ConfigMapClusterResourceSetnoWhen referenced by CRS

Core types

typeOwnerControllerNote
ExtensionConfigNone
ClusterClassNone
ClusterNone
MachineDeploymentsClusterno
MachineSetMachineDeploymentyes
MachineMachineSetyesWhen created by MachineSet
MachineKubeadmControlPlaneyesWhen created by KCP
MachineHealthChecksClusterno

Experimental types

typeOwnerControllerNote
ClusterResourcesSetNone
ClusterResourcesSetBindingClusterResourceSetnoMay have many CRS owners
MachinePoolClusterno

KubeadmControlPlane types

typeOwnerControllerNote
KubeadmControlPlaneClusteryes
KubeadmControlPlaneTemplateClusterClassno

Kubeadm bootstrap types

typeOwnerControllerNote
KubeadmConfigMachineyesWhen created for Machine
KubeadmConfigMachinePoolyesWhen created for MachinePool
KubeadmConfigTemplateClusternoWhen referenced in MachineDeployment spec
KubeadmConfigTemplateClusterClassnoWhen referenced in ClusterClass

Infrastructure provider types

typeOwnerControllerNote
InfrastructureMachineMachineyes
InfrastructureMachineTemplateClusternoWhen created by cluster topology controller
InfrastructureMachineTemplateClusterClassnoWhen referenced in a ClusterClass
InfrastructureClusterClusteryes
InfrastructureClusterTemplateClusterClassno
InfrastructureMachinePoolMachinePoolyes

API Reference

Packages

addons.cluster.x-k8s.io/v1beta2

Package v1beta2 contains API Schema definitions for the addons v1beta2 API group.

Resource Types

ClusterResourceSet

ClusterResourceSet is the Schema for the clusterresourcesets API. For advanced use cases an add-on provider should be used instead.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringaddons.cluster.x-k8s.io/v1beta2
kind stringClusterResourceSet
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
spec ClusterResourceSetSpecspec is the desired state of ClusterResourceSet.Required: {}
status ClusterResourceSetStatusstatus is the observed state of ClusterResourceSet.MinProperties: 1
Optional: {}

ClusterResourceSetBinding

ClusterResourceSetBinding lists all matching ClusterResourceSets with the cluster it belongs to.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringaddons.cluster.x-k8s.io/v1beta2
kind stringClusterResourceSetBinding
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
spec ClusterResourceSetBindingSpecspec is the desired state of ClusterResourceSetBinding.Required: {}

ClusterResourceSetBindingList

ClusterResourceSetBindingList contains a list of ClusterResourceSetBinding.

FieldDescriptionDefaultValidation
apiVersion stringaddons.cluster.x-k8s.io/v1beta2
kind stringClusterResourceSetBindingList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items ClusterResourceSetBinding arrayitems is the list of ClusterResourceSetBindings.

ClusterResourceSetBindingSpec

ClusterResourceSetBindingSpec defines the desired state of ClusterResourceSetBinding.

Appears in:

FieldDescriptionDefaultValidation
bindings ResourceSetBinding arraybindings is a list of ClusterResourceSets and their resources.MaxItems: 100
Optional: {}
clusterName stringclusterName is the name of the Cluster this binding applies to.MaxLength: 63
MinLength: 1
Required: {}

ClusterResourceSetDeprecatedStatus

ClusterResourceSetDeprecatedStatus groups all the status fields that are deprecated and will be removed in a future version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
v1beta1 ClusterResourceSetV1Beta1DeprecatedStatusv1beta1 groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped.Optional: {}

ClusterResourceSetList

ClusterResourceSetList contains a list of ClusterResourceSet.

FieldDescriptionDefaultValidation
apiVersion stringaddons.cluster.x-k8s.io/v1beta2
kind stringClusterResourceSetList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items ClusterResourceSet arrayitems is the list of ClusterResourceSets.

ClusterResourceSetSpec

ClusterResourceSetSpec defines the desired state of ClusterResourceSet.

Appears in:

FieldDescriptionDefaultValidation
clusterSelector LabelSelectorclusterSelector is the label selector for Clusters. The Clusters that are
selected by this will be the ones affected by this ClusterResourceSet.
It must match the Cluster labels. This field is immutable.
Label selector cannot be empty.
Required: {}
resources ResourceRef arrayresources is a list of Secrets/ConfigMaps where each contains 1 or more resources to be applied to remote clusters.MaxItems: 100
MinItems: 1
Required: {}
strategy stringstrategy is the strategy to be used during applying resources. Defaults to ApplyOnce. This field is immutable.Enum: [ApplyOnce Reconcile]
Optional: {}

ClusterResourceSetStatus

ClusterResourceSetStatus defines the observed state of ClusterResourceSet.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a ClusterResourceSet’s current state.
Known condition types are ResourcesApplied.
MaxItems: 32
Optional: {}
observedGeneration integerobservedGeneration reflects the generation of the most recently observed ClusterResourceSet.Minimum: 1
Optional: {}
deprecated ClusterResourceSetDeprecatedStatusdeprecated groups all the status fields that are deprecated and will be removed when all the nested field are removed.Optional: {}

ClusterResourceSetV1Beta1DeprecatedStatus

ClusterResourceSetV1Beta1DeprecatedStatus groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Conditionsconditions defines current state of the ClusterResourceSet.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}

ResourceBinding

ResourceBinding shows the status of a resource that belongs to a ClusterResourceSet matched by the owner cluster of the ClusterResourceSetBinding object.

Appears in:

FieldDescriptionDefaultValidation
name stringname of the resource that is in the same namespace with ClusterResourceSet object.MaxLength: 253
MinLength: 1
Required: {}
kind stringkind of the resource. Supported kinds are: Secrets and ConfigMaps.Enum: [Secret ConfigMap]
Required: {}
hash stringhash is the hash of a resource’s data. This can be used to decide if a resource is changed.
For “ApplyOnce” ClusterResourceSet.spec.strategy, this is no-op as that strategy does not act on change.
MaxLength: 256
MinLength: 1
Optional: {}
applied booleanapplied is to track if a resource is applied to the cluster or not.Required: {}

ResourceRef

ResourceRef specifies a resource.

Appears in:

FieldDescriptionDefaultValidation
name stringname of the resource that is in the same namespace with ClusterResourceSet object.MaxLength: 253
MinLength: 1
Required: {}
kind stringkind of the resource. Supported kinds are: Secrets and ConfigMaps.Enum: [Secret ConfigMap]
Required: {}

ResourceSetBinding

ResourceSetBinding keeps info on all of the resources in a ClusterResourceSet.

Appears in:

FieldDescriptionDefaultValidation
clusterResourceSetName stringclusterResourceSetName is the name of the ClusterResourceSet that is applied to the owner cluster of the binding.MaxLength: 253
MinLength: 1
Required: {}
resources ResourceBinding arrayresources is a list of resources that the ClusterResourceSet has.MaxItems: 100
Optional: {}

bootstrap.cluster.x-k8s.io/v1beta2

Package v1beta2 contains API Schema definitions for the kubeadm v1beta2 API group.

Resource Types

APIEndpoint

APIEndpoint struct contains elements of API server instance deployed on a node.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
advertiseAddress stringadvertiseAddress sets the IP address for the API server to advertise.MaxLength: 39
MinLength: 1
Optional: {}
bindPort integerbindPort sets the secure port for the API Server to bind to.
Defaults to 6443.
Minimum: 1
Optional: {}

APIServer

APIServer holds settings necessary for API server deployments in the cluster.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
extraArgs Arg arrayextraArgs is a list of args to pass to the control plane component.
The arg name must match the command line flag name except without leading dash(es).
Extra arguments will override existing default arguments set by kubeadm.
MaxItems: 100
MinItems: 1
Optional: {}
extraVolumes HostPathMount arrayextraVolumes is an extra set of host volumes, mounted to the control plane component.MaxItems: 100
MinItems: 1
Optional: {}
extraEnvs EnvVarextraEnvs is an extra set of environment variables to pass to the control plane component.
Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default.
This option takes effect only on Kubernetes >=1.31.0.
MaxItems: 100
MinItems: 1
Optional: {}
certSANs string arraycertSANs sets extra Subject Alternative Names for the API Server signing cert.MaxItems: 100
MinItems: 1
items:MaxLength: 253
items:MinLength: 1
Optional: {}

Arg

Arg represents an argument with a name and a value.

Appears in:

FieldDescriptionDefaultValidation
name stringname is the Name of the extraArg.MaxLength: 256
MinLength: 1
Required: {}
value stringvalue is the Value of the extraArg.MaxLength: 1024
MinLength: 0
Required: {}

BootstrapToken

BootstrapToken describes one bootstrap token, stored as a Secret in the cluster.

Appears in:

FieldDescriptionDefaultValidation
token BootstrapTokenStringtoken is used for establishing bidirectional trust between nodes and control-planes.
Used for joining nodes in the cluster.
MaxLength: 23
MinLength: 1
Type: string
Required: {}
description stringdescription sets a human-friendly message why this token exists and what it’s used
for, so other administrators can know its purpose.
MaxLength: 512
MinLength: 1
Optional: {}
ttlSeconds integerttlSeconds defines the time to live for this token. Defaults to 24h.
Expires and ttlSeconds are mutually exclusive.
Minimum: 0
Optional: {}
usages string arrayusages describes the ways in which this token can be used. Can by default be used
for establishing bidirectional trust, but that can be changed here.
MaxItems: 100
MinItems: 1
items:MaxLength: 256
items:MinLength: 1
Optional: {}
groups string arraygroups specifies the extra groups that this token will authenticate as when/if
used for authentication
MaxItems: 100
MinItems: 1
items:MaxLength: 256
items:MinLength: 1
Optional: {}

BootstrapTokenDiscovery

BootstrapTokenDiscovery is used to set the options for bootstrap token based discovery.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
token stringtoken is a token used to validate cluster information
fetched from the control-plane.
MaxLength: 512
MinLength: 1
Optional: {}
apiServerEndpoint stringapiServerEndpoint is an IP or domain name to the API server from which info will be fetched.MaxLength: 512
MinLength: 1
Optional: {}
caCertHashes string arraycaCertHashes specifies a set of public key pins to verify
when token-based discovery is used. The root CA found during discovery
must match one of these values. Specifying an empty set disables root CA
pinning, which can be unsafe. Each hash is specified as “:”,
where the only currently supported type is “sha256”. This is a hex-encoded
SHA-256 hash of the Subject Public Key Info (SPKI) object in DER-encoded
ASN.1. These hashes can be calculated using, for example, OpenSSL:
openssl x509 -pubkey -in ca.crt openssl rsa -pubin -outform der 2>&/dev/null | openssl dgst -sha256 -hex
MaxItems: 100
MinItems: 1
items:MaxLength: 512
items:MinLength: 1
Optional: {}
unsafeSkipCAVerification booleanunsafeSkipCAVerification allows token-based discovery
without CA verification via CACertHashes. This can weaken
the security of kubeadm since other nodes can impersonate the control-plane.
Optional: {}

BootstrapTokenString

BootstrapTokenString is a token of the format abcdef.abcdef0123456789 that is used for both validation of the practically of the API server from a joining node’s point of view and as an authentication method for the node in the bootstrap phase of “kubeadm join”. This token is and should be short-lived.

Validation:

  • MaxLength: 23
  • MinLength: 1
  • Type: string

Appears in:

ClusterConfiguration

ClusterConfiguration contains cluster-wide configuration for a kubeadm cluster.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
etcd Etcdetcd holds configuration for etcd.
NB: This value defaults to a Local (stacked) etcd
MinProperties: 1
Optional: {}
controlPlaneEndpoint stringcontrolPlaneEndpoint sets a stable IP address or DNS name for the control plane; it
can be a valid IP address or a RFC-1123 DNS subdomain, both with optional TCP port.
In case the ControlPlaneEndpoint is not specified, the AdvertiseAddress + BindPort
are used; in case the ControlPlaneEndpoint is specified but without a TCP port,
the BindPort is used.
Possible usages are:
e.g. In a cluster with more than one control plane instances, this field should be
assigned the address of the external load balancer in front of the
control plane instances.
e.g. in environments with enforced node recycling, the ControlPlaneEndpoint
could be used for assigning a stable DNS to the control plane.
NB: This value defaults to the first value in the Cluster object status.apiEndpoints array.
MaxLength: 512
MinLength: 1
Optional: {}
apiServer APIServerapiServer contains extra settings for the API server control plane componentMinProperties: 1
Optional: {}
controllerManager ControllerManagercontrollerManager contains extra settings for the controller manager control plane componentMinProperties: 1
Optional: {}
scheduler Schedulerscheduler contains extra settings for the scheduler control plane componentMinProperties: 1
Optional: {}
dns DNSdns defines the options for the DNS add-on installed in the cluster.MinProperties: 1
Optional: {}
certificatesDir stringcertificatesDir specifies where to store or look for all required certificates.
NB: if not provided, this will default to /etc/kubernetes/pki
MaxLength: 512
MinLength: 1
Optional: {}
imageRepository stringimageRepository sets the container registry to pull images from.
If not set, the default registry of kubeadm will be used (registry.k8s.io).
MaxLength: 512
MinLength: 1
Optional: {}
featureGates object (keys:string, values:boolean)featureGates enabled by the user.Optional: {}
certificateValidityPeriodDays integercertificateValidityPeriodDays specifies the validity period for non-CA certificates generated by kubeadm.
If not specified, kubeadm will use a default of 365 days (1 year).
This field is only supported with Kubernetes v1.31 or above.
Maximum: 1095
Minimum: 1
Optional: {}
caCertificateValidityPeriodDays integercaCertificateValidityPeriodDays specifies the validity period for CA certificates generated by Cluster API.
If not specified, Cluster API will use a default of 3650 days (10 years).
This field cannot be modified.
Maximum: 36500
Minimum: 1
Optional: {}
encryptionAlgorithm EncryptionAlgorithmTypeencryptionAlgorithm holds the type of asymmetric encryption algorithm used for keys and certificates.
Can be one of “RSA-2048”, “RSA-3072”, “RSA-4096”, “ECDSA-P256” or “ECDSA-P384”.
For Kubernetes 1.34 or above, “ECDSA-P384” is supported.
If not specified, Cluster API will use RSA-2048 as default.
When this field is modified every certificate generated afterward will use the new
encryptionAlgorithm. Existing CA certificates and service account keys are not rotated.
This field is only supported with Kubernetes v1.31 or above.
Enum: [ECDSA-P256 ECDSA-P384 RSA-2048 RSA-3072 RSA-4096]
Optional: {}

ContainerLinuxConfig

ContainerLinuxConfig contains CLC-specific configuration.

We use a structured type here to allow adding additional fields, for example ‘version’.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
additionalConfig stringadditionalConfig contains additional configuration to be merged with the Ignition
configuration generated by the bootstrapper controller. More info: https://coreos.github.io/ignition/operator-notes/#config-merging
The data format is documented here: https://kinvolk.io/docs/flatcar-container-linux/latest/provisioning/cl-config/
MaxLength: 32768
MinLength: 1
Optional: {}
strict booleanstrict controls if AdditionalConfig should be strictly parsed. If so, warnings are treated as errors.Optional: {}

ControllerManager

ControllerManager holds settings necessary for controller-manager deployments in the cluster.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
extraArgs Arg arrayextraArgs is a list of args to pass to the control plane component.
The arg name must match the command line flag name except without leading dash(es).
Extra arguments will override existing default arguments set by kubeadm.
MaxItems: 100
MinItems: 1
Optional: {}
extraVolumes HostPathMount arrayextraVolumes is an extra set of host volumes, mounted to the control plane component.MaxItems: 100
MinItems: 1
Optional: {}
extraEnvs EnvVarextraEnvs is an extra set of environment variables to pass to the control plane component.
Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default.
This option takes effect only on Kubernetes >=1.31.0.
MaxItems: 100
MinItems: 1
Optional: {}

DNS

DNS defines the DNS addon that should be used in the cluster.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
imageRepository stringimageRepository sets the container registry to pull images from.
if not set, the ImageRepository defined in ClusterConfiguration will be used instead.
MaxLength: 512
MinLength: 1
Optional: {}
imageTag stringimageTag allows to specify a tag for the image.
In case this value is set, kubeadm does not change automatically the version of the above components during upgrades.
MaxLength: 256
MinLength: 1
Optional: {}

Discovery

Discovery specifies the options for the kubelet to use during the TLS Bootstrap process.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
bootstrapToken BootstrapTokenDiscoverybootstrapToken is used to set the options for bootstrap token based discovery
BootstrapToken and File are mutually exclusive
MinProperties: 1
Optional: {}
file FileDiscoveryfile is used to specify a file or URL to a kubeconfig file from which to load cluster information
BootstrapToken and File are mutually exclusive
Optional: {}
tlsBootstrapToken stringtlsBootstrapToken is a token used for TLS bootstrapping.
If .BootstrapToken is set, this field is defaulted to .BootstrapToken.Token, but can be overridden.
If .File is set, this field must be set in case the KubeConfigFile does not contain any other authentication information
MaxLength: 512
MinLength: 1
Optional: {}

DiskSetup

DiskSetup defines input for generated disk_setup and fs_setup in cloud-init.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
partitions Partition arraypartitions specifies the list of the partitions to setup.ExactlyOneOf: [layout diskLayout]
MaxItems: 100
Optional: {}
filesystems Filesystem arrayfilesystems specifies the list of file systems to setup.MaxItems: 100
Optional: {}

Encoding

Underlying type: string

Encoding specifies the cloud-init file encoding.

Validation:

  • Enum: [base64 gzip gzip+base64]

Appears in:

FieldDescription
base64Base64 implies the contents of the file are encoded as base64.
gzipGzip implies the contents of the file are encoded with gzip.
gzip+base64GzipBase64 implies the contents of the file are first base64 encoded and then gzip encoded.

EncryptionAlgorithmType

Underlying type: string

EncryptionAlgorithmType can define an asymmetric encryption algorithm type.

Validation:

  • Enum: [ECDSA-P256 ECDSA-P384 RSA-2048 RSA-3072 RSA-4096]

Appears in:

FieldDescription
ECDSA-P256EncryptionAlgorithmECDSAP256 defines the ECDSA encryption algorithm type with curve P256.
ECDSA-P384EncryptionAlgorithmECDSAP384 defines the ECDSA encryption algorithm type with curve P384.
RSA-2048EncryptionAlgorithmRSA2048 defines the RSA encryption algorithm type with key size 2048 bits.
RSA-3072EncryptionAlgorithmRSA3072 defines the RSA encryption algorithm type with key size 3072 bits.
RSA-4096EncryptionAlgorithmRSA4096 defines the RSA encryption algorithm type with key size 4096 bits.

EnvVar

EnvVar represents an environment variable present in a Container.

Appears in:

FieldDescriptionDefaultValidation
name stringName of the environment variable.
May consist of any printable ASCII characters except ‘=’.
value stringVariable references $(VAR_NAME) are expanded
using the previously defined environment variables in the container and
any service environment variables. If a variable cannot be resolved,
the reference in the input string will be unchanged. Double $$ are reduced
to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e.
“$$(VAR_NAME)” will produce the string literal “$(VAR_NAME)”.
Escaped references will never be expanded, regardless of whether the variable
exists or not.
Defaults to “”.
Optional: {}
valueFrom EnvVarSourceSource for the environment variable’s value. Cannot be used if value is not empty.Optional: {}

Etcd

Etcd contains elements describing Etcd configuration.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
local LocalEtcdlocal provides configuration knobs for configuring the local etcd instance
Local and External are mutually exclusive
MinProperties: 1
Optional: {}
external ExternalEtcdexternal describes how to connect to an external etcd cluster
Local and External are mutually exclusive
Optional: {}

ExternalEtcd

ExternalEtcd describes an external etcd cluster. Kubeadm has no knowledge of where certificate files live and they must be supplied.

Appears in:

FieldDescriptionDefaultValidation
endpoints string arrayendpoints of etcd members. Required for ExternalEtcd.MaxItems: 50
MinItems: 1
items:MaxLength: 512
items:MinLength: 1
Required: {}
caFile stringcaFile is an SSL Certificate Authority file used to secure etcd communication.
Required if using a TLS connection.
MaxLength: 512
MinLength: 1
Required: {}
certFile stringcertFile is an SSL certification file used to secure etcd communication.
Required if using a TLS connection.
MaxLength: 512
MinLength: 1
Required: {}
keyFile stringkeyFile is an SSL key file used to secure etcd communication.
Required if using a TLS connection.
MaxLength: 512
MinLength: 1
Required: {}

File

File defines the input for generating write_files in cloud-init.

Appears in:

FieldDescriptionDefaultValidation
path stringpath specifies the full path on disk where to store the file.MaxLength: 512
MinLength: 1
Required: {}
owner stringowner specifies the ownership of the file, e.g. “root:root”.MaxLength: 256
MinLength: 1
Optional: {}
permissions stringpermissions specifies the permissions to assign to the file, e.g. “0640”.MaxLength: 16
MinLength: 1
Optional: {}
encoding Encodingencoding specifies the encoding of the file contents.Enum: [base64 gzip gzip+base64]
Optional: {}
append booleanappend specifies whether to append Content to existing file if Path exists.Optional: {}
content stringcontent is the actual content of the file.MaxLength: 10240
MinLength: 1
Optional: {}
contentFrom FileSourcecontentFrom is a referenced source of content to populate the file.Optional: {}
contentFormat FileContentFormatcontentFormat specifies how to interpret content after it is resolved (inline or from contentFrom).
When set to “Template”, content is rendered as a Go text/template.
Available template variables:
- .controlPlane.version: the Kubernetes version of the control plane (e.g. “v1.35.0”).
Only set when the cluster has a control plane reference that exposes spec.version.
When set to “Raw” or omitted, content is used verbatim.
Enum: [Raw Template]
Optional: {}

FileContentFormat

Underlying type: string

FileContentFormat specifies how file content is interpreted after resolving content/contentFrom and before writing bootstrap data.

Validation:

  • Enum: [Raw Template]

Appears in:

FieldDescription
RawFileContentFormatRaw means content is used verbatim.
TemplateFileContentFormatTemplate means content is rendered as a Go text/template.

FileDiscovery

FileDiscovery is used to specify a file or URL to a kubeconfig file from which to load cluster information.

Appears in:

FieldDescriptionDefaultValidation
kubeConfigPath stringkubeConfigPath is used to specify the actual file path or URL to the kubeconfig file from which to load cluster informationMaxLength: 512
MinLength: 1
Required: {}
kubeConfig FileDiscoveryKubeConfigkubeConfig is used (optionally) to generate a KubeConfig based on the KubeadmConfig’s information.
The file is generated at the path specified in KubeConfigPath.
Host address (server field) information is automatically populated based on the Cluster’s ControlPlaneEndpoint.
Certificate Authority (certificate-authority-data field) is gathered from the cluster’s CA secret.
Optional: {}

FileDiscoveryKubeConfig

FileDiscoveryKubeConfig contains elements describing how to generate the kubeconfig for bootstrapping.

Appears in:

FieldDescriptionDefaultValidation
cluster KubeConfigClustercluster contains information about how to communicate with the kubernetes cluster.
By default the following fields are automatically populated:
- Server with the Cluster’s ControlPlaneEndpoint.
- CertificateAuthorityData with the Cluster’s CA certificate.
MinProperties: 1
Optional: {}
user KubeConfigUseruser contains information that describes identity information.
This is used to tell the kubernetes cluster who you are.
MinProperties: 1
Required: {}

FileSource

FileSource is a union of all possible external source types for file data. Only one field may be populated in any given instance. Developers adding new sources of data for target systems should add them here.

Appears in:

FieldDescriptionDefaultValidation
secret SecretFileSourcesecret represents a secret that should populate this file.Required: {}

Filesystem

Filesystem defines the file systems to be created.

Appears in:

FieldDescriptionDefaultValidation
device stringdevice specifies the device nameMaxLength: 256
MinLength: 1
Required: {}
filesystem stringfilesystem specifies the file system type.MaxLength: 128
MinLength: 1
Required: {}
label stringlabel specifies the file system label to be used. If set to None, no label is used.MaxLength: 512
MinLength: 1
Optional: {}
partition stringpartition specifies the partition to use. The valid options are: “auto|any”, “auto”, “any”, “none”, and , where NUM is the actual partition number.MaxLength: 128
MinLength: 1
Optional: {}
overwrite booleanoverwrite defines whether or not to overwrite any existing filesystem.
If true, any pre-existing file system will be destroyed. Use with Caution.
Optional: {}
replaceFS stringreplaceFS is a special directive, used for Microsoft Azure that instructs cloud-init to replace a file system of <FS_TYPE>.
NOTE: unless you define a label, this requires the use of the ‘any’ partition directive.
MaxLength: 128
MinLength: 1
Optional: {}
extraOpts string arrayextraOpts defined extra options to add to the command for creating the file system.MaxItems: 100
items:MaxLength: 256
items:MinLength: 1
Optional: {}

Format

Underlying type: string

Format specifies the output format of the bootstrap data

Validation:

  • Enum: [cloud-config ignition]

Appears in:

FieldDescription
cloud-configCloudConfig make the bootstrap data to be of cloud-config format.
ignitionIgnition make the bootstrap data to be of Ignition format.

HostPathMount

HostPathMount contains elements describing volumes that are mounted from the host.

Appears in:

FieldDescriptionDefaultValidation
name stringname of the volume inside the pod template.MaxLength: 512
MinLength: 1
Required: {}
hostPath stringhostPath is the path in the host that will be mounted inside
the pod.
MaxLength: 512
MinLength: 1
Required: {}
mountPath stringmountPath is the path inside the pod where hostPath will be mounted.MaxLength: 512
MinLength: 1
Required: {}
readOnly booleanreadOnly controls write access to the volumeOptional: {}
pathType HostPathTypepathType is the type of the HostPath.Optional: {}

IgnitionSpec

IgnitionSpec contains Ignition specific configuration.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
containerLinuxConfig ContainerLinuxConfigcontainerLinuxConfig contains CLC specific configuration.MinProperties: 1
Optional: {}

InitConfiguration

InitConfiguration contains a list of elements that is specific “kubeadm init”-only runtime information.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
bootstrapTokens BootstrapToken arraybootstrapTokens is respected at kubeadm init time and describes a set of Bootstrap Tokens to create.
This information IS NOT uploaded to the kubeadm cluster configmap, partly because of its sensitive nature
MaxItems: 100
MinItems: 1
Optional: {}
nodeRegistration NodeRegistrationOptionsnodeRegistration holds fields that relate to registering the new control-plane node to the cluster.
When used in the context of control plane nodes, NodeRegistration should remain consistent
across both InitConfiguration and JoinConfiguration
MinProperties: 1
Optional: {}
localAPIEndpoint APIEndpointlocalAPIEndpoint represents the endpoint of the API server instance that’s deployed on this control plane node
In HA setups, this differs from ClusterConfiguration.ControlPlaneEndpoint in the sense that ControlPlaneEndpoint
is the global endpoint for the cluster, which then loadbalances the requests to each individual API server. This
configuration object lets you customize what IP/DNS name and port the local API server advertises it’s accessible
on. By default, kubeadm tries to auto-detect the IP of the default interface and use that, but in case that process
fails you may set the desired value here.
MinProperties: 1
Optional: {}
skipPhases string arrayskipPhases is a list of phases to skip during command execution.
The list of phases can be obtained with the “kubeadm init –help” command.
This option takes effect only on Kubernetes >=1.22.0.
MaxItems: 50
MinItems: 1
items:MaxLength: 256
items:MinLength: 1
Optional: {}
patches Patchespatches contains options related to applying patches to components deployed by kubeadm during
“kubeadm init”. The minimum kubernetes version needed to support Patches is v1.22
MinProperties: 1
Optional: {}
timeouts Timeoutstimeouts holds various timeouts that apply to kubeadm commands.MinProperties: 1
Optional: {}

JoinConfiguration

JoinConfiguration contains elements describing a particular node.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
nodeRegistration NodeRegistrationOptionsnodeRegistration holds fields that relate to registering the new control-plane node to the cluster.
When used in the context of control plane nodes, NodeRegistration should remain consistent
across both InitConfiguration and JoinConfiguration
MinProperties: 1
Optional: {}
caCertPath stringcaCertPath is the path to the SSL certificate authority used to
secure communications between node and control-plane.
Defaults to “/etc/kubernetes/pki/ca.crt”.
MaxLength: 512
MinLength: 1
Optional: {}
discovery Discoverydiscovery specifies the options for the kubelet to use during the TLS Bootstrap processMinProperties: 1
Optional: {}
controlPlane JoinControlPlanecontrolPlane defines the additional control plane instance to be deployed on the joining node.
If nil, no additional control plane instance will be deployed.
Optional: {}
skipPhases string arrayskipPhases is a list of phases to skip during command execution.
The list of phases can be obtained with the “kubeadm init –help” command.
This option takes effect only on Kubernetes >=1.22.0.
MaxItems: 50
MinItems: 1
items:MaxLength: 256
items:MinLength: 1
Optional: {}
patches Patchespatches contains options related to applying patches to components deployed by kubeadm during
“kubeadm join”. The minimum kubernetes version needed to support Patches is v1.22
MinProperties: 1
Optional: {}
timeouts Timeoutstimeouts holds various timeouts that apply to kubeadm commands.MinProperties: 1
Optional: {}

JoinControlPlane

JoinControlPlane contains elements describing an additional control plane instance to be deployed on the joining node.

Appears in:

FieldDescriptionDefaultValidation
localAPIEndpoint APIEndpointlocalAPIEndpoint represents the endpoint of the API server instance to be deployed on this node.MinProperties: 1
Optional: {}

KubeConfigAuthExec

KubeConfigAuthExec specifies a command to provide client credentials. The command is exec’d and outputs structured stdout holding credentials.

See the client.authentication.k8s.io API group for specifications of the exact input and output format.

Appears in:

FieldDescriptionDefaultValidation
command stringcommand to execute.MaxLength: 1024
MinLength: 1
Required: {}
args string arrayargs is the arguments to pass to the command when executing it.MaxItems: 100
MinItems: 1
items:MaxLength: 512
items:MinLength: 1
Optional: {}
env KubeConfigAuthExecEnv arrayenv defines additional environment variables to expose to the process. These
are unioned with the host’s environment, as well as variables client-go uses
to pass argument to the plugin.
MaxItems: 100
MinItems: 1
Optional: {}
apiVersion stringapiVersion is preferred input version of the ExecInfo. The returned ExecCredentials MUST use
the same encoding version as the input.
Defaults to client.authentication.k8s.io/v1 if not set.
MaxLength: 512
MinLength: 1
Optional: {}
provideClusterInfo booleanprovideClusterInfo determines whether or not to provide cluster information,
which could potentially contain very large CA data, to this exec plugin as a
part of the KUBERNETES_EXEC_INFO environment variable. By default, it is set
to false. Package k8s.io/client-go/tools/auth/exec provides helper methods for
reading this environment variable.
Optional: {}

KubeConfigAuthExecEnv

KubeConfigAuthExecEnv is used for setting environment variables when executing an exec-based credential plugin.

Appears in:

FieldDescriptionDefaultValidation
name stringname of the environment variableMaxLength: 512
MinLength: 1
Required: {}
value stringvalue of the environment variableMaxLength: 512
MinLength: 1
Required: {}

KubeConfigAuthProvider

KubeConfigAuthProvider holds the configuration for a specified auth provider.

Appears in:

FieldDescriptionDefaultValidation
name stringname is the name of the authentication plugin.MaxLength: 256
MinLength: 1
Required: {}
config object (keys:string, values:string)config holds the parameters for the authentication plugin.Optional: {}

KubeConfigCluster

KubeConfigCluster contains information about how to communicate with a kubernetes cluster.

Adapted from clientcmdv1.Cluster.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
server stringserver is the address of the kubernetes cluster (https://hostname:port).
Defaults to https:// + Cluster.Spec.ControlPlaneEndpoint.
MaxLength: 512
MinLength: 1
Optional: {}
tlsServerName stringtlsServerName is used to check server certificate. If TLSServerName is empty, the hostname used to contact the server is used.MaxLength: 512
MinLength: 1
Optional: {}
insecureSkipTLSVerify booleaninsecureSkipTLSVerify skips the validity check for the server’s certificate. This will make your HTTPS connections insecure.Optional: {}
certificateAuthorityData integer arraycertificateAuthorityData contains PEM-encoded certificate authority certificates.
Defaults to the Cluster’s CA certificate if empty.
MaxLength: 51200
MinLength: 1
Optional: {}
proxyURL stringproxyURL is the URL to the proxy to be used for all requests made by this
client. URLs with “http”, “https”, and “socks5” schemes are supported. If
this configuration is not provided or the empty string, the client
attempts to construct a proxy configuration from http_proxy and
https_proxy environment variables. If these environment variables are not
set, the client does not attempt to proxy requests.
socks5 proxying does not currently support spdy streaming endpoints (exec,
attach, port forward).
MaxLength: 512
MinLength: 1
Optional: {}

KubeConfigUser

KubeConfigUser contains information that describes identity information. This is used to tell the kubernetes cluster who you are.

Either authProvider or exec must be filled.

Adapted from clientcmdv1.AuthInfo.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
authProvider KubeConfigAuthProviderauthProvider specifies a custom authentication plugin for the kubernetes cluster.Optional: {}
exec KubeConfigAuthExecexec specifies a custom exec-based authentication plugin for the kubernetes cluster.Optional: {}

KubeadmConfig

KubeadmConfig is the Schema for the kubeadmconfigs API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringbootstrap.cluster.x-k8s.io/v1beta2
kind stringKubeadmConfig
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
spec KubeadmConfigSpecspec is the desired state of KubeadmConfig.MinProperties: 1
Optional: {}
status KubeadmConfigStatusstatus is the observed state of KubeadmConfig.MinProperties: 1
Optional: {}

KubeadmConfigDeprecatedStatus

KubeadmConfigDeprecatedStatus groups all the status fields that are deprecated and will be removed in a future version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
v1beta1 KubeadmConfigV1Beta1DeprecatedStatusv1beta1 groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped.Optional: {}

KubeadmConfigInitializationStatus

KubeadmConfigInitializationStatus provides observations of the KubeadmConfig initialization process.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
dataSecretCreated booleandataSecretCreated is true when the Machine’s boostrap secret is created.
NOTE: this field is part of the Cluster API contract, and it is used to orchestrate initial Machine provisioning.
Optional: {}

KubeadmConfigList

KubeadmConfigList contains a list of KubeadmConfig.

FieldDescriptionDefaultValidation
apiVersion stringbootstrap.cluster.x-k8s.io/v1beta2
kind stringKubeadmConfigList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items KubeadmConfig arrayitems is the list of KubeadmConfigs.

KubeadmConfigSpec

KubeadmConfigSpec defines the desired state of KubeadmConfig. Either ClusterConfiguration and InitConfiguration should be defined or the JoinConfiguration should be defined.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
clusterConfiguration ClusterConfigurationclusterConfiguration along with InitConfiguration are the configurations necessary for the init commandMinProperties: 1
Optional: {}
initConfiguration InitConfigurationinitConfiguration along with ClusterConfiguration are the configurations necessary for the init commandMinProperties: 1
Optional: {}
joinConfiguration JoinConfigurationjoinConfiguration is the kubeadm configuration for the join commandMinProperties: 1
Optional: {}
files File arrayfiles specifies extra files to be passed to user_data upon creation.MaxItems: 200
MinItems: 1
Optional: {}
diskSetup DiskSetupdiskSetup specifies options for the creation of partition tables and file systems on devices.MinProperties: 1
Optional: {}
mounts MountPoints arraymounts specifies a list of mount points to be setup.MaxItems: 100
MinItems: 1
items:MaxLength: 512
items:MinLength: 1
Optional: {}
bootCommands string arraybootCommands specifies extra commands to run very early in the boot process via the cloud-init bootcmd
module. bootcmd will run on every boot, ‘cloud-init-per’ command can be used to make bootcmd run exactly
once. This is typically run in the cloud-init.service systemd unit. This has no effect in Ignition.
MaxItems: 1000
MinItems: 1
items:MaxLength: 10240
items:MinLength: 1
Optional: {}
preKubeadmCommands string arraypreKubeadmCommands specifies extra commands to run before kubeadm runs.
With cloud-init, this is prepended to the runcmd module configuration, and is typically executed in
the cloud-final.service systemd unit. In Ignition, this is prepended to /etc/kubeadm.sh.
MaxItems: 1000
MinItems: 1
items:MaxLength: 10240
items:MinLength: 1
Optional: {}
postKubeadmCommands string arraypostKubeadmCommands specifies extra commands to run after kubeadm runs.
With cloud-init, this is appended to the runcmd module configuration, and is typically executed in
the cloud-final.service systemd unit. In Ignition, this is appended to /etc/kubeadm.sh.
MaxItems: 1000
MinItems: 1
items:MaxLength: 10240
items:MinLength: 1
Optional: {}
users User arrayusers specifies extra users to addMaxItems: 100
MinItems: 1
Optional: {}
ntp NTPntp specifies NTP configurationMinProperties: 1
Optional: {}
format Formatformat specifies the output format of the bootstrap data.
Defaults to cloud-config if not set.
Enum: [cloud-config ignition]
Optional: {}
verbosity integerverbosity is the number for the kubeadm log level verbosity.
It overrides the --v flag in kubeadm commands.
Optional: {}
ignition IgnitionSpecignition contains Ignition specific configuration.MinProperties: 1
Optional: {}

KubeadmConfigStatus

KubeadmConfigStatus defines the observed state of KubeadmConfig.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a KubeadmConfig’s current state.
Known condition types are Ready, DataSecretAvailable, CertificatesAvailable.
MaxItems: 32
Optional: {}
initialization KubeadmConfigInitializationStatusinitialization provides observations of the KubeadmConfig initialization process.
NOTE: Fields in this struct are part of the Cluster API contract and are used to orchestrate initial Machine provisioning.
MinProperties: 1
Optional: {}
dataSecretName stringdataSecretName is the name of the secret that stores the bootstrap data script.MaxLength: 253
MinLength: 1
Optional: {}
observedGeneration integerobservedGeneration is the latest generation observed by the controller.Minimum: 1
Optional: {}
deprecated KubeadmConfigDeprecatedStatusdeprecated groups all the status fields that are deprecated and will be removed when all the nested field are removed.Optional: {}

KubeadmConfigTemplate

KubeadmConfigTemplate is the Schema for the kubeadmconfigtemplates API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringbootstrap.cluster.x-k8s.io/v1beta2
kind stringKubeadmConfigTemplate
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
spec KubeadmConfigTemplateSpecspec is the desired state of KubeadmConfigTemplate.Optional: {}

KubeadmConfigTemplateList

KubeadmConfigTemplateList contains a list of KubeadmConfigTemplate.

FieldDescriptionDefaultValidation
apiVersion stringbootstrap.cluster.x-k8s.io/v1beta2
kind stringKubeadmConfigTemplateList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items KubeadmConfigTemplate arrayitems is the list of KubeadmConfigTemplates.

KubeadmConfigTemplateResource

KubeadmConfigTemplateResource defines the Template structure.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
spec KubeadmConfigSpecspec is the desired state of KubeadmConfig.MinProperties: 1
Optional: {}

KubeadmConfigTemplateSpec

KubeadmConfigTemplateSpec defines the desired state of KubeadmConfigTemplate.

Appears in:

FieldDescriptionDefaultValidation
template KubeadmConfigTemplateResourcetemplate defines the desired state of KubeadmConfigTemplate.MinProperties: 1
Required: {}

KubeadmConfigV1Beta1DeprecatedStatus

KubeadmConfigV1Beta1DeprecatedStatus groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Conditionsconditions defines current service state of the KubeadmConfig.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
failureReason stringfailureReason will be set on non-retryable errors
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
MaxLength: 256
MinLength: 1
Optional: {}
failureMessage stringfailureMessage will be set on non-retryable errors
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
MaxLength: 10240
MinLength: 1
Optional: {}

LocalEtcd

LocalEtcd describes that kubeadm should run an etcd cluster locally.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
imageRepository stringimageRepository sets the container registry to pull images from.
if not set, the ImageRepository defined in ClusterConfiguration will be used instead.
MaxLength: 512
MinLength: 1
Optional: {}
imageTag stringimageTag allows to specify a tag for the image.
In case this value is set, kubeadm does not change automatically the version of the above components during upgrades.
MaxLength: 256
MinLength: 1
Optional: {}
dataDir stringdataDir is the directory etcd will place its data.
Defaults to “/var/lib/etcd”.
MaxLength: 512
MinLength: 1
Optional: {}
extraArgs Arg arrayextraArgs is a list of args to pass to etcd.
The arg name must match the command line flag name except without leading dash(es).
Extra arguments will override existing default arguments set by kubeadm.
MaxItems: 100
MinItems: 1
Optional: {}
extraEnvs EnvVarextraEnvs is an extra set of environment variables to pass to etcd.
Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default.
This option takes effect only on Kubernetes >=1.31.0.
MaxItems: 100
MinItems: 1
Optional: {}
serverCertSANs string arrayserverCertSANs sets extra Subject Alternative Names for the etcd server signing cert.MaxItems: 100
MinItems: 1
items:MaxLength: 253
items:MinLength: 1
Optional: {}
peerCertSANs string arraypeerCertSANs sets extra Subject Alternative Names for the etcd peer signing cert.MaxItems: 100
MinItems: 1
items:MaxLength: 253
items:MinLength: 1
Optional: {}

MountPoints

Underlying type: string array

MountPoints defines input for generated mounts in cloud-init.

Validation:

  • MaxItems: 100
  • MinItems: 1
  • items:MaxLength: 512
  • items:MinLength: 1

Appears in:

NTP

NTP defines input for generated ntp in cloud-init.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
servers string arrayservers specifies which NTP servers to useMaxItems: 100
items:MaxLength: 512
items:MinLength: 1
Optional: {}
enabled booleanenabled specifies whether NTP should be enabledOptional: {}

NodeRegistrationOptions

NodeRegistrationOptions holds fields that relate to registering a new control-plane or node to the cluster, either via “kubeadm init” or “kubeadm join”. Note: The NodeRegistrationOptions struct has to be kept in sync with the structs in MarshalJSON.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
name stringname is the .Metadata.Name field of the Node API object that will be created in this kubeadm init or kubeadm join operation.
This field is also used in the CommonName field of the kubelet’s client certificate to the API server.
Defaults to the hostname of the node if not provided.
MaxLength: 253
MinLength: 1
Optional: {}
criSocket stringcriSocket is used to retrieve container runtime info. This information will be annotated to the Node API object, for later re-useMaxLength: 512
MinLength: 1
Optional: {}
taints Tainttaints specifies the taints the Node API object should be registered with. If this field is unset, i.e. nil, in the kubeadm init process
it will be defaulted to []v1.Taint{‘node-role.kubernetes.io/master=“”’}. If you don’t want to taint your control-plane node, set this field to an
empty slice, i.e. taints: [] in the YAML file. This field is solely used for Node registration.
MaxItems: 100
MinItems: 0
Optional: {}
kubeletExtraArgs Arg arraykubeletExtraArgs is a list of args to pass to kubelet.
The arg name must match the command line flag name except without leading dash(es).
Extra arguments will override existing default arguments set by kubeadm.
MaxItems: 100
MinItems: 1
Optional: {}
ignorePreflightErrors string arrayignorePreflightErrors provides a slice of pre-flight errors to be ignored when the current node is registered, e.g. ‘IsPrivilegedUser,Swap’.
Value ‘all’ ignores errors from all checks.
MaxItems: 50
MinItems: 1
items:MaxLength: 512
items:MinLength: 1
Optional: {}
imagePullPolicy PullPolicyimagePullPolicy specifies the policy for image pulling
during kubeadm “init” and “join” operations. The value of
this field must be one of “Always”, “IfNotPresent” or
“Never”. Defaults to “IfNotPresent” if not set.
Enum: [Always IfNotPresent Never]
Optional: {}
imagePullSerial booleanimagePullSerial specifies if image pulling performed by kubeadm must be done serially or in parallel.
This option takes effect only on Kubernetes >=1.31.0.
Default: true (defaulted in kubeadm)
Optional: {}

Partition

Partition defines how to create and layout a partition.

Validation:

  • ExactlyOneOf: [layout diskLayout]

Appears in:

FieldDescriptionDefaultValidation
device stringdevice is the name of the device.MaxLength: 256
MinLength: 1
Required: {}
layout booleanlayout specifies the device layout.
If it is true, a single partition will be created for the entire device.
When layout is false, it means don’t partition or ignore existing partitioning.
Mutually exclusive with diskLayout.
Optional: {}
overwrite booleanoverwrite describes whether to skip checks and create the partition if a partition or filesystem is found on the device.
Use with caution. Default is ‘false’.
Optional: {}
tableType stringtableType specifies the tupe of partition table. The following are supported:
‘mbr’: default and setups a MS-DOS partition table
‘gpt’: setups a GPT partition table
Enum: [mbr gpt]
Optional: {}
diskLayout PartitionSpec arraydiskLayout specifies an ordered list of partitions, where each item defines the
percentage of disk space and optional partition type for that partition.
The sum of all partition percentages must not be greater than 100.
Mutually exclusive with layout.
MaxItems: 100
MinItems: 1
Optional: {}

PartitionSpec

PartitionSpec defines the size and optional type for a partition.

Appears in:

FieldDescriptionDefaultValidation
percentage integerpercentage of disk that partition will take (1-100)Maximum: 100
Minimum: 1
Required: {}
partitionType stringpartitionType is the partition type (optional).
Supported values are Linux, LinuxSwap, LinuxRAID, LVM, Fat32, NTFS,
and LinuxExtended. These are translated to cloud-init partition type codes.
A full GPT partition GUID is also supported as a passthrough value.
MaxLength: 36
MinLength: 1
Optional: {}

PasswdSource

PasswdSource is a union of all possible external source types for passwd data. Only one field may be populated in any given instance. Developers adding new sources of data for target systems should add them here.

Appears in:

FieldDescriptionDefaultValidation
secret SecretPasswdSourcesecret represents a secret that should populate this password.Required: {}

Patches

Patches contains options related to applying patches to components deployed by kubeadm.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
directory stringdirectory is a path to a directory that contains files named “target[suffix][+patchtype].extension”.
For example, “kube-apiserver0+merge.yaml” or just “etcd.json”. “target” can be one of
“kube-apiserver”, “kube-controller-manager”, “kube-scheduler”, “etcd”. “patchtype” can be one
of “strategic” “merge” or “json” and they match the patch formats supported by kubectl.
The default “patchtype” is “strategic”. “extension” must be either “json” or “yaml”.
“suffix” is an optional string that can be used to determine which patches are applied
first alpha-numerically.
These files can be written into the target directory via KubeadmConfig.Files which
specifies additional files to be created on the machine, either with content inline or
by referencing a secret.
MaxLength: 512
MinLength: 1
Optional: {}

Scheduler

Scheduler holds settings necessary for scheduler deployments in the cluster.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
extraArgs Arg arrayextraArgs is a list of args to pass to the control plane component.
The arg name must match the command line flag name except without leading dash(es).
Extra arguments will override existing default arguments set by kubeadm.
MaxItems: 100
MinItems: 1
Optional: {}
extraVolumes HostPathMount arrayextraVolumes is an extra set of host volumes, mounted to the control plane component.MaxItems: 100
MinItems: 1
Optional: {}
extraEnvs EnvVarextraEnvs is an extra set of environment variables to pass to the control plane component.
Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default.
This option takes effect only on Kubernetes >=1.31.0.
MaxItems: 100
MinItems: 1
Optional: {}

SecretFileSource

SecretFileSource adapts a Secret into a FileSource.

The contents of the target Secret’s Data field will be presented as files using the keys in the Data field as the file names.

Appears in:

FieldDescriptionDefaultValidation
name stringname of the secret in the KubeadmBootstrapConfig’s namespace to use.MaxLength: 253
MinLength: 1
Required: {}
key stringkey is the key in the secret’s data map for this value.MaxLength: 256
MinLength: 1
Required: {}

SecretPasswdSource

SecretPasswdSource adapts a Secret into a PasswdSource.

The contents of the target Secret’s Data field will be presented as passwd using the keys in the Data field as the file names.

Appears in:

FieldDescriptionDefaultValidation
name stringname of the secret in the KubeadmBootstrapConfig’s namespace to use.MaxLength: 253
MinLength: 1
Required: {}
key stringkey is the key in the secret’s data map for this value.MaxLength: 256
MinLength: 1
Required: {}

Timeouts

Timeouts holds various timeouts that apply to kubeadm commands.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
controlPlaneComponentHealthCheckSeconds integercontrolPlaneComponentHealthCheckSeconds is the amount of time to wait for a control plane
component, such as the API server, to be healthy during “kubeadm init” and “kubeadm join”.
If not set, it defaults to 4m (240s).
Minimum: 0
Optional: {}
kubeletHealthCheckSeconds integerkubeletHealthCheckSeconds is the amount of time to wait for the kubelet to be healthy
during “kubeadm init” and “kubeadm join”.
If not set, it defaults to 4m (240s).
Minimum: 0
Optional: {}
kubernetesAPICallSeconds integerkubernetesAPICallSeconds is the amount of time to wait for the kubeadm client to complete a request to
the API server. This applies to all types of methods (GET, POST, etc).
If not set, it defaults to 1m (60s).
Minimum: 0
Optional: {}
etcdAPICallSeconds integeretcdAPICallSeconds is the amount of time to wait for the kubeadm etcd client to complete a request to
the etcd cluster.
If not set, it defaults to 2m (120s).
Minimum: 0
Optional: {}
tlsBootstrapSeconds integertlsBootstrapSeconds is the amount of time to wait for the kubelet to complete TLS bootstrap
for a joining node.
If not set, it defaults to 5m (300s).
Minimum: 0
Optional: {}
discoverySeconds integerdiscoverySeconds is the amount of time to wait for kubeadm to validate the API server identity
for a joining node.
If not set, it defaults to 5m (300s).
Minimum: 0
Optional: {}

User

User defines the input for a generated user in cloud-init.

Appears in:

FieldDescriptionDefaultValidation
name stringname specifies the user nameMaxLength: 256
MinLength: 1
Required: {}
gecos stringgecos specifies the gecos to use for the userMaxLength: 256
MinLength: 1
Optional: {}
groups stringgroups specifies the additional groups for the userMaxLength: 256
MinLength: 1
Optional: {}
homeDir stringhomeDir specifies the home directory to use for the userMaxLength: 256
MinLength: 1
Optional: {}
inactive booleaninactive specifies whether to mark the user as inactiveOptional: {}
shell stringshell specifies the user’s shellMaxLength: 256
MinLength: 1
Optional: {}
passwd stringpasswd specifies a hashed password for the userMaxLength: 256
MinLength: 1
Optional: {}
passwdFrom PasswdSourcepasswdFrom is a referenced source of passwd to populate the passwd.Optional: {}
primaryGroup stringprimaryGroup specifies the primary group for the userMaxLength: 256
MinLength: 1
Optional: {}
lockPassword booleanlockPassword specifies if password login should be disabledOptional: {}
sudo stringsudo specifies a sudo role for the userMaxLength: 256
MinLength: 1
Optional: {}
sshAuthorizedKeys string arraysshAuthorizedKeys specifies a list of ssh authorized keys for the userMaxItems: 100
items:MaxLength: 2048
items:MinLength: 1
Optional: {}

cluster.x-k8s.io/v1beta2

Package v1beta2 contains API Schema definitions for the cluster v1beta2 API group

Resource Types

APIEndpoint

APIEndpoint represents a reachable Kubernetes API endpoint.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
host stringhost is the hostname on which the API server is serving.MaxLength: 512
MinLength: 1
Optional: {}
port integerport is the port on which the API server is serving.Maximum: 65535
Minimum: 1
Optional: {}

Bootstrap

Bootstrap encapsulates fields to configure the Machine’s bootstrapping mechanism.

Appears in:

FieldDescriptionDefaultValidation
configRef ContractVersionedObjectReferenceconfigRef is a reference to a bootstrap provider-specific resource
that holds configuration details. The reference is optional to
allow users/operators to specify Bootstrap.DataSecretName without
the need of a controller.
Optional: {}
dataSecretName stringdataSecretName is the name of the secret that stores the bootstrap data script.
If nil, the Machine should remain in the Pending state.
MaxLength: 253
MinLength: 0
Optional: {}

Cluster

Cluster is the Schema for the clusters API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta2
kind stringCluster
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
spec ClusterSpecspec is the desired state of Cluster.MinProperties: 1
Required: {}
status ClusterStatusstatus is the observed state of Cluster.MinProperties: 1
Optional: {}

ClusterAvailabilityGate

ClusterAvailabilityGate contains the type of a Cluster condition to be used as availability gate.

Appears in:

FieldDescriptionDefaultValidation
conditionType stringconditionType refers to a condition with matching type in the Cluster’s condition list.
If the conditions doesn’t exist, it will be treated as unknown.
Note: Both Cluster API conditions or conditions added by 3rd party controllers can be used as availability gates.
MaxLength: 316
MinLength: 1
Pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
Required: {}
polarity ConditionPolaritypolarity of the conditionType specified in this availabilityGate.
Valid values are Positive, Negative and omitted.
When omitted, the default behaviour will be Positive.
A positive polarity means that the condition should report a true status under normal conditions.
A negative polarity means that the condition should report a false status under normal conditions.
Enum: [Positive Negative]
Optional: {}

ClusterClass

ClusterClass is a template which can be used to create managed topologies. NOTE: This CRD can only be used if the ClusterTopology feature gate is enabled.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta2
kind stringClusterClass
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
spec ClusterClassSpecspec is the desired state of ClusterClass.Required: {}
status ClusterClassStatusstatus is the observed state of ClusterClass.MinProperties: 1
Optional: {}

ClusterClassDeprecatedStatus

ClusterClassDeprecatedStatus groups all the status fields that are deprecated and will be removed in a future version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
v1beta1 ClusterClassV1Beta1DeprecatedStatusv1beta1 groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped.Optional: {}

ClusterClassList

ClusterClassList contains a list of Cluster.

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta2
kind stringClusterClassList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items ClusterClass arrayitems is the list of ClusterClasses.

ClusterClassPatch

ClusterClassPatch defines a patch which is applied to customize the referenced templates.

Appears in:

FieldDescriptionDefaultValidation
name stringname of the patch.MaxLength: 256
MinLength: 1
Required: {}
description stringdescription is a human-readable description of this patch.MaxLength: 1024
MinLength: 1
Optional: {}
enabledIf stringenabledIf is a Go template to be used to calculate if a patch should be enabled.
It can reference variables defined in .spec.variables and builtin variables.
The patch will be enabled if the template evaluates to true, otherwise it will
be disabled.
If EnabledIf is not set, the patch will be enabled per default.
MaxLength: 256
MinLength: 1
Optional: {}
definitions PatchDefinition arraydefinitions define inline patches.
Note: Patches will be applied in the order of the array.
Note: Exactly one of Definitions or External must be set.
MaxItems: 100
Optional: {}
external ExternalPatchDefinitionexternal defines an external patch.
Note: Exactly one of Definitions or External must be set.
Optional: {}

ClusterClassRef

ClusterClassRef is the ref to the ClusterClass that should be used for the topology.

Appears in:

FieldDescriptionDefaultValidation
name stringname is the name of the ClusterClass that should be used for the topology.
name must be a valid ClusterClass name and because of that be at most 253 characters in length
and it must consist only of lower case alphanumeric characters, hyphens (-) and periods (.), and must start
and end with an alphanumeric character.
MaxLength: 253
MinLength: 1
Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
Required: {}
namespace stringnamespace is the namespace of the ClusterClass that should be used for the topology.
If namespace is empty or not set, it is defaulted to the namespace of the Cluster object.
namespace must be a valid namespace name and because of that be at most 63 characters in length
and it must consist only of lower case alphanumeric characters or hyphens (-), and must start
and end with an alphanumeric character.
MaxLength: 63
MinLength: 1
Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
Optional: {}

ClusterClassSpec

ClusterClassSpec describes the desired state of the ClusterClass.

Appears in:

FieldDescriptionDefaultValidation
availabilityGates ClusterAvailabilityGate arrayavailabilityGates specifies additional conditions to include when evaluating Cluster Available condition.
NOTE: If a Cluster is using this ClusterClass, and this Cluster defines a custom list of availabilityGates,
such list overrides availabilityGates defined in this field.
MaxItems: 32
MinItems: 1
Optional: {}
infrastructure InfrastructureClassinfrastructure is a reference to a local struct that holds the details
for provisioning the infrastructure cluster for the Cluster.
Required: {}
controlPlane ControlPlaneClasscontrolPlane is a reference to a local struct that holds the details
for provisioning the Control Plane for the Cluster.
Required: {}
workers WorkersClassworkers describes the worker nodes for the cluster.
It is a collection of node types which can be used to create
the worker nodes of the cluster.
MinProperties: 1
Optional: {}
variables ClusterClassVariable arrayvariables defines the variables which can be configured
in the Cluster topology and are then used in patches.
MaxItems: 1000
MinItems: 1
Optional: {}
patches ClusterClassPatch arraypatches defines the patches which are applied to customize
referenced templates of a ClusterClass.
Note: Patches will be applied in the order of the array.
MaxItems: 1000
MinItems: 1
Optional: {}
upgrade ClusterClassUpgradeupgrade defines the upgrade configuration for clusters using this ClusterClass.MinProperties: 1
Optional: {}
kubernetesVersions string arraykubernetesVersions is the list of Kubernetes versions that can be
used for clusters using this ClusterClass.
The list of version must be ordered from the older to the newer version, and there should be
at least one version for every minor in between the first and the last version.
MaxItems: 100
MinItems: 1
items:MaxLength: 256
items:MinLength: 1
Optional: {}

ClusterClassStatus

ClusterClassStatus defines the observed state of the ClusterClass.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a ClusterClass’s current state.
Known condition types are VariablesReady, RefVersionsUpToDate, Paused.
MaxItems: 32
Optional: {}
variables ClusterClassStatusVariable arrayvariables is a list of ClusterClassStatusVariable that are defined for the ClusterClass.MaxItems: 1000
Optional: {}
observedGeneration integerobservedGeneration is the latest generation observed by the controller.Minimum: 1
Optional: {}
deprecated ClusterClassDeprecatedStatusdeprecated groups all the status fields that are deprecated and will be removed when all the nested field are removed.Optional: {}

ClusterClassStatusVariable

ClusterClassStatusVariable defines a variable which appears in the status of a ClusterClass.

Appears in:

FieldDescriptionDefaultValidation
name stringname is the name of the variable.MaxLength: 256
MinLength: 1
Required: {}
definitionsConflict booleandefinitionsConflict specifies whether or not there are conflicting definitions for a single variable name.Optional: {}
definitions ClusterClassStatusVariableDefinition arraydefinitions is a list of definitions for a variable.MaxItems: 100
MinItems: 1
Required: {}

ClusterClassStatusVariableDefinition

ClusterClassStatusVariableDefinition defines a variable which appears in the status of a ClusterClass.

Appears in:

FieldDescriptionDefaultValidation
from stringfrom specifies the origin of the variable definition.
This will be inline for variables defined in the ClusterClass or the name of a patch defined in the ClusterClass
for variables discovered from a DiscoverVariables runtime extensions.
MaxLength: 256
MinLength: 1
Required: {}
required booleanrequired specifies if the variable is required.
Note: this applies to the variable as a whole and thus the
top-level object defined in the schema. If nested fields are
required, this will be specified inside the schema.
Required: {}
deprecatedV1Beta1Metadata ClusterClassVariableMetadatadeprecatedV1Beta1Metadata is the metadata of a variable.
It can be used to add additional data for higher level tools to
a ClusterClassVariable.
Deprecated: This field is deprecated and will be removed when support for v1beta1 will be dropped. Please use XMetadata in JSONSchemaProps instead.
MinProperties: 1
Optional: {}
schema VariableSchemaschema defines the schema of the variable.Required: {}

ClusterClassTemplateReference

ClusterClassTemplateReference is a reference to a ClusterClass template.

Appears in:

FieldDescriptionDefaultValidation
kind stringkind of the template.
kind must consist of alphanumeric characters or ‘-’, start with an alphabetic character, and end with an alphanumeric character.
MaxLength: 63
MinLength: 1
Pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
Required: {}
name stringname of the template.
name must consist of lower case alphanumeric characters, ‘-’ or ‘.’, and must start and end with an alphanumeric character.
MaxLength: 253
MinLength: 1
Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
Required: {}
apiVersion stringapiVersion of the template.
apiVersion must be fully qualified domain name followed by / and a version.
MaxLength: 317
MinLength: 1
Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[a-z]([-a-z0-9]*[a-z0-9])?$
Required: {}

ClusterClassUpgrade

ClusterClassUpgrade defines the upgrade configuration for clusters using the ClusterClass.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
external ClusterClassUpgradeExternalexternal defines external runtime extensions for upgrade operations.MinProperties: 1
Optional: {}

ClusterClassUpgradeExternal

ClusterClassUpgradeExternal defines external runtime extensions for upgrade operations.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
generateUpgradePlanExtension stringgenerateUpgradePlanExtension references an extension which is called to generate upgrade plan.MaxLength: 512
MinLength: 1
Optional: {}

ClusterClassV1Beta1DeprecatedStatus

ClusterClassV1Beta1DeprecatedStatus groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Conditionsconditions defines current observed state of the ClusterClass.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}

ClusterClassVariable

ClusterClassVariable defines a variable which can be configured in the Cluster topology and used in patches.

Appears in:

FieldDescriptionDefaultValidation
name stringname of the variable.MaxLength: 256
MinLength: 1
Required: {}
required booleanrequired specifies if the variable is required.
Note: this applies to the variable as a whole and thus the
top-level object defined in the schema. If nested fields are
required, this will be specified inside the schema.
Required: {}
deprecatedV1Beta1Metadata ClusterClassVariableMetadatadeprecatedV1Beta1Metadata is the metadata of a variable.
It can be used to add additional data for higher level tools to
a ClusterClassVariable.
Deprecated: This field is deprecated and will be removed when support for v1beta1 will be dropped. Please use XMetadata in JSONSchemaProps instead.
MinProperties: 1
Optional: {}
schema VariableSchemaschema defines the schema of the variable.Required: {}

ClusterClassVariableMetadata

ClusterClassVariableMetadata is the metadata of a variable. It can be used to add additional data for higher level tools to a ClusterClassVariable.

Deprecated: This struct is deprecated and is going to be removed in the next apiVersion.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
labels object (keys:string, values:string)labels is a map of string keys and values that can be used to organize and categorize
(scope and select) variables.
Optional: {}
annotations object (keys:string, values:string)annotations is an unstructured key value map that can be used to store and
retrieve arbitrary metadata.
They are not queryable.
Optional: {}

ClusterControlPlaneStatus

ClusterControlPlaneStatus groups all the observations about control plane current state.

Appears in:

FieldDescriptionDefaultValidation
desiredReplicas integerdesiredReplicas is the total number of desired control plane machines in this cluster.Optional: {}
replicas integerreplicas is the total number of control plane machines in this cluster.
NOTE: replicas also includes machines still being provisioned or being deleted.
Optional: {}
upToDateReplicas integerupToDateReplicas is the number of up-to-date control plane machines in this cluster. A machine is considered up-to-date when Machine’s UpToDate condition is true.Optional: {}
readyReplicas integerreadyReplicas is the total number of ready control plane machines in this cluster. A machine is considered ready when Machine’s Ready condition is true.Optional: {}
availableReplicas integeravailableReplicas is the total number of available control plane machines in this cluster. A machine is considered available when Machine’s Available condition is true.Optional: {}
versions StatusVersion arrayversions is the aggregated Kubernetes versions in this control plane.MaxItems: 32
MinItems: 1
Optional: {}
upgradePlan StatusUpgradePlanVersion arrayupgradePlan reports the list of versions that would be applied to the control plane object according to the upgrade plan.
Note:
- This field is set only when the Cluster topology is managed by Cluster API and a Cluster upgrade is in progress.
- Once a version is applied to the control plane object, it is removed from the list (after a version
is applied to a control plane object, it might take some time for the actual upgrade to complete)
- During a chained upgrade, the upgrade plan is continuously re-computed, and this field will
report only the last known upgrade plan.
MaxItems: 32
MinItems: 1
Optional: {}

ClusterDeprecatedStatus

ClusterDeprecatedStatus groups all the status fields that are deprecated and will be removed in a future version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
v1beta1 ClusterV1Beta1DeprecatedStatusv1beta1 groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped.Optional: {}

ClusterInitializationStatus

ClusterInitializationStatus provides observations of the Cluster initialization process. NOTE: Fields in this struct are part of the Cluster API contract and are used to orchestrate initial Cluster provisioning.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
infrastructureProvisioned booleaninfrastructureProvisioned is true when the infrastructure provider reports that Cluster’s infrastructure is fully provisioned.
NOTE: this field is part of the Cluster API contract, and it is used to orchestrate provisioning.
The value of this field is never updated after provisioning is completed.
Optional: {}
controlPlaneInitialized booleancontrolPlaneInitialized denotes when the control plane is functional enough to accept requests.
This information is usually used as a signal for starting all the provisioning operations that depends on
a functional API server, but do not require a full HA control plane to exists, like e.g. join worker Machines,
install core addons like CNI, CPI, CSI etc.
NOTE: this field is part of the Cluster API contract, and it is used to orchestrate provisioning.
The value of this field is never updated after initialization is completed.
Optional: {}

ClusterList

ClusterList contains a list of Cluster.

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta2
kind stringClusterList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items Cluster arrayitems is the list of Clusters.

ClusterNetwork

ClusterNetwork specifies the different networking parameters for a cluster.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
apiServerPort integerapiServerPort specifies the port the API Server should bind to.
Defaults to 6443.
Maximum: 65535
Minimum: 1
Optional: {}
services NetworkRangesservices is the network ranges from which service VIPs are allocated.Optional: {}
pods NetworkRangespods is the network ranges from which Pod networks are allocated.Optional: {}
serviceDomain stringserviceDomain is the domain name for services.MaxLength: 253
MinLength: 1
Optional: {}

ClusterSpec

ClusterSpec defines the desired state of Cluster.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
paused booleanpaused can be used to prevent controllers from processing the Cluster and all its associated objects.Optional: {}
clusterNetwork ClusterNetworkclusterNetwork represents the cluster network configuration.MinProperties: 1
Optional: {}
controlPlaneEndpoint APIEndpointcontrolPlaneEndpoint represents the endpoint used to communicate with the control plane.MinProperties: 1
Optional: {}
controlPlaneRef ContractVersionedObjectReferencecontrolPlaneRef is an optional reference to a provider-specific resource that holds
the details for provisioning the Control Plane for a Cluster.
Optional: {}
infrastructureRef ContractVersionedObjectReferenceinfrastructureRef is a reference to a provider-specific resource that holds the details
for provisioning infrastructure for a cluster in said provider.
Optional: {}
topology Topologytopology encapsulates the topology for the cluster.
NOTE: It is required to enable the ClusterTopology
feature gate flag to activate managed topologies support.
Optional: {}
availabilityGates ClusterAvailabilityGate arrayavailabilityGates specifies additional conditions to include when evaluating Cluster Available condition.
If this field is not defined and the Cluster implements a managed topology, availabilityGates
from the corresponding ClusterClass will be used, if any.
MaxItems: 32
MinItems: 1
Optional: {}

ClusterStatus

ClusterStatus defines the observed state of Cluster.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a Cluster’s current state.
Known condition types are Available, InfrastructureReady, ControlPlaneInitialized, ControlPlaneAvailable, WorkersAvailable, MachinesReady
MachinesUpToDate, RemoteConnectionProbe, ScalingUp, ScalingDown, Remediating, Deleting, Paused.
Additionally, a TopologyReconciled condition will be added in case the Cluster is referencing a ClusterClass / defining a managed Topology.
MaxItems: 32
Optional: {}
initialization ClusterInitializationStatusinitialization provides observations of the Cluster initialization process.
NOTE: Fields in this struct are part of the Cluster API contract and are used to orchestrate initial Cluster provisioning.
MinProperties: 1
Optional: {}
controlPlane ClusterControlPlaneStatuscontrolPlane groups all the observations about Cluster’s ControlPlane current state.Optional: {}
workers WorkersStatusworkers groups all the observations about Cluster’s Workers current state.Optional: {}
failureDomains FailureDomain arrayfailureDomains is a slice of failure domain objects synced from the infrastructure provider.MaxItems: 100
MinItems: 1
Optional: {}
phase stringphase represents the current phase of cluster actuation.Enum: [Pending Provisioning Provisioned Deleting Failed Unknown]
Optional: {}
observedGeneration integerobservedGeneration is the latest generation observed by the controller.Minimum: 1
Optional: {}
deprecated ClusterDeprecatedStatusdeprecated groups all the status fields that are deprecated and will be removed when all the nested field are removed.Optional: {}

ClusterV1Beta1DeprecatedStatus

ClusterV1Beta1DeprecatedStatus groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Conditionsconditions defines current service state of the cluster.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
failureReason ClusterStatusErrorfailureReason indicates that there is a fatal problem reconciling the
state, and will be set to a token value suitable for
programmatic interpretation.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
failureMessage stringfailureMessage indicates that there is a fatal problem reconciling the
state, and will be set to a descriptive error message.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
MaxLength: 10240
MinLength: 1
Optional: {}

ClusterVariable

ClusterVariable can be used to customize the Cluster through patches. Each ClusterVariable is associated with a Variable definition in the ClusterClass status variables.

Appears in:

FieldDescriptionDefaultValidation
name stringname of the variable.MaxLength: 256
MinLength: 1
Required: {}
value JSONvalue of the variable.
Note: the value will be validated against the schema of the corresponding ClusterClassVariable
from the ClusterClass.
Note: We have to use apiextensionsv1.JSON instead of a custom JSON type, because controller-tools has a
hard-coded schema for apiextensionsv1.JSON which cannot be produced by another type via controller-tools,
i.e. it is not possible to have no type field.
Ref: https://github.com/kubernetes-sigs/controller-tools/blob/d0e03a142d0ecdd5491593e941ee1d6b5d91dba6/pkg/crd/known_types.go#L106-L111
Required: {}

Condition

Condition defines an observation of a Cluster API resource operational state.

Deprecated: This type is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.

Appears in:

FieldDescriptionDefaultValidation
type ConditionTypetype of condition in CamelCase or in foo.example.com/CamelCase.
Many .condition.type values are consistent across resources like Available, but because arbitrary conditions
can be useful (see .node.status.conditions), the ability to deconflict is important.
MaxLength: 256
MinLength: 1
Required: {}
status ConditionStatusstatus of the condition, one of True, False, Unknown.Required: {}
severity ConditionSeverityseverity provides an explicit classification of Reason code, so the users or machines can immediately
understand the current situation and act accordingly.
The Severity field MUST be set only when Status=False.
MaxLength: 32
Optional: {}
reason stringreason is the reason for the condition’s last transition in CamelCase.
The specific API may choose whether or not this field is considered a guaranteed API.
This field may be empty.
MaxLength: 256
MinLength: 1
Optional: {}
message stringmessage is a human readable message indicating details about the transition.
This field may be empty.
MaxLength: 10240
MinLength: 1
Optional: {}

ConditionPolarity

Underlying type: string

ConditionPolarity defines the polarity for a metav1.Condition.

Validation:

  • Enum: [Positive Negative]

Appears in:

FieldDescription
PositivePositivePolarityCondition describe a condition with positive polarity, a condition
where the normal state is True. e.g. NetworkReady.
NegativeNegativePolarityCondition describe a condition with negative polarity, a condition
where the normal state is False. e.g. MemoryPressure.

ConditionSeverity

Underlying type: string

ConditionSeverity expresses the severity of a Condition Type failing.

Deprecated: This type is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.

Validation:

  • MaxLength: 32

Appears in:

FieldDescription
ErrorConditionSeverityError specifies that a condition with Status=False is an error.
WarningConditionSeverityWarning specifies that a condition with Status=False is a warning.
InfoConditionSeverityInfo specifies that a condition with Status=False is informative.
``ConditionSeverityNone should apply only to conditions with Status=True.

ConditionType

Underlying type: string

ConditionType is a valid value for Condition.Type.

Deprecated: This type is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.

Validation:

  • MaxLength: 256
  • MinLength: 1

Appears in:

FieldDescription
ReadyReadyV1Beta1Condition defines the Ready condition type that summarizes the operational state of a Cluster API object.
InfrastructureReadyInfrastructureReadyV1Beta1Condition reports a summary of current status of the infrastructure object defined for this cluster/machine/machinepool.
This condition is mirrored from the Ready condition in the infrastructure ref object, and
the absence of this condition might signal problems in the reconcile external loops or the fact that
the infrastructure provider does not implement the Ready condition yet.
VariablesReconciledClusterClassVariablesReconciledV1Beta1Condition reports if the ClusterClass variables, including both inline and external
variables, have been successfully reconciled.
This signals that the ClusterClass is ready to be used to default and validate variables on Clusters using
this ClusterClass.
ControlPlaneInitializedControlPlaneInitializedV1Beta1Condition reports if the cluster’s control plane has been initialized such that the
cluster’s apiserver is reachable. If no Control Plane provider is in use this condition reports that at least one
control plane Machine has a node reference. Once this Condition is marked true, its value is never changed. See
the ControlPlaneReady condition for an indication of the current readiness of the cluster’s control plane.
ControlPlaneReadyControlPlaneReadyV1Beta1Condition reports the ready condition from the control plane object defined for this cluster.
This condition is mirrored from the Ready condition in the control plane ref object, and
the absence of this condition might signal problems in the reconcile external loops or the fact that
the control plane provider does not implement the Ready condition yet.
BootstrapReadyBootstrapReadyV1Beta1Condition reports a summary of current status of the bootstrap object defined for this machine.
This condition is mirrored from the Ready condition in the bootstrap ref object, and
the absence of this condition might signal problems in the reconcile external loops or the fact that
the bootstrap provider does not implement the Ready condition yet.
DrainingSucceededDrainingSucceededV1Beta1Condition provide evidence of the status of the node drain operation which happens during the machine
deletion process.
PreDrainDeleteHookSucceededPreDrainDeleteHookSucceededV1Beta1Condition reports a machine waiting for a PreDrainDeleteHook before being delete.
PreTerminateDeleteHookSucceededPreTerminateDeleteHookSucceededV1Beta1Condition reports a machine waiting for a PreDrainDeleteHook before being delete.
VolumeDetachSucceededVolumeDetachSucceededV1Beta1Condition reports a machine waiting for volumes to be detached.
HealthCheckSucceededMachineHealthCheckSucceededV1Beta1Condition is set on machines that have passed a healthcheck by the MachineHealthCheck controller.
In the event that the health check fails it will be set to False.
OwnerRemediatedMachineOwnerRemediatedV1Beta1Condition is set on machines that have failed a healthcheck by the MachineHealthCheck controller.
MachineOwnerRemediatedV1Beta1Condition is set to False after a health check fails, but should be changed to True by the owning controller after remediation succeeds.
ExternalRemediationTemplateAvailableExternalRemediationTemplateAvailableV1Beta1Condition is set on machinehealthchecks when MachineHealthCheck controller uses external remediation.
ExternalRemediationTemplateAvailableV1Beta1Condition is set to false if external remediation template is not found.
ExternalRemediationRequestAvailableExternalRemediationRequestAvailableV1Beta1Condition is set on machinehealthchecks when MachineHealthCheck controller uses external remediation.
ExternalRemediationRequestAvailableV1Beta1Condition is set to false if creating external remediation request fails.
NodeHealthyMachineNodeHealthyV1Beta1Condition provides info about the operational state of the Kubernetes node hosted on the machine by summarizing node conditions.
If the conditions defined in a Kubernetes node (i.e., NodeReady, NodeMemoryPressure, NodeDiskPressure and NodePIDPressure) are in a healthy state, it will be set to True.
RemediationAllowedRemediationAllowedV1Beta1Condition is set on MachineHealthChecks to show the status of whether the MachineHealthCheck is
allowed to remediate any Machines or whether it is blocked from remediating any further.
AvailableMachineDeploymentAvailableV1Beta1Condition means the MachineDeployment is available, that is, at least the minimum available
machines required (i.e. Spec.Replicas-MaxUnavailable when spec.rollout.strategy.type = RollingUpdate) are up and running for at least minReadySeconds.
MachineSetReadyMachineSetReadyV1Beta1Condition reports a summary of current status of the MachineSet owned by the MachineDeployment.
MachinesCreatedMachinesCreatedV1Beta1Condition documents that the machines controlled by the MachineSet are created.
When this condition is false, it indicates that there was an error when cloning the infrastructure/bootstrap template or
when generating the machine object.
MachinesReadyMachinesReadyV1Beta1Condition reports an aggregate of current status of the machines controlled by the MachineSet.
ResizedResizedV1Beta1Condition documents a MachineSet is resizing the set of controlled machines.
TopologyReconciledTopologyReconciledV1Beta1Condition provides evidence about the reconciliation of a Cluster topology into
the managed objects of the Cluster.
Status false means that for any reason, the values defined in Cluster.spec.topology are not yet applied to
managed objects on the Cluster; status true means that Cluster.spec.topology have been applied to
the objects in the Cluster (but this does not imply those objects are already reconciled to the spec provided).
RefVersionsUpToDateClusterClassRefVersionsUpToDateV1Beta1Condition documents if the references in the ClusterClass are
up-to-date (i.e. they are using the latest apiVersion of the current Cluster API contract from
the corresponding CRD).
ReplicasReadyReplicasReadyV1Beta1Condition reports an aggregate of current status of the replicas controlled by the MachinePool.

Conditions

Underlying type: Condition

Conditions provide observations of the operational state of a Cluster API resource.

Deprecated: This type is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.

Appears in:

FieldDescriptionDefaultValidation
type ConditionTypetype of condition in CamelCase or in foo.example.com/CamelCase.
Many .condition.type values are consistent across resources like Available, but because arbitrary conditions
can be useful (see .node.status.conditions), the ability to deconflict is important.
MaxLength: 256
MinLength: 1
Required: {}
status ConditionStatusstatus of the condition, one of True, False, Unknown.Required: {}
severity ConditionSeverityseverity provides an explicit classification of Reason code, so the users or machines can immediately
understand the current situation and act accordingly.
The Severity field MUST be set only when Status=False.
MaxLength: 32
Optional: {}
reason stringreason is the reason for the condition’s last transition in CamelCase.
The specific API may choose whether or not this field is considered a guaranteed API.
This field may be empty.
MaxLength: 256
MinLength: 1
Optional: {}
message stringmessage is a human readable message indicating details about the transition.
This field may be empty.
MaxLength: 10240
MinLength: 1
Optional: {}

ContractVersionedObjectReference

ContractVersionedObjectReference is a reference to a resource for which the version is inferred from contract labels.

Appears in:

FieldDescriptionDefaultValidation
kind stringkind of the resource being referenced.
kind must consist of alphanumeric characters or ‘-’, start with an alphabetic character, and end with an alphanumeric character.
MaxLength: 63
MinLength: 1
Pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
Required: {}
name stringname of the resource being referenced.
name must consist of lower case alphanumeric characters, ‘-’ or ‘.’, and must start and end with an alphanumeric character.
MaxLength: 253
MinLength: 1
Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
Required: {}
apiGroup stringapiGroup is the group of the resource being referenced.
apiGroup must be fully qualified domain name.
The corresponding version for this reference will be looked up from the contract
labels of the corresponding CRD of the resource being referenced.
MaxLength: 253
MinLength: 1
Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
Required: {}

ControlPlaneClass

ControlPlaneClass defines the class for the control plane.

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
templateRef ClusterClassTemplateReferencetemplateRef contains the reference to a provider-specific control plane template.Required: {}
machineInfrastructure ControlPlaneClassMachineInfrastructureTemplatemachineInfrastructure defines the metadata and infrastructure information
for control plane machines.
This field is supported if and only if the control plane provider template
referenced above is Machine based and supports setting replicas.
Optional: {}
healthCheck ControlPlaneClassHealthCheckhealthCheck defines a MachineHealthCheck for this ControlPlaneClass.
This field is supported if and only if the ControlPlane provider template
referenced above is Machine based and supports setting replicas.
MinProperties: 1
Optional: {}
naming ControlPlaneClassNamingSpecnaming allows changing the naming pattern used when creating the control plane provider object.MinProperties: 1
Optional: {}
deletion ControlPlaneClassMachineDeletionSpecdeletion contains configuration options for Machine deletion.MinProperties: 1
Optional: {}
taints MachineTaint arraytaints are the node taints that Cluster API will manage.
This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes,
e.g. the node controller might add the node.kubernetes.io/not-ready taint.
Only those taints defined in this list will be added or removed by core Cluster API controllers.
There can be at most 64 taints.
A pod would have to tolerate all existing taints to run on the corresponding node.
NOTE: This list is implemented as a “map” type, meaning that individual elements can be managed by different owners.
MaxItems: 64
MinItems: 1
Optional: {}
readinessGates MachineReadinessGate arrayreadinessGates specifies additional conditions to include when evaluating Machine Ready condition.
This field can be used e.g. to instruct the machine controller to include in the computation for Machine’s ready
computation a condition, managed by an external controllers, reporting the status of special software/hardware installed on the Machine.
NOTE: If a Cluster defines a custom list of readinessGates for the control plane,
such list overrides readinessGates defined in this field.
NOTE: Specific control plane provider implementations might automatically extend the list of readinessGates;
e.g. the kubeadm control provider adds ReadinessGates for the APIServerPodHealthy, SchedulerPodHealthy conditions, etc.
MaxItems: 32
MinItems: 1
Optional: {}

ControlPlaneClassHealthCheck

ControlPlaneClassHealthCheck defines a MachineHealthCheck for control plane machines.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
checks ControlPlaneClassHealthCheckCheckschecks are the checks that are used to evaluate if a Machine is healthy.
Independent of this configuration the MachineHealthCheck controller will always
flag Machines with cluster.x-k8s.io/remediate-machine annotation and
Machines with deleted Nodes as unhealthy.
Furthermore, if checks.nodeStartupTimeoutSeconds is not set it
is defaulted to 10 minutes and evaluated accordingly.
MinProperties: 1
Optional: {}
remediation ControlPlaneClassHealthCheckRemediationremediation configures if and how remediations are triggered if a Machine is unhealthy.
If remediation or remediation.triggerIf is not set,
remediation will always be triggered for unhealthy Machines.
If remediation or remediation.templateRef is not set,
the OwnerRemediated condition will be set on unhealthy Machines to trigger remediation via
the owner of the Machines, for example a MachineSet or a KubeadmControlPlane.
MinProperties: 1
Optional: {}

ControlPlaneClassHealthCheckChecks

ControlPlaneClassHealthCheckChecks are the checks that are used to evaluate if a control plane Machine is healthy.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
nodeStartupTimeoutSeconds integernodeStartupTimeoutSeconds allows to set the maximum time for MachineHealthCheck
to consider a Machine unhealthy if a corresponding Node isn’t associated
through a Spec.ProviderID field.
The duration set in this field is compared to the greatest of:
- Cluster’s infrastructure ready condition timestamp (if and when available)
- Control Plane’s initialized condition timestamp (if and when available)
- Machine’s infrastructure ready condition timestamp (if and when available)
- Machine’s metadata creation timestamp
Defaults to 10 minutes.
If you wish to disable this feature, set the value explicitly to 0.
Minimum: 0
Optional: {}
unhealthyNodeConditions UnhealthyNodeCondition arrayunhealthyNodeConditions contains a list of conditions that determine
whether a node is considered unhealthy. The conditions are combined in a
logical OR, i.e. if any of the conditions is met, the node is unhealthy.
MaxItems: 100
MinItems: 1
Optional: {}
unhealthyMachineConditions UnhealthyMachineCondition arrayunhealthyMachineConditions contains a list of the machine conditions that determine
whether a machine is considered unhealthy. The conditions are combined in a
logical OR, i.e. if any of the conditions is met, the machine is unhealthy.
MaxItems: 100
MinItems: 1
Optional: {}

ControlPlaneClassHealthCheckRemediation

ControlPlaneClassHealthCheckRemediation configures if and how remediations are triggered if a control plane Machine is unhealthy.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
triggerIf ControlPlaneClassHealthCheckRemediationTriggerIftriggerIf configures if remediations are triggered.
If this field is not set, remediations are always triggered.
MinProperties: 1
Optional: {}
templateRef MachineHealthCheckRemediationTemplateReferencetemplateRef is a reference to a remediation template
provided by an infrastructure provider.
This field is completely optional, when filled, the MachineHealthCheck controller
creates a new object from the template referenced and hands off remediation of the machine to
a controller that lives outside of Cluster API.
Optional: {}

ControlPlaneClassHealthCheckRemediationTriggerIf

ControlPlaneClassHealthCheckRemediationTriggerIf configures if remediations are triggered.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
unhealthyLessThanOrEqualTo IntOrStringunhealthyLessThanOrEqualTo specifies that remediations are only triggered if the number of
unhealthy Machines is less than or equal to the configured value.
unhealthyInRange takes precedence if set.
Optional: {}
unhealthyInRange stringunhealthyInRange specifies that remediations are only triggered if the number of
unhealthy Machines is in the configured range.
Takes precedence over unhealthyLessThanOrEqualTo.
Eg. “[3-5]” - This means that remediation will be allowed only when:
(a) there are at least 3 unhealthy Machines (and)
(b) there are at most 5 unhealthy Machines
MaxLength: 32
MinLength: 1
Pattern: ^\[[0-9]+-[0-9]+\]$
Optional: {}

ControlPlaneClassMachineDeletionSpec

ControlPlaneClassMachineDeletionSpec contains configuration options for Machine deletion.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
nodeDrainTimeoutSeconds integernodeDrainTimeoutSeconds is the total amount of time that the controller will spend on draining a node.
The default value is 0, meaning that the node can be drained without any time limitations.
NOTE: nodeDrainTimeoutSeconds is different from kubectl drain --timeout
NOTE: This value can be overridden while defining a Cluster.Topology.
Minimum: 0
Optional: {}
nodeVolumeDetachTimeoutSeconds integernodeVolumeDetachTimeoutSeconds is the total amount of time that the controller will spend on waiting for all volumes
to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
NOTE: This value can be overridden while defining a Cluster.Topology.
Minimum: 0
Optional: {}
nodeDeletionTimeoutSeconds integernodeDeletionTimeoutSeconds defines how long the controller will attempt to delete the Node that the Machine
hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely.
Defaults to 10 seconds.
NOTE: This value can be overridden while defining a Cluster.Topology.
Minimum: 0
Optional: {}

ControlPlaneClassMachineInfrastructureTemplate

ControlPlaneClassMachineInfrastructureTemplate defines the template for a MachineInfrastructure of a ControlPlane.

Appears in:

FieldDescriptionDefaultValidation
templateRef ClusterClassTemplateReferencetemplateRef is a required reference to the template for a MachineInfrastructure of a ControlPlane.Required: {}

ControlPlaneClassNamingSpec

ControlPlaneClassNamingSpec defines the naming strategy for control plane objects.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
template stringtemplate defines the template to use for generating the name of the ControlPlane object.
If not defined, it will fallback to \{\{ .cluster.name \}\}-\{\{ .random \}\}.
If the templated string exceeds 63 characters, it will be trimmed to 58 characters and will
get concatenated with a random suffix of length 5.
The templating mechanism provides the following arguments:
* .cluster.name: The name of the cluster object.
* .random: A random alphanumeric string, without vowels, of length 5.
MaxLength: 1024
MinLength: 1
Optional: {}

ControlPlaneTopology

ControlPlaneTopology specifies the parameters for the control plane nodes in the cluster.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
replicas integerreplicas is the number of control plane nodes.
If the value is not set, the ControlPlane object is created without the number of Replicas
and it’s assumed that the control plane controller does not implement support for this field.
When specified against a control plane provider that lacks support for this field, this value will be ignored.
Optional: {}
rollout ControlPlaneTopologyRolloutSpecrollout allows you to configure the behavior of rolling updates to the control plane.MinProperties: 1
Optional: {}
healthCheck ControlPlaneTopologyHealthCheckhealthCheck allows to enable, disable and override control plane health check
configuration from the ClusterClass for this control plane.
MinProperties: 1
Optional: {}
deletion ControlPlaneTopologyMachineDeletionSpecdeletion contains configuration options for Machine deletion.MinProperties: 1
Optional: {}
taints MachineTaint arraytaints are the node taints that Cluster API will manage.
This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes,
e.g. the node controller might add the node.kubernetes.io/not-ready taint.
Only those taints defined in this list will be added or removed by core Cluster API controllers.
There can be at most 64 taints.
A pod would have to tolerate all existing taints to run on the corresponding node.
NOTE: This list is implemented as a “map” type, meaning that individual elements can be managed by different owners.
MaxItems: 64
MinItems: 1
Optional: {}
readinessGates MachineReadinessGate arrayreadinessGates specifies additional conditions to include when evaluating Machine Ready condition.
This field can be used e.g. to instruct the machine controller to include in the computation for Machine’s ready
computation a condition, managed by an external controllers, reporting the status of special software/hardware installed on the Machine.
If this field is not defined, readinessGates from the corresponding ControlPlaneClass will be used, if any.
NOTE: Specific control plane provider implementations might automatically extend the list of readinessGates;
e.g. the kubeadm control provider adds ReadinessGates for the APIServerPodHealthy, SchedulerPodHealthy conditions, etc.
MaxItems: 32
MinItems: 1
Optional: {}
variables ControlPlaneVariablesvariables can be used to customize the ControlPlane through patches.MinProperties: 1
Optional: {}

ControlPlaneTopologyHealthCheck

ControlPlaneTopologyHealthCheck defines a MachineHealthCheck for control plane machines.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
enabled booleanenabled controls if a MachineHealthCheck should be created for the target machines.
If false: No MachineHealthCheck will be created.
If not set(default): A MachineHealthCheck will be created if it is defined here or
in the associated ClusterClass. If no MachineHealthCheck is defined then none will be created.
If true: A MachineHealthCheck is guaranteed to be created. Cluster validation will
block if enable is true and no MachineHealthCheck definition is available.
Optional: {}
checks ControlPlaneTopologyHealthCheckCheckschecks are the checks that are used to evaluate if a Machine is healthy.
If one of checks and remediation fields are set, the system assumes that an healthCheck override is defined,
and as a consequence the checks and remediation fields from Cluster will be used instead of the
corresponding fields in ClusterClass.
Independent of this configuration the MachineHealthCheck controller will always
flag Machines with cluster.x-k8s.io/remediate-machine annotation and
Machines with deleted Nodes as unhealthy.
Furthermore, if checks.nodeStartupTimeoutSeconds is not set it
is defaulted to 10 minutes and evaluated accordingly.
MinProperties: 1
Optional: {}
remediation ControlPlaneTopologyHealthCheckRemediationremediation configures if and how remediations are triggered if a Machine is unhealthy.
If one of checks and remediation fields are set, the system assumes that an healthCheck override is defined,
and as a consequence the checks and remediation fields from cluster will be used instead of the
corresponding fields in ClusterClass.
If an health check override is defined and remediation or remediation.triggerIf is not set,
remediation will always be triggered for unhealthy Machines.
If an health check override is defined and remediation or remediation.templateRef is not set,
the OwnerRemediated condition will be set on unhealthy Machines to trigger remediation via
the owner of the Machines, for example a MachineSet or a KubeadmControlPlane.
MinProperties: 1
Optional: {}

ControlPlaneTopologyHealthCheckChecks

ControlPlaneTopologyHealthCheckChecks are the checks that are used to evaluate if a control plane Machine is healthy.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
nodeStartupTimeoutSeconds integernodeStartupTimeoutSeconds allows to set the maximum time for MachineHealthCheck
to consider a Machine unhealthy if a corresponding Node isn’t associated
through a Spec.ProviderID field.
The duration set in this field is compared to the greatest of:
- Cluster’s infrastructure ready condition timestamp (if and when available)
- Control Plane’s initialized condition timestamp (if and when available)
- Machine’s infrastructure ready condition timestamp (if and when available)
- Machine’s metadata creation timestamp
Defaults to 10 minutes.
If you wish to disable this feature, set the value explicitly to 0.
Minimum: 0
Optional: {}
unhealthyNodeConditions UnhealthyNodeCondition arrayunhealthyNodeConditions contains a list of conditions that determine
whether a node is considered unhealthy. The conditions are combined in a
logical OR, i.e. if any of the conditions is met, the node is unhealthy.
MaxItems: 100
MinItems: 1
Optional: {}
unhealthyMachineConditions UnhealthyMachineCondition arrayunhealthyMachineConditions contains a list of the machine conditions that determine
whether a machine is considered unhealthy. The conditions are combined in a
logical OR, i.e. if any of the conditions is met, the machine is unhealthy.
MaxItems: 100
MinItems: 1
Optional: {}

ControlPlaneTopologyHealthCheckRemediation

ControlPlaneTopologyHealthCheckRemediation configures if and how remediations are triggered if a control plane Machine is unhealthy.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
triggerIf ControlPlaneTopologyHealthCheckRemediationTriggerIftriggerIf configures if remediations are triggered.
If this field is not set, remediations are always triggered.
MinProperties: 1
Optional: {}
templateRef MachineHealthCheckRemediationTemplateReferencetemplateRef is a reference to a remediation template
provided by an infrastructure provider.
This field is completely optional, when filled, the MachineHealthCheck controller
creates a new object from the template referenced and hands off remediation of the machine to
a controller that lives outside of Cluster API.
Optional: {}

ControlPlaneTopologyHealthCheckRemediationTriggerIf

ControlPlaneTopologyHealthCheckRemediationTriggerIf configures if remediations are triggered.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
unhealthyLessThanOrEqualTo IntOrStringunhealthyLessThanOrEqualTo specifies that remediations are only triggered if the number of
unhealthy Machines is less than or equal to the configured value.
unhealthyInRange takes precedence if set.
Optional: {}
unhealthyInRange stringunhealthyInRange specifies that remediations are only triggered if the number of
unhealthy Machines is in the configured range.
Takes precedence over unhealthyLessThanOrEqualTo.
Eg. “[3-5]” - This means that remediation will be allowed only when:
(a) there are at least 3 unhealthy Machines (and)
(b) there are at most 5 unhealthy Machines
MaxLength: 32
MinLength: 1
Pattern: ^\[[0-9]+-[0-9]+\]$
Optional: {}

ControlPlaneTopologyMachineDeletionSpec

ControlPlaneTopologyMachineDeletionSpec contains configuration options for Machine deletion.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
nodeDrainTimeoutSeconds integernodeDrainTimeoutSeconds is the total amount of time that the controller will spend on draining a node.
The default value is 0, meaning that the node can be drained without any time limitations.
NOTE: nodeDrainTimeoutSeconds is different from kubectl drain --timeout
Minimum: 0
Optional: {}
nodeVolumeDetachTimeoutSeconds integernodeVolumeDetachTimeoutSeconds is the total amount of time that the controller will spend on waiting for all volumes
to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
Minimum: 0
Optional: {}
nodeDeletionTimeoutSeconds integernodeDeletionTimeoutSeconds defines how long the controller will attempt to delete the Node that the Machine
hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely.
Defaults to 10 seconds.
Minimum: 0
Optional: {}

ControlPlaneTopologyRolloutSpec

ControlPlaneTopologyRolloutSpec defines the rollout behavior.

Validation:

  • MinProperties: 1

Appears in:

ControlPlaneVariables

ControlPlaneVariables can be used to provide variables for the ControlPlane.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
overrides ClusterVariable arrayoverrides can be used to override Cluster level variables.MaxItems: 1000
MinItems: 1
Optional: {}

ExternalPatchDefinition

ExternalPatchDefinition defines an external patch. Note: At least one of GeneratePatchesExtension or ValidateTopologyExtension must be set.

Appears in:

FieldDescriptionDefaultValidation
generatePatchesExtension stringgeneratePatchesExtension references an extension which is called to generate patches.MaxLength: 512
MinLength: 1
Optional: {}
validateTopologyExtension stringvalidateTopologyExtension references an extension which is called to validate the topology.MaxLength: 512
MinLength: 1
Optional: {}
discoverVariablesExtension stringdiscoverVariablesExtension references an extension which is called to discover variables.MaxLength: 512
MinLength: 1
Optional: {}
settings object (keys:string, values:string)settings defines key value pairs to be passed to the extensions.
Values defined here take precedence over the values defined in the
corresponding ExtensionConfig.
Optional: {}

FailureDomain

FailureDomain is the Schema for Cluster API failure domains. It allows controllers to understand how many failure domains a cluster can optionally span across.

Appears in:

FieldDescriptionDefaultValidation
name stringname is the name of the failure domain.MaxLength: 256
MinLength: 1
Required: {}
controlPlane booleancontrolPlane determines if this failure domain is suitable for use by control plane machines.Optional: {}
attributes object (keys:string, values:string)attributes is a free form map of attributes an infrastructure provider might use or require.Optional: {}

FieldValueErrorReason

Underlying type: string

FieldValueErrorReason is a machine-readable value providing more detail about why a field failed the validation.

Appears in:

FieldDescription
FieldValueRequiredFieldValueRequired is used to report required values that are not
provided (e.g. empty strings, null values, or empty arrays).
FieldValueDuplicateFieldValueDuplicate is used to report collisions of values that must be
unique (e.g. unique IDs).
FieldValueInvalidFieldValueInvalid is used to report malformed values (e.g. failed regex
match, too long, out of bounds).
FieldValueForbiddenFieldValueForbidden is used to report valid (as per formatting rules)
values which would be accepted under some conditions, but which are not
permitted by the current conditions (such as security policy).

InfrastructureClass

InfrastructureClass defines the class for the infrastructure cluster.

Appears in:

FieldDescriptionDefaultValidation
templateRef ClusterClassTemplateReferencetemplateRef contains the reference to a provider-specific infrastructure cluster template.Required: {}
naming InfrastructureClassNamingSpecnaming allows changing the naming pattern used when creating the infrastructure cluster object.MinProperties: 1
Optional: {}

InfrastructureClassNamingSpec

InfrastructureClassNamingSpec defines the naming strategy for infrastructure objects.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
template stringtemplate defines the template to use for generating the name of the Infrastructure object.
If not defined, it will fallback to \{\{ .cluster.name \}\}-\{\{ .random \}\}.
If the templated string exceeds 63 characters, it will be trimmed to 58 characters and will
get concatenated with a random suffix of length 5.
The templating mechanism provides the following arguments:
* .cluster.name: The name of the cluster object.
* .random: A random alphanumeric string, without vowels, of length 5.
MaxLength: 1024
MinLength: 1
Optional: {}

JSONPatch

JSONPatch defines a JSON patch.

Appears in:

FieldDescriptionDefaultValidation
op stringop defines the operation of the patch.
Note: Only add, replace and remove are supported.
Enum: [add replace remove]
Required: {}
path stringpath defines the path of the patch.
Note: Only the spec of a template can be patched, thus the path has to start with /spec/.
Note: For now the only allowed array modifications are append and prepend, i.e.:
* for op: add: only index 0 (prepend) and - (append) are allowed
* for op: replace or remove: no indexes are allowed
MaxLength: 512
MinLength: 1
Required: {}
value JSONvalue defines the value of the patch.
Note: Either Value or ValueFrom is required for add and replace
operations. Only one of them is allowed to be set at the same time.
Note: We have to use apiextensionsv1.JSON instead of our JSON type,
because controller-tools has a hard-coded schema for apiextensionsv1.JSON
which cannot be produced by another type (unset type field).
Ref: https://github.com/kubernetes-sigs/controller-tools/blob/d0e03a142d0ecdd5491593e941ee1d6b5d91dba6/pkg/crd/known_types.go#L106-L111
Optional: {}
valueFrom JSONPatchValuevalueFrom defines the value of the patch.
Note: Either Value or ValueFrom is required for add and replace
operations. Only one of them is allowed to be set at the same time.
Optional: {}

JSONPatchValue

JSONPatchValue defines the value of a patch. Note: Only one of the fields is allowed to be set at the same time.

Appears in:

FieldDescriptionDefaultValidation
variable stringvariable is the variable to be used as value.
Variable can be one of the variables defined in .spec.variables or a builtin variable.
MaxLength: 256
MinLength: 1
Optional: {}
template stringtemplate is the Go template to be used to calculate the value.
A template can reference variables defined in .spec.variables and builtin variables.
Note: The template must evaluate to a valid YAML or JSON value.
MaxLength: 10240
MinLength: 1
Optional: {}

JSONSchemaProps

JSONSchemaProps is a JSON-Schema following Specification Draft 4 (http://json-schema.org/). This struct has been initially copied from apiextensionsv1.JSONSchemaProps, but all fields which are not supported in CAPI have been removed.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
description stringdescription is a human-readable description of this variable.MaxLength: 4096
MinLength: 1
Optional: {}
example JSONexample is an example for this variable.Optional: {}
type stringtype is the type of the variable.
Valid values are: object, array, string, integer, number or boolean.
Enum: [object array string integer number boolean]
Optional: {}
properties object (keys:string, values:JSONSchemaProps)properties specifies fields of an object.
NOTE: Can only be set if type is object.
NOTE: Properties is mutually exclusive with AdditionalProperties.
NOTE: This field uses PreserveUnknownFields and Schemaless,
because recursive validation is not possible.
Schemaless: {}
Optional: {}
additionalProperties JSONSchemaPropsadditionalProperties specifies the schema of values in a map (keys are always strings).
NOTE: Can only be set if type is object.
NOTE: AdditionalProperties is mutually exclusive with Properties.
NOTE: This field uses PreserveUnknownFields and Schemaless,
because recursive validation is not possible.
MinProperties: 1
Schemaless: {}
Optional: {}
maxProperties integermaxProperties is the maximum amount of entries in a map or properties in an object.
NOTE: Can only be set if type is object.
Optional: {}
minProperties integerminProperties is the minimum amount of entries in a map or properties in an object.
NOTE: Can only be set if type is object.
Optional: {}
required string arrayrequired specifies which fields of an object are required.
NOTE: Can only be set if type is object.
MaxItems: 1000
MinItems: 1
items:MaxLength: 256
items:MinLength: 1
Optional: {}
items JSONSchemaPropsitems specifies fields of an array.
NOTE: Can only be set if type is array.
NOTE: This field uses PreserveUnknownFields and Schemaless,
because recursive validation is not possible.
MinProperties: 1
Schemaless: {}
Optional: {}
maxItems integermaxItems is the max length of an array variable.
NOTE: Can only be set if type is array.
Optional: {}
minItems integerminItems is the min length of an array variable.
NOTE: Can only be set if type is array.
Optional: {}
uniqueItems booleanuniqueItems specifies if items in an array must be unique.
NOTE: Can only be set if type is array.
Optional: {}
format stringformat is an OpenAPI v3 format string. Unknown formats are ignored.
For a list of supported formats please see: (of the k8s.io/apiextensions-apiserver version we’re currently using)
https://github.com/kubernetes/apiextensions-apiserver/blob/master/pkg/apiserver/validation/formats.go
NOTE: Can only be set if type is string.
MaxLength: 32
MinLength: 1
Optional: {}
maxLength integermaxLength is the max length of a string variable.
NOTE: Can only be set if type is string.
Optional: {}
minLength integerminLength is the min length of a string variable.
NOTE: Can only be set if type is string.
Optional: {}
pattern stringpattern is the regex which a string variable must match.
NOTE: Can only be set if type is string.
MaxLength: 512
MinLength: 1
Optional: {}
maximum integermaximum is the maximum of an integer or number variable.
If ExclusiveMaximum is false, the variable is valid if it is lower than, or equal to, the value of Maximum.
If ExclusiveMaximum is true, the variable is valid if it is strictly lower than the value of Maximum.
NOTE: Can only be set if type is integer or number.
Optional: {}
exclusiveMaximum booleanexclusiveMaximum specifies if the Maximum is exclusive.
NOTE: Can only be set if type is integer or number.
Optional: {}
minimum integerminimum is the minimum of an integer or number variable.
If ExclusiveMinimum is false, the variable is valid if it is greater than, or equal to, the value of Minimum.
If ExclusiveMinimum is true, the variable is valid if it is strictly greater than the value of Minimum.
NOTE: Can only be set if type is integer or number.
Optional: {}
exclusiveMinimum booleanexclusiveMinimum specifies if the Minimum is exclusive.
NOTE: Can only be set if type is integer or number.
Optional: {}
x-kubernetes-preserve-unknown-fields booleanx-kubernetes-preserve-unknown-fields allows setting fields in a variable object
which are not defined in the variable schema. This affects fields recursively,
except if nested properties or additionalProperties are specified in the schema.
Optional: {}
enum JSON arrayenum is the list of valid values of the variable.
NOTE: Can be set for all types.
MaxItems: 100
Optional: {}
default JSONdefault is the default value of the variable.
NOTE: Can be set for all types.
Optional: {}
x-kubernetes-validations ValidationRule arrayx-kubernetes-validations describes a list of validation rules written in the CEL expression language.MaxItems: 100
MinItems: 1
Optional: {}
x-metadata VariableSchemaMetadatax-metadata is the metadata of a variable or a nested field within a variable.
It can be used to add additional data for higher level tools.
MinProperties: 1
Optional: {}
x-kubernetes-int-or-string booleanx-kubernetes-int-or-string specifies that this value is
either an integer or a string. If this is true, an empty
type is allowed and type as child of anyOf is permitted
if following one of the following patterns:
1) anyOf:
- type: integer
- type: string
2) allOf:
- anyOf:
- type: integer
- type: string
- … zero or more
Optional: {}
allOf JSONSchemaProps arrayallOf specifies that the variable must validate against all of the subschemas in the array.
NOTE: This field uses PreserveUnknownFields and Schemaless,
because recursive validation is not possible.
MinProperties: 1
Schemaless: {}
Optional: {}
oneOf JSONSchemaProps arrayoneOf specifies that the variable must validate against exactly one of the subschemas in the array.
NOTE: This field uses PreserveUnknownFields and Schemaless,
because recursive validation is not possible.
MinProperties: 1
Schemaless: {}
Optional: {}
anyOf JSONSchemaProps arrayanyOf specifies that the variable must validate against one or more of the subschemas in the array.
NOTE: This field uses PreserveUnknownFields and Schemaless,
because recursive validation is not possible.
MinProperties: 1
Schemaless: {}
Optional: {}
not JSONSchemaPropsnot specifies that the variable must not validate against the subschema.
NOTE: This field uses PreserveUnknownFields and Schemaless,
because recursive validation is not possible.
MinProperties: 1
Schemaless: {}
Optional: {}

Machine

Machine is the Schema for the machines API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta2
kind stringMachine
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
spec MachineSpecspec is the desired state of Machine.Required: {}
status MachineStatusstatus is the observed state of Machine.MinProperties: 1
Optional: {}

MachineAddress

MachineAddress contains information for the node’s address.

Appears in:

FieldDescriptionDefaultValidation
type MachineAddressTypetype is the machine address type, one of Hostname, ExternalIP, InternalIP, ExternalDNS or InternalDNS.Enum: [Hostname ExternalIP InternalIP ExternalDNS InternalDNS]
Required: {}
address stringaddress is the machine address.MaxLength: 256
MinLength: 1
Required: {}

MachineAddressType

Underlying type: string

MachineAddressType describes a valid MachineAddress type.

Validation:

  • Enum: [Hostname ExternalIP InternalIP ExternalDNS InternalDNS]

Appears in:

FieldDescription
Hostname
ExternalIP
InternalIP
ExternalDNS
InternalDNS

MachineAddresses

Underlying type: MachineAddress

MachineAddresses is a slice of MachineAddress items to be used by infrastructure providers.

Validation:

  • MaxItems: 256

Appears in:

FieldDescriptionDefaultValidation
type MachineAddressTypetype is the machine address type, one of Hostname, ExternalIP, InternalIP, ExternalDNS or InternalDNS.Enum: [Hostname ExternalIP InternalIP ExternalDNS InternalDNS]
Required: {}
address stringaddress is the machine address.MaxLength: 256
MinLength: 1
Required: {}

MachineDeletionSpec

MachineDeletionSpec contains configuration options for Machine deletion.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
nodeDrainTimeoutSeconds integernodeDrainTimeoutSeconds is the total amount of time that the controller will spend on draining a node.
The default value is 0, meaning that the node can be drained without any time limitations.
NOTE: nodeDrainTimeoutSeconds is different from kubectl drain --timeout
Minimum: 0
Optional: {}
nodeVolumeDetachTimeoutSeconds integernodeVolumeDetachTimeoutSeconds is the total amount of time that the controller will spend on waiting for all volumes
to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
Minimum: 0
Optional: {}
nodeDeletionTimeoutSeconds integernodeDeletionTimeoutSeconds defines how long the controller will attempt to delete the Node that the Machine
hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely.
Defaults to 10 seconds.
Minimum: 0
Optional: {}

MachineDeletionStatus

MachineDeletionStatus is the deletion state of the Machine.

Appears in:

MachineDeployment

MachineDeployment is the Schema for the machinedeployments API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta2
kind stringMachineDeployment
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
spec MachineDeploymentSpecspec is the desired state of MachineDeployment.Required: {}
status MachineDeploymentStatusstatus is the observed state of MachineDeployment.MinProperties: 1
Optional: {}

MachineDeploymentClass

MachineDeploymentClass serves as a template to define a set of worker nodes of the cluster provisioned using the ClusterClass.

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
class stringclass denotes a type of worker node present in the cluster,
this name MUST be unique within a ClusterClass and can be referenced
in the Cluster to create a managed MachineDeployment.
MaxLength: 256
MinLength: 1
Required: {}
bootstrap MachineDeploymentClassBootstrapTemplatebootstrap contains the bootstrap template reference to be used
for the creation of worker Machines.
Required: {}
infrastructure MachineDeploymentClassInfrastructureTemplateinfrastructure contains the infrastructure template reference to be used
for the creation of worker Machines.
Required: {}
healthCheck MachineDeploymentClassHealthCheckhealthCheck defines a MachineHealthCheck for this MachineDeploymentClass.MinProperties: 1
Optional: {}
failureDomain stringfailureDomain is the failure domain the machines will be created in.
Must match the name of a FailureDomain from the Cluster status.
NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
MaxLength: 256
MinLength: 1
Optional: {}
naming MachineDeploymentClassNamingSpecnaming allows changing the naming pattern used when creating the MachineDeployment.MinProperties: 1
Optional: {}
deletion MachineDeploymentClassMachineDeletionSpecdeletion contains configuration options for Machine deletion.MinProperties: 1
Optional: {}
taints MachineTaint arraytaints are the node taints that Cluster API will manage.
This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes,
e.g. the node controller might add the node.kubernetes.io/not-ready taint.
Only those taints defined in this list will be added or removed by core Cluster API controllers.
There can be at most 64 taints.
A pod would have to tolerate all existing taints to run on the corresponding node.
NOTE: This list is implemented as a “map” type, meaning that individual elements can be managed by different owners.
MaxItems: 64
MinItems: 1
Optional: {}
minReadySeconds integerminReadySeconds is the minimum number of seconds for which a newly created machine should
be ready.
Defaults to 0 (machine will be considered available as soon as it
is ready)
NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
Minimum: 0
Optional: {}
readinessGates MachineReadinessGate arrayreadinessGates specifies additional conditions to include when evaluating Machine Ready condition.
This field can be used e.g. to instruct the machine controller to include in the computation for Machine’s ready
computation a condition, managed by an external controllers, reporting the status of special software/hardware installed on the Machine.
NOTE: If a Cluster defines a custom list of readinessGates for a MachineDeployment using this MachineDeploymentClass,
such list overrides readinessGates defined in this field.
MaxItems: 32
MinItems: 1
Optional: {}
rollout MachineDeploymentClassRolloutSpecrollout allows you to configure the behaviour of rolling updates to the MachineDeployment Machines.
It allows you to define the strategy used during rolling replacements.
MinProperties: 1
Optional: {}

MachineDeploymentClassBootstrapTemplate

MachineDeploymentClassBootstrapTemplate defines the BootstrapTemplate for a MachineDeployment.

Appears in:

FieldDescriptionDefaultValidation
templateRef ClusterClassTemplateReferencetemplateRef is a required reference to the BootstrapTemplate for a MachineDeployment.Required: {}

MachineDeploymentClassHealthCheck

MachineDeploymentClassHealthCheck defines a MachineHealthCheck for MachineDeployment machines.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
checks MachineDeploymentClassHealthCheckCheckschecks are the checks that are used to evaluate if a Machine is healthy.
Independent of this configuration the MachineHealthCheck controller will always
flag Machines with cluster.x-k8s.io/remediate-machine annotation and
Machines with deleted Nodes as unhealthy.
Furthermore, if checks.nodeStartupTimeoutSeconds is not set it
is defaulted to 10 minutes and evaluated accordingly.
MinProperties: 1
Optional: {}
remediation MachineDeploymentClassHealthCheckRemediationremediation configures if and how remediations are triggered if a Machine is unhealthy.
If remediation or remediation.triggerIf is not set,
remediation will always be triggered for unhealthy Machines.
If remediation or remediation.templateRef is not set,
the OwnerRemediated condition will be set on unhealthy Machines to trigger remediation via
the owner of the Machines, for example a MachineSet or a KubeadmControlPlane.
MinProperties: 1
Optional: {}

MachineDeploymentClassHealthCheckChecks

MachineDeploymentClassHealthCheckChecks are the checks that are used to evaluate if a MachineDeployment Machine is healthy.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
nodeStartupTimeoutSeconds integernodeStartupTimeoutSeconds allows to set the maximum time for MachineHealthCheck
to consider a Machine unhealthy if a corresponding Node isn’t associated
through a Spec.ProviderID field.
The duration set in this field is compared to the greatest of:
- Cluster’s infrastructure ready condition timestamp (if and when available)
- Control Plane’s initialized condition timestamp (if and when available)
- Machine’s infrastructure ready condition timestamp (if and when available)
- Machine’s metadata creation timestamp
Defaults to 10 minutes.
If you wish to disable this feature, set the value explicitly to 0.
Minimum: 0
Optional: {}
unhealthyNodeConditions UnhealthyNodeCondition arrayunhealthyNodeConditions contains a list of conditions that determine
whether a node is considered unhealthy. The conditions are combined in a
logical OR, i.e. if any of the conditions is met, the node is unhealthy.
MaxItems: 100
MinItems: 1
Optional: {}
unhealthyMachineConditions UnhealthyMachineCondition arrayunhealthyMachineConditions contains a list of the machine conditions that determine
whether a machine is considered unhealthy. The conditions are combined in a
logical OR, i.e. if any of the conditions is met, the machine is unhealthy.
MaxItems: 100
MinItems: 1
Optional: {}

MachineDeploymentClassHealthCheckRemediation

MachineDeploymentClassHealthCheckRemediation configures if and how remediations are triggered if a MachineDeployment Machine is unhealthy.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
maxInFlight IntOrStringmaxInFlight determines how many in flight remediations should happen at the same time.
Remediation only happens on the MachineSet with the most current revision, while
older MachineSets (usually present during rollout operations) aren’t allowed to remediate.
Note: In general (independent of remediations), unhealthy machines are always
prioritized during scale down operations over healthy ones.
MaxInFlight can be set to a fixed number or a percentage.
Example: when this is set to 20%, the MachineSet controller deletes at most 20% of
the desired replicas.
If not set, remediation is limited to all machines (bounded by replicas)
under the active MachineSet’s management.
Optional: {}
triggerIf MachineDeploymentClassHealthCheckRemediationTriggerIftriggerIf configures if remediations are triggered.
If this field is not set, remediations are always triggered.
MinProperties: 1
Optional: {}
templateRef MachineHealthCheckRemediationTemplateReferencetemplateRef is a reference to a remediation template
provided by an infrastructure provider.
This field is completely optional, when filled, the MachineHealthCheck controller
creates a new object from the template referenced and hands off remediation of the machine to
a controller that lives outside of Cluster API.
Optional: {}

MachineDeploymentClassHealthCheckRemediationTriggerIf

MachineDeploymentClassHealthCheckRemediationTriggerIf configures if remediations are triggered.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
unhealthyLessThanOrEqualTo IntOrStringunhealthyLessThanOrEqualTo specifies that remediations are only triggered if the number of
unhealthy Machines is less than or equal to the configured value.
unhealthyInRange takes precedence if set.
Optional: {}
unhealthyInRange stringunhealthyInRange specifies that remediations are only triggered if the number of
unhealthy Machines is in the configured range.
Takes precedence over unhealthyLessThanOrEqualTo.
Eg. “[3-5]” - This means that remediation will be allowed only when:
(a) there are at least 3 unhealthy Machines (and)
(b) there are at most 5 unhealthy Machines
MaxLength: 32
MinLength: 1
Pattern: ^\[[0-9]+-[0-9]+\]$
Optional: {}

MachineDeploymentClassInfrastructureTemplate

MachineDeploymentClassInfrastructureTemplate defines the InfrastructureTemplate for a MachineDeployment.

Appears in:

FieldDescriptionDefaultValidation
templateRef ClusterClassTemplateReferencetemplateRef is a required reference to the InfrastructureTemplate for a MachineDeployment.Required: {}

MachineDeploymentClassMachineDeletionSpec

MachineDeploymentClassMachineDeletionSpec contains configuration options for Machine deletion.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
order MachineSetDeletionOrderorder defines the order in which Machines are deleted when downscaling.
Defaults to “Random”. Valid values are “Random”, “Newest”, “Oldest”
Enum: [Random Newest Oldest]
Optional: {}
nodeDrainTimeoutSeconds integernodeDrainTimeoutSeconds is the total amount of time that the controller will spend on draining a node.
The default value is 0, meaning that the node can be drained without any time limitations.
NOTE: nodeDrainTimeoutSeconds is different from kubectl drain --timeout
NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
Minimum: 0
Optional: {}
nodeVolumeDetachTimeoutSeconds integernodeVolumeDetachTimeoutSeconds is the total amount of time that the controller will spend on waiting for all volumes
to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
Minimum: 0
Optional: {}
nodeDeletionTimeoutSeconds integernodeDeletionTimeoutSeconds defines how long the controller will attempt to delete the Node that the Machine
hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely.
Defaults to 10 seconds.
NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
Minimum: 0
Optional: {}

MachineDeploymentClassNamingSpec

MachineDeploymentClassNamingSpec defines the naming strategy for machine deployment objects.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
template stringtemplate defines the template to use for generating the name of the MachineDeployment object.
If not defined, it will fallback to \{\{ .cluster.name \}\}-\{\{ .machineDeployment.topologyName \}\}-\{\{ .random \}\}.
If the templated string exceeds 63 characters, it will be trimmed to 58 characters and will
get concatenated with a random suffix of length 5.
The templating mechanism provides the following arguments:
* .cluster.name: The name of the cluster object.
* .random: A random alphanumeric string, without vowels, of length 5.
* .machineDeployment.topologyName: The name of the MachineDeployment topology (Cluster.spec.topology.workers.machineDeployments[].name).
MaxLength: 1024
MinLength: 1
Optional: {}

MachineDeploymentClassRolloutSpec

MachineDeploymentClassRolloutSpec defines the rollout behavior.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
strategy MachineDeploymentClassRolloutStrategystrategy specifies how to roll out control plane Machines.MinProperties: 1
Optional: {}

MachineDeploymentClassRolloutStrategy

MachineDeploymentClassRolloutStrategy describes how to replace existing machines with new ones.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
type MachineDeploymentRolloutStrategyTypetype of rollout. Allowed values are RollingUpdate and OnDelete.
Default is RollingUpdate.
Enum: [RollingUpdate OnDelete]
Required: {}
rollingUpdate MachineDeploymentClassRolloutStrategyRollingUpdaterollingUpdate is the rolling update config params. Present only if
type = RollingUpdate.
MinProperties: 1
Optional: {}

MachineDeploymentClassRolloutStrategyRollingUpdate

MachineDeploymentClassRolloutStrategyRollingUpdate is used to control the desired behavior of rolling update.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
maxUnavailable IntOrStringmaxUnavailable is the maximum number of machines that can be unavailable during the update.
Value can be an absolute number (ex: 5) or a percentage of desired
machines (ex: 10%).
Absolute number is calculated from percentage by rounding down.
This can not be 0 if MaxSurge is 0.
Defaults to 0.
Example: when this is set to 30%, the old MachineSet can be scaled
down to 70% of desired machines immediately when the rolling update
starts. Once new machines are ready, old MachineSet can be scaled
down further, followed by scaling up the new MachineSet, ensuring
that the total number of machines available at all times
during the update is at least 70% of desired machines.
Optional: {}
maxSurge IntOrStringmaxSurge is the maximum number of machines that can be scheduled above the
desired number of machines.
Value can be an absolute number (ex: 5) or a percentage of
desired machines (ex: 10%).
This can not be 0 if MaxUnavailable is 0.
Absolute number is calculated from percentage by rounding up.
Defaults to 1.
Example: when this is set to 30%, the new MachineSet can be scaled
up immediately when the rolling update starts, such that the total
number of old and new machines do not exceed 130% of desired
machines. Once old machines have been killed, new MachineSet can
be scaled up further, ensuring that total number of machines running
at any time during the update is at most 130% of desired machines.
Optional: {}

MachineDeploymentDeletionSpec

MachineDeploymentDeletionSpec contains configuration options for MachineDeployment deletion.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
order MachineSetDeletionOrderorder defines the order in which Machines are deleted when downscaling.
Defaults to “Random”. Valid values are “Random”, “Newest”, “Oldest”
Enum: [Random Newest Oldest]
Optional: {}

MachineDeploymentDeprecatedStatus

MachineDeploymentDeprecatedStatus groups all the status fields that are deprecated and will be removed in a future version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
v1beta1 MachineDeploymentV1Beta1DeprecatedStatusv1beta1 groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped.Optional: {}

MachineDeploymentList

MachineDeploymentList contains a list of MachineDeployment.

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta2
kind stringMachineDeploymentList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items MachineDeployment arrayitems is the list of MachineDeployments.

MachineDeploymentRemediationSpec

MachineDeploymentRemediationSpec controls how unhealthy Machines are remediated.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
maxInFlight IntOrStringmaxInFlight determines how many in flight remediations should happen at the same time.
Remediation only happens on the MachineSet with the most current revision, while
older MachineSets (usually present during rollout operations) aren’t allowed to remediate.
Note: In general (independent of remediations), unhealthy machines are always
prioritized during scale down operations over healthy ones.
MaxInFlight can be set to a fixed number or a percentage.
Example: when this is set to 20%, the MachineSet controller deletes at most 20% of
the desired replicas.
If not set, remediation is limited to all machines (bounded by replicas)
under the active MachineSet’s management.
Optional: {}

MachineDeploymentRolloutSpec

MachineDeploymentRolloutSpec defines the rollout behavior.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
strategy MachineDeploymentRolloutStrategystrategy specifies how to roll out control plane Machines.MinProperties: 1
Optional: {}

MachineDeploymentRolloutStrategy

MachineDeploymentRolloutStrategy describes how to replace existing machines with new ones.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
type MachineDeploymentRolloutStrategyTypetype of rollout. Allowed values are RollingUpdate and OnDelete.
Default is RollingUpdate.
Enum: [RollingUpdate OnDelete]
Required: {}
rollingUpdate MachineDeploymentRolloutStrategyRollingUpdaterollingUpdate is the rolling update config params. Present only if
type = RollingUpdate.
MinProperties: 1
Optional: {}

MachineDeploymentRolloutStrategyRollingUpdate

MachineDeploymentRolloutStrategyRollingUpdate is used to control the desired behavior of rolling update.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
maxUnavailable IntOrStringmaxUnavailable is the maximum number of machines that can be unavailable during the update.
Value can be an absolute number (ex: 5) or a percentage of desired
machines (ex: 10%).
Absolute number is calculated from percentage by rounding down.
This can not be 0 if MaxSurge is 0.
Defaults to 0.
Example: when this is set to 30%, the old MachineSet can be scaled
down to 70% of desired machines immediately when the rolling update
starts. Once new machines are ready, old MachineSet can be scaled
down further, followed by scaling up the new MachineSet, ensuring
that the total number of machines available at all times
during the update is at least 70% of desired machines.
Optional: {}
maxSurge IntOrStringmaxSurge is the maximum number of machines that can be scheduled above the
desired number of machines.
Value can be an absolute number (ex: 5) or a percentage of
desired machines (ex: 10%).
This can not be 0 if MaxUnavailable is 0.
Absolute number is calculated from percentage by rounding up.
Defaults to 1.
Example: when this is set to 30%, the new MachineSet can be scaled
up immediately when the rolling update starts, such that the total
number of old and new machines do not exceed 130% of desired
machines. Once old machines have been killed, new MachineSet can
be scaled up further, ensuring that total number of machines running
at any time during the update is at most 130% of desired machines.
Optional: {}

MachineDeploymentRolloutStrategyType

Underlying type: string

MachineDeploymentRolloutStrategyType defines the type of MachineDeployment rollout strategies.

Validation:

  • Enum: [RollingUpdate OnDelete]

Appears in:

FieldDescription
RollingUpdateRollingUpdateMachineDeploymentStrategyType replaces the old MachineSet by new one using rolling update
i.e. gradually scale down the old MachineSet and scale up the new one.
OnDeleteOnDeleteMachineDeploymentStrategyType replaces old MachineSets when the deletion of the associated machines are completed.

MachineDeploymentSpec

MachineDeploymentSpec defines the desired state of MachineDeployment.

Appears in:

FieldDescriptionDefaultValidation
clusterName stringclusterName is the name of the Cluster this object belongs to.MaxLength: 63
MinLength: 1
Required: {}
replicas integerreplicas is the number of desired machines.
This is a pointer to distinguish between explicit zero and not specified.
Defaults to:
* if the Kubernetes autoscaler min size and max size annotations are set:
- if it’s a new MachineDeployment, use min size
- if the replicas field of the old MachineDeployment is < min size, use min size
- if the replicas field of the old MachineDeployment is > max size, use max size
- if the replicas field of the old MachineDeployment is in the (min size, max size) range, keep the value from the oldMD
* otherwise use 1
Note: Defaulting will be run whenever the replicas field is not set:
* A new MachineDeployment is created with replicas not set.
* On an existing MachineDeployment the replicas field was first set and is now unset.
Those cases are especially relevant for the following Kubernetes autoscaler use cases:
* A new MachineDeployment is created and replicas should be managed by the autoscaler
* An existing MachineDeployment which initially wasn’t controlled by the autoscaler
should be later controlled by the autoscaler
Optional: {}
rollout MachineDeploymentRolloutSpecrollout allows you to configure the behaviour of rolling updates to the MachineDeployment Machines.
It allows you to require that all Machines are replaced after a certain time,
and allows you to define the strategy used during rolling replacements.
MinProperties: 1
Optional: {}
selector LabelSelectorselector is the label selector for machines. Existing MachineSets whose machines are
selected by this will be the ones affected by this deployment.
It must match the machine template’s labels.
Required: {}
template MachineTemplateSpectemplate describes the machines that will be created.Required: {}
machineNaming MachineNamingSpecmachineNaming allows changing the naming pattern used when creating Machines.
Note: InfraMachines & BootstrapConfigs will use the same name as the corresponding Machines.
MinProperties: 1
Optional: {}
remediation MachineDeploymentRemediationSpecremediation controls how unhealthy Machines are remediated.MinProperties: 1
Optional: {}
deletion MachineDeploymentDeletionSpecdeletion contains configuration options for MachineDeployment deletion.MinProperties: 1
Optional: {}
paused booleanpaused indicates that the deployment is paused.Optional: {}

MachineDeploymentStatus

MachineDeploymentStatus defines the observed state of MachineDeployment.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a MachineDeployment’s current state.
Known condition types are Available, MachinesReady, MachinesUpToDate, ScalingUp, ScalingDown, Remediating, Deleting, Paused.
MaxItems: 32
Optional: {}
observedGeneration integerobservedGeneration is the generation observed by the deployment controller.Minimum: 1
Optional: {}
selector stringselector is the same as the label selector but in the string format to avoid introspection
by clients. The string will be in the same format as the query-param syntax.
More info about label selectors: http://kubernetes.io/docs/user-guide/labels#label-selectors
MaxLength: 4096
MinLength: 1
Optional: {}
replicas integerreplicas is the total number of non-terminated machines targeted by this deployment
(their labels match the selector).
Optional: {}
readyReplicas integerreadyReplicas is the number of ready replicas for this MachineDeployment. A machine is considered ready when Machine’s Ready condition is true.Optional: {}
availableReplicas integeravailableReplicas is the number of available replicas for this MachineDeployment. A machine is considered available when Machine’s Available condition is true.Optional: {}
upToDateReplicas integerupToDateReplicas is the number of up-to-date replicas targeted by this deployment. A machine is considered up-to-date when Machine’s UpToDate condition is true.Optional: {}
versions StatusVersion arrayversions is the aggregated Kubernetes versions in this MachineDeployment.MaxItems: 100
MinItems: 1
Optional: {}
phase stringphase represents the current phase of a MachineDeployment (ScalingUp, ScalingDown, Running, Failed, or Unknown).Enum: [ScalingUp ScalingDown Running Failed Unknown]
Optional: {}
deprecated MachineDeploymentDeprecatedStatusdeprecated groups all the status fields that are deprecated and will be removed when all the nested field are removed.Optional: {}

MachineDeploymentTopology

MachineDeploymentTopology specifies the different parameters for a set of worker nodes in the topology. This set of nodes is managed by a MachineDeployment object whose lifecycle is managed by the Cluster controller.

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
class stringclass is the name of the MachineDeploymentClass used to create the set of worker nodes.
This should match one of the deployment classes defined in the ClusterClass object
mentioned in the Cluster.Spec.Class field.
MaxLength: 256
MinLength: 1
Required: {}
name stringname is the unique identifier for this MachineDeploymentTopology.
The value is used with other unique identifiers to create a MachineDeployment’s Name
(e.g. cluster’s name, etc). In case the name is greater than the allowed maximum length,
the values are hashed together.
MaxLength: 63
MinLength: 1
Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
Required: {}
failureDomain stringfailureDomain is the failure domain the machines will be created in.
Must match a key in the FailureDomains map stored on the cluster object.
MaxLength: 256
MinLength: 1
Optional: {}
replicas integerreplicas is the number of worker nodes belonging to this set.
If the value is nil, the MachineDeployment is created without the number of Replicas (defaulting to 1)
and it’s assumed that an external entity (like cluster autoscaler) is responsible for the management
of this value.
Optional: {}
healthCheck MachineDeploymentTopologyHealthCheckhealthCheck allows to enable, disable and override MachineDeployment health check
configuration from the ClusterClass for this MachineDeployment.
MinProperties: 1
Optional: {}
deletion MachineDeploymentTopologyMachineDeletionSpecdeletion contains configuration options for Machine deletion.MinProperties: 1
Optional: {}
taints MachineTaint arraytaints are the node taints that Cluster API will manage.
This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes,
e.g. the node controller might add the node.kubernetes.io/not-ready taint.
Only those taints defined in this list will be added or removed by core Cluster API controllers.
There can be at most 64 taints.
A pod would have to tolerate all existing taints to run on the corresponding node.
NOTE: This list is implemented as a “map” type, meaning that individual elements can be managed by different owners.
MaxItems: 64
MinItems: 1
Optional: {}
minReadySeconds integerminReadySeconds is the minimum number of seconds for which a newly created machine should
be ready.
Defaults to 0 (machine will be considered available as soon as it
is ready)
Minimum: 0
Optional: {}
readinessGates MachineReadinessGate arrayreadinessGates specifies additional conditions to include when evaluating Machine Ready condition.
This field can be used e.g. to instruct the machine controller to include in the computation for Machine’s ready
computation a condition, managed by an external controllers, reporting the status of special software/hardware installed on the Machine.
If this field is not defined, readinessGates from the corresponding MachineDeploymentClass will be used, if any.
MaxItems: 32
MinItems: 1
Optional: {}
rollout MachineDeploymentTopologyRolloutSpecrollout allows you to configure the behaviour of rolling updates to the MachineDeployment Machines.
It allows you to define the strategy used during rolling replacements.
MinProperties: 1
Optional: {}
variables MachineDeploymentVariablesvariables can be used to customize the MachineDeployment through patches.MinProperties: 1
Optional: {}

MachineDeploymentTopologyHealthCheck

MachineDeploymentTopologyHealthCheck defines a MachineHealthCheck for MachineDeployment machines.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
enabled booleanenabled controls if a MachineHealthCheck should be created for the target machines.
If false: No MachineHealthCheck will be created.
If not set(default): A MachineHealthCheck will be created if it is defined here or
in the associated ClusterClass. If no MachineHealthCheck is defined then none will be created.
If true: A MachineHealthCheck is guaranteed to be created. Cluster validation will
block if enable is true and no MachineHealthCheck definition is available.
Optional: {}
checks MachineDeploymentTopologyHealthCheckCheckschecks are the checks that are used to evaluate if a Machine is healthy.
If one of checks and remediation fields are set, the system assumes that an healthCheck override is defined,
and as a consequence the checks and remediation fields from Cluster will be used instead of the
corresponding fields in ClusterClass.
Independent of this configuration the MachineHealthCheck controller will always
flag Machines with cluster.x-k8s.io/remediate-machine annotation and
Machines with deleted Nodes as unhealthy.
Furthermore, if checks.nodeStartupTimeoutSeconds is not set it
is defaulted to 10 minutes and evaluated accordingly.
MinProperties: 1
Optional: {}
remediation MachineDeploymentTopologyHealthCheckRemediationremediation configures if and how remediations are triggered if a Machine is unhealthy.
If one of checks and remediation fields are set, the system assumes that an healthCheck override is defined,
and as a consequence the checks and remediation fields from cluster will be used instead of the
corresponding fields in ClusterClass.
If an health check override is defined and remediation or remediation.triggerIf is not set,
remediation will always be triggered for unhealthy Machines.
If an health check override is defined and remediation or remediation.templateRef is not set,
the OwnerRemediated condition will be set on unhealthy Machines to trigger remediation via
the owner of the Machines, for example a MachineSet or a KubeadmControlPlane.
MinProperties: 1
Optional: {}

MachineDeploymentTopologyHealthCheckChecks

MachineDeploymentTopologyHealthCheckChecks are the checks that are used to evaluate if a MachineDeployment Machine is healthy.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
nodeStartupTimeoutSeconds integernodeStartupTimeoutSeconds allows to set the maximum time for MachineHealthCheck
to consider a Machine unhealthy if a corresponding Node isn’t associated
through a Spec.ProviderID field.
The duration set in this field is compared to the greatest of:
- Cluster’s infrastructure ready condition timestamp (if and when available)
- Control Plane’s initialized condition timestamp (if and when available)
- Machine’s infrastructure ready condition timestamp (if and when available)
- Machine’s metadata creation timestamp
Defaults to 10 minutes.
If you wish to disable this feature, set the value explicitly to 0.
Minimum: 0
Optional: {}
unhealthyNodeConditions UnhealthyNodeCondition arrayunhealthyNodeConditions contains a list of conditions that determine
whether a node is considered unhealthy. The conditions are combined in a
logical OR, i.e. if any of the conditions is met, the node is unhealthy.
MaxItems: 100
MinItems: 1
Optional: {}
unhealthyMachineConditions UnhealthyMachineCondition arrayunhealthyMachineConditions contains a list of the machine conditions that determine
whether a machine is considered unhealthy. The conditions are combined in a
logical OR, i.e. if any of the conditions is met, the machine is unhealthy.
MaxItems: 100
MinItems: 1
Optional: {}

MachineDeploymentTopologyHealthCheckRemediation

MachineDeploymentTopologyHealthCheckRemediation configures if and how remediations are triggered if a MachineDeployment Machine is unhealthy.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
maxInFlight IntOrStringmaxInFlight determines how many in flight remediations should happen at the same time.
Remediation only happens on the MachineSet with the most current revision, while
older MachineSets (usually present during rollout operations) aren’t allowed to remediate.
Note: In general (independent of remediations), unhealthy machines are always
prioritized during scale down operations over healthy ones.
MaxInFlight can be set to a fixed number or a percentage.
Example: when this is set to 20%, the MachineSet controller deletes at most 20% of
the desired replicas.
If not set, remediation is limited to all machines (bounded by replicas)
under the active MachineSet’s management.
Optional: {}
triggerIf MachineDeploymentTopologyHealthCheckRemediationTriggerIftriggerIf configures if remediations are triggered.
If this field is not set, remediations are always triggered.
MinProperties: 1
Optional: {}
templateRef MachineHealthCheckRemediationTemplateReferencetemplateRef is a reference to a remediation template
provided by an infrastructure provider.
This field is completely optional, when filled, the MachineHealthCheck controller
creates a new object from the template referenced and hands off remediation of the machine to
a controller that lives outside of Cluster API.
Optional: {}

MachineDeploymentTopologyHealthCheckRemediationTriggerIf

MachineDeploymentTopologyHealthCheckRemediationTriggerIf configures if remediations are triggered.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
unhealthyLessThanOrEqualTo IntOrStringunhealthyLessThanOrEqualTo specifies that remediations are only triggered if the number of
unhealthy Machines is less than or equal to the configured value.
unhealthyInRange takes precedence if set.
Optional: {}
unhealthyInRange stringunhealthyInRange specifies that remediations are only triggered if the number of
unhealthy Machines is in the configured range.
Takes precedence over unhealthyLessThanOrEqualTo.
Eg. “[3-5]” - This means that remediation will be allowed only when:
(a) there are at least 3 unhealthy Machines (and)
(b) there are at most 5 unhealthy Machines
MaxLength: 32
MinLength: 1
Pattern: ^\[[0-9]+-[0-9]+\]$
Optional: {}

MachineDeploymentTopologyMachineDeletionSpec

MachineDeploymentTopologyMachineDeletionSpec contains configuration options for Machine deletion.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
order MachineSetDeletionOrderorder defines the order in which Machines are deleted when downscaling.
Defaults to “Random”. Valid values are “Random”, “Newest”, “Oldest”
Enum: [Random Newest Oldest]
Optional: {}
nodeDrainTimeoutSeconds integernodeDrainTimeoutSeconds is the total amount of time that the controller will spend on draining a node.
The default value is 0, meaning that the node can be drained without any time limitations.
NOTE: nodeDrainTimeoutSeconds is different from kubectl drain --timeout
Minimum: 0
Optional: {}
nodeVolumeDetachTimeoutSeconds integernodeVolumeDetachTimeoutSeconds is the total amount of time that the controller will spend on waiting for all volumes
to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
Minimum: 0
Optional: {}
nodeDeletionTimeoutSeconds integernodeDeletionTimeoutSeconds defines how long the controller will attempt to delete the Node that the Machine
hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely.
Defaults to 10 seconds.
Minimum: 0
Optional: {}

MachineDeploymentTopologyRolloutSpec

MachineDeploymentTopologyRolloutSpec defines the rollout behavior.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
strategy MachineDeploymentTopologyRolloutStrategystrategy specifies how to roll out control plane Machines.MinProperties: 1
Optional: {}

MachineDeploymentTopologyRolloutStrategy

MachineDeploymentTopologyRolloutStrategy describes how to replace existing machines with new ones.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
type MachineDeploymentRolloutStrategyTypetype of rollout. Allowed values are RollingUpdate and OnDelete.
Default is RollingUpdate.
Enum: [RollingUpdate OnDelete]
Required: {}
rollingUpdate MachineDeploymentTopologyRolloutStrategyRollingUpdaterollingUpdate is the rolling update config params. Present only if
type = RollingUpdate.
MinProperties: 1
Optional: {}

MachineDeploymentTopologyRolloutStrategyRollingUpdate

MachineDeploymentTopologyRolloutStrategyRollingUpdate is used to control the desired behavior of rolling update.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
maxUnavailable IntOrStringmaxUnavailable is the maximum number of machines that can be unavailable during the update.
Value can be an absolute number (ex: 5) or a percentage of desired
machines (ex: 10%).
Absolute number is calculated from percentage by rounding down.
This can not be 0 if MaxSurge is 0.
Defaults to 0.
Example: when this is set to 30%, the old MachineSet can be scaled
down to 70% of desired machines immediately when the rolling update
starts. Once new machines are ready, old MachineSet can be scaled
down further, followed by scaling up the new MachineSet, ensuring
that the total number of machines available at all times
during the update is at least 70% of desired machines.
Optional: {}
maxSurge IntOrStringmaxSurge is the maximum number of machines that can be scheduled above the
desired number of machines.
Value can be an absolute number (ex: 5) or a percentage of
desired machines (ex: 10%).
This can not be 0 if MaxUnavailable is 0.
Absolute number is calculated from percentage by rounding up.
Defaults to 1.
Example: when this is set to 30%, the new MachineSet can be scaled
up immediately when the rolling update starts, such that the total
number of old and new machines do not exceed 130% of desired
machines. Once old machines have been killed, new MachineSet can
be scaled up further, ensuring that total number of machines running
at any time during the update is at most 130% of desired machines.
Optional: {}

MachineDeploymentV1Beta1DeprecatedStatus

MachineDeploymentV1Beta1DeprecatedStatus groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Conditionsconditions defines current service state of the MachineDeployment.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
updatedReplicas integerupdatedReplicas is the total number of non-terminated machines targeted by this deployment
that have the desired template spec.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
readyReplicas integerreadyReplicas is the total number of ready machines targeted by this deployment.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
availableReplicas integeravailableReplicas is the total number of available machines (ready for at least minReadySeconds)
targeted by this deployment.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
unavailableReplicas integerunavailableReplicas is the total number of unavailable machines targeted by this deployment.
This is the total number of machines that are still required for
the deployment to have 100% available capacity. They may either
be machines that are running but not yet available or machines
that still have not been created.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}

MachineDeploymentVariables

MachineDeploymentVariables can be used to provide variables for a specific MachineDeployment.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
overrides ClusterVariable arrayoverrides can be used to override Cluster level variables.MaxItems: 1000
MinItems: 1
Optional: {}

MachineDeprecatedStatus

MachineDeprecatedStatus groups all the status fields that are deprecated and will be removed in a future version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
v1beta1 MachineV1Beta1DeprecatedStatusv1beta1 groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}

MachineDrainRule

MachineDrainRule is the Schema for the MachineDrainRule API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta2
kind stringMachineDrainRule
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Required: {}
spec MachineDrainRuleSpecspec defines the spec of a MachineDrainRule.Required: {}

MachineDrainRuleDrainBehavior

Underlying type: string

MachineDrainRuleDrainBehavior defines the drain behavior. Can be either “Drain”, “Skip”, or “WaitCompleted”.

Validation:

  • Enum: [Drain Skip WaitCompleted]

Appears in:

FieldDescription
DrainMachineDrainRuleDrainBehaviorDrain means a Pod should be drained.
SkipMachineDrainRuleDrainBehaviorSkip means the drain for a Pod should be skipped.
WaitCompletedMachineDrainRuleDrainBehaviorWaitCompleted means the Pod should not be evicted,
but overall drain should wait until the Pod completes.

MachineDrainRuleDrainConfig

MachineDrainRuleDrainConfig configures if and how Pods are drained.

Appears in:

FieldDescriptionDefaultValidation
behavior MachineDrainRuleDrainBehaviorbehavior defines the drain behavior.
Can be either “Drain”, “Skip”, or “WaitCompleted”.
“Drain” means that the Pods to which this MachineDrainRule applies will be drained.
If behavior is set to “Drain” the order in which Pods are drained can be configured
with the order field. When draining Pods of a Node the Pods will be grouped by order
and one group after another will be drained (by increasing order). Cluster API will
wait until all Pods of a group are terminated / removed from the Node before starting
with the next group.
“Skip” means that the Pods to which this MachineDrainRule applies will be skipped during drain.
“WaitCompleted” means that the pods to which this MachineDrainRule applies will never be evicted
and we wait for them to be completed, it is enforced that pods marked with this behavior always have Order=0.
Enum: [Drain Skip WaitCompleted]
Required: {}
order integerorder defines the order in which Pods are drained.
Pods with higher order are drained after Pods with lower order.
order can only be set if behavior is set to “Drain”.
If order is not set, 0 will be used.
Valid values for order are from -2147483648 to 2147483647 (inclusive).
Optional: {}

MachineDrainRuleList

MachineDrainRuleList contains a list of MachineDrainRules.

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta2
kind stringMachineDrainRuleList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Required: {}
items MachineDrainRule arrayitems contains the items of the MachineDrainRuleList.

MachineDrainRuleMachineSelector

MachineDrainRuleMachineSelector defines to which Machines this MachineDrainRule should be applied.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
selector LabelSelectorselector is a label selector which selects Machines by their labels.
This field follows standard label selector semantics; if not present or
empty, it selects all Machines.
If clusterSelector is also set, then the selector as a whole selects
Machines matching selector belonging to Clusters selected by clusterSelector.
If clusterSelector is not set, it selects all Machines matching selector in
all Clusters.
Optional: {}
clusterSelector LabelSelectorclusterSelector is a label selector which selects Machines by the labels of
their Clusters.
This field follows standard label selector semantics; if not present or
empty, it selects Machines of all Clusters.
If selector is also set, then the selector as a whole selects
Machines matching selector belonging to Clusters selected by clusterSelector.
If selector is not set, it selects all Machines belonging to Clusters
selected by clusterSelector.
Optional: {}

MachineDrainRulePodSelector

MachineDrainRulePodSelector defines to which Pods this MachineDrainRule should be applied.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
selector LabelSelectorselector is a label selector which selects Pods by their labels.
This field follows standard label selector semantics; if not present or
empty, it selects all Pods.
If namespaceSelector is also set, then the selector as a whole selects
Pods matching selector in Namespaces selected by namespaceSelector.
If namespaceSelector is not set, it selects all Pods matching selector in
all Namespaces.
Optional: {}
namespaceSelector LabelSelectornamespaceSelector is a label selector which selects Pods by the labels of
their Namespaces.
This field follows standard label selector semantics; if not present or
empty, it selects Pods of all Namespaces.
If selector is also set, then the selector as a whole selects
Pods matching selector in Namespaces selected by namespaceSelector.
If selector is not set, it selects all Pods in Namespaces selected by
namespaceSelector.
Optional: {}

MachineDrainRuleSpec

MachineDrainRuleSpec defines the spec of a MachineDrainRule.

Appears in:

FieldDescriptionDefaultValidation
drain MachineDrainRuleDrainConfigdrain configures if and how Pods are drained.Required: {}
machines MachineDrainRuleMachineSelector arraymachines defines to which Machines this MachineDrainRule should be applied.
If machines is not set, the MachineDrainRule applies to all Machines in the Namespace.
If machines contains multiple selectors, the results are ORed.
Within a single Machine selector the results of selector and clusterSelector are ANDed.
Machines will be selected from all Clusters in the Namespace unless otherwise
restricted with the clusterSelector.
Example: Selects control plane Machines in all Clusters or
Machines with label “os” == “linux” in Clusters with label
“stage” == “production”.
- selector:
matchExpressions:
- key: cluster.x-k8s.io/control-plane
operator: Exists
- selector:
matchLabels:
os: linux
clusterSelector:
matchExpressions:
- key: stage
operator: In
values:
- production
MaxItems: 32
MinItems: 1
MinProperties: 1
Optional: {}
pods MachineDrainRulePodSelector arraypods defines to which Pods this MachineDrainRule should be applied.
If pods is not set, the MachineDrainRule applies to all Pods in all Namespaces.
If pods contains multiple selectors, the results are ORed.
Within a single Pod selector the results of selector and namespaceSelector are ANDed.
Pods will be selected from all Namespaces unless otherwise
restricted with the namespaceSelector.
Example: Selects Pods with label “app” == “logging” in all Namespaces or
Pods with label “app” == “prometheus” in the “monitoring”
Namespace.
- selector:
matchExpressions:
- key: app
operator: In
values:
- logging
- selector:
matchLabels:
app: prometheus
namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoring
MaxItems: 32
MinItems: 1
MinProperties: 1
Optional: {}

MachineHealthCheck

MachineHealthCheck is the Schema for the machinehealthchecks API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta2
kind stringMachineHealthCheck
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
spec MachineHealthCheckSpecspec is the specification of machine health check policyRequired: {}
status MachineHealthCheckStatusstatus is the most recently observed status of MachineHealthCheck resourceMinProperties: 1
Optional: {}

MachineHealthCheckChecks

MachineHealthCheckChecks are the checks that are used to evaluate if a Machine is healthy.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
nodeStartupTimeoutSeconds integernodeStartupTimeoutSeconds allows to set the maximum time for MachineHealthCheck
to consider a Machine unhealthy if a corresponding Node isn’t associated
through a Spec.ProviderID field.
The duration set in this field is compared to the greatest of:
- Cluster’s infrastructure ready condition timestamp (if and when available)
- Control Plane’s initialized condition timestamp (if and when available)
- Machine’s infrastructure ready condition timestamp (if and when available)
- Machine’s metadata creation timestamp
Defaults to 10 minutes.
If you wish to disable this feature, set the value explicitly to 0.
Minimum: 0
Optional: {}
unhealthyNodeConditions UnhealthyNodeCondition arrayunhealthyNodeConditions contains a list of conditions that determine
whether a node is considered unhealthy. The conditions are combined in a
logical OR, i.e. if any of the conditions is met, the node is unhealthy.
MaxItems: 100
MinItems: 1
Optional: {}
unhealthyMachineConditions UnhealthyMachineCondition arrayunhealthyMachineConditions contains a list of the machine conditions that determine
whether a machine is considered unhealthy. The conditions are combined in a
logical OR, i.e. if any of the conditions is met, the machine is unhealthy.
MaxItems: 100
MinItems: 1
Optional: {}

MachineHealthCheckDeprecatedStatus

MachineHealthCheckDeprecatedStatus groups all the status fields that are deprecated and will be removed in a future version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
v1beta1 MachineHealthCheckV1Beta1DeprecatedStatusv1beta1 groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped.Optional: {}

MachineHealthCheckList

MachineHealthCheckList contains a list of MachineHealthCheck.

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta2
kind stringMachineHealthCheckList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items MachineHealthCheck arrayitems is the list of MachineHealthChecks.

MachineHealthCheckRemediation

MachineHealthCheckRemediation configures if and how remediations are triggered if a Machine is unhealthy.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
triggerIf MachineHealthCheckRemediationTriggerIftriggerIf configures if remediations are triggered.
If this field is not set, remediations are always triggered.
MinProperties: 1
Optional: {}
templateRef MachineHealthCheckRemediationTemplateReferencetemplateRef is a reference to a remediation template
provided by an infrastructure provider.
This field is completely optional, when filled, the MachineHealthCheck controller
creates a new object from the template referenced and hands off remediation of the machine to
a controller that lives outside of Cluster API.
Optional: {}

MachineHealthCheckRemediationTemplateReference

MachineHealthCheckRemediationTemplateReference is a reference to a remediation template.

Appears in:

FieldDescriptionDefaultValidation
kind stringkind of the remediation template.
kind must consist of alphanumeric characters or ‘-’, start with an alphabetic character, and end with an alphanumeric character.
MaxLength: 63
MinLength: 1
Pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
Required: {}
name stringname of the remediation template.
name must consist of lower case alphanumeric characters, ‘-’ or ‘.’, and must start and end with an alphanumeric character.
MaxLength: 253
MinLength: 1
Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
Required: {}
apiVersion stringapiVersion of the remediation template.
apiVersion must be fully qualified domain name followed by / and a version.
NOTE: This field must be kept in sync with the APIVersion of the remediation template.
MaxLength: 317
MinLength: 1
Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[a-z]([-a-z0-9]*[a-z0-9])?$
Required: {}

MachineHealthCheckRemediationTriggerIf

MachineHealthCheckRemediationTriggerIf configures if remediations are triggered.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
unhealthyLessThanOrEqualTo IntOrStringunhealthyLessThanOrEqualTo specifies that remediations are only triggered if the number of
unhealthy Machines is less than or equal to the configured value.
unhealthyInRange takes precedence if set.
Optional: {}
unhealthyInRange stringunhealthyInRange specifies that remediations are only triggered if the number of
unhealthy Machines is in the configured range.
Takes precedence over unhealthyLessThanOrEqualTo.
Eg. “[3-5]” - This means that remediation will be allowed only when:
(a) there are at least 3 unhealthy Machines (and)
(b) there are at most 5 unhealthy Machines
MaxLength: 32
MinLength: 1
Pattern: ^\[[0-9]+-[0-9]+\]$
Optional: {}

MachineHealthCheckSpec

MachineHealthCheckSpec defines the desired state of MachineHealthCheck.

Appears in:

FieldDescriptionDefaultValidation
clusterName stringclusterName is the name of the Cluster this object belongs to.MaxLength: 63
MinLength: 1
Required: {}
selector LabelSelectorselector is a label selector to match machines whose health will be exercisedRequired: {}
checks MachineHealthCheckCheckschecks are the checks that are used to evaluate if a Machine is healthy.
Independent of this configuration the MachineHealthCheck controller will always
flag Machines with cluster.x-k8s.io/remediate-machine annotation and
Machines with deleted Nodes as unhealthy.
Furthermore, if checks.nodeStartupTimeoutSeconds is not set it
is defaulted to 10 minutes and evaluated accordingly.
MinProperties: 1
Optional: {}
remediation MachineHealthCheckRemediationremediation configures if and how remediations are triggered if a Machine is unhealthy.
If remediation or remediation.triggerIf is not set,
remediation will always be triggered for unhealthy Machines.
If remediation or remediation.templateRef is not set,
the OwnerRemediated condition will be set on unhealthy Machines to trigger remediation via
the owner of the Machines, for example a MachineSet or a KubeadmControlPlane.
MinProperties: 1
Optional: {}

MachineHealthCheckStatus

MachineHealthCheckStatus defines the observed state of MachineHealthCheck.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a MachineHealthCheck’s current state.
Known condition types are RemediationAllowed, Paused.
MaxItems: 32
Optional: {}
expectedMachines integerexpectedMachines is the total number of machines counted by this machine health checkMinimum: 0
Optional: {}
currentHealthy integercurrentHealthy is the total number of healthy machines counted by this machine health checkMinimum: 0
Optional: {}
remediationsAllowed integerremediationsAllowed is the number of further remediations allowed by this machine health check before
maxUnhealthy short circuiting will be applied
Minimum: 0
Optional: {}
observedGeneration integerobservedGeneration is the latest generation observed by the controller.Minimum: 1
Optional: {}
targets string arraytargets shows the current list of machines the machine health check is watchingMaxItems: 10000
items:MaxLength: 253
items:MinLength: 1
Optional: {}
deprecated MachineHealthCheckDeprecatedStatusdeprecated groups all the status fields that are deprecated and will be removed when all the nested field are removed.Optional: {}

MachineHealthCheckV1Beta1DeprecatedStatus

MachineHealthCheckV1Beta1DeprecatedStatus groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Conditionsconditions defines current service state of the MachineHealthCheck.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}

MachineInitializationStatus

MachineInitializationStatus provides observations of the Machine initialization process. NOTE: Fields in this struct are part of the Cluster API contract and are used to orchestrate initial Machine provisioning.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
infrastructureProvisioned booleaninfrastructureProvisioned is true when the infrastructure provider reports that Machine’s infrastructure is fully provisioned.
NOTE: this field is part of the Cluster API contract, and it is used to orchestrate provisioning.
The value of this field is never updated after provisioning is completed.
Optional: {}
bootstrapDataSecretCreated booleanbootstrapDataSecretCreated is true when the bootstrap provider reports that the Machine’s boostrap secret is created.
NOTE: this field is part of the Cluster API contract, and it is used to orchestrate provisioning.
The value of this field is never updated after provisioning is completed.
Optional: {}

MachineList

MachineList contains a list of Machine.

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta2
kind stringMachineList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items Machine arrayitems is the list of Machines.

MachineNamingSpec

MachineNamingSpec allows changing the naming pattern used when creating Machines. Note: InfraMachines & BootstrapConfigs will use the same name as the corresponding Machines.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
template stringtemplate defines the template to use for generating the names of the
Machine objects.
If not defined, it will fallback to \{\{ .machineSet.name \}\}-\{\{ .random \}\}.
If the generated name string exceeds 63 characters, it will be trimmed to
58 characters and will
get concatenated with a random suffix of length 5.
Length of the template string must not exceed 256 characters.
The template allows the following variables .cluster.name,
.machineSet.name and .random.
The variable .cluster.name retrieves the name of the cluster object
that owns the Machines being created.
The variable .machineSet.name retrieves the name of the MachineSet
object that owns the Machines being created.
The variable .random is substituted with random alphanumeric string,
without vowels, of length 5. This variable is required part of the
template. If not provided, validation will fail.
MaxLength: 256
MinLength: 1
Optional: {}

MachineNodeReference

MachineNodeReference is a reference to the node running on the machine.

Appears in:

FieldDescriptionDefaultValidation
name stringname of the node.
name must consist of lower case alphanumeric characters, ‘-’ or ‘.’, and must start and end with an alphanumeric character.
MaxLength: 253
MinLength: 1
Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
Required: {}

MachinePool

MachinePool is the Schema for the machinepools API. NOTE: This CRD can only be used if the MachinePool feature gate is enabled.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta2
kind stringMachinePool
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
spec MachinePoolSpecspec is the desired state of MachinePool.Required: {}
status MachinePoolStatusstatus is the observed state of MachinePool.MinProperties: 1
Optional: {}

MachinePoolClass

MachinePoolClass serves as a template to define a pool of worker nodes of the cluster provisioned using ClusterClass.

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
class stringclass denotes a type of machine pool present in the cluster,
this name MUST be unique within a ClusterClass and can be referenced
in the Cluster to create a managed MachinePool.
MaxLength: 256
MinLength: 1
Required: {}
bootstrap MachinePoolClassBootstrapTemplatebootstrap contains the bootstrap template reference to be used
for the creation of the Machines in the MachinePool.
Required: {}
infrastructure MachinePoolClassInfrastructureTemplateinfrastructure contains the infrastructure template reference to be used
for the creation of the MachinePool.
Required: {}
failureDomains string arrayfailureDomains is the list of failure domains the MachinePool should be attached to.
Must match a key in the FailureDomains map stored on the cluster object.
NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.
MaxItems: 100
items:MaxLength: 256
items:MinLength: 1
Optional: {}
naming MachinePoolClassNamingSpecnaming allows changing the naming pattern used when creating the MachinePool.MinProperties: 1
Optional: {}
deletion MachinePoolClassMachineDeletionSpecdeletion contains configuration options for Machine deletion.MinProperties: 1
Optional: {}
taints MachineTaint arraytaints are the node taints that Cluster API will manage.
This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes,
e.g. the node controller might add the node.kubernetes.io/not-ready taint.
Only those taints defined in this list will be added or removed by core Cluster API controllers.
There can be at most 64 taints.
A pod would have to tolerate all existing taints to run on the corresponding node.
NOTE: This list is implemented as a “map” type, meaning that individual elements can be managed by different owners.
MaxItems: 64
MinItems: 1
Optional: {}
minReadySeconds integerminReadySeconds is the minimum number of seconds for which a newly created machine pool should
be ready.
Defaults to 0 (machine will be considered available as soon as it
is ready)
NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.
Minimum: 0
Optional: {}

MachinePoolClassBootstrapTemplate

MachinePoolClassBootstrapTemplate defines the BootstrapTemplate for a MachinePool.

Appears in:

FieldDescriptionDefaultValidation
templateRef ClusterClassTemplateReferencetemplateRef is a required reference to the BootstrapTemplate for a MachinePool.Required: {}

MachinePoolClassInfrastructureTemplate

MachinePoolClassInfrastructureTemplate defines the InfrastructureTemplate for a MachinePool.

Appears in:

FieldDescriptionDefaultValidation
templateRef ClusterClassTemplateReferencetemplateRef is a required reference to the InfrastructureTemplate for a MachinePool.Required: {}

MachinePoolClassMachineDeletionSpec

MachinePoolClassMachineDeletionSpec contains configuration options for Machine deletion.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
nodeDrainTimeoutSeconds integernodeDrainTimeoutSeconds is the total amount of time that the controller will spend on draining a node.
The default value is 0, meaning that the node can be drained without any time limitations.
NOTE: nodeDrainTimeoutSeconds is different from kubectl drain --timeout
NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.
Minimum: 0
Optional: {}
nodeVolumeDetachTimeoutSeconds integernodeVolumeDetachTimeoutSeconds is the total amount of time that the controller will spend on waiting for all volumes
to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.
Minimum: 0
Optional: {}
nodeDeletionTimeoutSeconds integernodeDeletionTimeoutSeconds defines how long the controller will attempt to delete the Node that the Machine
hosts after the Machine Pool is marked for deletion. A duration of 0 will retry deletion indefinitely.
Defaults to 10 seconds.
NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.
Minimum: 0
Optional: {}

MachinePoolClassNamingSpec

MachinePoolClassNamingSpec defines the naming strategy for MachinePool objects.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
template stringtemplate defines the template to use for generating the name of the MachinePool object.
If not defined, it will fallback to \{\{ .cluster.name \}\}-\{\{ .machinePool.topologyName \}\}-\{\{ .random \}\}.
If the templated string exceeds 63 characters, it will be trimmed to 58 characters and will
get concatenated with a random suffix of length 5.
The templating mechanism provides the following arguments:
* .cluster.name: The name of the cluster object.
* .random: A random alphanumeric string, without vowels, of length 5.
* .machinePool.topologyName: The name of the MachinePool topology (Cluster.spec.topology.workers.machinePools[].name).
MaxLength: 1024
MinLength: 1
Optional: {}

MachinePoolDeprecatedStatus

MachinePoolDeprecatedStatus groups all the status fields that are deprecated and will be removed in a future version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
v1beta1 MachinePoolV1Beta1DeprecatedStatusv1beta1 groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped.Optional: {}

MachinePoolInitializationStatus

MachinePoolInitializationStatus provides observations of the MachinePool initialization process. NOTE: Fields in this struct are part of the Cluster API contract and are used to orchestrate initial MachinePool provisioning.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
infrastructureProvisioned booleaninfrastructureProvisioned is true when the infrastructure provider reports that MachinePool’s infrastructure is fully provisioned.
NOTE: this field is part of the Cluster API contract, and it is used to orchestrate provisioning.
The value of this field is never updated after provisioning is completed.
Optional: {}
bootstrapDataSecretCreated booleanbootstrapDataSecretCreated is true when the bootstrap provider reports that the MachinePool’s boostrap secret is created.
NOTE: this field is part of the Cluster API contract, and it is used to orchestrate provisioning.
The value of this field is never updated after provisioning is completed.
Optional: {}

MachinePoolList

MachinePoolList contains a list of MachinePool.

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta2
kind stringMachinePoolList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items MachinePool arrayitems is the list of MachinePools.

MachinePoolSpec

MachinePoolSpec defines the desired state of MachinePool.

Appears in:

FieldDescriptionDefaultValidation
clusterName stringclusterName is the name of the Cluster this object belongs to.MaxLength: 63
MinLength: 1
Required: {}
replicas integerreplicas is the number of desired machines. Defaults to 1.
This is a pointer to distinguish between explicit zero and not specified.
Optional: {}
template MachineTemplateSpectemplate describes the machines that will be created.Required: {}
providerIDList string arrayproviderIDList are the identification IDs of machine instances provided by the provider.
This field must match the provider IDs as seen on the node objects corresponding to a machine pool’s machine instances.
MaxItems: 10000
items:MaxLength: 512
items:MinLength: 1
Optional: {}
failureDomains string arrayfailureDomains is the list of failure domains this MachinePool should be attached to.MaxItems: 100
items:MaxLength: 256
items:MinLength: 1
Optional: {}

MachinePoolStatus

MachinePoolStatus defines the observed state of MachinePool.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a MachinePool’s current state.
Known condition types are Available, BootstrapConfigReady, InfrastructureReady, MachinesReady, MachinesUpToDate,
ScalingUp, ScalingDown, Remediating, Deleting, Paused.
MaxItems: 32
Optional: {}
initialization MachinePoolInitializationStatusinitialization provides observations of the MachinePool initialization process.
NOTE: Fields in this struct are part of the Cluster API contract and are used to orchestrate initial MachinePool provisioning.
MinProperties: 1
Optional: {}
nodeRefs ObjectReference arraynodeRefs will point to the corresponding Nodes if they exist.MaxItems: 10000
Optional: {}
replicas integerreplicas is the most recently observed number of replicas.Optional: {}
readyReplicas integerreadyReplicas is the number of ready replicas for this MachinePool. A machine is considered ready when Machine’s Ready condition is true.Optional: {}
availableReplicas integeravailableReplicas is the number of available replicas for this MachinePool. A machine is considered available when Machine’s Available condition is true.Optional: {}
upToDateReplicas integerupToDateReplicas is the number of up-to-date replicas targeted by this MachinePool. A machine is considered up-to-date when Machine’s UpToDate condition is true.Optional: {}
versions StatusVersion arrayversions is the aggregated Kubernetes versions in this MachinePool.MaxItems: 100
MinItems: 1
Optional: {}
phase stringphase represents the current phase of cluster actuation.Enum: [Pending Provisioning Provisioned Running ScalingUp ScalingDown Scaling Deleting Failed Unknown]
Optional: {}
observedGeneration integerobservedGeneration is the latest generation observed by the controller.Minimum: 1
Optional: {}
deprecated MachinePoolDeprecatedStatusdeprecated groups all the status fields that are deprecated and will be removed when all the nested field are removed.Optional: {}

MachinePoolTopology

MachinePoolTopology specifies the different parameters for a pool of worker nodes in the topology. This pool of nodes is managed by a MachinePool object whose lifecycle is managed by the Cluster controller.

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
class stringclass is the name of the MachinePoolClass used to create the pool of worker nodes.
This should match one of the deployment classes defined in the ClusterClass object
mentioned in the Cluster.Spec.Class field.
MaxLength: 256
MinLength: 1
Required: {}
name stringname is the unique identifier for this MachinePoolTopology.
The value is used with other unique identifiers to create a MachinePool’s Name
(e.g. cluster’s name, etc). In case the name is greater than the allowed maximum length,
the values are hashed together.
MaxLength: 63
MinLength: 1
Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
Required: {}
failureDomains string arrayfailureDomains is the list of failure domains the machine pool will be created in.
Must match a key in the FailureDomains map stored on the cluster object.
MaxItems: 100
MinItems: 1
items:MaxLength: 256
items:MinLength: 1
Optional: {}
deletion MachinePoolTopologyMachineDeletionSpecdeletion contains configuration options for Machine deletion.MinProperties: 1
Optional: {}
taints MachineTaint arraytaints are the node taints that Cluster API will manage.
This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes,
e.g. the node controller might add the node.kubernetes.io/not-ready taint.
Only those taints defined in this list will be added or removed by core Cluster API controllers.
There can be at most 64 taints.
A pod would have to tolerate all existing taints to run on the corresponding node.
NOTE: This list is implemented as a “map” type, meaning that individual elements can be managed by different owners.
MaxItems: 64
MinItems: 1
Optional: {}
minReadySeconds integerminReadySeconds is the minimum number of seconds for which a newly created machine pool should
be ready.
Defaults to 0 (machine will be considered available as soon as it
is ready)
Minimum: 0
Optional: {}
replicas integerreplicas is the number of nodes belonging to this pool.
If the value is nil, the MachinePool is created without the number of Replicas (defaulting to 1)
and it’s assumed that an external entity (like cluster autoscaler) is responsible for the management
of this value.
Optional: {}
variables MachinePoolVariablesvariables can be used to customize the MachinePool through patches.MinProperties: 1
Optional: {}

MachinePoolTopologyMachineDeletionSpec

MachinePoolTopologyMachineDeletionSpec contains configuration options for Machine deletion.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
nodeDrainTimeoutSeconds integernodeDrainTimeoutSeconds is the total amount of time that the controller will spend on draining a node.
The default value is 0, meaning that the node can be drained without any time limitations.
NOTE: nodeDrainTimeoutSeconds is different from kubectl drain --timeout
Minimum: 0
Optional: {}
nodeVolumeDetachTimeoutSeconds integernodeVolumeDetachTimeoutSeconds is the total amount of time that the controller will spend on waiting for all volumes
to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
Minimum: 0
Optional: {}
nodeDeletionTimeoutSeconds integernodeDeletionTimeoutSeconds defines how long the controller will attempt to delete the Node that the MachinePool
hosts after the MachinePool is marked for deletion. A duration of 0 will retry deletion indefinitely.
Defaults to 10 seconds.
Minimum: 0
Optional: {}

MachinePoolV1Beta1DeprecatedStatus

MachinePoolV1Beta1DeprecatedStatus groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Conditionsconditions define the current service state of the MachinePool.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
failureReason MachinePoolStatusFailurefailureReason indicates that there is a problem reconciling the state, and
will be set to a token value suitable for programmatic interpretation.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
failureMessage stringfailureMessage indicates that there is a problem reconciling the state,
and will be set to a descriptive error message.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
MaxLength: 10240
MinLength: 1
Optional: {}
readyReplicas integerreadyReplicas is the number of ready replicas for this MachinePool. A machine is considered ready when the node has been created and is “Ready”.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
availableReplicas integeravailableReplicas is the number of available replicas (ready for at least minReadySeconds) for this MachinePool.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
unavailableReplicas integerunavailableReplicas is the total number of unavailable machine instances targeted by this machine pool.
This is the total number of machine instances that are still required for
the machine pool to have 100% available capacity. They may either
be machine instances that are running but not yet available or machine instances
that still have not been created.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}

MachinePoolVariables

MachinePoolVariables can be used to provide variables for a specific MachinePool.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
overrides ClusterVariable arrayoverrides can be used to override Cluster level variables.MaxItems: 1000
MinItems: 1
Optional: {}

MachineReadinessGate

MachineReadinessGate contains the type of a Machine condition to be used as a readiness gate.

Appears in:

FieldDescriptionDefaultValidation
conditionType stringconditionType refers to a condition with matching type in the Machine’s condition list.
If the conditions doesn’t exist, it will be treated as unknown.
Note: Both Cluster API conditions or conditions added by 3rd party controllers can be used as readiness gates.
MaxLength: 316
MinLength: 1
Pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
Required: {}
polarity ConditionPolaritypolarity of the conditionType specified in this readinessGate.
Valid values are Positive, Negative and omitted.
When omitted, the default behaviour will be Positive.
A positive polarity means that the condition should report a true status under normal conditions.
A negative polarity means that the condition should report a false status under normal conditions.
Enum: [Positive Negative]
Optional: {}

MachineSet

MachineSet is the Schema for the machinesets API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta2
kind stringMachineSet
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
spec MachineSetSpecspec is the desired state of MachineSet.Required: {}
status MachineSetStatusstatus is the observed state of MachineSet.MinProperties: 1
Optional: {}

MachineSetDeletionOrder

Underlying type: string

MachineSetDeletionOrder defines how priority is assigned to nodes to delete when downscaling a MachineSet. Defaults to “Random”.

Validation:

  • Enum: [Random Newest Oldest]

Appears in:

FieldDescription
RandomRandomMachineSetDeletionOrder prioritizes both Machines that have the annotation
“cluster.x-k8s.io/delete-machine=yes” and Machines that are unhealthy
(Status.FailureReason or Status.FailureMessage are set to a non-empty value
or NodeHealthy type of Status.Conditions is not true).
Finally, it picks Machines at random to delete.
NewestNewestMachineSetDeletionOrder prioritizes both Machines that have the annotation
“cluster.x-k8s.io/delete-machine=yes” and Machines that are unhealthy
(Status.FailureReason or Status.FailureMessage are set to a non-empty value
or NodeHealthy type of Status.Conditions is not true).
It then prioritizes the newest Machines for deletion based on the Machine’s CreationTimestamp.
OldestOldestMachineSetDeletionOrder prioritizes both Machines that have the annotation
“cluster.x-k8s.io/delete-machine=yes” and Machines that are unhealthy
(Status.FailureReason or Status.FailureMessage are set to a non-empty value
or NodeHealthy type of Status.Conditions is not true).
It then prioritizes the oldest Machines for deletion based on the Machine’s CreationTimestamp.

MachineSetDeletionSpec

MachineSetDeletionSpec contains configuration options for MachineSet deletion.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
order MachineSetDeletionOrderorder defines the order in which Machines are deleted when downscaling.
Defaults to “Random”. Valid values are “Random”, “Newest”, “Oldest”
Enum: [Random Newest Oldest]
Optional: {}

MachineSetDeprecatedStatus

MachineSetDeprecatedStatus groups all the status fields that are deprecated and will be removed in a future version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
v1beta1 MachineSetV1Beta1DeprecatedStatusv1beta1 groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped.Optional: {}

MachineSetList

MachineSetList contains a list of MachineSet.

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta2
kind stringMachineSetList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items MachineSet arrayitems is the list of MachineSets.

MachineSetSpec

MachineSetSpec defines the desired state of MachineSet.

Appears in:

FieldDescriptionDefaultValidation
clusterName stringclusterName is the name of the Cluster this object belongs to.MaxLength: 63
MinLength: 1
Required: {}
replicas integerreplicas is the number of desired replicas.
This is a pointer to distinguish between explicit zero and unspecified.
Defaults to:
* if the Kubernetes autoscaler min size and max size annotations are set:
- if it’s a new MachineSet, use min size
- if the replicas field of the old MachineSet is < min size, use min size
- if the replicas field of the old MachineSet is > max size, use max size
- if the replicas field of the old MachineSet is in the (min size, max size) range, keep the value from the oldMS
* otherwise use 1
Note: Defaulting will be run whenever the replicas field is not set:
* A new MachineSet is created with replicas not set.
* On an existing MachineSet the replicas field was first set and is now unset.
Those cases are especially relevant for the following Kubernetes autoscaler use cases:
* A new MachineSet is created and replicas should be managed by the autoscaler
* An existing MachineSet which initially wasn’t controlled by the autoscaler
should be later controlled by the autoscaler
Optional: {}
selector LabelSelectorselector is a label query over machines that should match the replica count.
Label keys and values that must match in order to be controlled by this MachineSet.
It must match the machine template’s labels.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
Required: {}
template MachineTemplateSpectemplate is the object that describes the machine that will be created if
insufficient replicas are detected.
Object references to custom resources are treated as templates.
Required: {}
machineNaming MachineNamingSpecmachineNaming allows changing the naming pattern used when creating Machines.
Note: InfraMachines & BootstrapConfigs will use the same name as the corresponding Machines.
MinProperties: 1
Optional: {}
deletion MachineSetDeletionSpecdeletion contains configuration options for MachineSet deletion.MinProperties: 1
Optional: {}

MachineSetStatus

MachineSetStatus defines the observed state of MachineSet.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a MachineSet’s current state.
Known condition types are MachinesReady, MachinesUpToDate, ScalingUp, ScalingDown, Remediating, Deleting, Paused.
MaxItems: 32
Optional: {}
selector stringselector is the same as the label selector but in the string format to avoid introspection
by clients. The string will be in the same format as the query-param syntax.
More info about label selectors: http://kubernetes.io/docs/user-guide/labels#label-selectors
MaxLength: 4096
MinLength: 1
Optional: {}
replicas integerreplicas is the most recently observed number of replicas.Optional: {}
readyReplicas integerreadyReplicas is the number of ready replicas for this MachineSet. A machine is considered ready when Machine’s Ready condition is true.Optional: {}
availableReplicas integeravailableReplicas is the number of available replicas for this MachineSet. A machine is considered available when Machine’s Available condition is true.Optional: {}
upToDateReplicas integerupToDateReplicas is the number of up-to-date replicas for this MachineSet. A machine is considered up-to-date when Machine’s UpToDate condition is true.Optional: {}
versions StatusVersion arrayversions is the aggregated Kubernetes versions in this MachineSet.MaxItems: 100
MinItems: 1
Optional: {}
observedGeneration integerobservedGeneration reflects the generation of the most recently observed MachineSet.Minimum: 1
Optional: {}
deprecated MachineSetDeprecatedStatusdeprecated groups all the status fields that are deprecated and will be removed when all the nested field are removed.Optional: {}

MachineSetV1Beta1DeprecatedStatus

MachineSetV1Beta1DeprecatedStatus groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Conditionsconditions defines current service state of the MachineSet.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
failureReason MachineSetStatusErrorfailureReason will be set in the event that there is a terminal problem
reconciling the Machine and will contain a succinct value suitable
for machine interpretation.
In the event that there is a terminal problem reconciling the
replicas, both FailureReason and FailureMessage will be set. FailureReason
will be populated with a succinct value suitable for machine
interpretation, while FailureMessage will contain a more verbose
string suitable for logging and human consumption.
These fields should not be set for transitive errors that a
controller faces that are expected to be fixed automatically over
time (like service outages), but instead indicate that something is
fundamentally wrong with the MachineTemplate’s spec or the configuration of
the machine controller, and that manual intervention is required. Examples
of terminal errors would be invalid combinations of settings in the
spec, values that are unsupported by the machine controller, or the
responsible machine controller itself being critically misconfigured.
Any transient errors that occur during the reconciliation of Machines
can be added as events to the MachineSet object and/or logged in the
controller’s output.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
failureMessage stringfailureMessage will be set in the event that there is a terminal problem
reconciling the Machine and will contain a more verbose string suitable
for logging and human consumption.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
MaxLength: 10240
MinLength: 1
Optional: {}
fullyLabeledReplicas integerfullyLabeledReplicas is the number of replicas that have labels matching the labels of the machine template of the MachineSet.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
readyReplicas integerreadyReplicas is the number of ready replicas for this MachineSet. A machine is considered ready when the node has been created and is “Ready”.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
availableReplicas integeravailableReplicas is the number of available replicas (ready for at least minReadySeconds) for this MachineSet.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}

MachineSpec

MachineSpec defines the desired state of Machine.

Appears in:

FieldDescriptionDefaultValidation
clusterName stringclusterName is the name of the Cluster this object belongs to.MaxLength: 63
MinLength: 1
Required: {}
bootstrap Bootstrapbootstrap is a reference to a local struct which encapsulates
fields to configure the Machine’s bootstrapping mechanism.
Required: {}
infrastructureRef ContractVersionedObjectReferenceinfrastructureRef is a required reference to a custom resource
offered by an infrastructure provider.
Required: {}
version stringversion defines the desired Kubernetes version.
This field is meant to be optionally used by bootstrap providers.
MaxLength: 256
MinLength: 1
Optional: {}
providerID stringproviderID is the identification ID of the machine provided by the provider.
This field must match the provider ID as seen on the node object corresponding to this machine.
This field is required by higher level consumers of cluster-api. Example use case is cluster autoscaler
with cluster-api as provider. Clean-up logic in the autoscaler compares machines to nodes to find out
machines at provider which could not get registered as Kubernetes nodes. With cluster-api as a
generic out-of-tree provider for autoscaler, this field is required by autoscaler to be
able to have a provider view of the list of machines. Another list of nodes is queried from the k8s apiserver
and then a comparison is done to find out unregistered machines and are marked for delete.
This field will be set by the actuators and consumed by higher level entities like autoscaler that will
be interfacing with cluster-api as generic provider.
MaxLength: 512
MinLength: 1
Optional: {}
failureDomain stringfailureDomain is the failure domain the machine will be created in.
Must match the name of a FailureDomain from the Cluster status.
MaxLength: 256
MinLength: 1
Optional: {}
minReadySeconds integerminReadySeconds is the minimum number of seconds for which a Machine should be ready before considering it available.
Defaults to 0 (Machine will be considered available as soon as the Machine is ready)
Minimum: 0
Optional: {}
readinessGates MachineReadinessGate arrayreadinessGates specifies additional conditions to include when evaluating Machine Ready condition.
This field can be used e.g. by Cluster API control plane providers to extend the semantic of the
Ready condition for the Machine they control, like the kubeadm control provider adding ReadinessGates
for the APIServerPodHealthy, SchedulerPodHealthy conditions, etc.
Another example are external controllers, e.g. responsible to install special software/hardware on the Machines;
they can include the status of those components with a new condition and add this condition to ReadinessGates.
NOTE: In case readinessGates conditions start with the APIServer, ControllerManager, Scheduler prefix, and all those
readiness gates condition are reporting the same message, when computing the Machine’s Ready condition those
readinessGates will be replaced by a single entry reporting “Control plane components: “ + message.
This helps to improve readability of conditions bubbling up to the Machine’s owner resource / to the Cluster).
MaxItems: 32
MinItems: 1
Optional: {}
deletion MachineDeletionSpecdeletion contains configuration options for Machine deletion.MinProperties: 1
Optional: {}
taints MachineTaint arraytaints are the node taints that Cluster API will manage.
This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes,
e.g. the node controller might add the node.kubernetes.io/not-ready taint.
Only those taints defined in this list will be added or removed by core Cluster API controllers.
There can be at most 64 taints.
A pod would have to tolerate all existing taints to run on the corresponding node.
NOTE: This list is implemented as a “map” type, meaning that individual elements can be managed by different owners.
MaxItems: 64
MinItems: 1
Optional: {}

MachineStatus

MachineStatus defines the observed state of Machine.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a Machine’s current state.
Known condition types are Available, Ready, UpToDate, BootstrapConfigReady, InfrastructureReady, NodeReady,
NodeHealthy, Updating, Deleting, Paused.
If a MachineHealthCheck is targeting this machine, also HealthCheckSucceeded, OwnerRemediated conditions are added.
Additionally control plane Machines controlled by KubeadmControlPlane will have following additional conditions:
APIServerPodHealthy, ControllerManagerPodHealthy, SchedulerPodHealthy, EtcdPodHealthy, EtcdMemberHealthy, NodeKubeadmLabelsAndTaintsSet.
MaxItems: 32
Optional: {}
initialization MachineInitializationStatusinitialization provides observations of the Machine initialization process.
NOTE: Fields in this struct are part of the Cluster API contract and are used to orchestrate initial Machine provisioning.
MinProperties: 1
Optional: {}
nodeRef MachineNodeReferencenodeRef will point to the corresponding Node if it exists.Optional: {}
nodeInfo NodeSystemInfonodeInfo is a set of ids/uuids to uniquely identify the node.
More info: https://kubernetes.io/docs/concepts/nodes/node/#info
Optional: {}
addresses MachineAddressesaddresses is a list of addresses assigned to the machine.
This field is copied from the infrastructure provider reference.
MaxItems: 256
Optional: {}
failureDomain stringfailureDomain is the failure domain where the Machine has been scheduled.MaxLength: 256
MinLength: 1
Optional: {}
phase stringphase represents the current phase of machine actuation.Enum: [Pending Provisioning Provisioned Running Updating Deleting Deleted Failed Unknown]
Optional: {}
observedGeneration integerobservedGeneration is the latest generation observed by the controller.Minimum: 1
Optional: {}
deletion MachineDeletionStatusdeletion contains information relating to removal of the Machine.
Only present when the Machine has a deletionTimestamp and drain or wait for volume detach started.
Optional: {}
deprecated MachineDeprecatedStatusdeprecated groups all the status fields that are deprecated and will be removed when all the nested field are removed.Optional: {}

MachineTaint

MachineTaint defines a taint equivalent to corev1.Taint, but additionally having a propagation field.

Appears in:

FieldDescriptionDefaultValidation
key stringkey is the taint key to be applied to a node.
Must be a valid qualified name of maximum size 63 characters
with an optional subdomain prefix of maximum size 253 characters,
separated by a /.
MaxLength: 317
MinLength: 1
Pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/)?([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$
Required: {}
value stringvalue is the taint value corresponding to the taint key.
It must be a valid label value of maximum size 63 characters.
MaxLength: 63
MinLength: 1
Pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$
Optional: {}
effect TaintEffecteffect is the effect for the taint. Valid values are NoSchedule, PreferNoSchedule and NoExecute.Enum: [NoSchedule PreferNoSchedule NoExecute]
Required: {}
propagation MachineTaintPropagationpropagation defines how this taint should be propagated to nodes.
Valid values are ‘Always’ and ‘OnInitialization’.
Always: The taint will be continuously reconciled. If it is not set for a node, it will be added during reconciliation.
OnInitialization: The taint will be added during node initialization. If it gets removed from the node later on it will not get added again.
Enum: [Always OnInitialization]
Required: {}

MachineTaintPropagation

Underlying type: string

MachineTaintPropagation defines when a taint should be propagated to nodes.

Validation:

  • Enum: [Always OnInitialization]

Appears in:

FieldDescription
AlwaysMachineTaintPropagationAlways means the taint should be continuously reconciled and kept on the node.
- If an Always taint is added to the Machine, the taint will be added to the node.
- If an Always taint is removed from the Machine, the taint will be removed from the node.
- If an OnInitialization taint is changed to Always, the Machine controller will ensure the taint is set on the node.
- If an Always taint is removed from the node, it will be re-added during reconciliation.
OnInitializationMachineTaintPropagationOnInitialization means the taint should be set once during initialization and then
left alone.
- If an OnInitialization taint is added to the Machine, the taint will only be added to the node on initialization.
- If an OnInitialization taint is removed from the Machine nothing will be changed on the node.
- If an Always taint is changed to OnInitialization, the taint will only be added to the node on initialization.
- If an OnInitialization taint is removed from the node, it will not be re-added during reconciliation.

MachineTemplateSpec

MachineTemplateSpec describes the data needed to create a Machine from a template.

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
spec MachineSpecspec is the specification of the desired behavior of the machine.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
Required: {}

MachineV1Beta1DeprecatedStatus

MachineV1Beta1DeprecatedStatus groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Conditionsconditions defines current service state of the Machine.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
failureReason MachineStatusErrorfailureReason will be set in the event that there is a terminal problem
reconciling the Machine and will contain a succinct value suitable
for machine interpretation.
This field should not be set for transitive errors that a controller
faces that are expected to be fixed automatically over
time (like service outages), but instead indicate that something is
fundamentally wrong with the Machine’s spec or the configuration of
the controller, and that manual intervention is required. Examples
of terminal errors would be invalid combinations of settings in the
spec, values that are unsupported by the controller, or the
responsible controller itself being critically misconfigured.
Any transient errors that occur during the reconciliation of Machines
can be added as events to the Machine object and/or logged in the
controller’s output.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
failureMessage stringfailureMessage will be set in the event that there is a terminal problem
reconciling the Machine and will contain a more verbose string suitable
for logging and human consumption.
This field should not be set for transitive errors that a controller
faces that are expected to be fixed automatically over
time (like service outages), but instead indicate that something is
fundamentally wrong with the Machine’s spec or the configuration of
the controller, and that manual intervention is required. Examples
of terminal errors would be invalid combinations of settings in the
spec, values that are unsupported by the controller, or the
responsible controller itself being critically misconfigured.
Any transient errors that occur during the reconciliation of Machines
can be added as events to the Machine object and/or logged in the
controller’s output.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
MaxLength: 10240
MinLength: 1
Optional: {}

NetworkRanges

NetworkRanges represents ranges of network addresses.

Appears in:

FieldDescriptionDefaultValidation
cidrBlocks string arraycidrBlocks is a list of CIDR blocks.MaxItems: 100
MinItems: 1
items:MaxLength: 43
items:MinLength: 1
Required: {}

ObjectMeta

ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create. This is a copy of customizable fields from metav1.ObjectMeta.

ObjectMeta is embedded in Machine.Spec, MachineDeployment.Template and MachineSet.Template, which are not top-level Kubernetes objects. Given that metav1.ObjectMeta has lots of special cases and read-only fields which end up in the generated CRD validation, having it as a subset simplifies the API and some issues that can impact user experience.

During the upgrade to controller-tools@v2 for v1alpha2, we noticed a failure would occur running Cluster API test suite against the new CRDs, specifically spec.metadata.creationTimestamp in body must be of type string: "null". The investigation showed that controller-tools@v2 behaves differently than its previous version when handling types from metav1 package.

In more details, we found that embedded (non-top level) types that embedded metav1.ObjectMeta had validation properties, including for creationTimestamp (metav1.Time). The metav1.Time type specifies a custom json marshaller that, when IsZero() is true, returns null which breaks validation because the field isn’t marked as nullable.

In future versions, controller-tools@v2 might allow overriding the type and validation for embedded types. When that happens, this hack should be revisited.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
labels object (keys:string, values:string)labels is a map of string keys and values that can be used to organize and categorize
(scope and select) objects. May match selectors of replication controllers
and services.
More info: http://kubernetes.io/docs/user-guide/labels
Optional: {}
annotations object (keys:string, values:string)annotations is an unstructured key value map stored with a resource that may be
set by external tools to store and retrieve arbitrary metadata. They are not
queryable and should be preserved when modifying objects.
More info: http://kubernetes.io/docs/user-guide/annotations
Optional: {}

PatchDefinition

PatchDefinition defines a patch which is applied to customize the referenced templates.

Appears in:

FieldDescriptionDefaultValidation
selector PatchSelectorselector defines on which templates the patch should be applied.Required: {}
jsonPatches JSONPatch arrayjsonPatches defines the patches which should be applied on the templates
matching the selector.
Note: Patches will be applied in the order of the array.
MaxItems: 100
MinItems: 1
Required: {}

PatchSelector

PatchSelector defines on which templates the patch should be applied. Note: Matching on APIVersion and Kind is mandatory, to enforce that the patches are written for the correct version. The version of the references in the ClusterClass may be automatically updated during reconciliation if there is a newer version for the same contract. Note: The results of selection based on the individual fields are ANDed.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringapiVersion filters templates by apiVersion.
apiVersion must be fully qualified domain name followed by / and a version.
MaxLength: 317
MinLength: 1
Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[a-z]([-a-z0-9]*[a-z0-9])?$
Required: {}
kind stringkind filters templates by kind.
kind must consist of alphanumeric characters or ‘-’, start with an alphabetic character, and end with an alphanumeric character.
MaxLength: 63
MinLength: 1
Pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
Required: {}
matchResources PatchSelectorMatchmatchResources selects templates based on where they are referenced.MinProperties: 1
Required: {}

PatchSelectorMatch

PatchSelectorMatch selects templates based on where they are referenced. Note: The selector must match at least one template. Note: The results of selection based on the individual fields are ORed.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
controlPlane booleancontrolPlane selects templates referenced in .spec.ControlPlane.
Note: this will match the controlPlane and also the controlPlane
machineInfrastructure (depending on the kind and apiVersion).
Optional: {}
infrastructureCluster booleaninfrastructureCluster selects templates referenced in .spec.infrastructure.Optional: {}
machineDeploymentClass PatchSelectorMatchMachineDeploymentClassmachineDeploymentClass selects templates referenced in specific MachineDeploymentClasses in
.spec.workers.machineDeployments.
Optional: {}
machinePoolClass PatchSelectorMatchMachinePoolClassmachinePoolClass selects templates referenced in specific MachinePoolClasses in
.spec.workers.machinePools.
Optional: {}

PatchSelectorMatchMachineDeploymentClass

PatchSelectorMatchMachineDeploymentClass selects templates referenced in specific MachineDeploymentClasses in .spec.workers.machineDeployments.

Appears in:

FieldDescriptionDefaultValidation
names string arraynames selects templates by class names.MaxItems: 100
items:MaxLength: 256
items:MinLength: 1
Optional: {}

PatchSelectorMatchMachinePoolClass

PatchSelectorMatchMachinePoolClass selects templates referenced in specific MachinePoolClasses in .spec.workers.machinePools.

Appears in:

FieldDescriptionDefaultValidation
names string arraynames selects templates by class names.MaxItems: 100
items:MaxLength: 256
items:MinLength: 1
Optional: {}

StatusUpgradePlanVersion

StatusUpgradePlanVersion groups upgrade plan version-related status information.

Appears in:

FieldDescriptionDefaultValidation
version stringversion is the Kubernetes version.MaxLength: 256
MinLength: 1
Required: {}

StatusVersion

StatusVersion groups version-related status information.

Appears in:

FieldDescriptionDefaultValidation
version stringversion is the Kubernetes version.MaxLength: 256
MinLength: 1
Required: {}
replicas integerreplicas is the number of replicas at this version.Minimum: 1
Optional: {}

Topology

Topology encapsulates the information of the managed resources.

Appears in:

FieldDescriptionDefaultValidation
classRef ClusterClassRefclassRef is the ref to the ClusterClass that should be used for the topology.Required: {}
version stringversion is the Kubernetes version of the cluster.MaxLength: 256
MinLength: 1
Required: {}
controlPlane ControlPlaneTopologycontrolPlane describes the cluster control plane.MinProperties: 1
Optional: {}
workers WorkersTopologyworkers encapsulates the different constructs that form the worker nodes
for the cluster.
MinProperties: 1
Optional: {}
variables ClusterVariable arrayvariables can be used to customize the Cluster through
patches. They must comply to the corresponding
VariableClasses defined in the ClusterClass.
MaxItems: 1000
MinItems: 1
Optional: {}

UnhealthyMachineCondition

UnhealthyMachineCondition represents a Machine condition type and value with a timeout specified as a duration. When the named condition has been in the given status for at least the timeout value, a machine is considered unhealthy.

Appears in:

FieldDescriptionDefaultValidation
type stringtype of Machine conditionMaxLength: 316
MinLength: 1
Pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
Required: {}
status ConditionStatusstatus of the condition, one of True, False, Unknown.Enum: [True False Unknown]
Required: {}
timeoutSeconds integertimeoutSeconds is the duration that a machine must be in a given status for,
after which the machine is considered unhealthy.
For example, with a value of “3600”, the machine must match the status
for at least 1 hour before being considered unhealthy.
Minimum: 0
Required: {}

UnhealthyNodeCondition

UnhealthyNodeCondition represents a Node condition type and value with a timeout specified as a duration. When the named condition has been in the given status for at least the timeout value, a node is considered unhealthy.

Appears in:

FieldDescriptionDefaultValidation
type NodeConditionTypetype of Node conditionMinLength: 1
Type: string
Required: {}
status ConditionStatusstatus of the condition, one of True, False, Unknown.MinLength: 1
Type: string
Required: {}
timeoutSeconds integertimeoutSeconds is the duration that a node must be in a given status for,
after which the node is considered unhealthy.
For example, with a value of “3600”, the node must match the status
for at least 1 hour before being considered unhealthy.
Minimum: 0
Required: {}

VariableSchema

VariableSchema defines the schema of a variable.

Appears in:

FieldDescriptionDefaultValidation
openAPIV3Schema JSONSchemaPropsopenAPIV3Schema defines the schema of a variable via OpenAPI v3
schema. The schema is a subset of the schema used in
Kubernetes CRDs.
MinProperties: 1
Required: {}

VariableSchemaMetadata

Underlying type: struct{Labels map[string]string “json:"labels,omitempty"”; Annotations map[string]string “json:"annotations,omitempty"”}

VariableSchemaMetadata is the metadata of a variable or a nested field within a variable. It can be used to add additional data for higher level tools.

Validation:

  • MinProperties: 1

Appears in:

WorkersClass

WorkersClass is a collection of deployment classes.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
machineDeployments MachineDeploymentClass arraymachineDeployments is a list of machine deployment classes that can be used to create
a set of worker nodes.
MaxItems: 100
MinItems: 1
Optional: {}
machinePools MachinePoolClass arraymachinePools is a list of machine pool classes that can be used to create
a set of worker nodes.
MaxItems: 100
MinItems: 1
Optional: {}

WorkersStatus

WorkersStatus groups all the observations about workers current state.

Appears in:

FieldDescriptionDefaultValidation
desiredReplicas integerdesiredReplicas is the total number of desired worker machines in this cluster.Optional: {}
replicas integerreplicas is the total number of worker machines in this cluster.
NOTE: replicas also includes machines still being provisioned or being deleted.
Optional: {}
upToDateReplicas integerupToDateReplicas is the number of up-to-date worker machines in this cluster. A machine is considered up-to-date when Machine’s UpToDate condition is true.Optional: {}
readyReplicas integerreadyReplicas is the total number of ready worker machines in this cluster. A machine is considered ready when Machine’s Ready condition is true.Optional: {}
availableReplicas integeravailableReplicas is the total number of available worker machines in this cluster. A machine is considered available when Machine’s Available condition is true.Optional: {}
versions StatusVersion arrayversions is the aggregated Kubernetes versions in cluster workers.MaxItems: 32
MinItems: 1
Optional: {}
upgradePlan StatusUpgradePlanVersion arrayupgradePlan reports the list of versions that would be applied to the worker objects (all MachineDeployments and MachinePools).
Note:
- This field is set only when the Cluster topology is managed by Cluster API and a Cluster upgrade is in progress.
- Once a version is applied to the worker objects, it is removed from the list (after a version
is applied to a worker object, it might take some time for the actual upgrade to complete)
- During a chained upgrade, the upgrade plan is continuously re-computed, and this field will
report only the last known upgrade plan.
MaxItems: 32
MinItems: 1
Optional: {}

WorkersTopology

WorkersTopology represents the different sets of worker nodes in the cluster.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
machineDeployments MachineDeploymentTopology arraymachineDeployments is a list of machine deployments in the cluster.MaxItems: 2000
MinItems: 1
Optional: {}
machinePools MachinePoolTopology arraymachinePools is a list of machine pools in the cluster.MaxItems: 2000
MinItems: 1
Optional: {}

controlplane.cluster.x-k8s.io/v1beta2

Package v1beta2 contains API Schema definitions for the kubeadm v1beta2 API group.

Resource Types

KubeadmControlPlane

KubeadmControlPlane is the Schema for the KubeadmControlPlane API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringcontrolplane.cluster.x-k8s.io/v1beta2
kind stringKubeadmControlPlane
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
spec KubeadmControlPlaneSpecspec is the desired state of KubeadmControlPlane.Required: {}
status KubeadmControlPlaneStatusstatus is the observed state of KubeadmControlPlane.MinProperties: 1
Optional: {}

KubeadmControlPlaneDeprecatedStatus

KubeadmControlPlaneDeprecatedStatus groups all the status fields that are deprecated and will be removed in a future version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
v1beta1 KubeadmControlPlaneV1Beta1DeprecatedStatusv1beta1 groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped.Optional: {}

KubeadmControlPlaneInitializationStatus

KubeadmControlPlaneInitializationStatus provides observations of the KubeadmControlPlane initialization process.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
controlPlaneInitialized booleancontrolPlaneInitialized is true when the KubeadmControlPlane provider reports that the Kubernetes control plane is initialized;
A control plane is considered initialized when it can accept requests, no matter if this happens before
the control plane is fully provisioned or not.
NOTE: this field is part of the Cluster API contract, and it is used to orchestrate initial Machine provisioning.
Optional: {}

KubeadmControlPlaneList

KubeadmControlPlaneList contains a list of KubeadmControlPlane.

FieldDescriptionDefaultValidation
apiVersion stringcontrolplane.cluster.x-k8s.io/v1beta2
kind stringKubeadmControlPlaneList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items KubeadmControlPlane arrayitems is the list of KubeadmControlPlanes.

KubeadmControlPlaneMachineTemplate

KubeadmControlPlaneMachineTemplate defines the template for Machines in a KubeadmControlPlane object.

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
spec KubeadmControlPlaneMachineTemplateSpecspec defines the spec for Machines
in a KubeadmControlPlane object.
Required: {}

KubeadmControlPlaneMachineTemplateDeletionSpec

KubeadmControlPlaneMachineTemplateDeletionSpec contains configuration options for Machine deletion.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
nodeDrainTimeoutSeconds integernodeDrainTimeoutSeconds is the total amount of time that the controller will spend on draining a controlplane node
The default value is 0, meaning that the node can be drained without any time limitations.
NOTE: nodeDrainTimeoutSeconds is different from kubectl drain --timeout
Minimum: 0
Optional: {}
nodeVolumeDetachTimeoutSeconds integernodeVolumeDetachTimeoutSeconds is the total amount of time that the controller will spend on waiting for all volumes
to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
Minimum: 0
Optional: {}
nodeDeletionTimeoutSeconds integernodeDeletionTimeoutSeconds defines how long the machine controller will attempt to delete the Node that the Machine
hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely.
If no value is provided, the default value for this property of the Machine resource will be used.
Minimum: 0
Optional: {}

KubeadmControlPlaneMachineTemplateSpec

KubeadmControlPlaneMachineTemplateSpec defines the spec for Machines in a KubeadmControlPlane object.

Appears in:

FieldDescriptionDefaultValidation
infrastructureRef ContractVersionedObjectReferenceinfrastructureRef is a required reference to a custom resource
offered by an infrastructure provider.
Required: {}
readinessGates MachineReadinessGate arrayreadinessGates specifies additional conditions to include when evaluating Machine Ready condition;
KubeadmControlPlane will always add readinessGates for the condition it is setting on the Machine:
NodeKubeadmLabelsAndTaintsSet, APIServerPodHealthy, SchedulerPodHealthy, ControllerManagerPodHealthy, and if etcd is managed by CKP also
EtcdPodHealthy, EtcdMemberHealthy.
This field can be used e.g. to instruct the machine controller to include in the computation for Machine’s ready
computation a condition, managed by an external controllers, reporting the status of special software/hardware installed on the Machine.
MaxItems: 32
MinItems: 1
Optional: {}
deletion KubeadmControlPlaneMachineTemplateDeletionSpecdeletion contains configuration options for Machine deletion.MinProperties: 1
Optional: {}
taints MachineTaint arraytaints are the node taints that Cluster API will manage.
This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes,
e.g. the node controller might add the node.kubernetes.io/not-ready taint.
Only those taints defined in this list will be added or removed by core Cluster API controllers.
There can be at most 64 taints.
A pod would have to tolerate all existing taints to run on the corresponding node.
NOTE: This list is implemented as a “map” type, meaning that individual elements can be managed by different owners.
MaxItems: 64
MinItems: 1
Optional: {}

KubeadmControlPlaneRemediationSpec

KubeadmControlPlaneRemediationSpec controls how unhealthy control plane Machines are remediated.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
maxRetry integermaxRetry is the Max number of retries while attempting to remediate an unhealthy machine.
A retry happens when a machine that was created as a replacement for an unhealthy machine also fails.
For example, given a control plane with three machines M1, M2, M3:
M1 become unhealthy; remediation happens, and M1-1 is created as a replacement.
If M1-1 (replacement of M1) has problems while bootstrapping it will become unhealthy, and then be
remediated; such operation is considered a retry, remediation-retry #1.
If M1-2 (replacement of M1-1) becomes unhealthy, remediation-retry #2 will happen, etc.
A retry could happen only after retryPeriodSeconds from the previous retry.
If a machine is marked as unhealthy after minHealthyPeriodSeconds from the previous remediation expired,
this is not considered a retry anymore because the new issue is assumed unrelated from the previous one.
If not set, the remedation will be retried infinitely.
Optional: {}
retryPeriodSeconds integerretryPeriodSeconds is the duration that KCP should wait before remediating a machine being created as a replacement
for an unhealthy machine (a retry).
If not set, a retry will happen immediately.
Minimum: 0
Optional: {}
minHealthyPeriodSeconds integerminHealthyPeriodSeconds defines the duration after which KCP will consider any failure to a machine unrelated
from the previous one. In this case the remediation is not considered a retry anymore, and thus the retry
counter restarts from 0. For example, assuming minHealthyPeriodSeconds is set to 1h (default)
M1 become unhealthy; remediation happens, and M1-1 is created as a replacement.
If M1-1 (replacement of M1) has problems within the 1hr after the creation, also
this machine will be remediated and this operation is considered a retry - a problem related
to the original issue happened to M1 -.
If instead the problem on M1-1 is happening after minHealthyPeriodSeconds expired, e.g. four days after
m1-1 has been created as a remediation of M1, the problem on M1-1 is considered unrelated to
the original issue happened to M1.
If not set, this value is defaulted to 1h.
Minimum: 0
Optional: {}

KubeadmControlPlaneRolloutBeforeSpec

KubeadmControlPlaneRolloutBeforeSpec describes when a rollout should be performed on the KCP machines.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
certificatesExpiryDays integercertificatesExpiryDays indicates a rollout needs to be performed if the
certificates of the machine will expire within the specified days.
The minimum for this field is 7.
Minimum: 7
Optional: {}

KubeadmControlPlaneRolloutSpec

KubeadmControlPlaneRolloutSpec allows you to configure the behaviour of rolling updates to the control plane Machines. It allows you to require that all Machines are replaced before or after a certain time, and allows you to define the strategy used during rolling replacements.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
before KubeadmControlPlaneRolloutBeforeSpecbefore is a field to indicate a rollout should be performed
if the specified criteria is met.
MinProperties: 1
Optional: {}
strategy KubeadmControlPlaneRolloutStrategystrategy specifies how to roll out control plane Machines.MinProperties: 1
Optional: {}

KubeadmControlPlaneRolloutStrategy

KubeadmControlPlaneRolloutStrategy describes how to replace existing machines with new ones.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
type KubeadmControlPlaneRolloutStrategyTypetype of rollout. Currently the only supported strategy is
“RollingUpdate”.
Default is RollingUpdate.
Enum: [RollingUpdate]
Required: {}
rollingUpdate KubeadmControlPlaneRolloutStrategyRollingUpdaterollingUpdate is the rolling update config params. Present only if
type = RollingUpdate.
MinProperties: 1
Optional: {}

KubeadmControlPlaneRolloutStrategyRollingUpdate

KubeadmControlPlaneRolloutStrategyRollingUpdate is used to control the desired behavior of rolling update.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
maxSurge IntOrStringmaxSurge is the maximum number of control planes that can be scheduled above or under the
desired number of control planes.
Value can be an absolute number 1 or 0.
Defaults to 1.
Example: when this is set to 1, the control plane can be scaled
up immediately when the rolling update starts.
Optional: {}

KubeadmControlPlaneRolloutStrategyType

Underlying type: string

KubeadmControlPlaneRolloutStrategyType defines the rollout strategies for a KubeadmControlPlane.

Validation:

  • Enum: [RollingUpdate]

Appears in:

FieldDescription
RollingUpdateRollingUpdateStrategyType replaces the old control planes by new one using rolling update
i.e. gradually scale up or down the old control planes and scale up or down the new one.

KubeadmControlPlaneSpec

KubeadmControlPlaneSpec defines the desired state of KubeadmControlPlane.

Appears in:

FieldDescriptionDefaultValidation
replicas integerreplicas is the number of desired machines. Defaults to 1. When stacked etcd is used only
odd numbers are permitted, as per etcd best practice.
This is a pointer to distinguish between explicit zero and not specified.
Optional: {}
version stringversion defines the desired Kubernetes version.MaxLength: 256
MinLength: 1
Required: {}
machineTemplate KubeadmControlPlaneMachineTemplatemachineTemplate contains information about how machines
should be shaped when creating or updating a control plane.
Required: {}
kubeadmConfigSpec KubeadmConfigSpeckubeadmConfigSpec is a KubeadmConfigSpec
to use for initializing and joining machines to the control plane.
MinProperties: 1
Optional: {}
rollout KubeadmControlPlaneRolloutSpecrollout allows you to configure the behaviour of rolling updates to the control plane Machines.
It allows you to require that all Machines are replaced before or after a certain time,
and allows you to define the strategy used during rolling replacements.
MinProperties: 1
Optional: {}
remediation KubeadmControlPlaneRemediationSpecremediation controls how unhealthy Machines are remediated.MinProperties: 1
Optional: {}
machineNaming MachineNamingSpecmachineNaming allows changing the naming pattern used when creating Machines.
InfraMachines & KubeadmConfigs will use the same name as the corresponding Machines.
MinProperties: 1
Optional: {}

KubeadmControlPlaneStatus

KubeadmControlPlaneStatus defines the observed state of KubeadmControlPlane.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a KubeadmControlPlane’s current state.
Known condition types are Available, CertificatesAvailable, EtcdClusterAvailable, MachinesReady, MachinesUpToDate,
ScalingUp, ScalingDown, Remediating, Deleting, Paused.
MaxItems: 32
Optional: {}
initialization KubeadmControlPlaneInitializationStatusinitialization provides observations of the KubeadmControlPlane initialization process.
NOTE: Fields in this struct are part of the Cluster API contract and are used to orchestrate initial Machine provisioning.
MinProperties: 1
Optional: {}
selector stringselector is the label selector in string format to avoid introspection
by clients, and is used to provide the CRD-based integration for the
scale subresource and additional integrations for things like kubectl
describe.. The string will be in the same format as the query-param syntax.
More info about label selectors: http://kubernetes.io/docs/user-guide/labels#label-selectors
MaxLength: 4096
MinLength: 1
Optional: {}
replicas integerreplicas is the total number of non-terminated machines targeted by this control plane
(their labels match the selector).
Optional: {}
readyReplicas integerreadyReplicas is the number of ready replicas for this KubeadmControlPlane. A machine is considered ready when Machine’s Ready condition is true.Optional: {}
availableReplicas integeravailableReplicas is the number of available replicas targeted by this KubeadmControlPlane. A machine is considered available when Machine’s Available condition is true.Optional: {}
upToDateReplicas integerupToDateReplicas is the number of up-to-date replicas targeted by this KubeadmControlPlane. A machine is considered up-to-date when Machine’s UpToDate condition is true.Optional: {}
versions StatusVersion arrayversions is the aggregated Kubernetes versions in this KubeadmControlPlane.MaxItems: 100
MinItems: 1
Optional: {}
version stringversion represents the minimum Kubernetes version for the control plane machines
in the cluster.
Deprecated: This field is deprecated and is going to be removed in a future API version. Please use status.versions instead.
MaxLength: 256
MinLength: 1
Optional: {}
observedGeneration integerobservedGeneration is the latest generation observed by the controller.Minimum: 1
Optional: {}
lastRemediation LastRemediationStatuslastRemediation stores info about last remediation performed.Optional: {}
deprecated KubeadmControlPlaneDeprecatedStatusdeprecated groups all the status fields that are deprecated and will be removed when all the nested field are removed.Optional: {}

KubeadmControlPlaneTemplate

KubeadmControlPlaneTemplate is the Schema for the kubeadmcontrolplanetemplates API. NOTE: This CRD can only be used if the ClusterTopology feature gate is enabled.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringcontrolplane.cluster.x-k8s.io/v1beta2
kind stringKubeadmControlPlaneTemplate
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
spec KubeadmControlPlaneTemplateSpecspec is the desired state of KubeadmControlPlaneTemplate.Optional: {}

KubeadmControlPlaneTemplateList

KubeadmControlPlaneTemplateList contains a list of KubeadmControlPlaneTemplate.

FieldDescriptionDefaultValidation
apiVersion stringcontrolplane.cluster.x-k8s.io/v1beta2
kind stringKubeadmControlPlaneTemplateList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items KubeadmControlPlaneTemplate arrayitems is the list of KubeadmControlPlaneTemplates.

KubeadmControlPlaneTemplateMachineTemplate

KubeadmControlPlaneTemplateMachineTemplate defines the template for Machines in a KubeadmControlPlaneTemplate object. NOTE: KubeadmControlPlaneTemplateMachineTemplate is similar to KubeadmControlPlaneMachineTemplate but omits ObjectMeta and InfrastructureRef fields. These fields do not make sense on the KubeadmControlPlaneTemplate, because they are calculated by the Cluster topology reconciler during reconciliation and thus cannot be configured on the KubeadmControlPlaneTemplate.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
spec KubeadmControlPlaneTemplateMachineTemplateSpecspec defines the spec for Machines
in a KubeadmControlPlane object.
MinProperties: 1
Optional: {}

KubeadmControlPlaneTemplateMachineTemplateDeletionSpec

KubeadmControlPlaneTemplateMachineTemplateDeletionSpec contains configuration options for Machine deletion.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
nodeDrainTimeoutSeconds integernodeDrainTimeoutSeconds is the total amount of time that the controller will spend on draining a controlplane node
The default value is 0, meaning that the node can be drained without any time limitations.
NOTE: nodeDrainTimeoutSeconds is different from kubectl drain --timeout
Minimum: 0
Optional: {}
nodeVolumeDetachTimeoutSeconds integernodeVolumeDetachTimeoutSeconds is the total amount of time that the controller will spend on waiting for all volumes
to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
Minimum: 0
Optional: {}
nodeDeletionTimeoutSeconds integernodeDeletionTimeoutSeconds defines how long the machine controller will attempt to delete the Node that the Machine
hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely.
If no value is provided, the default value for this property of the Machine resource will be used.
Minimum: 0
Optional: {}

KubeadmControlPlaneTemplateMachineTemplateSpec

KubeadmControlPlaneTemplateMachineTemplateSpec defines the spec for Machines in a KubeadmControlPlane object.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
deletion KubeadmControlPlaneTemplateMachineTemplateDeletionSpecdeletion contains configuration options for Machine deletion.MinProperties: 1
Optional: {}
taints MachineTaint arraytaints are the node taints that Cluster API will manage.
This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes,
e.g. the node controller might add the node.kubernetes.io/not-ready taint.
Only those taints defined in this list will be added or removed by core Cluster API controllers.
There can be at most 64 taints.
A pod would have to tolerate all existing taints to run on the corresponding node.
NOTE: This list is implemented as a “map” type, meaning that individual elements can be managed by different owners.
MaxItems: 64
MinItems: 1
Optional: {}

KubeadmControlPlaneTemplateResource

KubeadmControlPlaneTemplateResource describes the data needed to create a KubeadmControlPlane from a template.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
spec KubeadmControlPlaneTemplateResourceSpecspec is the desired state of KubeadmControlPlaneTemplateResource.MinProperties: 1
Optional: {}

KubeadmControlPlaneTemplateResourceSpec

KubeadmControlPlaneTemplateResourceSpec defines the desired state of KubeadmControlPlane. NOTE: KubeadmControlPlaneTemplateResourceSpec is similar to KubeadmControlPlaneSpec but omits Replicas and Version fields. These fields do not make sense on the KubeadmControlPlaneTemplate, because they are calculated by the Cluster topology reconciler during reconciliation and thus cannot be configured on the KubeadmControlPlaneTemplate.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
machineTemplate KubeadmControlPlaneTemplateMachineTemplatemachineTemplate contains information about how machines
should be shaped when creating or updating a control plane.
MinProperties: 1
Optional: {}
kubeadmConfigSpec KubeadmConfigSpeckubeadmConfigSpec is a KubeadmConfigSpec
to use for initializing and joining machines to the control plane.
MinProperties: 1
Optional: {}
rollout KubeadmControlPlaneRolloutSpecrollout allows you to configure the behaviour of rolling updates to the control plane Machines.
It allows you to require that all Machines are replaced before or after a certain time,
and allows you to define the strategy used during rolling replacements.
MinProperties: 1
Optional: {}
remediation KubeadmControlPlaneRemediationSpecremediation controls how unhealthy Machines are remediated.MinProperties: 1
Optional: {}
machineNaming MachineNamingSpecmachineNaming allows changing the naming pattern used when creating Machines.
InfraMachines & KubeadmConfigs will use the same name as the corresponding Machines.
MinProperties: 1
Optional: {}

KubeadmControlPlaneTemplateSpec

KubeadmControlPlaneTemplateSpec defines the desired state of KubeadmControlPlaneTemplate.

Appears in:

FieldDescriptionDefaultValidation
template KubeadmControlPlaneTemplateResourcetemplate defines the desired state of KubeadmControlPlaneTemplate.MinProperties: 1
Required: {}

KubeadmControlPlaneV1Beta1DeprecatedStatus

KubeadmControlPlaneV1Beta1DeprecatedStatus groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Conditionsconditions defines current service state of the KubeadmControlPlane.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
failureReason KubeadmControlPlaneStatusErrorfailureReason indicates that there is a terminal problem reconciling the
state, and will be set to a token value suitable for
programmatic interpretation.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
failureMessage stringfailureMessage indicates that there is a terminal problem reconciling the
state, and will be set to a descriptive error message.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
MaxLength: 10240
MinLength: 1
Optional: {}
updatedReplicas integerupdatedReplicas is the total number of non-terminated machines targeted by this control plane
that have the desired template spec.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
readyReplicas integerreadyReplicas is the total number of fully running and ready control plane machines.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
unavailableReplicas integerunavailableReplicas is the total number of unavailable machines targeted by this control plane.
This is the total number of machines that are still required for
the deployment to have 100% available capacity. They may either
be machines that are running but not yet ready or machines
that still have not been created.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}

LastRemediationStatus

LastRemediationStatus stores info about last remediation performed. NOTE: if for any reason information about last remediation are lost, RetryCount is going to restart from 0 and thus more remediations than expected might happen.

Appears in:

FieldDescriptionDefaultValidation
machine stringmachine is the machine name of the latest machine being remediated.MaxLength: 253
MinLength: 1
Required: {}
retryCount integerretryCount used to keep track of remediation retry for the last remediated machine.
A retry happens when a machine that was created as a replacement for an unhealthy machine also fails.
Minimum: 0
Required: {}

MachineNamingSpec

MachineNamingSpec allows changing the naming pattern used when creating Machines. InfraMachines & KubeadmConfigs will use the same name as the corresponding Machines.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
template stringtemplate defines the template to use for generating the names of the Machine objects.
If not defined, it will fallback to \{\{ .kubeadmControlPlane.name \}\}-\{\{ .random \}\}.
If the generated name string exceeds 63 characters, it will be trimmed to 58 characters and will
get concatenated with a random suffix of length 5.
Length of the template string must not exceed 256 characters.
The template allows the following variables .cluster.name, .kubeadmControlPlane.name and .random.
The variable .cluster.name retrieves the name of the cluster object that owns the Machines being created.
The variable .kubeadmControlPlane.name retrieves the name of the KubeadmControlPlane object that owns the Machines being created.
The variable .random is substituted with random alphanumeric string, without vowels, of length 5. This variable is required
part of the template. If not provided, validation will fail.
MaxLength: 256
MinLength: 1
Optional: {}

ipam.cluster.x-k8s.io/v1beta2

Package v1beta2 contains API Schema definitions for the v1beta2 IPAM API.

Resource Types

IPAddress

IPAddress is the Schema for the ipaddress API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringipam.cluster.x-k8s.io/v1beta2
kind stringIPAddress
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
spec IPAddressSpecspec is the desired state of IPAddress.Required: {}

IPAddressClaim

IPAddressClaim is the Schema for the ipaddressclaim API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringipam.cluster.x-k8s.io/v1beta2
kind stringIPAddressClaim
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
spec IPAddressClaimSpecspec is the desired state of IPAddressClaim.Required: {}
status IPAddressClaimStatusstatus is the observed state of IPAddressClaim.MinProperties: 1
Optional: {}

IPAddressClaimDeprecatedStatus

IPAddressClaimDeprecatedStatus groups all the status fields that are deprecated and will be removed in a future version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
v1beta1 IPAddressClaimV1Beta1DeprecatedStatusv1beta1 groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped.Optional: {}

IPAddressClaimList

IPAddressClaimList is a list of IPAddressClaims.

FieldDescriptionDefaultValidation
apiVersion stringipam.cluster.x-k8s.io/v1beta2
kind stringIPAddressClaimList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items IPAddressClaim arrayitems is the list of IPAddressClaims.

IPAddressClaimReference

IPAddressClaimReference is a reference to an IPAddressClaim.

Appears in:

FieldDescriptionDefaultValidation
name stringname of the IPAddressClaim.
name must consist of lower case alphanumeric characters, ‘-’ or ‘.’, and must start and end with an alphanumeric character.
MaxLength: 253
MinLength: 1
Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
Required: {}

IPAddressClaimSpec

IPAddressClaimSpec is the desired state of an IPAddressClaim.

Appears in:

FieldDescriptionDefaultValidation
clusterName stringclusterName is the name of the Cluster this object belongs to.MaxLength: 63
MinLength: 1
Optional: {}
poolRef IPPoolReferencepoolRef is a reference to the pool from which an IP address should be created.Required: {}

IPAddressClaimStatus

IPAddressClaimStatus is the observed status of a IPAddressClaim.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a IPAddressClaim’s current state.
Known condition types are Ready.
MaxItems: 32
Optional: {}
addressRef IPAddressReferenceaddressRef is a reference to the address that was created for this claim.Optional: {}
deprecated IPAddressClaimDeprecatedStatusdeprecated groups all the status fields that are deprecated and will be removed when all the nested field are removed.Optional: {}

IPAddressClaimV1Beta1DeprecatedStatus

IPAddressClaimV1Beta1DeprecatedStatus groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Conditionsconditions summarises the current state of the IPAddressClaim
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}

IPAddressList

IPAddressList is a list of IPAddress.

FieldDescriptionDefaultValidation
apiVersion stringipam.cluster.x-k8s.io/v1beta2
kind stringIPAddressList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items IPAddress arrayitems is the list of IPAddresses.

IPAddressReference

IPAddressReference is a reference to an IPAddress.

Appears in:

FieldDescriptionDefaultValidation
name stringname of the IPAddress.
name must consist of lower case alphanumeric characters, ‘-’ or ‘.’, and must start and end with an alphanumeric character.
MaxLength: 253
MinLength: 1
Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
Required: {}

IPAddressSpec

IPAddressSpec is the desired state of an IPAddress.

Appears in:

FieldDescriptionDefaultValidation
claimRef IPAddressClaimReferenceclaimRef is a reference to the claim this IPAddress was created for.Required: {}
poolRef IPPoolReferencepoolRef is a reference to the pool that this IPAddress was created from.Required: {}
address stringaddress is the IP address.MaxLength: 39
MinLength: 1
Required: {}
prefix integerprefix is the prefix of the address.Maximum: 128
Minimum: 0
Required: {}
gateway stringgateway is the network gateway of the network the address is from.MaxLength: 39
MinLength: 1
Optional: {}

IPPoolReference

IPPoolReference is a reference to an IPPool.

Appears in:

FieldDescriptionDefaultValidation
name stringname of the IPPool.
name must consist of lower case alphanumeric characters, ‘-’ or ‘.’, and must start and end with an alphanumeric character.
MaxLength: 253
MinLength: 1
Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
Required: {}
kind stringkind of the IPPool.
kind must consist of alphanumeric characters or ‘-’, start with an alphabetic character, and end with an alphanumeric character.
MaxLength: 63
MinLength: 1
Pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
Required: {}
apiGroup stringapiGroup of the IPPool.
apiGroup must be fully qualified domain name.
MaxLength: 253
MinLength: 1
Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
Required: {}

runtime.cluster.x-k8s.io/v1beta2

Package v1beta2 contains the v1beta2 implementation of ExtensionConfig.

Resource Types

ClientConfig

ClientConfig contains the information to make a client connection with an Extension server.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
url stringurl gives the location of the Extension server, in standard URL form
(scheme://host:port/path).
Note: Exactly one of url or service must be specified.
The scheme must be “https”.
The host should not refer to a service running in the cluster; use
the service field instead.
A path is optional, and if present may be any string permissible in
a URL. If a path is set it will be used as prefix to the hook-specific path.
Attempting to use a user or basic auth e.g. “user:password@” is not
allowed. Fragments (“#…”) and query parameters (“?…”) are not
allowed either.
MaxLength: 512
MinLength: 1
Optional: {}
service ServiceReferenceservice is a reference to the Kubernetes service for the Extension server.
Note: Exactly one of url or service must be specified.
If the Extension server is running within a cluster, then you should use service.
Optional: {}
caBundle integer arraycaBundle is a PEM encoded CA bundle which will be used to validate the Extension server’s server certificate.MaxLength: 51200
MinLength: 1
Optional: {}

ExtensionConfig

ExtensionConfig is the Schema for the ExtensionConfig API. NOTE: This CRD can only be used if the RuntimeSDK feature gate is enabled.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringruntime.cluster.x-k8s.io/v1beta2
kind stringExtensionConfig
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.MinProperties: 1
Optional: {}
spec ExtensionConfigSpecspec is the desired state of the ExtensionConfig.Required: {}
status ExtensionConfigStatusstatus is the current state of the ExtensionConfigMinProperties: 1
Optional: {}

ExtensionConfigDeprecatedStatus

ExtensionConfigDeprecatedStatus groups all the status fields that are deprecated and will be removed in a future version.

Appears in:

FieldDescriptionDefaultValidation
v1beta1 ExtensionConfigV1Beta1DeprecatedStatusv1beta1 groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}

ExtensionConfigList

ExtensionConfigList contains a list of ExtensionConfig.

FieldDescriptionDefaultValidation
apiVersion stringruntime.cluster.x-k8s.io/v1beta2
kind stringExtensionConfigList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items ExtensionConfig arrayitems is the list of ExtensionConfigs.

ExtensionConfigSpec

ExtensionConfigSpec defines the desired state of ExtensionConfig.

Appears in:

FieldDescriptionDefaultValidation
clientConfig ClientConfigclientConfig defines how to communicate with the Extension server.MinProperties: 1
Required: {}
namespaceSelector LabelSelectornamespaceSelector decides whether to call the hook for an object based
on whether the namespace for that object matches the selector.
Defaults to the empty LabelSelector, which matches all objects.
Optional: {}
settings object (keys:string, values:string)settings defines key value pairs to be passed to all calls
to all supported RuntimeExtensions.
Note: Settings can be overridden on the ClusterClass.
Optional: {}

ExtensionConfigStatus

ExtensionConfigStatus defines the observed state of ExtensionConfig.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a ExtensionConfig’s current state.
Known condition types are Discovered, Paused.
MaxItems: 32
Optional: {}
handlers ExtensionHandler arrayhandlers defines the current ExtensionHandlers supported by an Extension.MaxItems: 512
Optional: {}
deprecated ExtensionConfigDeprecatedStatusdeprecated groups all the status fields that are deprecated and will be removed when all the nested field are removed.Optional: {}

ExtensionConfigV1Beta1DeprecatedStatus

ExtensionConfigV1Beta1DeprecatedStatus groups all the status fields that are deprecated and will be removed when support for v1beta1 will be dropped. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Conditionsconditions defines current service state of the ExtensionConfig.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}

ExtensionHandler

ExtensionHandler specifies the details of a handler for a particular runtime hook registered by an Extension server.

Appears in:

FieldDescriptionDefaultValidation
name stringname is the unique name of the ExtensionHandler.MaxLength: 512
MinLength: 1
Required: {}
requestHook GroupVersionHookrequestHook defines the versioned runtime hook which this ExtensionHandler serves.Required: {}
timeoutSeconds integertimeoutSeconds defines the timeout duration for client calls to the ExtensionHandler.
Defaults to 10 if not set.
Minimum: 1
Optional: {}
failurePolicy FailurePolicyfailurePolicy defines how failures in calls to the ExtensionHandler should be handled by a client.
Defaults to Fail if not set.
Enum: [Ignore Fail]
Optional: {}

FailurePolicy

Underlying type: string

FailurePolicy specifies how unrecognized errors when calling the ExtensionHandler are handled. FailurePolicy helps with extensions not working consistently, e.g. due to an intermittent network issue. The following type of errors are never ignored by FailurePolicy Ignore:

  • Misconfigurations (e.g. incompatible types)
  • Extension explicitly returns a Status Failure.

Validation:

  • Enum: [Ignore Fail]

Appears in:

FieldDescription
IgnoreFailurePolicyIgnore means that an error when calling the extension is ignored.
FailFailurePolicyFail means that an error when calling the extension is propagated as an error.

GroupVersionHook

GroupVersionHook defines the runtime hook when the ExtensionHandler is called.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringapiVersion is the group and version of the Hook.MaxLength: 512
MinLength: 1
Required: {}
hook stringhook is the name of the hook.MaxLength: 256
MinLength: 1
Required: {}

ServiceReference

ServiceReference holds a reference to a Kubernetes Service of an Extension server.

Appears in:

FieldDescriptionDefaultValidation
namespace stringnamespace is the namespace of the service.MaxLength: 63
MinLength: 1
Required: {}
name stringname is the name of the service.MaxLength: 63
MinLength: 1
Required: {}
path stringpath is an optional URL path and if present may be any string permissible in
a URL. If a path is set it will be used as prefix to the hook-specific path.
MaxLength: 512
MinLength: 1
Optional: {}
port integerport is the port on the service that’s hosting the Extension server.
Defaults to 443.
Port should be a valid port number (1-65535, inclusive).
Optional: {}

This page documents deprecated API packages. For current types, see CRD API Reference (v1beta2).

API Reference

Packages

addons.cluster.x-k8s.io/v1beta1

Package v1beta1 contains API Schema definitions for the addons v1beta1 API group

Deprecated: This package is deprecated and is going to be removed when support for v1beta1 will be dropped.

Resource Types

ClusterResourceSet

ClusterResourceSet is the Schema for the clusterresourcesets API. For advanced use cases an add-on provider should be used instead.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringaddons.cluster.x-k8s.io/v1beta1
kind stringClusterResourceSet
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
spec ClusterResourceSetSpecspec is the desired state of ClusterResourceSet.Optional: {}
status ClusterResourceSetStatusstatus is the observed state of ClusterResourceSet.Optional: {}

ClusterResourceSetBinding

ClusterResourceSetBinding lists all matching ClusterResourceSets with the cluster it belongs to.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringaddons.cluster.x-k8s.io/v1beta1
kind stringClusterResourceSetBinding
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
spec ClusterResourceSetBindingSpecspec is the desired state of ClusterResourceSetBinding.Optional: {}

ClusterResourceSetBindingList

ClusterResourceSetBindingList contains a list of ClusterResourceSetBinding.

FieldDescriptionDefaultValidation
apiVersion stringaddons.cluster.x-k8s.io/v1beta1
kind stringClusterResourceSetBindingList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items ClusterResourceSetBinding arrayitems is the list of ClusterResourceSetBindings.

ClusterResourceSetBindingSpec

ClusterResourceSetBindingSpec defines the desired state of ClusterResourceSetBinding.

Appears in:

FieldDescriptionDefaultValidation
bindings ResourceSetBinding arraybindings is a list of ClusterResourceSets and their resources.MaxItems: 100
Optional: {}
clusterName stringclusterName is the name of the Cluster this binding applies to.
Note: this field mandatory in v1beta2.
MaxLength: 63
MinLength: 1
Optional: {}

ClusterResourceSetList

ClusterResourceSetList contains a list of ClusterResourceSet.

FieldDescriptionDefaultValidation
apiVersion stringaddons.cluster.x-k8s.io/v1beta1
kind stringClusterResourceSetList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items ClusterResourceSet arrayitems is the list of ClusterResourceSets.

ClusterResourceSetSpec

ClusterResourceSetSpec defines the desired state of ClusterResourceSet.

Appears in:

FieldDescriptionDefaultValidation
clusterSelector LabelSelectorclusterSelector is the label selector for Clusters. The Clusters that are
selected by this will be the ones affected by this ClusterResourceSet.
It must match the Cluster labels. This field is immutable.
Label selector cannot be empty.
Required: {}
resources ResourceRef arrayresources is a list of Secrets/ConfigMaps where each contains 1 or more resources to be applied to remote clusters.MaxItems: 100
Optional: {}
strategy stringstrategy is the strategy to be used during applying resources. Defaults to ApplyOnce. This field is immutable.Enum: [ApplyOnce Reconcile]
Optional: {}

ClusterResourceSetStatus

ClusterResourceSetStatus defines the observed state of ClusterResourceSet.

Appears in:

FieldDescriptionDefaultValidation
observedGeneration integerobservedGeneration reflects the generation of the most recently observed ClusterResourceSet.Optional: {}
conditions Conditionsconditions defines current state of the ClusterResourceSet.Optional: {}
v1beta2 ClusterResourceSetV1Beta2Statusv1beta2 groups all the fields that will be added or modified in ClusterResourceSet’s status with the V1Beta2 version.Optional: {}

ClusterResourceSetV1Beta2Status

ClusterResourceSetV1Beta2Status groups all the fields that will be added or modified in ClusterResourceSet with the V1Beta2 version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a ClusterResourceSet’s current state.
Known condition types are ResourceSetApplied, Deleting.
MaxItems: 32
Optional: {}

ResourceBinding

ResourceBinding shows the status of a resource that belongs to a ClusterResourceSet matched by the owner cluster of the ClusterResourceSetBinding object.

Appears in:

FieldDescriptionDefaultValidation
name stringname of the resource that is in the same namespace with ClusterResourceSet object.MaxLength: 253
MinLength: 1
Required: {}
kind stringkind of the resource. Supported kinds are: Secrets and ConfigMaps.Enum: [Secret ConfigMap]
Required: {}
hash stringhash is the hash of a resource’s data. This can be used to decide if a resource is changed.
For “ApplyOnce” ClusterResourceSet.spec.strategy, this is no-op as that strategy does not act on change.
MaxLength: 256
MinLength: 1
Optional: {}
applied booleanapplied is to track if a resource is applied to the cluster or not.Required: {}

ResourceRef

ResourceRef specifies a resource.

Appears in:

FieldDescriptionDefaultValidation
name stringname of the resource that is in the same namespace with ClusterResourceSet object.MaxLength: 253
MinLength: 1
Required: {}
kind stringkind of the resource. Supported kinds are: Secrets and ConfigMaps.Enum: [Secret ConfigMap]
Required: {}

ResourceSetBinding

ResourceSetBinding keeps info on all of the resources in a ClusterResourceSet.

Appears in:

FieldDescriptionDefaultValidation
clusterResourceSetName stringclusterResourceSetName is the name of the ClusterResourceSet that is applied to the owner cluster of the binding.MaxLength: 253
MinLength: 1
Required: {}
resources ResourceBinding arrayresources is a list of resources that the ClusterResourceSet has.MaxItems: 100
Optional: {}

bootstrap.cluster.x-k8s.io/v1beta1

Package v1beta1 contains API Schema definitions for the kubeadm v1beta1 API group.

Deprecated: This package is deprecated and is going to be removed when support for v1beta1 will be dropped.

Resource Types

APIEndpoint

APIEndpoint struct contains elements of API server instance deployed on a node.

Appears in:

FieldDescriptionDefaultValidation
advertiseAddress stringadvertiseAddress sets the IP address for the API server to advertise.MaxLength: 39
MinLength: 1
Optional: {}
bindPort integerbindPort sets the secure port for the API Server to bind to.
Defaults to 6443.
Optional: {}

APIServer

APIServer holds settings necessary for API server deployments in the cluster.

Appears in:

FieldDescriptionDefaultValidation
extraArgs object (keys:string, values:string)extraArgs is an extra set of flags to pass to the control plane component.Optional: {}
extraVolumes HostPathMount arrayextraVolumes is an extra set of host volumes, mounted to the control plane component.MaxItems: 100
Optional: {}
extraEnvs EnvVar arrayextraEnvs is an extra set of environment variables to pass to the control plane component.
Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default.
This option takes effect only on Kubernetes >=1.31.0.
MaxItems: 100
Optional: {}
certSANs string arraycertSANs sets extra Subject Alternative Names for the API Server signing cert.MaxItems: 100
items:MaxLength: 253
items:MinLength: 1
Optional: {}
timeoutForControlPlane DurationtimeoutForControlPlane controls the timeout that we use for API server to appearOptional: {}

BootstrapToken

BootstrapToken describes one bootstrap token, stored as a Secret in the cluster.

Appears in:

FieldDescriptionDefaultValidation
token BootstrapTokenStringtoken is used for establishing bidirectional trust between nodes and control-planes.
Used for joining nodes in the cluster.
Type: string
Required: {}
description stringdescription sets a human-friendly message why this token exists and what it’s used
for, so other administrators can know its purpose.
MaxLength: 512
MinLength: 1
Optional: {}
ttl Durationttl defines the time to live for this token. Defaults to 24h.
Expires and TTL are mutually exclusive.
Optional: {}
usages string arrayusages describes the ways in which this token can be used. Can by default be used
for establishing bidirectional trust, but that can be changed here.
MaxItems: 100
items:MaxLength: 256
items:MinLength: 1
Optional: {}
groups string arraygroups specifies the extra groups that this token will authenticate as when/if
used for authentication
MaxItems: 100
items:MaxLength: 256
items:MinLength: 1
Optional: {}

BootstrapTokenDiscovery

BootstrapTokenDiscovery is used to set the options for bootstrap token based discovery.

Appears in:

FieldDescriptionDefaultValidation
token stringtoken is a token used to validate cluster information
fetched from the control-plane.
MaxLength: 512
MinLength: 1
Optional: {}
apiServerEndpoint stringapiServerEndpoint is an IP or domain name to the API server from which info will be fetched.MaxLength: 512
MinLength: 1
Optional: {}
caCertHashes string arraycaCertHashes specifies a set of public key pins to verify
when token-based discovery is used. The root CA found during discovery
must match one of these values. Specifying an empty set disables root CA
pinning, which can be unsafe. Each hash is specified as “:”,
where the only currently supported type is “sha256”. This is a hex-encoded
SHA-256 hash of the Subject Public Key Info (SPKI) object in DER-encoded
ASN.1. These hashes can be calculated using, for example, OpenSSL:
openssl x509 -pubkey -in ca.crt openssl rsa -pubin -outform der 2>&/dev/null | openssl dgst -sha256 -hex
MaxItems: 100
items:MaxLength: 512
items:MinLength: 1
Optional: {}
unsafeSkipCAVerification booleanunsafeSkipCAVerification allows token-based discovery
without CA verification via CACertHashes. This can weaken
the security of kubeadm since other nodes can impersonate the control-plane.
Optional: {}

BootstrapTokenString

BootstrapTokenString is a token of the format abcdef.abcdef0123456789 that is used for both validation of the practically of the API server from a joining node’s point of view and as an authentication method for the node in the bootstrap phase of “kubeadm join”. This token is and should be short-lived.

Validation:

  • Type: string

Appears in:

ClusterConfiguration

ClusterConfiguration contains cluster-wide configuration for a kubeadm cluster.

Appears in:

FieldDescriptionDefaultValidation
etcd Etcdetcd holds configuration for etcd.
NB: This value defaults to a Local (stacked) etcd
Optional: {}
networking Networkingnetworking holds configuration for the networking topology of the cluster.
NB: This value defaults to the Cluster object spec.clusterNetwork.
Optional: {}
kubernetesVersion stringkubernetesVersion is the target version of the control plane.
NB: This value defaults to the Machine object spec.version
MaxLength: 256
MinLength: 1
Optional: {}
controlPlaneEndpoint stringcontrolPlaneEndpoint sets a stable IP address or DNS name for the control plane; it
can be a valid IP address or a RFC-1123 DNS subdomain, both with optional TCP port.
In case the ControlPlaneEndpoint is not specified, the AdvertiseAddress + BindPort
are used; in case the ControlPlaneEndpoint is specified but without a TCP port,
the BindPort is used.
Possible usages are:
e.g. In a cluster with more than one control plane instances, this field should be
assigned the address of the external load balancer in front of the
control plane instances.
e.g. in environments with enforced node recycling, the ControlPlaneEndpoint
could be used for assigning a stable DNS to the control plane.
NB: This value defaults to the first value in the Cluster object status.apiEndpoints array.
MaxLength: 512
MinLength: 1
Optional: {}
apiServer APIServerapiServer contains extra settings for the API server control plane componentOptional: {}
controllerManager ControlPlaneComponentcontrollerManager contains extra settings for the controller manager control plane componentOptional: {}
scheduler ControlPlaneComponentscheduler contains extra settings for the scheduler control plane componentOptional: {}
dns DNSdns defines the options for the DNS add-on installed in the cluster.Optional: {}
certificatesDir stringcertificatesDir specifies where to store or look for all required certificates.
NB: if not provided, this will default to /etc/kubernetes/pki
MaxLength: 512
MinLength: 1
Optional: {}
imageRepository stringimageRepository sets the container registry to pull images from.
* If not set, the default registry of kubeadm will be used, i.e.
* registry.k8s.io (new registry): >= v1.22.17, >= v1.23.15, >= v1.24.9, >= v1.25.0
* k8s.gcr.io (old registry): all older versions
Please note that when imageRepository is not set we don’t allow upgrades to
versions >= v1.22.0 which use the old registry (k8s.gcr.io). Please use
a newer patch version with the new registry instead (i.e. >= v1.22.17,
>= v1.23.15, >= v1.24.9, >= v1.25.0).
* If the version is a CI build (kubernetes version starts with ci/ or ci-cross/)
gcr.io/k8s-staging-ci-images will be used as a default for control plane components
and for kube-proxy, while registry.k8s.io will be used for all the other images.
MaxLength: 512
MinLength: 1
Optional: {}
featureGates object (keys:string, values:boolean)featureGates enabled by the user.Optional: {}
certificateValidityPeriodDays integercertificateValidityPeriodDays specifies the validity period for non-CA certificates generated by kubeadm.
If not specified, kubeadm will use a default of 365 days (1 year).
This field is only supported with Kubernetes v1.31 or above.
Maximum: 1095
Minimum: 1
Optional: {}
caCertificateValidityPeriodDays integercaCertificateValidityPeriodDays specifies the validity period for CA certificates generated by Cluster API.
If not specified, Cluster API will use a default of 3650 days (10 years).
This field cannot be modified.
Maximum: 36500
Minimum: 1
Optional: {}
encryptionAlgorithm EncryptionAlgorithmTypeencryptionAlgorithm holds the type of asymmetric encryption algorithm used for keys and certificates.
Can be one of “RSA-2048”, “RSA-3072”, “RSA-4096”, “ECDSA-P256” or “ECDSA-P384”.
For Kubernetes 1.34 or above, “ECDSA-P384” is supported.
If not specified, Cluster API will use RSA-2048 as default.
When this field is modified every certificate generated afterward will use the new
encryptionAlgorithm. Existing CA certificates and service account keys are not rotated.
This field is only supported with Kubernetes v1.31 or above.
Enum: [ECDSA-P256 ECDSA-P384 RSA-2048 RSA-3072 RSA-4096]
Optional: {}
clusterName stringclusterName is the cluster nameMaxLength: 63
MinLength: 1
Optional: {}

ContainerLinuxConfig

ContainerLinuxConfig contains CLC-specific configuration.

We use a structured type here to allow adding additional fields, for example ‘version’.

Appears in:

FieldDescriptionDefaultValidation
additionalConfig stringadditionalConfig contains additional configuration to be merged with the Ignition
configuration generated by the bootstrapper controller. More info: https://coreos.github.io/ignition/operator-notes/#config-merging
The data format is documented here: https://kinvolk.io/docs/flatcar-container-linux/latest/provisioning/cl-config/
MaxLength: 32768
MinLength: 1
Optional: {}
strict booleanstrict controls if AdditionalConfig should be strictly parsed. If so, warnings are treated as errors.Optional: {}

ControlPlaneComponent

ControlPlaneComponent holds settings common to control plane component of the cluster.

Appears in:

FieldDescriptionDefaultValidation
extraArgs object (keys:string, values:string)extraArgs is an extra set of flags to pass to the control plane component.Optional: {}
extraVolumes HostPathMount arrayextraVolumes is an extra set of host volumes, mounted to the control plane component.MaxItems: 100
Optional: {}
extraEnvs EnvVar arrayextraEnvs is an extra set of environment variables to pass to the control plane component.
Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default.
This option takes effect only on Kubernetes >=1.31.0.
MaxItems: 100
Optional: {}

DNS

DNS defines the DNS addon that should be used in the cluster.

Appears in:

FieldDescriptionDefaultValidation
imageRepository stringimageRepository sets the container registry to pull images from.
if not set, the ImageRepository defined in ClusterConfiguration will be used instead.
MaxLength: 512
MinLength: 1
Optional: {}
imageTag stringimageTag allows to specify a tag for the image.
In case this value is set, kubeadm does not change automatically the version of the above components during upgrades.
MaxLength: 256
MinLength: 1
Optional: {}

Discovery

Discovery specifies the options for the kubelet to use during the TLS Bootstrap process.

Appears in:

FieldDescriptionDefaultValidation
bootstrapToken BootstrapTokenDiscoverybootstrapToken is used to set the options for bootstrap token based discovery
BootstrapToken and File are mutually exclusive
Optional: {}
file FileDiscoveryfile is used to specify a file or URL to a kubeconfig file from which to load cluster information
BootstrapToken and File are mutually exclusive
Optional: {}
tlsBootstrapToken stringtlsBootstrapToken is a token used for TLS bootstrapping.
If .BootstrapToken is set, this field is defaulted to .BootstrapToken.Token, but can be overridden.
If .File is set, this field must be set in case the KubeConfigFile does not contain any other authentication information
MaxLength: 512
MinLength: 1
Optional: {}
timeout Durationtimeout modifies the discovery timeoutOptional: {}

DiskSetup

DiskSetup defines input for generated disk_setup and fs_setup in cloud-init.

Appears in:

FieldDescriptionDefaultValidation
partitions Partition arraypartitions specifies the list of the partitions to setup.MaxItems: 100
Optional: {}
filesystems Filesystem arrayfilesystems specifies the list of file systems to setup.MaxItems: 100
Optional: {}

Encoding

Underlying type: string

Encoding specifies the cloud-init file encoding.

Validation:

  • Enum: [base64 gzip gzip+base64]

Appears in:

FieldDescription
base64Base64 implies the contents of the file are encoded as base64.
gzipGzip implies the contents of the file are encoded with gzip.
gzip+base64GzipBase64 implies the contents of the file are first base64 encoded and then gzip encoded.

EncryptionAlgorithmType

Underlying type: string

EncryptionAlgorithmType can define an asymmetric encryption algorithm type.

Validation:

  • Enum: [ECDSA-P256 ECDSA-P384 RSA-2048 RSA-3072 RSA-4096]

Appears in:

FieldDescription
ECDSA-P256EncryptionAlgorithmECDSAP256 defines the ECDSA encryption algorithm type with curve P256.
ECDSA-P384EncryptionAlgorithmECDSAP384 defines the ECDSA encryption algorithm type with curve P384.
RSA-2048EncryptionAlgorithmRSA2048 defines the RSA encryption algorithm type with key size 2048 bits.
RSA-3072EncryptionAlgorithmRSA3072 defines the RSA encryption algorithm type with key size 3072 bits.
RSA-4096EncryptionAlgorithmRSA4096 defines the RSA encryption algorithm type with key size 4096 bits.

EnvVar

EnvVar represents an environment variable present in a Container.

Appears in:

FieldDescriptionDefaultValidation
name stringName of the environment variable.
May consist of any printable ASCII characters except ‘=’.
value stringVariable references $(VAR_NAME) are expanded
using the previously defined environment variables in the container and
any service environment variables. If a variable cannot be resolved,
the reference in the input string will be unchanged. Double $$ are reduced
to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e.
“$$(VAR_NAME)” will produce the string literal “$(VAR_NAME)”.
Escaped references will never be expanded, regardless of whether the variable
exists or not.
Defaults to “”.
Optional: {}
valueFrom EnvVarSourceSource for the environment variable’s value. Cannot be used if value is not empty.Optional: {}

Etcd

Etcd contains elements describing Etcd configuration.

Appears in:

FieldDescriptionDefaultValidation
local LocalEtcdlocal provides configuration knobs for configuring the local etcd instance
Local and External are mutually exclusive
Optional: {}
external ExternalEtcdexternal describes how to connect to an external etcd cluster
Local and External are mutually exclusive
Optional: {}

ExternalEtcd

ExternalEtcd describes an external etcd cluster. Kubeadm has no knowledge of where certificate files live and they must be supplied.

Appears in:

FieldDescriptionDefaultValidation
endpoints string arrayendpoints of etcd members. Required for ExternalEtcd.MaxItems: 50
items:MaxLength: 512
items:MinLength: 1
Required: {}
caFile stringcaFile is an SSL Certificate Authority file used to secure etcd communication.
Required if using a TLS connection.
MaxLength: 512
MinLength: 1
Required: {}
certFile stringcertFile is an SSL certification file used to secure etcd communication.
Required if using a TLS connection.
MaxLength: 512
MinLength: 1
Required: {}
keyFile stringkeyFile is an SSL key file used to secure etcd communication.
Required if using a TLS connection.
MaxLength: 512
MinLength: 1
Required: {}

File

File defines the input for generating write_files in cloud-init.

Appears in:

FieldDescriptionDefaultValidation
path stringpath specifies the full path on disk where to store the file.MaxLength: 512
MinLength: 1
Required: {}
owner stringowner specifies the ownership of the file, e.g. “root:root”.MaxLength: 256
MinLength: 1
Optional: {}
permissions stringpermissions specifies the permissions to assign to the file, e.g. “0640”.MaxLength: 16
MinLength: 1
Optional: {}
encoding Encodingencoding specifies the encoding of the file contents.Enum: [base64 gzip gzip+base64]
Optional: {}
append booleanappend specifies whether to append Content to existing file if Path exists.Optional: {}
content stringcontent is the actual content of the file.MaxLength: 10240
MinLength: 1
Optional: {}
contentFrom FileSourcecontentFrom is a referenced source of content to populate the file.Optional: {}
contentFormat FileContentFormatcontentFormat specifies how to interpret content after it is resolved (inline or from contentFrom).
When set to “Template”, content is rendered as a Go text/template.
Available template variables:
- .controlPlane.version: the Kubernetes version of the control plane (e.g. “v1.35.0”).
Only set when the cluster has a control plane reference that exposes spec.version.
When set to “Raw” or omitted, content is used verbatim.
Enum: [Raw Template]
Optional: {}

FileContentFormat

Underlying type: string

FileContentFormat specifies how file content is interpreted after resolving content/contentFrom and before writing bootstrap data.

Validation:

  • Enum: [Raw Template]

Appears in:

FieldDescription
RawFileContentFormatRaw means content is used verbatim.
TemplateFileContentFormatTemplate means content is rendered as a Go text/template.

FileDiscovery

FileDiscovery is used to specify a file or URL to a kubeconfig file from which to load cluster information.

Appears in:

FieldDescriptionDefaultValidation
kubeConfigPath stringkubeConfigPath is used to specify the actual file path or URL to the kubeconfig file from which to load cluster informationMaxLength: 512
MinLength: 1
Required: {}
kubeConfig FileDiscoveryKubeConfigkubeConfig is used (optionally) to generate a KubeConfig based on the KubeadmConfig’s information.
The file is generated at the path specified in KubeConfigPath.
Host address (server field) information is automatically populated based on the Cluster’s ControlPlaneEndpoint.
Certificate Authority (certificate-authority-data field) is gathered from the cluster’s CA secret.
Optional: {}

FileDiscoveryKubeConfig

FileDiscoveryKubeConfig contains elements describing how to generate the kubeconfig for bootstrapping.

Appears in:

FieldDescriptionDefaultValidation
cluster KubeConfigClustercluster contains information about how to communicate with the kubernetes cluster.
By default the following fields are automatically populated:
- Server with the Cluster’s ControlPlaneEndpoint.
- CertificateAuthorityData with the Cluster’s CA certificate.
Optional: {}
user KubeConfigUseruser contains information that describes identity information.
This is used to tell the kubernetes cluster who you are.
Required: {}

FileSource

FileSource is a union of all possible external source types for file data. Only one field may be populated in any given instance. Developers adding new sources of data for target systems should add them here.

Appears in:

FieldDescriptionDefaultValidation
secret SecretFileSourcesecret represents a secret that should populate this file.Required: {}

Filesystem

Filesystem defines the file systems to be created.

Appears in:

FieldDescriptionDefaultValidation
device stringdevice specifies the device nameMaxLength: 256
MinLength: 1
Required: {}
filesystem stringfilesystem specifies the file system type.MaxLength: 128
MinLength: 1
Required: {}
label stringlabel specifies the file system label to be used. If set to None, no label is used.MaxLength: 512
MinLength: 1
Optional: {}
partition stringpartition specifies the partition to use. The valid options are: “auto|any”, “auto”, “any”, “none”, and , where NUM is the actual partition number.MaxLength: 128
MinLength: 1
Optional: {}
overwrite booleanoverwrite defines whether or not to overwrite any existing filesystem.
If true, any pre-existing file system will be destroyed. Use with Caution.
Optional: {}
replaceFS stringreplaceFS is a special directive, used for Microsoft Azure that instructs cloud-init to replace a file system of <FS_TYPE>.
NOTE: unless you define a label, this requires the use of the ‘any’ partition directive.
MaxLength: 128
MinLength: 1
Optional: {}
extraOpts string arrayextraOpts defined extra options to add to the command for creating the file system.MaxItems: 100
items:MaxLength: 256
items:MinLength: 1
Optional: {}

Format

Underlying type: string

Format specifies the output format of the bootstrap data

Validation:

  • Enum: [cloud-config ignition]

Appears in:

FieldDescription
cloud-configCloudConfig make the bootstrap data to be of cloud-config format.
ignitionIgnition make the bootstrap data to be of Ignition format.

HostPathMount

HostPathMount contains elements describing volumes that are mounted from the host.

Appears in:

FieldDescriptionDefaultValidation
name stringname of the volume inside the pod template.MaxLength: 512
MinLength: 1
Required: {}
hostPath stringhostPath is the path in the host that will be mounted inside
the pod.
MaxLength: 512
MinLength: 1
Required: {}
mountPath stringmountPath is the path inside the pod where hostPath will be mounted.MaxLength: 512
MinLength: 1
Required: {}
readOnly booleanreadOnly controls write access to the volumeOptional: {}
pathType HostPathTypepathType is the type of the HostPath.Optional: {}

IgnitionSpec

IgnitionSpec contains Ignition specific configuration.

Appears in:

FieldDescriptionDefaultValidation
containerLinuxConfig ContainerLinuxConfigcontainerLinuxConfig contains CLC specific configuration.Optional: {}

ImageMeta

ImageMeta allows to customize the image used for components that are not originated from the Kubernetes/Kubernetes release process.

Appears in:

FieldDescriptionDefaultValidation
imageRepository stringimageRepository sets the container registry to pull images from.
if not set, the ImageRepository defined in ClusterConfiguration will be used instead.
MaxLength: 512
MinLength: 1
Optional: {}
imageTag stringimageTag allows to specify a tag for the image.
In case this value is set, kubeadm does not change automatically the version of the above components during upgrades.
MaxLength: 256
MinLength: 1
Optional: {}

InitConfiguration

InitConfiguration contains a list of elements that is specific “kubeadm init”-only runtime information.

Appears in:

FieldDescriptionDefaultValidation
bootstrapTokens BootstrapToken arraybootstrapTokens is respected at kubeadm init time and describes a set of Bootstrap Tokens to create.
This information IS NOT uploaded to the kubeadm cluster configmap, partly because of its sensitive nature
MaxItems: 100
Optional: {}
nodeRegistration NodeRegistrationOptionsnodeRegistration holds fields that relate to registering the new control-plane node to the cluster.
When used in the context of control plane nodes, NodeRegistration should remain consistent
across both InitConfiguration and JoinConfiguration
Optional: {}
localAPIEndpoint APIEndpointlocalAPIEndpoint represents the endpoint of the API server instance that’s deployed on this control plane node
In HA setups, this differs from ClusterConfiguration.ControlPlaneEndpoint in the sense that ControlPlaneEndpoint
is the global endpoint for the cluster, which then loadbalances the requests to each individual API server. This
configuration object lets you customize what IP/DNS name and port the local API server advertises it’s accessible
on. By default, kubeadm tries to auto-detect the IP of the default interface and use that, but in case that process
fails you may set the desired value here.
Optional: {}
skipPhases string arrayskipPhases is a list of phases to skip during command execution.
The list of phases can be obtained with the “kubeadm init –help” command.
This option takes effect only on Kubernetes >=1.22.0.
MaxItems: 50
items:MaxLength: 256
items:MinLength: 1
Optional: {}
patches Patchespatches contains options related to applying patches to components deployed by kubeadm during
“kubeadm init”. The minimum kubernetes version needed to support Patches is v1.22
Optional: {}

JoinConfiguration

JoinConfiguration contains elements describing a particular node.

Appears in:

FieldDescriptionDefaultValidation
nodeRegistration NodeRegistrationOptionsnodeRegistration holds fields that relate to registering the new control-plane node to the cluster.
When used in the context of control plane nodes, NodeRegistration should remain consistent
across both InitConfiguration and JoinConfiguration
Optional: {}
caCertPath stringcaCertPath is the path to the SSL certificate authority used to
secure comunications between node and control-plane.
Defaults to “/etc/kubernetes/pki/ca.crt”.
MaxLength: 512
MinLength: 1
Optional: {}
discovery Discoverydiscovery specifies the options for the kubelet to use during the TLS Bootstrap processOptional: {}
controlPlane JoinControlPlanecontrolPlane defines the additional control plane instance to be deployed on the joining node.
If nil, no additional control plane instance will be deployed.
Optional: {}
skipPhases string arrayskipPhases is a list of phases to skip during command execution.
The list of phases can be obtained with the “kubeadm init –help” command.
This option takes effect only on Kubernetes >=1.22.0.
MaxItems: 50
items:MaxLength: 256
items:MinLength: 1
Optional: {}
patches Patchespatches contains options related to applying patches to components deployed by kubeadm during
“kubeadm join”. The minimum kubernetes version needed to support Patches is v1.22
Optional: {}

JoinControlPlane

JoinControlPlane contains elements describing an additional control plane instance to be deployed on the joining node.

Appears in:

FieldDescriptionDefaultValidation
localAPIEndpoint APIEndpointlocalAPIEndpoint represents the endpoint of the API server instance to be deployed on this node.Optional: {}

KubeConfigAuthExec

KubeConfigAuthExec specifies a command to provide client credentials. The command is exec’d and outputs structured stdout holding credentials.

See the client.authentication.k8s.io API group for specifications of the exact input and output format.

Appears in:

FieldDescriptionDefaultValidation
command stringcommand to execute.MaxLength: 1024
MinLength: 1
Required: {}
args string arrayargs is the arguments to pass to the command when executing it.MaxItems: 100
items:MaxLength: 512
items:MinLength: 1
Optional: {}
env KubeConfigAuthExecEnv arrayenv defines additional environment variables to expose to the process. These
are unioned with the host’s environment, as well as variables client-go uses
to pass argument to the plugin.
MaxItems: 100
Optional: {}
apiVersion stringapiVersion is preferred input version of the ExecInfo. The returned ExecCredentials MUST use
the same encoding version as the input.
Defaults to client.authentication.k8s.io/v1 if not set.
MaxLength: 512
MinLength: 1
Optional: {}
provideClusterInfo booleanprovideClusterInfo determines whether or not to provide cluster information,
which could potentially contain very large CA data, to this exec plugin as a
part of the KUBERNETES_EXEC_INFO environment variable. By default, it is set
to false. Package k8s.io/client-go/tools/auth/exec provides helper methods for
reading this environment variable.
Optional: {}

KubeConfigAuthExecEnv

Underlying type: struct{Name string “json:"name"”; Value string “json:"value"”}

KubeConfigAuthExecEnv is used for setting environment variables when executing an exec-based credential plugin.

Appears in:

KubeConfigAuthProvider

KubeConfigAuthProvider holds the configuration for a specified auth provider.

Appears in:

FieldDescriptionDefaultValidation
name stringname is the name of the authentication plugin.MaxLength: 256
MinLength: 1
Required: {}
config object (keys:string, values:string)config holds the parameters for the authentication plugin.Optional: {}

KubeConfigCluster

KubeConfigCluster contains information about how to communicate with a kubernetes cluster.

Adapted from clientcmdv1.Cluster.

Appears in:

FieldDescriptionDefaultValidation
server stringserver is the address of the kubernetes cluster (https://hostname:port).
Defaults to https:// + Cluster.Spec.ControlPlaneEndpoint.
MaxLength: 512
MinLength: 1
Optional: {}
tlsServerName stringtlsServerName is used to check server certificate. If TLSServerName is empty, the hostname used to contact the server is used.MaxLength: 512
MinLength: 1
Optional: {}
insecureSkipTLSVerify booleaninsecureSkipTLSVerify skips the validity check for the server’s certificate. This will make your HTTPS connections insecure.Optional: {}
certificateAuthorityData integer arraycertificateAuthorityData contains PEM-encoded certificate authority certificates.
Defaults to the Cluster’s CA certificate if empty.
MaxLength: 51200
MinLength: 1
Optional: {}
proxyURL stringproxyURL is the URL to the proxy to be used for all requests made by this
client. URLs with “http”, “https”, and “socks5” schemes are supported. If
this configuration is not provided or the empty string, the client
attempts to construct a proxy configuration from http_proxy and
https_proxy environment variables. If these environment variables are not
set, the client does not attempt to proxy requests.
socks5 proxying does not currently support spdy streaming endpoints (exec,
attach, port forward).
MaxLength: 512
MinLength: 1
Optional: {}

KubeConfigUser

KubeConfigUser contains information that describes identity information. This is used to tell the kubernetes cluster who you are.

Either authProvider or exec must be filled.

Adapted from clientcmdv1.AuthInfo.

Appears in:

FieldDescriptionDefaultValidation
authProvider KubeConfigAuthProviderauthProvider specifies a custom authentication plugin for the kubernetes cluster.Optional: {}
exec KubeConfigAuthExecexec specifies a custom exec-based authentication plugin for the kubernetes cluster.Optional: {}

KubeadmConfig

KubeadmConfig is the Schema for the kubeadmconfigs API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringbootstrap.cluster.x-k8s.io/v1beta1
kind stringKubeadmConfig
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
spec KubeadmConfigSpecspec is the desired state of KubeadmConfig.Optional: {}
status KubeadmConfigStatusstatus is the observed state of KubeadmConfig.Optional: {}

KubeadmConfigList

KubeadmConfigList contains a list of KubeadmConfig.

FieldDescriptionDefaultValidation
apiVersion stringbootstrap.cluster.x-k8s.io/v1beta1
kind stringKubeadmConfigList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items KubeadmConfig arrayitems is the list of KubeadmConfigs.

KubeadmConfigSpec

KubeadmConfigSpec defines the desired state of KubeadmConfig. Either ClusterConfiguration and InitConfiguration should be defined or the JoinConfiguration should be defined.

Appears in:

FieldDescriptionDefaultValidation
clusterConfiguration ClusterConfigurationclusterConfiguration along with InitConfiguration are the configurations necessary for the init commandOptional: {}
initConfiguration InitConfigurationinitConfiguration along with ClusterConfiguration are the configurations necessary for the init commandOptional: {}
joinConfiguration JoinConfigurationjoinConfiguration is the kubeadm configuration for the join commandOptional: {}
files File arrayfiles specifies extra files to be passed to user_data upon creation.MaxItems: 200
Optional: {}
diskSetup DiskSetupdiskSetup specifies options for the creation of partition tables and file systems on devices.Optional: {}
mounts MountPoints arraymounts specifies a list of mount points to be setup.MaxItems: 100
items:MaxLength: 512
items:MinLength: 1
Optional: {}
bootCommands string arraybootCommands specifies extra commands to run very early in the boot process via the cloud-init bootcmd
module. bootcmd will run on every boot, ‘cloud-init-per’ command can be used to make bootcmd run exactly
once. This is typically run in the cloud-init.service systemd unit. This has no effect in Ignition.
MaxItems: 1000
items:MaxLength: 10240
items:MinLength: 1
Optional: {}
preKubeadmCommands string arraypreKubeadmCommands specifies extra commands to run before kubeadm runs.
With cloud-init, this is prepended to the runcmd module configuration, and is typically executed in
the cloud-final.service systemd unit. In Ignition, this is prepended to /etc/kubeadm.sh.
MaxItems: 1000
items:MaxLength: 10240
items:MinLength: 1
Optional: {}
postKubeadmCommands string arraypostKubeadmCommands specifies extra commands to run after kubeadm runs.
With cloud-init, this is appended to the runcmd module configuration, and is typically executed in
the cloud-final.service systemd unit. In Ignition, this is appended to /etc/kubeadm.sh.
MaxItems: 1000
items:MaxLength: 10240
items:MinLength: 1
Optional: {}
users User arrayusers specifies extra users to addMaxItems: 100
Optional: {}
ntp NTPntp specifies NTP configurationOptional: {}
format Formatformat specifies the output format of the bootstrap dataEnum: [cloud-config ignition]
Optional: {}
verbosity integerverbosity is the number for the kubeadm log level verbosity.
It overrides the --v flag in kubeadm commands.
Optional: {}
useExperimentalRetryJoin booleanuseExperimentalRetryJoin replaces a basic kubeadm command with a shell
script with retries for joins.
This is meant to be an experimental temporary workaround on some environments
where joins fail due to timing (and other issues). The long term goal is to add retries to
kubeadm proper and use that functionality.
This will add about 40KB to userdata
For more information, refer to https://github.com/kubernetes-sigs/cluster-api/pull/2763#discussion_r397306055.
Deprecated: This experimental fix is no longer needed and this field will be removed in a future release.
When removing also remove from staticcheck exclude-rules for SA1019 in golangci.yml
Optional: {}
ignition IgnitionSpecignition contains Ignition specific configuration.Optional: {}

KubeadmConfigStatus

KubeadmConfigStatus defines the observed state of KubeadmConfig.

Appears in:

FieldDescriptionDefaultValidation
ready booleanready indicates the BootstrapData field is ready to be consumedOptional: {}
dataSecretName stringdataSecretName is the name of the secret that stores the bootstrap data script.MaxLength: 253
MinLength: 1
Optional: {}
failureReason stringfailureReason will be set on non-retryable errors
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
MaxLength: 256
MinLength: 1
Optional: {}
failureMessage stringfailureMessage will be set on non-retryable errors
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
MaxLength: 10240
MinLength: 1
Optional: {}
observedGeneration integerobservedGeneration is the latest generation observed by the controller.Optional: {}
conditions Conditionsconditions defines current service state of the KubeadmConfig.Optional: {}
v1beta2 KubeadmConfigV1Beta2Statusv1beta2 groups all the fields that will be added or modified in KubeadmConfig’s status with the V1Beta2 version.Optional: {}

KubeadmConfigTemplate

KubeadmConfigTemplate is the Schema for the kubeadmconfigtemplates API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringbootstrap.cluster.x-k8s.io/v1beta1
kind stringKubeadmConfigTemplate
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
spec KubeadmConfigTemplateSpecspec is the desired state of KubeadmConfigTemplate.Optional: {}

KubeadmConfigTemplateList

KubeadmConfigTemplateList contains a list of KubeadmConfigTemplate.

FieldDescriptionDefaultValidation
apiVersion stringbootstrap.cluster.x-k8s.io/v1beta1
kind stringKubeadmConfigTemplateList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items KubeadmConfigTemplate arrayitems is the list of KubeadmConfigTemplates.

KubeadmConfigTemplateResource

KubeadmConfigTemplateResource defines the Template structure.

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
spec KubeadmConfigSpecspec is the desired state of KubeadmConfig.Optional: {}

KubeadmConfigTemplateSpec

KubeadmConfigTemplateSpec defines the desired state of KubeadmConfigTemplate.

Appears in:

FieldDescriptionDefaultValidation
template KubeadmConfigTemplateResourcetemplate defines the desired state of KubeadmConfigTemplate.Required: {}

KubeadmConfigV1Beta2Status

KubeadmConfigV1Beta2Status groups all the fields that will be added or modified in KubeadmConfig with the V1Beta2 version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a KubeadmConfig’s current state.
Known condition types are Ready, DataSecretAvailable, CertificatesAvailable.
MaxItems: 32
Optional: {}

LocalEtcd

LocalEtcd describes that kubeadm should run an etcd cluster locally.

Appears in:

FieldDescriptionDefaultValidation
imageRepository stringimageRepository sets the container registry to pull images from.
if not set, the ImageRepository defined in ClusterConfiguration will be used instead.
MaxLength: 512
MinLength: 1
Optional: {}
imageTag stringimageTag allows to specify a tag for the image.
In case this value is set, kubeadm does not change automatically the version of the above components during upgrades.
MaxLength: 256
MinLength: 1
Optional: {}
dataDir stringdataDir is the directory etcd will place its data.
Defaults to “/var/lib/etcd”.
MaxLength: 512
MinLength: 1
Optional: {}
extraArgs object (keys:string, values:string)extraArgs are extra arguments provided to the etcd binary
when run inside a static pod.
Optional: {}
extraEnvs EnvVar arrayextraEnvs is an extra set of environment variables to pass to the control plane component.
Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default.
This option takes effect only on Kubernetes >=1.31.0.
MaxItems: 100
Optional: {}
serverCertSANs string arrayserverCertSANs sets extra Subject Alternative Names for the etcd server signing cert.MaxItems: 100
items:MaxLength: 253
items:MinLength: 1
Optional: {}
peerCertSANs string arraypeerCertSANs sets extra Subject Alternative Names for the etcd peer signing cert.MaxItems: 100
items:MaxLength: 253
items:MinLength: 1
Optional: {}

MountPoints

Underlying type: string array

MountPoints defines input for generated mounts in cloud-init.

Validation:

  • items:MaxLength: 512
  • items:MinLength: 1

Appears in:

NTP

NTP defines input for generated ntp in cloud-init.

Appears in:

FieldDescriptionDefaultValidation
servers string arrayservers specifies which NTP servers to useMaxItems: 100
items:MaxLength: 512
items:MinLength: 1
Optional: {}
enabled booleanenabled specifies whether NTP should be enabledOptional: {}

Networking

Networking contains elements describing cluster’s networking configuration.

Appears in:

FieldDescriptionDefaultValidation
serviceSubnet stringserviceSubnet is the subnet used by k8s services.
Defaults to a comma-delimited string of the Cluster object’s spec.clusterNetwork.pods.cidrBlocks, or
to “10.96.0.0/12” if that’s unset.
MaxLength: 1024
MinLength: 1
Optional: {}
podSubnet stringpodSubnet is the subnet used by pods.
If unset, the API server will not allocate CIDR ranges for every node.
Defaults to a comma-delimited string of the Cluster object’s spec.clusterNetwork.services.cidrBlocks if that is set
MaxLength: 1024
MinLength: 1
Optional: {}
dnsDomain stringdnsDomain is the dns domain used by k8s services. Defaults to “cluster.local”.MaxLength: 253
MinLength: 1
Optional: {}

NodeRegistrationOptions

NodeRegistrationOptions holds fields that relate to registering a new control-plane or node to the cluster, either via “kubeadm init” or “kubeadm join”. Note: The NodeRegistrationOptions struct has to be kept in sync with the structs in MarshalJSON.

Appears in:

FieldDescriptionDefaultValidation
name stringname is the .Metadata.Name field of the Node API object that will be created in this kubeadm init or kubeadm join operation.
This field is also used in the CommonName field of the kubelet’s client certificate to the API server.
Defaults to the hostname of the node if not provided.
MaxLength: 253
MinLength: 1
Optional: {}
criSocket stringcriSocket is used to retrieve container runtime info. This information will be annotated to the Node API object, for later re-useMaxLength: 512
MinLength: 1
Optional: {}
taints Taint arraytaints specifies the taints the Node API object should be registered with. If this field is unset, i.e. nil, in the kubeadm init process
it will be defaulted to []v1.Taint{‘node-role.kubernetes.io/master=“”’}. If you don’t want to taint your control-plane node, set this field to an
empty slice, i.e. taints: [] in the YAML file. This field is solely used for Node registration.
MaxItems: 100
Optional: {}
kubeletExtraArgs object (keys:string, values:string)kubeletExtraArgs passes through extra arguments to the kubelet. The arguments here are passed to the kubelet command line via the environment file
kubeadm writes at runtime for the kubelet to source. This overrides the generic base-level configuration in the kubelet-config-1.X ConfigMap
Flags have higher priority when parsing. These values are local and specific to the node kubeadm is executing on.
Optional: {}
ignorePreflightErrors string arrayignorePreflightErrors provides a slice of pre-flight errors to be ignored when the current node is registered.MaxItems: 50
items:MaxLength: 512
items:MinLength: 1
Optional: {}
imagePullPolicy stringimagePullPolicy specifies the policy for image pulling
during kubeadm “init” and “join” operations. The value of
this field must be one of “Always”, “IfNotPresent” or
“Never”. Defaults to “IfNotPresent”. This can be used only
with Kubernetes version equal to 1.22 and later.
Enum: [Always IfNotPresent Never]
Optional: {}
imagePullSerial booleanimagePullSerial specifies if image pulling performed by kubeadm must be done serially or in parallel.
This option takes effect only on Kubernetes >=1.31.0.
Default: true (defaulted in kubeadm)
Optional: {}

Partition

Partition defines how to create and layout a partition.

Appears in:

FieldDescriptionDefaultValidation
device stringdevice is the name of the device.MaxLength: 256
MinLength: 1
Required: {}
layout booleanlayout specifies the device layout.
If it is true, a single partition will be created for the entire device.
When layout is false, it means don’t partition or ignore existing partitioning.
Required: {}
overwrite booleanoverwrite describes whether to skip checks and create the partition if a partition or filesystem is found on the device.
Use with caution. Default is ‘false’.
Optional: {}
tableType stringtableType specifies the tupe of partition table. The following are supported:
‘mbr’: default and setups a MS-DOS partition table
‘gpt’: setups a GPT partition table
Enum: [mbr gpt]
Optional: {}
diskLayout PartitionSpec arraydiskLayout specifies an ordered list of partitions, where each item defines the
percentage of disk space and optional partition type for that partition.
The sum of all partition percentages must not be greater than 100.
MaxItems: 100
MinItems: 1
Optional: {}

PartitionSpec

PartitionSpec defines the size and optional type for a partition.

Appears in:

FieldDescriptionDefaultValidation
percentage integerpercentage of disk that partition will take (1-100)Maximum: 100
Minimum: 1
Required: {}
partitionType stringpartitionType is the partition type (optional).
Supported values are Linux, LinuxSwap, LinuxRAID, LVM, Fat32, NTFS,
and LinuxExtended. These are translated to cloud-init partition type codes.
A full GPT partition GUID is also supported as a passthrough value.
MaxLength: 36
MinLength: 1
Optional: {}

PasswdSource

PasswdSource is a union of all possible external source types for passwd data. Only one field may be populated in any given instance. Developers adding new sources of data for target systems should add them here.

Appears in:

FieldDescriptionDefaultValidation
secret SecretPasswdSourcesecret represents a secret that should populate this password.Required: {}

Patches

Patches contains options related to applying patches to components deployed by kubeadm.

Appears in:

FieldDescriptionDefaultValidation
directory stringdirectory is a path to a directory that contains files named “target[suffix][+patchtype].extension”.
For example, “kube-apiserver0+merge.yaml” or just “etcd.json”. “target” can be one of
“kube-apiserver”, “kube-controller-manager”, “kube-scheduler”, “etcd”. “patchtype” can be one
of “strategic” “merge” or “json” and they match the patch formats supported by kubectl.
The default “patchtype” is “strategic”. “extension” must be either “json” or “yaml”.
“suffix” is an optional string that can be used to determine which patches are applied
first alpha-numerically.
These files can be written into the target directory via KubeadmConfig.Files which
specifies additional files to be created on the machine, either with content inline or
by referencing a secret.
MaxLength: 512
MinLength: 1
Optional: {}

SecretFileSource

SecretFileSource adapts a Secret into a FileSource.

The contents of the target Secret’s Data field will be presented as files using the keys in the Data field as the file names.

Appears in:

FieldDescriptionDefaultValidation
name stringname of the secret in the KubeadmBootstrapConfig’s namespace to use.MaxLength: 253
MinLength: 1
Required: {}
key stringkey is the key in the secret’s data map for this value.MaxLength: 256
MinLength: 1
Required: {}

SecretPasswdSource

SecretPasswdSource adapts a Secret into a PasswdSource.

The contents of the target Secret’s Data field will be presented as passwd using the keys in the Data field as the file names.

Appears in:

FieldDescriptionDefaultValidation
name stringname of the secret in the KubeadmBootstrapConfig’s namespace to use.MaxLength: 253
MinLength: 1
Required: {}
key stringkey is the key in the secret’s data map for this value.MaxLength: 256
MinLength: 1
Required: {}

User

User defines the input for a generated user in cloud-init.

Appears in:

FieldDescriptionDefaultValidation
name stringname specifies the user nameMaxLength: 256
MinLength: 1
Required: {}
gecos stringgecos specifies the gecos to use for the userMaxLength: 256
MinLength: 1
Optional: {}
groups stringgroups specifies the additional groups for the userMaxLength: 256
MinLength: 1
Optional: {}
homeDir stringhomeDir specifies the home directory to use for the userMaxLength: 256
MinLength: 1
Optional: {}
inactive booleaninactive specifies whether to mark the user as inactiveOptional: {}
shell stringshell specifies the user’s shellMaxLength: 256
MinLength: 1
Optional: {}
passwd stringpasswd specifies a hashed password for the userMaxLength: 256
MinLength: 1
Optional: {}
passwdFrom PasswdSourcepasswdFrom is a referenced source of passwd to populate the passwd.Optional: {}
primaryGroup stringprimaryGroup specifies the primary group for the userMaxLength: 256
MinLength: 1
Optional: {}
lockPassword booleanlockPassword specifies if password login should be disabledOptional: {}
sudo stringsudo specifies a sudo role for the userMaxLength: 256
MinLength: 1
Optional: {}
sshAuthorizedKeys string arraysshAuthorizedKeys specifies a list of ssh authorized keys for the userMaxItems: 100
items:MaxLength: 2048
items:MinLength: 1
Optional: {}

cluster.x-k8s.io/v1beta1

Package v1beta1 contains API Schema definitions for the cluster v1beta1 API group

Deprecated: This package is deprecated and is going to be removed when support for v1beta1 will be dropped.

Resource Types

APIEndpoint

APIEndpoint represents a reachable Kubernetes API endpoint.

Appears in:

FieldDescriptionDefaultValidation
host stringhost is the hostname on which the API server is serving.MaxLength: 512
Optional: {}
port integerport is the port on which the API server is serving.Optional: {}

Bootstrap

Bootstrap encapsulates fields to configure the Machine’s bootstrapping mechanism.

Appears in:

FieldDescriptionDefaultValidation
configRef ObjectReferenceconfigRef is a reference to a bootstrap provider-specific resource
that holds configuration details. The reference is optional to
allow users/operators to specify Bootstrap.DataSecretName without
the need of a controller.
Optional: {}
dataSecretName stringdataSecretName is the name of the secret that stores the bootstrap data script.
If nil, the Machine should remain in the Pending state.
MaxLength: 253
MinLength: 0
Optional: {}

Cluster

Cluster is the Schema for the clusters API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta1
kind stringCluster
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
spec ClusterSpecspec is the desired state of Cluster.Optional: {}
status ClusterStatusstatus is the observed state of Cluster.Optional: {}

ClusterAvailabilityGate

ClusterAvailabilityGate contains the type of a Cluster condition to be used as availability gate.

Appears in:

FieldDescriptionDefaultValidation
conditionType stringconditionType refers to a condition with matching type in the Cluster’s condition list.
If the conditions doesn’t exist, it will be treated as unknown.
Note: Both Cluster API conditions or conditions added by 3rd party controllers can be used as availability gates.
MaxLength: 316
MinLength: 1
Pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
Required: {}
polarity ConditionPolaritypolarity of the conditionType specified in this availabilityGate.
Valid values are Positive, Negative and omitted.
When omitted, the default behaviour will be Positive.
A positive polarity means that the condition should report a true status under normal conditions.
A negative polarity means that the condition should report a false status under normal conditions.
Enum: [Positive Negative]
Optional: {}

ClusterClass

ClusterClass is a template which can be used to create managed topologies.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta1
kind stringClusterClass
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
spec ClusterClassSpecspec is the desired state of ClusterClass.Optional: {}
status ClusterClassStatusstatus is the observed state of ClusterClass.Optional: {}

ClusterClassList

ClusterClassList contains a list of Cluster.

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta1
kind stringClusterClassList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items ClusterClass arrayitems is the list of ClusterClasses.

ClusterClassPatch

ClusterClassPatch defines a patch which is applied to customize the referenced templates.

Appears in:

FieldDescriptionDefaultValidation
name stringname of the patch.MaxLength: 256
MinLength: 1
Required: {}
description stringdescription is a human-readable description of this patch.MaxLength: 1024
MinLength: 1
Optional: {}
enabledIf stringenabledIf is a Go template to be used to calculate if a patch should be enabled.
It can reference variables defined in .spec.variables and builtin variables.
The patch will be enabled if the template evaluates to true, otherwise it will
be disabled.
If EnabledIf is not set, the patch will be enabled per default.
MaxLength: 256
MinLength: 1
Optional: {}
definitions PatchDefinition arraydefinitions define inline patches.
Note: Patches will be applied in the order of the array.
Note: Exactly one of Definitions or External must be set.
MaxItems: 100
Optional: {}
external ExternalPatchDefinitionexternal defines an external patch.
Note: Exactly one of Definitions or External must be set.
Optional: {}

ClusterClassSpec

ClusterClassSpec describes the desired state of the ClusterClass.

Appears in:

FieldDescriptionDefaultValidation
availabilityGates ClusterAvailabilityGate arrayavailabilityGates specifies additional conditions to include when evaluating Cluster Available condition.
NOTE: this field is considered only for computing v1beta2 conditions.
NOTE: If a Cluster is using this ClusterClass, and this Cluster defines a custom list of availabilityGates,
such list overrides availabilityGates defined in this field.
MaxItems: 32
Optional: {}
infrastructure LocalObjectTemplateinfrastructure is a reference to a provider-specific template that holds
the details for provisioning infrastructure specific cluster
for the underlying provider.
The underlying provider is responsible for the implementation
of the template to an infrastructure cluster.
Optional: {}
infrastructureNamingStrategy InfrastructureNamingStrategyinfrastructureNamingStrategy allows changing the naming pattern used when creating the infrastructure object.Optional: {}
controlPlane ControlPlaneClasscontrolPlane is a reference to a local struct that holds the details
for provisioning the Control Plane for the Cluster.
Optional: {}
workers WorkersClassworkers describes the worker nodes for the cluster.
It is a collection of node types which can be used to create
the worker nodes of the cluster.
Optional: {}
variables ClusterClassVariable arrayvariables defines the variables which can be configured
in the Cluster topology and are then used in patches.
MaxItems: 1000
Optional: {}
patches ClusterClassPatch arraypatches defines the patches which are applied to customize
referenced templates of a ClusterClass.
Note: Patches will be applied in the order of the array.
MaxItems: 1000
Optional: {}
upgrade ClusterClassUpgradeupgrade defines the upgrade configuration for clusters using this ClusterClass.MinProperties: 1
Optional: {}
kubernetesVersions string arraykubernetesVersions is the list of Kubernetes versions that can be
used for clusters using this ClusterClass.
The list of version must be ordered from the older to the newer version, and there should be
at least one version for every minor in between the first and the last version.
MaxItems: 100
MinItems: 1
items:MaxLength: 256
items:MinLength: 1
Optional: {}

ClusterClassStatus

ClusterClassStatus defines the observed state of the ClusterClass.

Appears in:

FieldDescriptionDefaultValidation
variables ClusterClassStatusVariable arrayvariables is a list of ClusterClassStatusVariable that are defined for the ClusterClass.MaxItems: 1000
Optional: {}
conditions Conditionsconditions defines current observed state of the ClusterClass.Optional: {}
observedGeneration integerobservedGeneration is the latest generation observed by the controller.Optional: {}
v1beta2 ClusterClassV1Beta2Statusv1beta2 groups all the fields that will be added or modified in ClusterClass’s status with the V1Beta2 version.Optional: {}

ClusterClassStatusVariable

ClusterClassStatusVariable defines a variable which appears in the status of a ClusterClass.

Appears in:

FieldDescriptionDefaultValidation
name stringname is the name of the variable.MaxLength: 256
MinLength: 1
Required: {}
definitionsConflict booleandefinitionsConflict specifies whether or not there are conflicting definitions for a single variable name.Optional: {}
definitions ClusterClassStatusVariableDefinition arraydefinitions is a list of definitions for a variable.MaxItems: 100
Required: {}

ClusterClassStatusVariableDefinition

ClusterClassStatusVariableDefinition defines a variable which appears in the status of a ClusterClass.

Appears in:

FieldDescriptionDefaultValidation
from stringfrom specifies the origin of the variable definition.
This will be inline for variables defined in the ClusterClass or the name of a patch defined in the ClusterClass
for variables discovered from a DiscoverVariables runtime extensions.
MaxLength: 256
MinLength: 1
Required: {}
required booleanrequired specifies if the variable is required.
Note: this applies to the variable as a whole and thus the
top-level object defined in the schema. If nested fields are
required, this will be specified inside the schema.
Required: {}
metadata ClusterClassVariableMetadataRefer to Kubernetes API documentation for fields of metadata.Optional: {}
schema VariableSchemaschema defines the schema of the variable.Required: {}

ClusterClassUpgrade

ClusterClassUpgrade defines the upgrade configuration for clusters using the ClusterClass.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
external ClusterClassUpgradeExternalexternal defines external runtime extensions for upgrade operations.MinProperties: 1
Optional: {}

ClusterClassUpgradeExternal

ClusterClassUpgradeExternal defines external runtime extensions for upgrade operations.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
generateUpgradePlanExtension stringgenerateUpgradePlanExtension references an extension which is called to generate upgrade plan.MaxLength: 512
MinLength: 1
Optional: {}

ClusterClassV1Beta2Status

ClusterClassV1Beta2Status groups all the fields that will be added or modified in ClusterClass with the V1Beta2 version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a ClusterClass’s current state.
Known condition types are VariablesReady, RefVersionsUpToDate, Paused.
MaxItems: 32
Optional: {}

ClusterClassVariable

ClusterClassVariable defines a variable which can be configured in the Cluster topology and used in patches.

Appears in:

FieldDescriptionDefaultValidation
name stringname of the variable.MaxLength: 256
MinLength: 1
Required: {}
required booleanrequired specifies if the variable is required.
Note: this applies to the variable as a whole and thus the
top-level object defined in the schema. If nested fields are
required, this will be specified inside the schema.
Required: {}
metadata ClusterClassVariableMetadataRefer to Kubernetes API documentation for fields of metadata.Optional: {}
schema VariableSchemaschema defines the schema of the variable.Required: {}

ClusterClassVariableMetadata

ClusterClassVariableMetadata is the metadata of a variable. It can be used to add additional data for higher level tools to a ClusterClassVariable.

Deprecated: This struct is deprecated and is going to be removed in the next apiVersion.

Appears in:

FieldDescriptionDefaultValidation
labels object (keys:string, values:string)labels is a map of string keys and values that can be used to organize and categorize
(scope and select) variables.
Optional: {}
annotations object (keys:string, values:string)annotations is an unstructured key value map that can be used to store and
retrieve arbitrary metadata.
They are not queryable.
Optional: {}

ClusterControlPlaneStatus

ClusterControlPlaneStatus groups all the observations about control plane current state.

Appears in:

FieldDescriptionDefaultValidation
desiredReplicas integerdesiredReplicas is the total number of desired control plane machines in this cluster.Optional: {}
replicas integerreplicas is the total number of control plane machines in this cluster.
NOTE: replicas also includes machines still being provisioned or being deleted.
Optional: {}
upToDateReplicas integerupToDateReplicas is the number of up-to-date control plane machines in this cluster. A machine is considered up-to-date when Machine’s UpToDate condition is true.Optional: {}
readyReplicas integerreadyReplicas is the total number of ready control plane machines in this cluster. A machine is considered ready when Machine’s Ready condition is true.Optional: {}
availableReplicas integeravailableReplicas is the total number of available control plane machines in this cluster. A machine is considered available when Machine’s Available condition is true.Optional: {}
versions StatusVersion arrayversions is the aggregated Kubernetes versions in this control plane.MaxItems: 32
MinItems: 1
Optional: {}
upgradePlan StatusUpgradePlanVersion arrayupgradePlan reports the list of versions that would be applied to the control plane object according to the upgrade plan.
Note:
- This field is set only when the Cluster topology is managed by Cluster API and a Cluster upgrade is in progress.
- Once a version is applied to the control plane object, it is removed from the list (after a version
is applied to a control plane object, it might take some time for the actual upgrade to complete)
- During a chained upgrade, the upgrade plan is continuously re-computed, and this field will
report only the last known upgrade plan.
MaxItems: 32
MinItems: 1
Optional: {}

ClusterList

ClusterList contains a list of Cluster.

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta1
kind stringClusterList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items Cluster arrayitems is the list of Clusters.

ClusterNetwork

ClusterNetwork specifies the different networking parameters for a cluster.

Appears in:

FieldDescriptionDefaultValidation
apiServerPort integerapiServerPort specifies the port the API Server should bind to.
Defaults to 6443.
Optional: {}
services NetworkRangesservices is the network ranges from which service VIPs are allocated.Optional: {}
pods NetworkRangespods is the network ranges from which Pod networks are allocated.Optional: {}
serviceDomain stringserviceDomain is the domain name for services.MaxLength: 253
MinLength: 1
Optional: {}

ClusterSpec

ClusterSpec defines the desired state of Cluster.

Appears in:

FieldDescriptionDefaultValidation
paused booleanpaused can be used to prevent controllers from processing the Cluster and all its associated objects.Optional: {}
clusterNetwork ClusterNetworkclusterNetwork represents the cluster network configuration.Optional: {}
controlPlaneEndpoint APIEndpointcontrolPlaneEndpoint represents the endpoint used to communicate with the control plane.Optional: {}
controlPlaneRef ObjectReferencecontrolPlaneRef is an optional reference to a provider-specific resource that holds
the details for provisioning the Control Plane for a Cluster.
Optional: {}
infrastructureRef ObjectReferenceinfrastructureRef is a reference to a provider-specific resource that holds the details
for provisioning infrastructure for a cluster in said provider.
Optional: {}
topology Topologytopology encapsulates the topology for the cluster.
NOTE: It is required to enable the ClusterTopology
feature gate flag to activate managed topologies support.
Optional: {}
availabilityGates ClusterAvailabilityGate arrayavailabilityGates specifies additional conditions to include when evaluating Cluster Available condition.
If this field is not defined and the Cluster implements a managed topology, availabilityGates
from the corresponding ClusterClass will be used, if any.
NOTE: this field is considered only for computing v1beta2 conditions.
MaxItems: 32
Optional: {}

ClusterStatus

ClusterStatus defines the observed state of Cluster.

Appears in:

FieldDescriptionDefaultValidation
failureDomains FailureDomainsfailureDomains is a slice of failure domain objects synced from the infrastructure provider.Optional: {}
failureReason ClusterStatusErrorfailureReason indicates that there is a fatal problem reconciling the
state, and will be set to a token value suitable for
programmatic interpretation.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
failureMessage stringfailureMessage indicates that there is a fatal problem reconciling the
state, and will be set to a descriptive error message.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
MaxLength: 10240
MinLength: 1
Optional: {}
phase stringphase represents the current phase of cluster actuation.Enum: [Pending Provisioning Provisioned Deleting Failed Unknown]
Optional: {}
infrastructureReady booleaninfrastructureReady is the state of the infrastructure provider.Optional: {}
controlPlaneReady booleancontrolPlaneReady denotes if the control plane became ready during initial provisioning
to receive requests.
NOTE: this field is part of the Cluster API contract and it is used to orchestrate provisioning.
The value of this field is never updated after provisioning is completed. Please use conditions
to check the operational state of the control plane.
Optional: {}
conditions Conditionsconditions defines current service state of the cluster.Optional: {}
observedGeneration integerobservedGeneration is the latest generation observed by the controller.Optional: {}
v1beta2 ClusterV1Beta2Statusv1beta2 groups all the fields that will be added or modified in Cluster’s status with the V1Beta2 version.Optional: {}

ClusterV1Beta2Status

ClusterV1Beta2Status groups all the fields that will be added or modified in Cluster with the V1Beta2 version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a Cluster’s current state.
Known condition types are Available, InfrastructureReady, ControlPlaneInitialized, ControlPlaneAvailable, WorkersAvailable, MachinesReady
MachinesUpToDate, RemoteConnectionProbe, ScalingUp, ScalingDown, Remediating, Deleting, Paused.
Additionally, a TopologyReconciled condition will be added in case the Cluster is referencing a ClusterClass / defining a managed Topology.
MaxItems: 32
Optional: {}
controlPlane ClusterControlPlaneStatuscontrolPlane groups all the observations about Cluster’s ControlPlane current state.Optional: {}
workers WorkersStatusworkers groups all the observations about Cluster’s Workers current state.Optional: {}

ClusterVariable

ClusterVariable can be used to customize the Cluster through patches. Each ClusterVariable is associated with a Variable definition in the ClusterClass status variables.

Appears in:

FieldDescriptionDefaultValidation
name stringname of the variable.MaxLength: 256
MinLength: 1
Required: {}
definitionFrom stringdefinitionFrom specifies where the definition of this Variable is from.
Deprecated: This field is deprecated, must not be set anymore and is going to be removed in the next apiVersion.
MaxLength: 256
Optional: {}
value JSONvalue of the variable.
Note: the value will be validated against the schema of the corresponding ClusterClassVariable
from the ClusterClass.
Note: We have to use apiextensionsv1.JSON instead of a custom JSON type, because controller-tools has a
hard-coded schema for apiextensionsv1.JSON which cannot be produced by another type via controller-tools,
i.e. it is not possible to have no type field.
Ref: https://github.com/kubernetes-sigs/controller-tools/blob/d0e03a142d0ecdd5491593e941ee1d6b5d91dba6/pkg/crd/known_types.go#L106-L111
Required: {}

Condition

Condition defines an observation of a Cluster API resource operational state.

Appears in:

FieldDescriptionDefaultValidation
type ConditionTypetype of condition in CamelCase or in foo.example.com/CamelCase.
Many .condition.type values are consistent across resources like Available, but because arbitrary conditions
can be useful (see .node.status.conditions), the ability to deconflict is important.
MaxLength: 256
MinLength: 1
Required: {}
status ConditionStatusstatus of the condition, one of True, False, Unknown.Required: {}
severity ConditionSeverityseverity provides an explicit classification of Reason code, so the users or machines can immediately
understand the current situation and act accordingly.
The Severity field MUST be set only when Status=False.
MaxLength: 32
Optional: {}
reason stringreason is the reason for the condition’s last transition in CamelCase.
The specific API may choose whether or not this field is considered a guaranteed API.
This field may be empty.
MaxLength: 256
MinLength: 1
Optional: {}
message stringmessage is a human readable message indicating details about the transition.
This field may be empty.
MaxLength: 10240
MinLength: 1
Optional: {}

ConditionPolarity

Underlying type: string

ConditionPolarity defines the polarity for a metav1.Condition.

Appears in:

FieldDescription
PositivePositivePolarityCondition describe a condition with positive polarity, a condition
where the normal state is True. e.g. NetworkReady.
NegativeNegativePolarityCondition describe a condition with negative polarity, a condition
where the normal state is False. e.g. MemoryPressure.

ConditionSeverity

Underlying type: string

ConditionSeverity expresses the severity of a Condition Type failing.

Validation:

  • MaxLength: 32

Appears in:

FieldDescription
ErrorConditionSeverityError specifies that a condition with Status=False is an error.
WarningConditionSeverityWarning specifies that a condition with Status=False is a warning.
InfoConditionSeverityInfo specifies that a condition with Status=False is informative.
``ConditionSeverityNone should apply only to conditions with Status=True.

ConditionType

Underlying type: string

ConditionType is a valid value for Condition.Type.

Validation:

  • MaxLength: 256
  • MinLength: 1

Appears in:

FieldDescription
ReadyReadyCondition defines the Ready condition type that summarizes the operational state of a Cluster API object.
InfrastructureReadyInfrastructureReadyCondition reports a summary of current status of the infrastructure object defined for this cluster/machine/machinepool.
This condition is mirrored from the Ready condition in the infrastructure ref object, and
the absence of this condition might signal problems in the reconcile external loops or the fact that
the infrastructure provider does not implement the Ready condition yet.
VariablesReconciledClusterClassVariablesReconciledCondition reports if the ClusterClass variables, including both inline and external
variables, have been successfully reconciled.
This signals that the ClusterClass is ready to be used to default and validate variables on Clusters using
this ClusterClass.
ControlPlaneInitializedControlPlaneInitializedCondition reports if the cluster’s control plane has been initialized such that the
cluster’s apiserver is reachable. If no Control Plane provider is in use this condition reports that at least one
control plane Machine has a node reference. Once this Condition is marked true, its value is never changed. See
the ControlPlaneReady condition for an indication of the current readiness of the cluster’s control plane.
ControlPlaneReadyControlPlaneReadyCondition reports the ready condition from the control plane object defined for this cluster.
This condition is mirrored from the Ready condition in the control plane ref object, and
the absence of this condition might signal problems in the reconcile external loops or the fact that
the control plane provider does not implement the Ready condition yet.
BootstrapReadyBootstrapReadyCondition reports a summary of current status of the bootstrap object defined for this machine.
This condition is mirrored from the Ready condition in the bootstrap ref object, and
the absence of this condition might signal problems in the reconcile external loops or the fact that
the bootstrap provider does not implement the Ready condition yet.
DrainingSucceededDrainingSucceededCondition provide evidence of the status of the node drain operation which happens during the machine
deletion process.
PreDrainDeleteHookSucceededPreDrainDeleteHookSucceededCondition reports a machine waiting for a PreDrainDeleteHook before being delete.
PreTerminateDeleteHookSucceededPreTerminateDeleteHookSucceededCondition reports a machine waiting for a PreDrainDeleteHook before being delete.
VolumeDetachSucceededVolumeDetachSucceededCondition reports a machine waiting for volumes to be detached.
HealthCheckSucceededMachineHealthCheckSucceededCondition is set on machines that have passed a healthcheck by the MachineHealthCheck controller.
In the event that the health check fails it will be set to False.
OwnerRemediatedMachineOwnerRemediatedCondition is set on machines that have failed a healthcheck by the MachineHealthCheck controller.
MachineOwnerRemediatedCondition is set to False after a health check fails, but should be changed to True by the owning controller after remediation succeeds.
ExternalRemediationTemplateAvailableExternalRemediationTemplateAvailableCondition is set on machinehealthchecks when MachineHealthCheck controller uses external remediation.
ExternalRemediationTemplateAvailableCondition is set to false if external remediation template is not found.
ExternalRemediationRequestAvailableExternalRemediationRequestAvailableCondition is set on machinehealthchecks when MachineHealthCheck controller uses external remediation.
ExternalRemediationRequestAvailableCondition is set to false if creating external remediation request fails.
NodeHealthyMachineNodeHealthyCondition provides info about the operational state of the Kubernetes node hosted on the machine by summarizing node conditions.
If the conditions defined in a Kubernetes node (i.e., NodeReady, NodeMemoryPressure, NodeDiskPressure and NodePIDPressure) are in a healthy state, it will be set to True.
RemediationAllowedRemediationAllowedCondition is set on MachineHealthChecks to show the status of whether the MachineHealthCheck is
allowed to remediate any Machines or whether it is blocked from remediating any further.
AvailableMachineDeploymentAvailableCondition means the MachineDeployment is available, that is, at least the minimum available
machines required (i.e. Spec.Replicas-MaxUnavailable when MachineDeploymentStrategyType = RollingUpdate) are up and running for at least minReadySeconds.
MachineSetReadyMachineSetReadyCondition reports a summary of current status of the MachineSet owned by the MachineDeployment.
MachinesCreatedMachinesCreatedCondition documents that the machines controlled by the MachineSet are created.
When this condition is false, it indicates that there was an error when cloning the infrastructure/bootstrap template or
when generating the machine object.
MachinesReadyMachinesReadyCondition reports an aggregate of current status of the machines controlled by the MachineSet.
ResizedResizedCondition documents a MachineSet is resizing the set of controlled machines.
TopologyReconciledTopologyReconciledCondition provides evidence about the reconciliation of a Cluster topology into
the managed objects of the Cluster.
Status false means that for any reason, the values defined in Cluster.spec.topology are not yet applied to
managed objects on the Cluster; status true means that Cluster.spec.topology have been applied to
the objects in the Cluster (but this does not imply those objects are already reconciled to the spec provided).
RefVersionsUpToDateClusterClassRefVersionsUpToDateCondition documents if the references in the ClusterClass are
up-to-date (i.e. they are using the latest apiVersion of the current Cluster API contract from
the corresponding CRD).
ReplicasReadyReplicasReadyCondition reports an aggregate of current status of the replicas controlled by the MachinePool.

Conditions

Underlying type: Condition

Conditions provide observations of the operational state of a Cluster API resource.

Appears in:

FieldDescriptionDefaultValidation
type ConditionTypetype of condition in CamelCase or in foo.example.com/CamelCase.
Many .condition.type values are consistent across resources like Available, but because arbitrary conditions
can be useful (see .node.status.conditions), the ability to deconflict is important.
MaxLength: 256
MinLength: 1
Required: {}
status ConditionStatusstatus of the condition, one of True, False, Unknown.Required: {}
severity ConditionSeverityseverity provides an explicit classification of Reason code, so the users or machines can immediately
understand the current situation and act accordingly.
The Severity field MUST be set only when Status=False.
MaxLength: 32
Optional: {}
reason stringreason is the reason for the condition’s last transition in CamelCase.
The specific API may choose whether or not this field is considered a guaranteed API.
This field may be empty.
MaxLength: 256
MinLength: 1
Optional: {}
message stringmessage is a human readable message indicating details about the transition.
This field may be empty.
MaxLength: 10240
MinLength: 1
Optional: {}

ControlPlaneClass

ControlPlaneClass defines the class for the control plane.

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
ref ObjectReferenceref is a required reference to a custom resource
offered by a provider.
Required: {}
machineInfrastructure LocalObjectTemplatemachineInfrastructure defines the metadata and infrastructure information
for control plane machines.
This field is supported if and only if the control plane provider template
referenced above is Machine based and supports setting replicas.
Optional: {}
machineHealthCheck MachineHealthCheckClassmachineHealthCheck defines a MachineHealthCheck for this ControlPlaneClass.
This field is supported if and only if the ControlPlane provider template
referenced above is Machine based and supports setting replicas.
Optional: {}
namingStrategy ControlPlaneClassNamingStrategynamingStrategy allows changing the naming pattern used when creating the control plane provider object.Optional: {}
nodeDrainTimeout DurationnodeDrainTimeout is the total amount of time that the controller will spend on draining a node.
The default value is 0, meaning that the node can be drained without any time limitations.
NOTE: NodeDrainTimeout is different from kubectl drain --timeout
NOTE: This value can be overridden while defining a Cluster.Topology.
Optional: {}
nodeVolumeDetachTimeout DurationnodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes
to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
NOTE: This value can be overridden while defining a Cluster.Topology.
Optional: {}
nodeDeletionTimeout DurationnodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine
hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely.
Defaults to 10 seconds.
NOTE: This value can be overridden while defining a Cluster.Topology.
Optional: {}
taints MachineTaint arraytaints are the node taints that Cluster API will manage.
This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes,
e.g. the node controller might add the node.kubernetes.io/not-ready taint.
Only those taints defined in this list will be added or removed by core Cluster API controllers.
There can be at most 64 taints.
A pod would have to tolerate all existing taints to run on the corresponding node.
NOTE: This list is implemented as a “map” type, meaning that individual elements can be managed by different owners.
MaxItems: 64
MinItems: 1
Optional: {}
readinessGates MachineReadinessGate arrayreadinessGates specifies additional conditions to include when evaluating Machine Ready condition.
This field can be used e.g. to instruct the machine controller to include in the computation for Machine’s ready
computation a condition, managed by an external controllers, reporting the status of special software/hardware installed on the Machine.
NOTE: This field is considered only for computing v1beta2 conditions.
NOTE: If a Cluster defines a custom list of readinessGates for the control plane,
such list overrides readinessGates defined in this field.
NOTE: Specific control plane provider implementations might automatically extend the list of readinessGates;
e.g. the kubeadm control provider adds ReadinessGates for the APIServerPodHealthy, SchedulerPodHealthy conditions, etc.
MaxItems: 32
Optional: {}

ControlPlaneClassNamingStrategy

ControlPlaneClassNamingStrategy defines the naming strategy for control plane objects.

Appears in:

FieldDescriptionDefaultValidation
template stringtemplate defines the template to use for generating the name of the ControlPlane object.
If not defined, it will fallback to \{\{ .cluster.name \}\}-\{\{ .random \}\}.
If the templated string exceeds 63 characters, it will be trimmed to 58 characters and will
get concatenated with a random suffix of length 5.
The templating mechanism provides the following arguments:
* .cluster.name: The name of the cluster object.
* .random: A random alphanumeric string, without vowels, of length 5.
MaxLength: 1024
MinLength: 1
Optional: {}

ControlPlaneTopology

ControlPlaneTopology specifies the parameters for the control plane nodes in the cluster.

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
replicas integerreplicas is the number of control plane nodes.
If the value is nil, the ControlPlane object is created without the number of Replicas
and it’s assumed that the control plane controller does not implement support for this field.
When specified against a control plane provider that lacks support for this field, this value will be ignored.
Optional: {}
rollout ControlPlaneTopologyRolloutSpecrollout allows you to configure the behavior of rolling updates to the control plane.MinProperties: 1
Optional: {}
machineHealthCheck MachineHealthCheckTopologymachineHealthCheck allows to enable, disable and override
the MachineHealthCheck configuration in the ClusterClass for this control plane.
Optional: {}
nodeDrainTimeout DurationnodeDrainTimeout is the total amount of time that the controller will spend on draining a node.
The default value is 0, meaning that the node can be drained without any time limitations.
NOTE: NodeDrainTimeout is different from kubectl drain --timeout
Optional: {}
nodeVolumeDetachTimeout DurationnodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes
to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
Optional: {}
nodeDeletionTimeout DurationnodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine
hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely.
Defaults to 10 seconds.
Optional: {}
taints MachineTaint arraytaints are the node taints that Cluster API will manage.
This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes,
e.g. the node controller might add the node.kubernetes.io/not-ready taint.
Only those taints defined in this list will be added or removed by core Cluster API controllers.
There can be at most 64 taints.
A pod would have to tolerate all existing taints to run on the corresponding node.
NOTE: This list is implemented as a “map” type, meaning that individual elements can be managed by different owners.
MaxItems: 64
MinItems: 1
Optional: {}
readinessGates MachineReadinessGate arrayreadinessGates specifies additional conditions to include when evaluating Machine Ready condition.
This field can be used e.g. to instruct the machine controller to include in the computation for Machine’s ready
computation a condition, managed by an external controllers, reporting the status of special software/hardware installed on the Machine.
If this field is not defined, readinessGates from the corresponding ControlPlaneClass will be used, if any.
NOTE: This field is considered only for computing v1beta2 conditions.
NOTE: Specific control plane provider implementations might automatically extend the list of readinessGates;
e.g. the kubeadm control provider adds ReadinessGates for the APIServerPodHealthy, SchedulerPodHealthy conditions, etc.
MaxItems: 32
Optional: {}
variables ControlPlaneVariablesvariables can be used to customize the ControlPlane through patches.Optional: {}

ControlPlaneTopologyRolloutSpec

ControlPlaneTopologyRolloutSpec defines the rollout behavior.

Validation:

  • MinProperties: 1

Appears in:

ControlPlaneVariables

ControlPlaneVariables can be used to provide variables for the ControlPlane.

Appears in:

FieldDescriptionDefaultValidation
overrides ClusterVariable arrayoverrides can be used to override Cluster level variables.MaxItems: 1000
Optional: {}

ExternalPatchDefinition

ExternalPatchDefinition defines an external patch. Note: At least one of GenerateExtension or ValidateExtension must be set.

Appears in:

FieldDescriptionDefaultValidation
generateExtension stringgenerateExtension references an extension which is called to generate patches.MaxLength: 512
MinLength: 1
Optional: {}
validateExtension stringvalidateExtension references an extension which is called to validate the topology.MaxLength: 512
MinLength: 1
Optional: {}
discoverVariablesExtension stringdiscoverVariablesExtension references an extension which is called to discover variables.MaxLength: 512
MinLength: 1
Optional: {}
settings object (keys:string, values:string)settings defines key value pairs to be passed to the extensions.
Values defined here take precedence over the values defined in the
corresponding ExtensionConfig.
Optional: {}

FailureDomainSpec

FailureDomainSpec is the Schema for Cluster API failure domains. It allows controllers to understand how many failure domains a cluster can optionally span across.

Appears in:

FieldDescriptionDefaultValidation
controlPlane booleancontrolPlane determines if this failure domain is suitable for use by control plane machines.Optional: {}
attributes object (keys:string, values:string)attributes is a free form map of attributes an infrastructure provider might use or require.Optional: {}

FailureDomains

Underlying type: map[string]FailureDomainSpec

FailureDomains is a slice of FailureDomains.

Appears in:

FieldValueErrorReason

Underlying type: string

FieldValueErrorReason is a machine-readable value providing more detail about why a field failed the validation.

Appears in:

FieldDescription
FieldValueRequiredFieldValueRequired is used to report required values that are not
provided (e.g. empty strings, null values, or empty arrays).
FieldValueDuplicateFieldValueDuplicate is used to report collisions of values that must be
unique (e.g. unique IDs).
FieldValueInvalidFieldValueInvalid is used to report malformed values (e.g. failed regex
match, too long, out of bounds).
FieldValueForbiddenFieldValueForbidden is used to report valid (as per formatting rules)
values which would be accepted under some conditions, but which are not
permitted by the current conditions (such as security policy).

InfrastructureNamingStrategy

InfrastructureNamingStrategy defines the naming strategy for infrastructure objects.

Appears in:

FieldDescriptionDefaultValidation
template stringtemplate defines the template to use for generating the name of the Infrastructure object.
If not defined, it will fallback to \{\{ .cluster.name \}\}-\{\{ .random \}\}.
If the templated string exceeds 63 characters, it will be trimmed to 58 characters and will
get concatenated with a random suffix of length 5.
The templating mechanism provides the following arguments:
* .cluster.name: The name of the cluster object.
* .random: A random alphanumeric string, without vowels, of length 5.
MaxLength: 1024
MinLength: 1
Optional: {}

JSONPatch

JSONPatch defines a JSON patch.

Appears in:

FieldDescriptionDefaultValidation
op stringop defines the operation of the patch.
Note: Only add, replace and remove are supported.
Enum: [add replace remove]
Required: {}
path stringpath defines the path of the patch.
Note: Only the spec of a template can be patched, thus the path has to start with /spec/.
Note: For now the only allowed array modifications are append and prepend, i.e.:
* for op: add: only index 0 (prepend) and - (append) are allowed
* for op: replace or remove: no indexes are allowed
MaxLength: 512
MinLength: 1
Required: {}
value JSONvalue defines the value of the patch.
Note: Either Value or ValueFrom is required for add and replace
operations. Only one of them is allowed to be set at the same time.
Note: We have to use apiextensionsv1.JSON instead of our JSON type,
because controller-tools has a hard-coded schema for apiextensionsv1.JSON
which cannot be produced by another type (unset type field).
Ref: https://github.com/kubernetes-sigs/controller-tools/blob/d0e03a142d0ecdd5491593e941ee1d6b5d91dba6/pkg/crd/known_types.go#L106-L111
Optional: {}
valueFrom JSONPatchValuevalueFrom defines the value of the patch.
Note: Either Value or ValueFrom is required for add and replace
operations. Only one of them is allowed to be set at the same time.
Optional: {}

JSONPatchValue

JSONPatchValue defines the value of a patch. Note: Only one of the fields is allowed to be set at the same time.

Appears in:

FieldDescriptionDefaultValidation
variable stringvariable is the variable to be used as value.
Variable can be one of the variables defined in .spec.variables or a builtin variable.
MaxLength: 256
MinLength: 1
Optional: {}
template stringtemplate is the Go template to be used to calculate the value.
A template can reference variables defined in .spec.variables and builtin variables.
Note: The template must evaluate to a valid YAML or JSON value.
MaxLength: 10240
MinLength: 1
Optional: {}

JSONSchemaProps

JSONSchemaProps is a JSON-Schema following Specification Draft 4 (http://json-schema.org/). This struct has been initially copied from apiextensionsv1.JSONSchemaProps, but all fields which are not supported in CAPI have been removed.

Appears in:

FieldDescriptionDefaultValidation
description stringdescription is a human-readable description of this variable.MaxLength: 4096
MinLength: 1
Optional: {}
example JSONexample is an example for this variable.Optional: {}
type stringtype is the type of the variable.
Valid values are: object, array, string, integer, number or boolean.
Enum: [object array string integer number boolean]
Optional: {}
properties object (keys:string, values:JSONSchemaProps)properties specifies fields of an object.
NOTE: Can only be set if type is object.
NOTE: Properties is mutually exclusive with AdditionalProperties.
NOTE: This field uses PreserveUnknownFields and Schemaless,
because recursive validation is not possible.
Schemaless: {}
Optional: {}
additionalProperties JSONSchemaPropsadditionalProperties specifies the schema of values in a map (keys are always strings).
NOTE: Can only be set if type is object.
NOTE: AdditionalProperties is mutually exclusive with Properties.
NOTE: This field uses PreserveUnknownFields and Schemaless,
because recursive validation is not possible.
Schemaless: {}
Optional: {}
maxProperties integermaxProperties is the maximum amount of entries in a map or properties in an object.
NOTE: Can only be set if type is object.
Optional: {}
minProperties integerminProperties is the minimum amount of entries in a map or properties in an object.
NOTE: Can only be set if type is object.
Optional: {}
required string arrayrequired specifies which fields of an object are required.
NOTE: Can only be set if type is object.
MaxItems: 1000
items:MaxLength: 256
items:MinLength: 1
Optional: {}
items JSONSchemaPropsitems specifies fields of an array.
NOTE: Can only be set if type is array.
NOTE: This field uses PreserveUnknownFields and Schemaless,
because recursive validation is not possible.
Schemaless: {}
Optional: {}
maxItems integermaxItems is the max length of an array variable.
NOTE: Can only be set if type is array.
Optional: {}
minItems integerminItems is the min length of an array variable.
NOTE: Can only be set if type is array.
Optional: {}
uniqueItems booleanuniqueItems specifies if items in an array must be unique.
NOTE: Can only be set if type is array.
Optional: {}
format stringformat is an OpenAPI v3 format string. Unknown formats are ignored.
For a list of supported formats please see: (of the k8s.io/apiextensions-apiserver version we’re currently using)
https://github.com/kubernetes/apiextensions-apiserver/blob/master/pkg/apiserver/validation/formats.go
NOTE: Can only be set if type is string.
MaxLength: 32
MinLength: 1
Optional: {}
maxLength integermaxLength is the max length of a string variable.
NOTE: Can only be set if type is string.
Optional: {}
minLength integerminLength is the min length of a string variable.
NOTE: Can only be set if type is string.
Optional: {}
pattern stringpattern is the regex which a string variable must match.
NOTE: Can only be set if type is string.
MaxLength: 512
MinLength: 1
Optional: {}
maximum integermaximum is the maximum of an integer or number variable.
If ExclusiveMaximum is false, the variable is valid if it is lower than, or equal to, the value of Maximum.
If ExclusiveMaximum is true, the variable is valid if it is strictly lower than the value of Maximum.
NOTE: Can only be set if type is integer or number.
Optional: {}
exclusiveMaximum booleanexclusiveMaximum specifies if the Maximum is exclusive.
NOTE: Can only be set if type is integer or number.
Optional: {}
minimum integerminimum is the minimum of an integer or number variable.
If ExclusiveMinimum is false, the variable is valid if it is greater than, or equal to, the value of Minimum.
If ExclusiveMinimum is true, the variable is valid if it is strictly greater than the value of Minimum.
NOTE: Can only be set if type is integer or number.
Optional: {}
exclusiveMinimum booleanexclusiveMinimum specifies if the Minimum is exclusive.
NOTE: Can only be set if type is integer or number.
Optional: {}
x-kubernetes-preserve-unknown-fields booleanx-kubernetes-preserve-unknown-fields allows setting fields in a variable object
which are not defined in the variable schema. This affects fields recursively,
except if nested properties or additionalProperties are specified in the schema.
Optional: {}
enum JSON arrayenum is the list of valid values of the variable.
NOTE: Can be set for all types.
MaxItems: 100
Optional: {}
default JSONdefault is the default value of the variable.
NOTE: Can be set for all types.
Optional: {}
x-kubernetes-validations ValidationRule arrayx-kubernetes-validations describes a list of validation rules written in the CEL expression language.MaxItems: 100
Optional: {}
x-metadata VariableSchemaMetadatax-metadata is the metadata of a variable or a nested field within a variable.
It can be used to add additional data for higher level tools.
Optional: {}
x-kubernetes-int-or-string booleanx-kubernetes-int-or-string specifies that this value is
either an integer or a string. If this is true, an empty
type is allowed and type as child of anyOf is permitted
if following one of the following patterns:
1) anyOf:
- type: integer
- type: string
2) allOf:
- anyOf:
- type: integer
- type: string
- … zero or more
Optional: {}
allOf JSONSchemaProps arrayallOf specifies that the variable must validate against all of the subschemas in the array.
NOTE: This field uses PreserveUnknownFields and Schemaless,
because recursive validation is not possible.
Schemaless: {}
Optional: {}
oneOf JSONSchemaProps arrayoneOf specifies that the variable must validate against exactly one of the subschemas in the array.
NOTE: This field uses PreserveUnknownFields and Schemaless,
because recursive validation is not possible.
Schemaless: {}
Optional: {}
anyOf JSONSchemaProps arrayanyOf specifies that the variable must validate against one or more of the subschemas in the array.
NOTE: This field uses PreserveUnknownFields and Schemaless,
because recursive validation is not possible.
Schemaless: {}
Optional: {}
not JSONSchemaPropsnot specifies that the variable must not validate against the subschema.
NOTE: This field uses PreserveUnknownFields and Schemaless,
because recursive validation is not possible.
Schemaless: {}
Optional: {}

LocalObjectTemplate

LocalObjectTemplate defines a template for a topology Class.

Appears in:

FieldDescriptionDefaultValidation
ref ObjectReferenceref is a required reference to a custom resource
offered by a provider.
Required: {}

Machine

Machine is the Schema for the machines API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta1
kind stringMachine
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
spec MachineSpecspec is the desired state of Machine.Optional: {}
status MachineStatusstatus is the observed state of Machine.Optional: {}

MachineAddress

MachineAddress contains information for the node’s address.

Appears in:

FieldDescriptionDefaultValidation
type MachineAddressTypetype is the machine address type, one of Hostname, ExternalIP, InternalIP, ExternalDNS or InternalDNS.Enum: [Hostname ExternalIP InternalIP ExternalDNS InternalDNS]
Required: {}
address stringaddress is the machine address.MaxLength: 256
MinLength: 1
Required: {}

MachineAddressType

Underlying type: string

MachineAddressType describes a valid MachineAddress type.

Validation:

  • Enum: [Hostname ExternalIP InternalIP ExternalDNS InternalDNS]

Appears in:

FieldDescription
Hostname
ExternalIP
InternalIP
ExternalDNS
InternalDNS

MachineAddresses

Underlying type: MachineAddress

MachineAddresses is a slice of MachineAddress items to be used by infrastructure providers.

Appears in:

FieldDescriptionDefaultValidation
type MachineAddressTypetype is the machine address type, one of Hostname, ExternalIP, InternalIP, ExternalDNS or InternalDNS.Enum: [Hostname ExternalIP InternalIP ExternalDNS InternalDNS]
Required: {}
address stringaddress is the machine address.MaxLength: 256
MinLength: 1
Required: {}

MachineDeletionStatus

MachineDeletionStatus is the deletion state of the Machine.

Appears in:

MachineDeployment

MachineDeployment is the Schema for the machinedeployments API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta1
kind stringMachineDeployment
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
spec MachineDeploymentSpecspec is the desired state of MachineDeployment.Optional: {}
status MachineDeploymentStatusstatus is the observed state of MachineDeployment.Optional: {}

MachineDeploymentClass

MachineDeploymentClass serves as a template to define a set of worker nodes of the cluster provisioned using the ClusterClass.

Appears in:

FieldDescriptionDefaultValidation
class stringclass denotes a type of worker node present in the cluster,
this name MUST be unique within a ClusterClass and can be referenced
in the Cluster to create a managed MachineDeployment.
MaxLength: 256
MinLength: 1
Required: {}
template MachineDeploymentClassTemplatetemplate is a local struct containing a collection of templates for creation of
MachineDeployment objects representing a set of worker nodes.
Required: {}
machineHealthCheck MachineHealthCheckClassmachineHealthCheck defines a MachineHealthCheck for this MachineDeploymentClass.Optional: {}
failureDomain stringfailureDomain is the failure domain the machines will be created in.
Must match a key in the FailureDomains map stored on the cluster object.
NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
MaxLength: 256
MinLength: 1
Optional: {}
namingStrategy MachineDeploymentClassNamingStrategynamingStrategy allows changing the naming pattern used when creating the MachineDeployment.Optional: {}
nodeDrainTimeout DurationnodeDrainTimeout is the total amount of time that the controller will spend on draining a node.
The default value is 0, meaning that the node can be drained without any time limitations.
NOTE: NodeDrainTimeout is different from kubectl drain --timeout
NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
Optional: {}
nodeVolumeDetachTimeout DurationnodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes
to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
Optional: {}
nodeDeletionTimeout DurationnodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine
hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely.
Defaults to 10 seconds.
NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
Optional: {}
taints MachineTaint arraytaints are the node taints that Cluster API will manage.
This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes,
e.g. the node controller might add the node.kubernetes.io/not-ready taint.
Only those taints defined in this list will be added or removed by core Cluster API controllers.
There can be at most 64 taints.
A pod would have to tolerate all existing taints to run on the corresponding node.
NOTE: This list is implemented as a “map” type, meaning that individual elements can be managed by different owners.
MaxItems: 64
MinItems: 1
Optional: {}
minReadySeconds integerminReadySeconds is the minimum number of seconds for which a newly created machine should
be ready.
Defaults to 0 (machine will be considered available as soon as it
is ready)
NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
Optional: {}
readinessGates MachineReadinessGate arrayreadinessGates specifies additional conditions to include when evaluating Machine Ready condition.
This field can be used e.g. to instruct the machine controller to include in the computation for Machine’s ready
computation a condition, managed by an external controllers, reporting the status of special software/hardware installed on the Machine.
NOTE: This field is considered only for computing v1beta2 conditions.
NOTE: If a Cluster defines a custom list of readinessGates for a MachineDeployment using this MachineDeploymentClass,
such list overrides readinessGates defined in this field.
MaxItems: 32
Optional: {}
strategy MachineDeploymentStrategystrategy is the deployment strategy to use to replace existing machines with
new ones.
NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass.
Optional: {}

MachineDeploymentClassNamingStrategy

MachineDeploymentClassNamingStrategy defines the naming strategy for machine deployment objects.

Appears in:

FieldDescriptionDefaultValidation
template stringtemplate defines the template to use for generating the name of the MachineDeployment object.
If not defined, it will fallback to \{\{ .cluster.name \}\}-\{\{ .machineDeployment.topologyName \}\}-\{\{ .random \}\}.
If the templated string exceeds 63 characters, it will be trimmed to 58 characters and will
get concatenated with a random suffix of length 5.
The templating mechanism provides the following arguments:
* .cluster.name: The name of the cluster object.
* .random: A random alphanumeric string, without vowels, of length 5.
* .machineDeployment.topologyName: The name of the MachineDeployment topology (Cluster.spec.topology.workers.machineDeployments[].name).
MaxLength: 1024
MinLength: 1
Optional: {}

MachineDeploymentClassTemplate

MachineDeploymentClassTemplate defines how a MachineDeployment generated from a MachineDeploymentClass should look like.

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
bootstrap LocalObjectTemplatebootstrap contains the bootstrap template reference to be used
for the creation of worker Machines.
Required: {}
infrastructure LocalObjectTemplateinfrastructure contains the infrastructure template reference to be used
for the creation of worker Machines.
Required: {}

MachineDeploymentList

MachineDeploymentList contains a list of MachineDeployment.

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta1
kind stringMachineDeploymentList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items MachineDeployment arrayitems is the list of MachineDeployments.

MachineDeploymentSpec

MachineDeploymentSpec defines the desired state of MachineDeployment.

Appears in:

FieldDescriptionDefaultValidation
clusterName stringclusterName is the name of the Cluster this object belongs to.MaxLength: 63
MinLength: 1
Required: {}
replicas integerreplicas is the number of desired machines.
This is a pointer to distinguish between explicit zero and not specified.
Defaults to:
* if the Kubernetes autoscaler min size and max size annotations are set:
- if it’s a new MachineDeployment, use min size
- if the replicas field of the old MachineDeployment is < min size, use min size
- if the replicas field of the old MachineDeployment is > max size, use max size
- if the replicas field of the old MachineDeployment is in the (min size, max size) range, keep the value from the oldMD
* otherwise use 1
Note: Defaulting will be run whenever the replicas field is not set:
* A new MachineDeployment is created with replicas not set.
* On an existing MachineDeployment the replicas field was first set and is now unset.
Those cases are especially relevant for the following Kubernetes autoscaler use cases:
* A new MachineDeployment is created and replicas should be managed by the autoscaler
* An existing MachineDeployment which initially wasn’t controlled by the autoscaler
should be later controlled by the autoscaler
Optional: {}
selector LabelSelectorselector is the label selector for machines. Existing MachineSets whose machines are
selected by this will be the ones affected by this deployment.
It must match the machine template’s labels.
Required: {}
template MachineTemplateSpectemplate describes the machines that will be created.Required: {}
strategy MachineDeploymentStrategystrategy is the deployment strategy to use to replace existing machines with
new ones.
Optional: {}
machineNamingStrategy MachineNamingStrategymachineNamingStrategy allows changing the naming pattern used when creating Machines.
Note: InfraMachines & BootstrapConfigs will use the same name as the corresponding Machines.
Optional: {}
minReadySeconds integerminReadySeconds is the minimum number of seconds for which a Node for a newly created machine should be ready before considering the replica available.
Defaults to 0 (machine will be considered available as soon as the Node is ready)
Optional: {}
revisionHistoryLimit integerrevisionHistoryLimit is the number of old MachineSets to retain to allow rollback.
This is a pointer to distinguish between explicit zero and not specified.
Defaults to 1.
Deprecated: This field is deprecated and is going to be removed in the next apiVersion. Please see https://github.com/kubernetes-sigs/cluster-api/issues/10479 for more details.
Optional: {}
paused booleanpaused indicates that the deployment is paused.Optional: {}
progressDeadlineSeconds integerprogressDeadlineSeconds is the maximum time in seconds for a deployment to make progress before it
is considered to be failed. The deployment controller will continue to
process failed deployments and a condition with a ProgressDeadlineExceeded
reason will be surfaced in the deployment status. Note that progress will
not be estimated during the time a deployment is paused. Defaults to 600s.
Deprecated: This field is deprecated and is going to be removed in the next apiVersion. Please see https://github.com/kubernetes-sigs/cluster-api/issues/11470 for more details.
Optional: {}

MachineDeploymentStatus

MachineDeploymentStatus defines the observed state of MachineDeployment.

Appears in:

FieldDescriptionDefaultValidation
observedGeneration integerobservedGeneration is the generation observed by the deployment controller.Optional: {}
selector stringselector is the same as the label selector but in the string format to avoid introspection
by clients. The string will be in the same format as the query-param syntax.
More info about label selectors: http://kubernetes.io/docs/user-guide/labels#label-selectors
MaxLength: 4096
MinLength: 1
Optional: {}
replicas integerreplicas is the total number of non-terminated machines targeted by this deployment
(their labels match the selector).
Optional: {}
updatedReplicas integerupdatedReplicas is the total number of non-terminated machines targeted by this deployment
that have the desired template spec.
Optional: {}
readyReplicas integerreadyReplicas is the total number of ready machines targeted by this deployment.Optional: {}
availableReplicas integeravailableReplicas is the total number of available machines (ready for at least minReadySeconds)
targeted by this deployment.
Optional: {}
unavailableReplicas integerunavailableReplicas is the total number of unavailable machines targeted by this deployment.
This is the total number of machines that are still required for
the deployment to have 100% available capacity. They may either
be machines that are running but not yet available or machines
that still have not been created.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
phase stringphase represents the current phase of a MachineDeployment (ScalingUp, ScalingDown, Running, Failed, or Unknown).Enum: [ScalingUp ScalingDown Running Failed Unknown]
Optional: {}
conditions Conditionsconditions defines current service state of the MachineDeployment.Optional: {}
versions StatusVersion arrayversions is the aggregated Kubernetes versions in this MachineDeployment.MaxItems: 100
MinItems: 1
Optional: {}
v1beta2 MachineDeploymentV1Beta2Statusv1beta2 groups all the fields that will be added or modified in MachineDeployment’s status with the V1Beta2 version.Optional: {}

MachineDeploymentStrategy

MachineDeploymentStrategy describes how to replace existing machines with new ones.

Appears in:

FieldDescriptionDefaultValidation
type MachineDeploymentStrategyTypetype of deployment. Allowed values are RollingUpdate and OnDelete.
The default is RollingUpdate.
Enum: [RollingUpdate OnDelete]
Optional: {}
rollingUpdate MachineRollingUpdateDeploymentrollingUpdate is the rolling update config params. Present only if
MachineDeploymentStrategyType = RollingUpdate.
Optional: {}
remediation RemediationStrategyremediation controls the strategy of remediating unhealthy machines
and how remediating operations should occur during the lifecycle of the dependant MachineSets.
Optional: {}

MachineDeploymentStrategyType

Underlying type: string

MachineDeploymentStrategyType defines the type of MachineDeployment rollout strategies.

Appears in:

FieldDescription
RollingUpdateRollingUpdateMachineDeploymentStrategyType replaces the old MachineSet by new one using rolling update
i.e. gradually scale down the old MachineSet and scale up the new one.
OnDeleteOnDeleteMachineDeploymentStrategyType replaces old MachineSets when the deletion of the associated machines are completed.

MachineDeploymentTopology

MachineDeploymentTopology specifies the different parameters for a set of worker nodes in the topology. This set of nodes is managed by a MachineDeployment object whose lifecycle is managed by the Cluster controller.

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
class stringclass is the name of the MachineDeploymentClass used to create the set of worker nodes.
This should match one of the deployment classes defined in the ClusterClass object
mentioned in the Cluster.Spec.Class field.
MaxLength: 256
MinLength: 1
Required: {}
name stringname is the unique identifier for this MachineDeploymentTopology.
The value is used with other unique identifiers to create a MachineDeployment’s Name
(e.g. cluster’s name, etc). In case the name is greater than the allowed maximum length,
the values are hashed together.
MaxLength: 63
MinLength: 1
Required: {}
failureDomain stringfailureDomain is the failure domain the machines will be created in.
Must match a key in the FailureDomains map stored on the cluster object.
MaxLength: 256
MinLength: 1
Optional: {}
replicas integerreplicas is the number of worker nodes belonging to this set.
If the value is nil, the MachineDeployment is created without the number of Replicas (defaulting to 1)
and it’s assumed that an external entity (like cluster autoscaler) is responsible for the management
of this value.
Optional: {}
machineHealthCheck MachineHealthCheckTopologymachineHealthCheck allows to enable, disable and override
the MachineHealthCheck configuration in the ClusterClass for this MachineDeployment.
Optional: {}
nodeDrainTimeout DurationnodeDrainTimeout is the total amount of time that the controller will spend on draining a node.
The default value is 0, meaning that the node can be drained without any time limitations.
NOTE: NodeDrainTimeout is different from kubectl drain --timeout
Optional: {}
nodeVolumeDetachTimeout DurationnodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes
to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
Optional: {}
nodeDeletionTimeout DurationnodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine
hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely.
Defaults to 10 seconds.
Optional: {}
taints MachineTaint arraytaints are the node taints that Cluster API will manage.
This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes,
e.g. the node controller might add the node.kubernetes.io/not-ready taint.
Only those taints defined in this list will be added or removed by core Cluster API controllers.
There can be at most 64 taints.
A pod would have to tolerate all existing taints to run on the corresponding node.
NOTE: This list is implemented as a “map” type, meaning that individual elements can be managed by different owners.
MaxItems: 64
MinItems: 1
Optional: {}
minReadySeconds integerminReadySeconds is the minimum number of seconds for which a newly created machine should
be ready.
Defaults to 0 (machine will be considered available as soon as it
is ready)
Optional: {}
readinessGates MachineReadinessGate arrayreadinessGates specifies additional conditions to include when evaluating Machine Ready condition.
This field can be used e.g. to instruct the machine controller to include in the computation for Machine’s ready
computation a condition, managed by an external controllers, reporting the status of special software/hardware installed on the Machine.
If this field is not defined, readinessGates from the corresponding MachineDeploymentClass will be used, if any.
NOTE: This field is considered only for computing v1beta2 conditions.
MaxItems: 32
Optional: {}
rollout MachineDeploymentTopologyRolloutSpecrollout allows you to configure the behaviour of rolling updates to the MachineDeployment Machines.
It allows you to define the strategy used during rolling replacements.
MinProperties: 1
Optional: {}
strategy MachineDeploymentStrategystrategy is the deployment strategy to use to replace existing machines with
new ones.
Optional: {}
variables MachineDeploymentVariablesvariables can be used to customize the MachineDeployment through patches.Optional: {}

MachineDeploymentTopologyRolloutSpec

MachineDeploymentTopologyRolloutSpec defines the rollout behavior.

Validation:

  • MinProperties: 1

Appears in:

MachineDeploymentV1Beta2Status

MachineDeploymentV1Beta2Status groups all the fields that will be added or modified in MachineDeployment with the V1Beta2 version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a MachineDeployment’s current state.
Known condition types are Available, MachinesReady, MachinesUpToDate, ScalingUp, ScalingDown, Remediating, Deleting, Paused.
MaxItems: 32
Optional: {}
readyReplicas integerreadyReplicas is the number of ready replicas for this MachineDeployment. A machine is considered ready when Machine’s Ready condition is true.Optional: {}
availableReplicas integeravailableReplicas is the number of available replicas for this MachineDeployment. A machine is considered available when Machine’s Available condition is true.Optional: {}
upToDateReplicas integerupToDateReplicas is the number of up-to-date replicas targeted by this deployment. A machine is considered up-to-date when Machine’s UpToDate condition is true.Optional: {}

MachineDeploymentVariables

MachineDeploymentVariables can be used to provide variables for a specific MachineDeployment.

Appears in:

FieldDescriptionDefaultValidation
overrides ClusterVariable arrayoverrides can be used to override Cluster level variables.MaxItems: 1000
Optional: {}

MachineDrainRule

MachineDrainRule is the Schema for the MachineDrainRule API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta1
kind stringMachineDrainRule
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Required: {}
spec MachineDrainRuleSpecspec defines the spec of a MachineDrainRule.Required: {}

MachineDrainRuleDrainBehavior

Underlying type: string

MachineDrainRuleDrainBehavior defines the drain behavior. Can be either “Drain”, “Skip”, or “WaitCompleted”.

Validation:

  • Enum: [Drain Skip WaitCompleted]

Appears in:

FieldDescription
DrainMachineDrainRuleDrainBehaviorDrain means a Pod should be drained.
SkipMachineDrainRuleDrainBehaviorSkip means the drain for a Pod should be skipped.
WaitCompletedMachineDrainRuleDrainBehaviorWaitCompleted means the Pod should not be evicted,
but overall drain should wait until the Pod completes.

MachineDrainRuleDrainConfig

MachineDrainRuleDrainConfig configures if and how Pods are drained.

Appears in:

FieldDescriptionDefaultValidation
behavior MachineDrainRuleDrainBehaviorbehavior defines the drain behavior.
Can be either “Drain”, “Skip”, or “WaitCompleted”.
“Drain” means that the Pods to which this MachineDrainRule applies will be drained.
If behavior is set to “Drain” the order in which Pods are drained can be configured
with the order field. When draining Pods of a Node the Pods will be grouped by order
and one group after another will be drained (by increasing order). Cluster API will
wait until all Pods of a group are terminated / removed from the Node before starting
with the next group.
“Skip” means that the Pods to which this MachineDrainRule applies will be skipped during drain.
“WaitCompleted” means that the pods to which this MachineDrainRule applies will never be evicted
and we wait for them to be completed, it is enforced that pods marked with this behavior always have Order=0.
Enum: [Drain Skip WaitCompleted]
Required: {}
order integerorder defines the order in which Pods are drained.
Pods with higher order are drained after Pods with lower order.
order can only be set if behavior is set to “Drain”.
If order is not set, 0 will be used.
Valid values for order are from -2147483648 to 2147483647 (inclusive).
Optional: {}

MachineDrainRuleList

MachineDrainRuleList contains a list of MachineDrainRules.

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta1
kind stringMachineDrainRuleList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Required: {}
items MachineDrainRule arrayitems contains the items of the MachineDrainRuleList.

MachineDrainRuleMachineSelector

MachineDrainRuleMachineSelector defines to which Machines this MachineDrainRule should be applied.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
selector LabelSelectorselector is a label selector which selects Machines by their labels.
This field follows standard label selector semantics; if not present or
empty, it selects all Machines.
If clusterSelector is also set, then the selector as a whole selects
Machines matching selector belonging to Clusters selected by clusterSelector.
If clusterSelector is not set, it selects all Machines matching selector in
all Clusters.
Optional: {}
clusterSelector LabelSelectorclusterSelector is a label selector which selects Machines by the labels of
their Clusters.
This field follows standard label selector semantics; if not present or
empty, it selects Machines of all Clusters.
If selector is also set, then the selector as a whole selects
Machines matching selector belonging to Clusters selected by clusterSelector.
If selector is not set, it selects all Machines belonging to Clusters
selected by clusterSelector.
Optional: {}

MachineDrainRulePodSelector

MachineDrainRulePodSelector defines to which Pods this MachineDrainRule should be applied.

Validation:

  • MinProperties: 1

Appears in:

FieldDescriptionDefaultValidation
selector LabelSelectorselector is a label selector which selects Pods by their labels.
This field follows standard label selector semantics; if not present or
empty, it selects all Pods.
If namespaceSelector is also set, then the selector as a whole selects
Pods matching selector in Namespaces selected by namespaceSelector.
If namespaceSelector is not set, it selects all Pods matching selector in
all Namespaces.
Optional: {}
namespaceSelector LabelSelectornamespaceSelector is a label selector which selects Pods by the labels of
their Namespaces.
This field follows standard label selector semantics; if not present or
empty, it selects Pods of all Namespaces.
If selector is also set, then the selector as a whole selects
Pods matching selector in Namespaces selected by namespaceSelector.
If selector is not set, it selects all Pods in Namespaces selected by
namespaceSelector.
Optional: {}

MachineDrainRuleSpec

MachineDrainRuleSpec defines the spec of a MachineDrainRule.

Appears in:

FieldDescriptionDefaultValidation
drain MachineDrainRuleDrainConfigdrain configures if and how Pods are drained.Required: {}
machines MachineDrainRuleMachineSelector arraymachines defines to which Machines this MachineDrainRule should be applied.
If machines is not set, the MachineDrainRule applies to all Machines in the Namespace.
If machines contains multiple selectors, the results are ORed.
Within a single Machine selector the results of selector and clusterSelector are ANDed.
Machines will be selected from all Clusters in the Namespace unless otherwise
restricted with the clusterSelector.
Example: Selects control plane Machines in all Clusters or
Machines with label “os” == “linux” in Clusters with label
“stage” == “production”.
- selector:
matchExpressions:
- key: cluster.x-k8s.io/control-plane
operator: Exists
- selector:
matchLabels:
os: linux
clusterSelector:
matchExpressions:
- key: stage
operator: In
values:
- production
MaxItems: 32
MinItems: 1
MinProperties: 1
Optional: {}
pods MachineDrainRulePodSelector arraypods defines to which Pods this MachineDrainRule should be applied.
If pods is not set, the MachineDrainRule applies to all Pods in all Namespaces.
If pods contains multiple selectors, the results are ORed.
Within a single Pod selector the results of selector and namespaceSelector are ANDed.
Pods will be selected from all Namespaces unless otherwise
restricted with the namespaceSelector.
Example: Selects Pods with label “app” == “logging” in all Namespaces or
Pods with label “app” == “prometheus” in the “monitoring”
Namespace.
- selector:
matchExpressions:
- key: app
operator: In
values:
- logging
- selector:
matchLabels:
app: prometheus
namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoring
MaxItems: 32
MinItems: 1
MinProperties: 1
Optional: {}

MachineHealthCheck

MachineHealthCheck is the Schema for the machinehealthchecks API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta1
kind stringMachineHealthCheck
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
spec MachineHealthCheckSpecspec is the specification of machine health check policyOptional: {}
status MachineHealthCheckStatusstatus is the most recently observed status of MachineHealthCheck resourceOptional: {}

MachineHealthCheckClass

MachineHealthCheckClass defines a MachineHealthCheck for a group of Machines.

Appears in:

FieldDescriptionDefaultValidation
unhealthyConditions UnhealthyCondition arrayunhealthyConditions contains a list of the conditions that determine
whether a node is considered unhealthy. The conditions are combined in a
logical OR, i.e. if any of the conditions is met, the node is unhealthy.
MaxItems: 100
Optional: {}
unhealthyMachineConditions UnhealthyMachineCondition arrayunhealthyMachineConditions contains a list of the machine conditions that determine
whether a machine is considered unhealthy. The conditions are combined in a
logical OR, i.e. if any of the conditions is met, the machine is unhealthy.
MaxItems: 100
MinItems: 1
Optional: {}
maxUnhealthy IntOrStringmaxUnhealthy specifies the maximum number of unhealthy machines allowed.
Any further remediation is only allowed if at most “maxUnhealthy” machines selected by
“selector” are not healthy.
Optional: {}
unhealthyRange stringunhealthyRange specifies the range of unhealthy machines allowed.
Any further remediation is only allowed if the number of machines selected by “selector” as not healthy
is within the range of “unhealthyRange”. Takes precedence over maxUnhealthy.
Eg. “[3-5]” - This means that remediation will be allowed only when:
(a) there are at least 3 unhealthy machines (and)
(b) there are at most 5 unhealthy machines
MaxLength: 32
MinLength: 1
Pattern: ^\[[0-9]+-[0-9]+\]$
Optional: {}
nodeStartupTimeout DurationnodeStartupTimeout allows to set the maximum time for MachineHealthCheck
to consider a Machine unhealthy if a corresponding Node isn’t associated
through a Spec.ProviderID field.
The duration set in this field is compared to the greatest of:
- Cluster’s infrastructure ready condition timestamp (if and when available)
- Control Plane’s initialized condition timestamp (if and when available)
- Machine’s infrastructure ready condition timestamp (if and when available)
- Machine’s metadata creation timestamp
Defaults to 10 minutes.
If you wish to disable this feature, set the value explicitly to 0.
Optional: {}
remediationTemplate ObjectReferenceremediationTemplate is a reference to a remediation template
provided by an infrastructure provider.
This field is completely optional, when filled, the MachineHealthCheck controller
creates a new object from the template referenced and hands off remediation of the machine to
a controller that lives outside of Cluster API.
Optional: {}

MachineHealthCheckList

MachineHealthCheckList contains a list of MachineHealthCheck.

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta1
kind stringMachineHealthCheckList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items MachineHealthCheck arrayitems is the list of MachineHealthChecks.

MachineHealthCheckSpec

MachineHealthCheckSpec defines the desired state of MachineHealthCheck.

Appears in:

FieldDescriptionDefaultValidation
clusterName stringclusterName is the name of the Cluster this object belongs to.MaxLength: 63
MinLength: 1
Required: {}
selector LabelSelectorselector is a label selector to match machines whose health will be exercisedRequired: {}
unhealthyConditions UnhealthyCondition arrayunhealthyConditions contains a list of the conditions that determine
whether a node is considered unhealthy. The conditions are combined in a
logical OR, i.e. if any of the conditions is met, the node is unhealthy.
MaxItems: 100
Optional: {}
unhealthyMachineConditions UnhealthyMachineCondition arrayunhealthyMachineConditions contains a list of the machine conditions that determine
whether a machine is considered unhealthy. The conditions are combined in a
logical OR, i.e. if any of the conditions is met, the machine is unhealthy.
MaxItems: 100
MinItems: 1
Optional: {}
maxUnhealthy IntOrStringmaxUnhealthy specifies the maximum number of unhealthy machines allowed.
Any further remediation is only allowed if at most “maxUnhealthy” machines selected by
“selector” are not healthy.
Deprecated: This field is deprecated and is going to be removed in the next apiVersion. Please see https://github.com/kubernetes-sigs/cluster-api/issues/10722 for more details.
Optional: {}
unhealthyRange stringunhealthyRange specifies the range of unhealthy machines allowed.
Any further remediation is only allowed if the number of machines selected by “selector” as not healthy
is within the range of “unhealthyRange”. Takes precedence over maxUnhealthy.
Eg. “[3-5]” - This means that remediation will be allowed only when:
(a) there are at least 3 unhealthy machines (and)
(b) there are at most 5 unhealthy machines
Deprecated: This field is deprecated and is going to be removed in the next apiVersion. Please see https://github.com/kubernetes-sigs/cluster-api/issues/10722 for more details.
MaxLength: 32
MinLength: 1
Pattern: ^\[[0-9]+-[0-9]+\]$
Optional: {}
nodeStartupTimeout DurationnodeStartupTimeout allows to set the maximum time for MachineHealthCheck
to consider a Machine unhealthy if a corresponding Node isn’t associated
through a Spec.ProviderID field.
The duration set in this field is compared to the greatest of:
- Cluster’s infrastructure ready condition timestamp (if and when available)
- Control Plane’s initialized condition timestamp (if and when available)
- Machine’s infrastructure ready condition timestamp (if and when available)
- Machine’s metadata creation timestamp
Defaults to 10 minutes.
If you wish to disable this feature, set the value explicitly to 0.
Optional: {}
remediationTemplate ObjectReferenceremediationTemplate is a reference to a remediation template
provided by an infrastructure provider.
This field is completely optional, when filled, the MachineHealthCheck controller
creates a new object from the template referenced and hands off remediation of the machine to
a controller that lives outside of Cluster API.
Optional: {}

MachineHealthCheckStatus

MachineHealthCheckStatus defines the observed state of MachineHealthCheck.

Appears in:

FieldDescriptionDefaultValidation
expectedMachines integerexpectedMachines is the total number of machines counted by this machine health checkMinimum: 0
Optional: {}
currentHealthy integercurrentHealthy is the total number of healthy machines counted by this machine health checkMinimum: 0
Optional: {}
remediationsAllowed integerremediationsAllowed is the number of further remediations allowed by this machine health check before
maxUnhealthy short circuiting will be applied
Minimum: 0
Optional: {}
observedGeneration integerobservedGeneration is the latest generation observed by the controller.Optional: {}
targets string arraytargets shows the current list of machines the machine health check is watchingMaxItems: 10000
items:MaxLength: 253
items:MinLength: 1
Optional: {}
conditions Conditionsconditions defines current service state of the MachineHealthCheck.Optional: {}
v1beta2 MachineHealthCheckV1Beta2Statusv1beta2 groups all the fields that will be added or modified in MachineHealthCheck’s status with the V1Beta2 version.Optional: {}

MachineHealthCheckTopology

MachineHealthCheckTopology defines a MachineHealthCheck for a group of machines.

Appears in:

FieldDescriptionDefaultValidation
enable booleanenable controls if a MachineHealthCheck should be created for the target machines.
If false: No MachineHealthCheck will be created.
If not set(default): A MachineHealthCheck will be created if it is defined here or
in the associated ClusterClass. If no MachineHealthCheck is defined then none will be created.
If true: A MachineHealthCheck is guaranteed to be created. Cluster validation will
block if enable is true and no MachineHealthCheck definition is available.
Optional: {}
unhealthyConditions UnhealthyCondition arrayunhealthyConditions contains a list of the conditions that determine
whether a node is considered unhealthy. The conditions are combined in a
logical OR, i.e. if any of the conditions is met, the node is unhealthy.
MaxItems: 100
Optional: {}
unhealthyMachineConditions UnhealthyMachineCondition arrayunhealthyMachineConditions contains a list of the machine conditions that determine
whether a machine is considered unhealthy. The conditions are combined in a
logical OR, i.e. if any of the conditions is met, the machine is unhealthy.
MaxItems: 100
MinItems: 1
Optional: {}
maxUnhealthy IntOrStringmaxUnhealthy specifies the maximum number of unhealthy machines allowed.
Any further remediation is only allowed if at most “maxUnhealthy” machines selected by
“selector” are not healthy.
Optional: {}
unhealthyRange stringunhealthyRange specifies the range of unhealthy machines allowed.
Any further remediation is only allowed if the number of machines selected by “selector” as not healthy
is within the range of “unhealthyRange”. Takes precedence over maxUnhealthy.
Eg. “[3-5]” - This means that remediation will be allowed only when:
(a) there are at least 3 unhealthy machines (and)
(b) there are at most 5 unhealthy machines
MaxLength: 32
MinLength: 1
Pattern: ^\[[0-9]+-[0-9]+\]$
Optional: {}
nodeStartupTimeout DurationnodeStartupTimeout allows to set the maximum time for MachineHealthCheck
to consider a Machine unhealthy if a corresponding Node isn’t associated
through a Spec.ProviderID field.
The duration set in this field is compared to the greatest of:
- Cluster’s infrastructure ready condition timestamp (if and when available)
- Control Plane’s initialized condition timestamp (if and when available)
- Machine’s infrastructure ready condition timestamp (if and when available)
- Machine’s metadata creation timestamp
Defaults to 10 minutes.
If you wish to disable this feature, set the value explicitly to 0.
Optional: {}
remediationTemplate ObjectReferenceremediationTemplate is a reference to a remediation template
provided by an infrastructure provider.
This field is completely optional, when filled, the MachineHealthCheck controller
creates a new object from the template referenced and hands off remediation of the machine to
a controller that lives outside of Cluster API.
Optional: {}

MachineHealthCheckV1Beta2Status

MachineHealthCheckV1Beta2Status groups all the fields that will be added or modified in MachineHealthCheck with the V1Beta2 version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a MachineHealthCheck’s current state.
Known condition types are RemediationAllowed, Paused.
MaxItems: 32
Optional: {}

MachineList

MachineList contains a list of Machine.

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta1
kind stringMachineList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items Machine arrayitems is the list of Machines.

MachineNamingStrategy

MachineNamingStrategy allows changing the naming pattern used when creating Machines. Note: InfraMachines & BootstrapConfigs will use the same name as the corresponding Machines.

Appears in:

FieldDescriptionDefaultValidation
template stringtemplate defines the template to use for generating the names of the
Machine objects.
If not defined, it will fallback to \{\{ .machineSet.name \}\}-\{\{ .random \}\}.
If the generated name string exceeds 63 characters, it will be trimmed to
58 characters and will
get concatenated with a random suffix of length 5.
Length of the template string must not exceed 256 characters.
The template allows the following variables .cluster.name,
.machineSet.name and .random.
The variable .cluster.name retrieves the name of the cluster object
that owns the Machines being created.
The variable .machineSet.name retrieves the name of the MachineSet
object that owns the Machines being created.
The variable .random is substituted with random alphanumeric string,
without vowels, of length 5. This variable is required part of the
template. If not provided, validation will fail.
MaxLength: 256
MinLength: 1
Optional: {}

MachinePool

MachinePool is the Schema for the machinepools API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta1
kind stringMachinePool
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
spec MachinePoolSpecspec is the desired state of MachinePool.Optional: {}
status MachinePoolStatusstatus is the observed state of MachinePool.Optional: {}

MachinePoolClass

MachinePoolClass serves as a template to define a pool of worker nodes of the cluster provisioned using ClusterClass.

Appears in:

FieldDescriptionDefaultValidation
class stringclass denotes a type of machine pool present in the cluster,
this name MUST be unique within a ClusterClass and can be referenced
in the Cluster to create a managed MachinePool.
MaxLength: 256
MinLength: 1
Required: {}
template MachinePoolClassTemplatetemplate is a local struct containing a collection of templates for creation of
MachinePools objects representing a pool of worker nodes.
Required: {}
failureDomains string arrayfailureDomains is the list of failure domains the MachinePool should be attached to.
Must match a key in the FailureDomains map stored on the cluster object.
NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.
MaxItems: 100
items:MaxLength: 256
items:MinLength: 1
Optional: {}
namingStrategy MachinePoolClassNamingStrategynamingStrategy allows changing the naming pattern used when creating the MachinePool.Optional: {}
nodeDrainTimeout DurationnodeDrainTimeout is the total amount of time that the controller will spend on draining a node.
The default value is 0, meaning that the node can be drained without any time limitations.
NOTE: NodeDrainTimeout is different from kubectl drain --timeout
NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.
Optional: {}
nodeVolumeDetachTimeout DurationnodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes
to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.
Optional: {}
nodeDeletionTimeout DurationnodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine
hosts after the Machine Pool is marked for deletion. A duration of 0 will retry deletion indefinitely.
Defaults to 10 seconds.
NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.
Optional: {}
taints MachineTaint arraytaints are the node taints that Cluster API will manage.
This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes,
e.g. the node controller might add the node.kubernetes.io/not-ready taint.
Only those taints defined in this list will be added or removed by core Cluster API controllers.
There can be at most 64 taints.
A pod would have to tolerate all existing taints to run on the corresponding node.
NOTE: This list is implemented as a “map” type, meaning that individual elements can be managed by different owners.
MaxItems: 64
MinItems: 1
Optional: {}
minReadySeconds integerminReadySeconds is the minimum number of seconds for which a newly created machine pool should
be ready.
Defaults to 0 (machine will be considered available as soon as it
is ready)
NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass.
Optional: {}

MachinePoolClassNamingStrategy

MachinePoolClassNamingStrategy defines the naming strategy for machine pool objects.

Appears in:

FieldDescriptionDefaultValidation
template stringtemplate defines the template to use for generating the name of the MachinePool object.
If not defined, it will fallback to \{\{ .cluster.name \}\}-\{\{ .machinePool.topologyName \}\}-\{\{ .random \}\}.
If the templated string exceeds 63 characters, it will be trimmed to 58 characters and will
get concatenated with a random suffix of length 5.
The templating mechanism provides the following arguments:
* .cluster.name: The name of the cluster object.
* .random: A random alphanumeric string, without vowels, of length 5.
* .machinePool.topologyName: The name of the MachinePool topology (Cluster.spec.topology.workers.machinePools[].name).
MaxLength: 1024
MinLength: 1
Optional: {}

MachinePoolClassTemplate

MachinePoolClassTemplate defines how a MachinePool generated from a MachinePoolClass should look like.

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
bootstrap LocalObjectTemplatebootstrap contains the bootstrap template reference to be used
for the creation of the Machines in the MachinePool.
Required: {}
infrastructure LocalObjectTemplateinfrastructure contains the infrastructure template reference to be used
for the creation of the MachinePool.
Required: {}

MachinePoolList

MachinePoolList contains a list of MachinePool.

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta1
kind stringMachinePoolList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items MachinePool arrayitems is the list of MachinePools.

MachinePoolSpec

MachinePoolSpec defines the desired state of MachinePool.

Appears in:

FieldDescriptionDefaultValidation
clusterName stringclusterName is the name of the Cluster this object belongs to.MaxLength: 63
MinLength: 1
Required: {}
replicas integerreplicas is the number of desired machines. Defaults to 1.
This is a pointer to distinguish between explicit zero and not specified.
Optional: {}
template MachineTemplateSpectemplate describes the machines that will be created.Required: {}
minReadySeconds integerminReadySeconds is the minimum number of seconds for which a newly created machine instances should
be ready.
Defaults to 0 (machine instance will be considered available as soon as it
is ready)
Optional: {}
providerIDList string arrayproviderIDList are the identification IDs of machine instances provided by the provider.
This field must match the provider IDs as seen on the node objects corresponding to a machine pool’s machine instances.
MaxItems: 10000
items:MaxLength: 512
items:MinLength: 1
Optional: {}
failureDomains string arrayfailureDomains is the list of failure domains this MachinePool should be attached to.MaxItems: 100
items:MaxLength: 256
items:MinLength: 1
Optional: {}

MachinePoolStatus

MachinePoolStatus defines the observed state of MachinePool.

Appears in:

FieldDescriptionDefaultValidation
nodeRefs ObjectReference arraynodeRefs will point to the corresponding Nodes if they exist.MaxItems: 10000
Optional: {}
replicas integerreplicas is the most recently observed number of replicas.Optional: {}
readyReplicas integerreadyReplicas is the number of ready replicas for this MachinePool. A machine is considered ready when the node has been created and is “Ready”.Optional: {}
availableReplicas integeravailableReplicas is the number of available replicas (ready for at least minReadySeconds) for this MachinePool.Optional: {}
unavailableReplicas integerunavailableReplicas is the total number of unavailable machine instances targeted by this machine pool.
This is the total number of machine instances that are still required for
the machine pool to have 100% available capacity. They may either
be machine instances that are running but not yet available or machine instances
that still have not been created.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
failureReason MachinePoolStatusFailurefailureReason indicates that there is a problem reconciling the state, and
will be set to a token value suitable for programmatic interpretation.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
failureMessage stringfailureMessage indicates that there is a problem reconciling the state,
and will be set to a descriptive error message.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
MaxLength: 10240
MinLength: 1
Optional: {}
phase stringphase represents the current phase of cluster actuation.Enum: [Pending Provisioning Provisioned Running ScalingUp ScalingDown Scaling Deleting Failed Unknown]
Optional: {}
bootstrapReady booleanbootstrapReady is the state of the bootstrap provider.Optional: {}
infrastructureReady booleaninfrastructureReady is the state of the infrastructure provider.Optional: {}
observedGeneration integerobservedGeneration is the latest generation observed by the controller.Optional: {}
conditions Conditionsconditions define the current service state of the MachinePool.Optional: {}
versions StatusVersion arrayversions is the aggregated Kubernetes versions in this MachinePool.MaxItems: 100
MinItems: 1
Optional: {}
v1beta2 MachinePoolV1Beta2Statusv1beta2 groups all the fields that will be added or modified in MachinePool’s status with the V1Beta2 version.Optional: {}

MachinePoolTopology

MachinePoolTopology specifies the different parameters for a pool of worker nodes in the topology. This pool of nodes is managed by a MachinePool object whose lifecycle is managed by the Cluster controller.

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
class stringclass is the name of the MachinePoolClass used to create the pool of worker nodes.
This should match one of the deployment classes defined in the ClusterClass object
mentioned in the Cluster.Spec.Class field.
MaxLength: 256
MinLength: 1
Required: {}
name stringname is the unique identifier for this MachinePoolTopology.
The value is used with other unique identifiers to create a MachinePool’s Name
(e.g. cluster’s name, etc). In case the name is greater than the allowed maximum length,
the values are hashed together.
MaxLength: 63
MinLength: 1
Required: {}
failureDomains string arrayfailureDomains is the list of failure domains the machine pool will be created in.
Must match a key in the FailureDomains map stored on the cluster object.
MaxItems: 100
items:MaxLength: 256
items:MinLength: 1
Optional: {}
nodeDrainTimeout DurationnodeDrainTimeout is the total amount of time that the controller will spend on draining a node.
The default value is 0, meaning that the node can be drained without any time limitations.
NOTE: NodeDrainTimeout is different from kubectl drain --timeout
Optional: {}
nodeVolumeDetachTimeout DurationnodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes
to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
Optional: {}
nodeDeletionTimeout DurationnodeDeletionTimeout defines how long the controller will attempt to delete the Node that the MachinePool
hosts after the MachinePool is marked for deletion. A duration of 0 will retry deletion indefinitely.
Defaults to 10 seconds.
Optional: {}
taints MachineTaint arraytaints are the node taints that Cluster API will manage.
This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes,
e.g. the node controller might add the node.kubernetes.io/not-ready taint.
Only those taints defined in this list will be added or removed by core Cluster API controllers.
There can be at most 64 taints.
A pod would have to tolerate all existing taints to run on the corresponding node.
NOTE: This list is implemented as a “map” type, meaning that individual elements can be managed by different owners.
MaxItems: 64
MinItems: 1
Optional: {}
minReadySeconds integerminReadySeconds is the minimum number of seconds for which a newly created machine pool should
be ready.
Defaults to 0 (machine will be considered available as soon as it
is ready)
Optional: {}
replicas integerreplicas is the number of nodes belonging to this pool.
If the value is nil, the MachinePool is created without the number of Replicas (defaulting to 1)
and it’s assumed that an external entity (like cluster autoscaler) is responsible for the management
of this value.
Optional: {}
variables MachinePoolVariablesvariables can be used to customize the MachinePool through patches.Optional: {}

MachinePoolV1Beta2Status

MachinePoolV1Beta2Status groups all the fields that will be added or modified in MachinePoolStatus with the V1Beta2 version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a MachinePool’s current state.
Known condition types are Available, BootstrapConfigReady, InfrastructureReady, MachinesReady, MachinesUpToDate,
ScalingUp, ScalingDown, Remediating, Deleting, Paused.
MaxItems: 32
Optional: {}
readyReplicas integerreadyReplicas is the number of ready replicas for this MachinePool. A machine is considered ready when Machine’s Ready condition is true.Optional: {}
availableReplicas integeravailableReplicas is the number of available replicas for this MachinePool. A machine is considered available when Machine’s Available condition is true.Optional: {}
upToDateReplicas integerupToDateReplicas is the number of up-to-date replicas targeted by this MachinePool. A machine is considered up-to-date when Machine’s UpToDate condition is true.Optional: {}

MachinePoolVariables

MachinePoolVariables can be used to provide variables for a specific MachinePool.

Appears in:

FieldDescriptionDefaultValidation
overrides ClusterVariable arrayoverrides can be used to override Cluster level variables.MaxItems: 1000
Optional: {}

MachineReadinessGate

MachineReadinessGate contains the type of a Machine condition to be used as a readiness gate.

Appears in:

FieldDescriptionDefaultValidation
conditionType stringconditionType refers to a condition with matching type in the Machine’s condition list.
If the conditions doesn’t exist, it will be treated as unknown.
Note: Both Cluster API conditions or conditions added by 3rd party controllers can be used as readiness gates.
MaxLength: 316
MinLength: 1
Pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
Required: {}
polarity ConditionPolaritypolarity of the conditionType specified in this readinessGate.
Valid values are Positive, Negative and omitted.
When omitted, the default behaviour will be Positive.
A positive polarity means that the condition should report a true status under normal conditions.
A negative polarity means that the condition should report a false status under normal conditions.
Enum: [Positive Negative]
Optional: {}

MachineRollingUpdateDeployment

Underlying type: struct{MaxUnavailable *k8s.io/apimachinery/pkg/util/intstr.IntOrString “json:"maxUnavailable,omitempty"”; MaxSurge *k8s.io/apimachinery/pkg/util/intstr.IntOrString “json:"maxSurge,omitempty"”; DeletePolicy *string “json:"deletePolicy,omitempty"”}

MachineRollingUpdateDeployment is used to control the desired behavior of rolling update.

Appears in:

MachineSet

MachineSet is the Schema for the machinesets API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta1
kind stringMachineSet
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
spec MachineSetSpecspec is the desired state of MachineSet.Optional: {}
status MachineSetStatusstatus is the observed state of MachineSet.Optional: {}

MachineSetList

MachineSetList contains a list of MachineSet.

FieldDescriptionDefaultValidation
apiVersion stringcluster.x-k8s.io/v1beta1
kind stringMachineSetList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items MachineSet arrayitems is the list of MachineSets.

MachineSetSpec

MachineSetSpec defines the desired state of MachineSet.

Appears in:

FieldDescriptionDefaultValidation
clusterName stringclusterName is the name of the Cluster this object belongs to.MaxLength: 63
MinLength: 1
Required: {}
replicas integerreplicas is the number of desired replicas.
This is a pointer to distinguish between explicit zero and unspecified.
Defaults to:
* if the Kubernetes autoscaler min size and max size annotations are set:
- if it’s a new MachineSet, use min size
- if the replicas field of the old MachineSet is < min size, use min size
- if the replicas field of the old MachineSet is > max size, use max size
- if the replicas field of the old MachineSet is in the (min size, max size) range, keep the value from the oldMS
* otherwise use 1
Note: Defaulting will be run whenever the replicas field is not set:
* A new MachineSet is created with replicas not set.
* On an existing MachineSet the replicas field was first set and is now unset.
Those cases are especially relevant for the following Kubernetes autoscaler use cases:
* A new MachineSet is created and replicas should be managed by the autoscaler
* An existing MachineSet which initially wasn’t controlled by the autoscaler
should be later controlled by the autoscaler
Optional: {}
minReadySeconds integerminReadySeconds is the minimum number of seconds for which a Node for a newly created machine should be ready before considering the replica available.
Defaults to 0 (machine will be considered available as soon as the Node is ready)
Optional: {}
deletePolicy stringdeletePolicy defines the policy used to identify nodes to delete when downscaling.
Defaults to “Random”. Valid values are “Random”, “Newest”, “Oldest”
Enum: [Random Newest Oldest]
Optional: {}
selector LabelSelectorselector is a label query over machines that should match the replica count.
Label keys and values that must match in order to be controlled by this MachineSet.
It must match the machine template’s labels.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
Required: {}
template MachineTemplateSpectemplate is the object that describes the machine that will be created if
insufficient replicas are detected.
Object references to custom resources are treated as templates.
Optional: {}
machineNamingStrategy MachineNamingStrategymachineNamingStrategy allows changing the naming pattern used when creating Machines.
Note: InfraMachines & BootstrapConfigs will use the same name as the corresponding Machines.
Optional: {}

MachineSetStatus

MachineSetStatus defines the observed state of MachineSet.

Appears in:

FieldDescriptionDefaultValidation
selector stringselector is the same as the label selector but in the string format to avoid introspection
by clients. The string will be in the same format as the query-param syntax.
More info about label selectors: http://kubernetes.io/docs/user-guide/labels#label-selectors
MaxLength: 4096
MinLength: 1
Optional: {}
replicas integerreplicas is the most recently observed number of replicas.Optional: {}
fullyLabeledReplicas integerfullyLabeledReplicas is the number of replicas that have labels matching the labels of the machine template of the MachineSet.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
readyReplicas integerreadyReplicas is the number of ready replicas for this MachineSet. A machine is considered ready when the node has been created and is “Ready”.Optional: {}
availableReplicas integeravailableReplicas is the number of available replicas (ready for at least minReadySeconds) for this MachineSet.Optional: {}
observedGeneration integerobservedGeneration reflects the generation of the most recently observed MachineSet.Optional: {}
failureReason MachineSetStatusErrorfailureReason will be set in the event that there is a terminal problem
reconciling the Machine and will contain a succinct value suitable
for machine interpretation.
In the event that there is a terminal problem reconciling the
replicas, both FailureReason and FailureMessage will be set. FailureReason
will be populated with a succinct value suitable for machine
interpretation, while FailureMessage will contain a more verbose
string suitable for logging and human consumption.
These fields should not be set for transitive errors that a
controller faces that are expected to be fixed automatically over
time (like service outages), but instead indicate that something is
fundamentally wrong with the MachineTemplate’s spec or the configuration of
the machine controller, and that manual intervention is required. Examples
of terminal errors would be invalid combinations of settings in the
spec, values that are unsupported by the machine controller, or the
responsible machine controller itself being critically misconfigured.
Any transient errors that occur during the reconciliation of Machines
can be added as events to the MachineSet object and/or logged in the
controller’s output.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
failureMessage stringfailureMessage will be set in the event that there is a terminal problem
reconciling the Machine and will contain a more verbose string suitable
for logging and human consumption.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
MaxLength: 10240
MinLength: 1
Optional: {}
conditions Conditionsconditions defines current service state of the MachineSet.Optional: {}
versions StatusVersion arrayversions is the aggregated Kubernetes versions in this MachineSet.MaxItems: 100
MinItems: 1
Optional: {}
v1beta2 MachineSetV1Beta2Statusv1beta2 groups all the fields that will be added or modified in MachineSet’s status with the V1Beta2 version.Optional: {}

MachineSetV1Beta2Status

MachineSetV1Beta2Status groups all the fields that will be added or modified in MachineSetStatus with the V1Beta2 version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a MachineSet’s current state.
Known condition types are MachinesReady, MachinesUpToDate, ScalingUp, ScalingDown, Remediating, Deleting, Paused.
MaxItems: 32
Optional: {}
readyReplicas integerreadyReplicas is the number of ready replicas for this MachineSet. A machine is considered ready when Machine’s Ready condition is true.Optional: {}
availableReplicas integeravailableReplicas is the number of available replicas for this MachineSet. A machine is considered available when Machine’s Available condition is true.Optional: {}
upToDateReplicas integerupToDateReplicas is the number of up-to-date replicas for this MachineSet. A machine is considered up-to-date when Machine’s UpToDate condition is true.Optional: {}

MachineSpec

MachineSpec defines the desired state of Machine.

Appears in:

FieldDescriptionDefaultValidation
clusterName stringclusterName is the name of the Cluster this object belongs to.MaxLength: 63
MinLength: 1
Required: {}
bootstrap Bootstrapbootstrap is a reference to a local struct which encapsulates
fields to configure the Machine’s bootstrapping mechanism.
Required: {}
infrastructureRef ObjectReferenceinfrastructureRef is a required reference to a custom resource
offered by an infrastructure provider.
Required: {}
version stringversion defines the desired Kubernetes version.
This field is meant to be optionally used by bootstrap providers.
MaxLength: 256
MinLength: 1
Optional: {}
providerID stringproviderID is the identification ID of the machine provided by the provider.
This field must match the provider ID as seen on the node object corresponding to this machine.
This field is required by higher level consumers of cluster-api. Example use case is cluster autoscaler
with cluster-api as provider. Clean-up logic in the autoscaler compares machines to nodes to find out
machines at provider which could not get registered as Kubernetes nodes. With cluster-api as a
generic out-of-tree provider for autoscaler, this field is required by autoscaler to be
able to have a provider view of the list of machines. Another list of nodes is queried from the k8s apiserver
and then a comparison is done to find out unregistered machines and are marked for delete.
This field will be set by the actuators and consumed by higher level entities like autoscaler that will
be interfacing with cluster-api as generic provider.
MaxLength: 512
MinLength: 1
Optional: {}
failureDomain stringfailureDomain is the failure domain the machine will be created in.
Must match a key in the FailureDomains map stored on the cluster object.
MaxLength: 256
MinLength: 1
Optional: {}
readinessGates MachineReadinessGate arrayreadinessGates specifies additional conditions to include when evaluating Machine Ready condition.
This field can be used e.g. by Cluster API control plane providers to extend the semantic of the
Ready condition for the Machine they control, like the kubeadm control provider adding ReadinessGates
for the APIServerPodHealthy, SchedulerPodHealthy conditions, etc.
Another example are external controllers, e.g. responsible to install special software/hardware on the Machines;
they can include the status of those components with a new condition and add this condition to ReadinessGates.
NOTE: This field is considered only for computing v1beta2 conditions.
NOTE: In case readinessGates conditions start with the APIServer, ControllerManager, Scheduler prefix, and all those
readiness gates condition are reporting the same message, when computing the Machine’s Ready condition those
readinessGates will be replaced by a single entry reporting “Control plane components: “ + message.
This helps to improve readability of conditions bubbling up to the Machine’s owner resource / to the Cluster).
MaxItems: 32
Optional: {}
nodeDrainTimeout DurationnodeDrainTimeout is the total amount of time that the controller will spend on draining a node.
The default value is 0, meaning that the node can be drained without any time limitations.
NOTE: NodeDrainTimeout is different from kubectl drain --timeout
Optional: {}
nodeVolumeDetachTimeout DurationnodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes
to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
Optional: {}
nodeDeletionTimeout DurationnodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine
hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely.
Defaults to 10 seconds.
Optional: {}
taints MachineTaint arraytaints are the node taints that Cluster API will manage.
This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes,
e.g. the node controller might add the node.kubernetes.io/not-ready taint.
Only those taints defined in this list will be added or removed by core Cluster API controllers.
There can be at most 64 taints.
A pod would have to tolerate all existing taints to run on the corresponding node.
NOTE: This list is implemented as a “map” type, meaning that individual elements can be managed by different owners.
MaxItems: 64
MinItems: 1
Optional: {}

MachineStatus

MachineStatus defines the observed state of Machine.

Appears in:

FieldDescriptionDefaultValidation
nodeRef ObjectReferencenodeRef will point to the corresponding Node if it exists.Optional: {}
nodeInfo NodeSystemInfonodeInfo is a set of ids/uuids to uniquely identify the node.
More info: https://kubernetes.io/docs/concepts/nodes/node/#info
Optional: {}
failureReason MachineStatusErrorfailureReason will be set in the event that there is a terminal problem
reconciling the Machine and will contain a succinct value suitable
for machine interpretation.
This field should not be set for transitive errors that a controller
faces that are expected to be fixed automatically over
time (like service outages), but instead indicate that something is
fundamentally wrong with the Machine’s spec or the configuration of
the controller, and that manual intervention is required. Examples
of terminal errors would be invalid combinations of settings in the
spec, values that are unsupported by the controller, or the
responsible controller itself being critically misconfigured.
Any transient errors that occur during the reconciliation of Machines
can be added as events to the Machine object and/or logged in the
controller’s output.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
failureMessage stringfailureMessage will be set in the event that there is a terminal problem
reconciling the Machine and will contain a more verbose string suitable
for logging and human consumption.
This field should not be set for transitive errors that a controller
faces that are expected to be fixed automatically over
time (like service outages), but instead indicate that something is
fundamentally wrong with the Machine’s spec or the configuration of
the controller, and that manual intervention is required. Examples
of terminal errors would be invalid combinations of settings in the
spec, values that are unsupported by the controller, or the
responsible controller itself being critically misconfigured.
Any transient errors that occur during the reconciliation of Machines
can be added as events to the Machine object and/or logged in the
controller’s output.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
MaxLength: 10240
MinLength: 1
Optional: {}
addresses MachineAddressesaddresses is a list of addresses assigned to the machine.
This field is copied from the infrastructure provider reference.
Optional: {}
phase stringphase represents the current phase of machine actuation.Enum: [Pending Provisioning Provisioned Running Deleting Deleted Failed Unknown]
Optional: {}
bootstrapReady booleanbootstrapReady is the state of the bootstrap provider.Optional: {}
infrastructureReady booleaninfrastructureReady is the state of the infrastructure provider.Optional: {}
observedGeneration integerobservedGeneration is the latest generation observed by the controller.Optional: {}
conditions Conditionsconditions defines current service state of the Machine.Optional: {}
deletion MachineDeletionStatusdeletion contains information relating to removal of the Machine.
Only present when the Machine has a deletionTimestamp and drain or wait for volume detach started.
Optional: {}
v1beta2 MachineV1Beta2Statusv1beta2 groups all the fields that will be added or modified in Machine’s status with the V1Beta2 version.Optional: {}

MachineTaint

MachineTaint defines a taint equivalent to corev1.Taint, but additionally having a propagation field.

Appears in:

FieldDescriptionDefaultValidation
key stringkey is the taint key to be applied to a node.
Must be a valid qualified name of maximum size 63 characters
with an optional subdomain prefix of maximum size 253 characters,
separated by a /.
MaxLength: 317
MinLength: 1
Pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/)?([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$
Required: {}
value stringvalue is the taint value corresponding to the taint key.
It must be a valid label value of maximum size 63 characters.
MaxLength: 63
MinLength: 1
Pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$
Optional: {}
effect TaintEffecteffect is the effect for the taint. Valid values are NoSchedule, PreferNoSchedule and NoExecute.Enum: [NoSchedule PreferNoSchedule NoExecute]
Required: {}
propagation MachineTaintPropagationpropagation defines how this taint should be propagated to nodes.
Valid values are ‘Always’ and ‘OnInitialization’.
Always: The taint will be continuously reconciled. If it is not set for a node, it will be added during reconciliation.
OnInitialization: The taint will be added during node initialization. If it gets removed from the node later on it will not get added again.
Enum: [Always OnInitialization]
Required: {}

MachineTaintPropagation

Underlying type: string

MachineTaintPropagation defines when a taint should be propagated to nodes.

Validation:

  • Enum: [Always OnInitialization]

Appears in:

FieldDescription
AlwaysMachineTaintPropagationAlways means the taint should be continuously reconciled and kept on the node.
- If an Always taint is added to the Machine, the taint will be added to the node.
- If an Always taint is removed from the Machine, the taint will be removed from the node.
- If an OnInitialization taint is changed to Always, the Machine controller will ensure the taint is set on the node.
- If an Always taint is removed from the node, it will be re-added during reconciliation.
OnInitializationMachineTaintPropagationOnInitialization means the taint should be set once during initialization and then
left alone.
- If an OnInitialization taint is added to the Machine, the taint will only be added to the node on initialization.
- If an OnInitialization taint is removed from the Machine nothing will be changed on the node.
- If an Always taint is changed to OnInitialization, the taint will only be added to the node on initialization.
- If an OnInitialization taint is removed from the node, it will not be re-added during reconciliation.

MachineTemplateSpec

MachineTemplateSpec describes the data needed to create a Machine from a template.

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
spec MachineSpecspec is the specification of the desired behavior of the machine.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
Optional: {}

MachineV1Beta2Status

MachineV1Beta2Status groups all the fields that will be added or modified in MachineStatus with the V1Beta2 version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a Machine’s current state.
Known condition types are Available, Ready, UpToDate, BootstrapConfigReady, InfrastructureReady, NodeReady,
NodeHealthy, Deleting, Paused.
If a MachineHealthCheck is targeting this machine, also HealthCheckSucceeded, OwnerRemediated conditions are added.
Additionally control plane Machines controlled by KubeadmControlPlane will have following additional conditions:
APIServerPodHealthy, ControllerManagerPodHealthy, SchedulerPodHealthy, EtcdPodHealthy, EtcdMemberHealthy.
MaxItems: 32
Optional: {}

NetworkRanges

NetworkRanges represents ranges of network addresses.

Appears in:

FieldDescriptionDefaultValidation
cidrBlocks string arraycidrBlocks is a list of CIDR blocks.MaxItems: 100
items:MaxLength: 43
items:MinLength: 1
Required: {}

ObjectMeta

ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create. This is a copy of customizable fields from metav1.ObjectMeta.

ObjectMeta is embedded in Machine.Spec, MachineDeployment.Template and MachineSet.Template, which are not top-level Kubernetes objects. Given that metav1.ObjectMeta has lots of special cases and read-only fields which end up in the generated CRD validation, having it as a subset simplifies the API and some issues that can impact user experience.

During the upgrade to controller-tools@v2 for v1alpha2, we noticed a failure would occur running Cluster API test suite against the new CRDs, specifically spec.metadata.creationTimestamp in body must be of type string: "null". The investigation showed that controller-tools@v2 behaves differently than its previous version when handling types from metav1 package.

In more details, we found that embedded (non-top level) types that embedded metav1.ObjectMeta had validation properties, including for creationTimestamp (metav1.Time). The metav1.Time type specifies a custom json marshaller that, when IsZero() is true, returns null which breaks validation because the field isn’t marked as nullable.

In future versions, controller-tools@v2 might allow overriding the type and validation for embedded types. When that happens, this hack should be revisited.

Appears in:

FieldDescriptionDefaultValidation
labels object (keys:string, values:string)labels is a map of string keys and values that can be used to organize and categorize
(scope and select) objects. May match selectors of replication controllers
and services.
More info: http://kubernetes.io/docs/user-guide/labels
Optional: {}
annotations object (keys:string, values:string)annotations is an unstructured key value map stored with a resource that may be
set by external tools to store and retrieve arbitrary metadata. They are not
queryable and should be preserved when modifying objects.
More info: http://kubernetes.io/docs/user-guide/annotations
Optional: {}

PatchDefinition

PatchDefinition defines a patch which is applied to customize the referenced templates.

Appears in:

FieldDescriptionDefaultValidation
selector PatchSelectorselector defines on which templates the patch should be applied.Required: {}
jsonPatches JSONPatch arrayjsonPatches defines the patches which should be applied on the templates
matching the selector.
Note: Patches will be applied in the order of the array.
MaxItems: 100
Required: {}

PatchSelector

PatchSelector defines on which templates the patch should be applied. Note: Matching on APIVersion and Kind is mandatory, to enforce that the patches are written for the correct version. The version of the references in the ClusterClass may be automatically updated during reconciliation if there is a newer version for the same contract. Note: The results of selection based on the individual fields are ANDed.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringapiVersion filters templates by apiVersion.MaxLength: 512
MinLength: 1
Required: {}
kind stringkind filters templates by kind.MaxLength: 256
MinLength: 1
Required: {}
matchResources PatchSelectorMatchmatchResources selects templates based on where they are referenced.Required: {}

PatchSelectorMatch

PatchSelectorMatch selects templates based on where they are referenced. Note: The selector must match at least one template. Note: The results of selection based on the individual fields are ORed.

Appears in:

FieldDescriptionDefaultValidation
controlPlane booleancontrolPlane selects templates referenced in .spec.ControlPlane.
Note: this will match the controlPlane and also the controlPlane
machineInfrastructure (depending on the kind and apiVersion).
Optional: {}
infrastructureCluster booleaninfrastructureCluster selects templates referenced in .spec.infrastructure.Optional: {}
machineDeploymentClass PatchSelectorMatchMachineDeploymentClassmachineDeploymentClass selects templates referenced in specific MachineDeploymentClasses in
.spec.workers.machineDeployments.
Optional: {}
machinePoolClass PatchSelectorMatchMachinePoolClassmachinePoolClass selects templates referenced in specific MachinePoolClasses in
.spec.workers.machinePools.
Optional: {}

PatchSelectorMatchMachineDeploymentClass

PatchSelectorMatchMachineDeploymentClass selects templates referenced in specific MachineDeploymentClasses in .spec.workers.machineDeployments.

Appears in:

FieldDescriptionDefaultValidation
names string arraynames selects templates by class names.MaxItems: 100
items:MaxLength: 256
items:MinLength: 1
Optional: {}

PatchSelectorMatchMachinePoolClass

PatchSelectorMatchMachinePoolClass selects templates referenced in specific MachinePoolClasses in .spec.workers.machinePools.

Appears in:

FieldDescriptionDefaultValidation
names string arraynames selects templates by class names.MaxItems: 100
items:MaxLength: 256
items:MinLength: 1
Optional: {}

RemediationStrategy

Underlying type: struct{MaxInFlight *k8s.io/apimachinery/pkg/util/intstr.IntOrString “json:"maxInFlight,omitempty"”}

RemediationStrategy allows to define how the MachineSet can control scaling operations.

Appears in:

StatusUpgradePlanVersion

StatusUpgradePlanVersion groups upgrade plan version-related status information.

Appears in:

FieldDescriptionDefaultValidation
version stringversion is the Kubernetes version.MaxLength: 256
MinLength: 1
Required: {}

StatusVersion

StatusVersion groups version-related status information.

Appears in:

FieldDescriptionDefaultValidation
version stringversion is the Kubernetes version.MaxLength: 256
MinLength: 1
Required: {}
replicas integerreplicas is the number of replicas at this version.Minimum: 1
Optional: {}

Topology

Topology encapsulates the information of the managed resources.

Appears in:

FieldDescriptionDefaultValidation
class stringclass is the name of the ClusterClass object to create the topology.MaxLength: 253
MinLength: 1
Required: {}
classNamespace stringclassNamespace is the namespace of the ClusterClass that should be used for the topology.
If classNamespace is empty or not set, it is defaulted to the namespace of the Cluster object.
classNamespace must be a valid namespace name and because of that be at most 63 characters in length
and it must consist only of lower case alphanumeric characters or hyphens (-), and must start
and end with an alphanumeric character.
MaxLength: 63
MinLength: 1
Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
Optional: {}
version stringversion is the Kubernetes version of the cluster.MaxLength: 256
MinLength: 1
Required: {}
controlPlane ControlPlaneTopologycontrolPlane describes the cluster control plane.Optional: {}
workers WorkersTopologyworkers encapsulates the different constructs that form the worker nodes
for the cluster.
Optional: {}
variables ClusterVariable arrayvariables can be used to customize the Cluster through
patches. They must comply to the corresponding
VariableClasses defined in the ClusterClass.
MaxItems: 1000
Optional: {}

UnhealthyCondition

UnhealthyCondition represents a Node condition type and value with a timeout specified as a duration. When the named condition has been in the given status for at least the timeout value, a node is considered unhealthy.

Appears in:

FieldDescriptionDefaultValidation
type NodeConditionTypetype of Node conditionMinLength: 1
Type: string
Required: {}
status ConditionStatusstatus of the condition, one of True, False, Unknown.MinLength: 1
Type: string
Required: {}
timeout Durationtimeout is the duration that a node must be in a given status for,
after which the node is considered unhealthy.
For example, with a value of “1h”, the node must match the status
for at least 1 hour before being considered unhealthy.
Required: {}

UnhealthyMachineCondition

UnhealthyMachineCondition represents a Machine condition type and value with a timeout specified as a duration. When the named condition has been in the given status for at least the timeout value, a machine is considered unhealthy.

Appears in:

FieldDescriptionDefaultValidation
type stringtype of Machine conditionMaxLength: 316
MinLength: 1
Pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
Required: {}
status ConditionStatusstatus of the condition, one of True, False, Unknown.Enum: [True False Unknown]
Required: {}
timeout Durationtimeout is the duration that a Machine must be in a given status for,
after which the Machine is considered unhealthy.
For example, with a value of “1h”, the Machine must match the status
for at least 1 hour before being considered unhealthy.
Required: {}

VariableSchema

VariableSchema defines the schema of a variable.

Appears in:

FieldDescriptionDefaultValidation
openAPIV3Schema JSONSchemaPropsopenAPIV3Schema defines the schema of a variable via OpenAPI v3
schema. The schema is a subset of the schema used in
Kubernetes CRDs.
Required: {}

WorkersClass

WorkersClass is a collection of deployment classes.

Appears in:

FieldDescriptionDefaultValidation
machineDeployments MachineDeploymentClass arraymachineDeployments is a list of machine deployment classes that can be used to create
a set of worker nodes.
MaxItems: 100
Optional: {}
machinePools MachinePoolClass arraymachinePools is a list of machine pool classes that can be used to create
a set of worker nodes.
MaxItems: 100
Optional: {}

WorkersStatus

WorkersStatus groups all the observations about workers current state.

Appears in:

FieldDescriptionDefaultValidation
desiredReplicas integerdesiredReplicas is the total number of desired worker machines in this cluster.Optional: {}
replicas integerreplicas is the total number of worker machines in this cluster.
NOTE: replicas also includes machines still being provisioned or being deleted.
Optional: {}
upToDateReplicas integerupToDateReplicas is the number of up-to-date worker machines in this cluster. A machine is considered up-to-date when Machine’s UpToDate condition is true.Optional: {}
readyReplicas integerreadyReplicas is the total number of ready worker machines in this cluster. A machine is considered ready when Machine’s Ready condition is true.Optional: {}
availableReplicas integeravailableReplicas is the total number of available worker machines in this cluster. A machine is considered available when Machine’s Available condition is true.Optional: {}
versions StatusVersion arrayversions is the aggregated Kubernetes versions in cluster workers.MaxItems: 32
MinItems: 1
Optional: {}
upgradePlan StatusUpgradePlanVersion arrayupgradePlan reports the list of versions that would be applied to the worker objects (all MachineDeployments and MachinePools).
Note:
- This field is set only when the Cluster topology is managed by Cluster API and a Cluster upgrade is in progress.
- Once a version is applied to the worker objects, it is removed from the list (after a version
is applied to a worker object, it might take some time for the actual upgrade to complete)
- During a chained upgrade, the upgrade plan is continuously re-computed, and this field will
report only the last known upgrade plan.
MaxItems: 32
MinItems: 1
Optional: {}

WorkersTopology

WorkersTopology represents the different sets of worker nodes in the cluster.

Appears in:

FieldDescriptionDefaultValidation
machineDeployments MachineDeploymentTopology arraymachineDeployments is a list of machine deployments in the cluster.MaxItems: 2000
Optional: {}
machinePools MachinePoolTopology arraymachinePools is a list of machine pools in the cluster.MaxItems: 2000
Optional: {}

controlplane.cluster.x-k8s.io/v1beta1

Package v1beta1 contains API Schema definitions for the kubeadm v1beta1 API group,

Deprecated: This package is deprecated and is going to be removed when support for v1beta1 will be dropped.

Resource Types

KubeadmControlPlane

KubeadmControlPlane is the Schema for the KubeadmControlPlane API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringcontrolplane.cluster.x-k8s.io/v1beta1
kind stringKubeadmControlPlane
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
spec KubeadmControlPlaneSpecspec is the desired state of KubeadmControlPlane.Optional: {}
status KubeadmControlPlaneStatusstatus is the observed state of KubeadmControlPlane.Optional: {}

KubeadmControlPlaneList

KubeadmControlPlaneList contains a list of KubeadmControlPlane.

FieldDescriptionDefaultValidation
apiVersion stringcontrolplane.cluster.x-k8s.io/v1beta1
kind stringKubeadmControlPlaneList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items KubeadmControlPlane arrayitems is the list of KubeadmControlPlanes.

KubeadmControlPlaneMachineTemplate

KubeadmControlPlaneMachineTemplate defines the template for Machines in a KubeadmControlPlane object.

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
infrastructureRef ObjectReferenceinfrastructureRef is a required reference to a custom resource
offered by an infrastructure provider.
Required: {}
readinessGates MachineReadinessGate arrayreadinessGates specifies additional conditions to include when evaluating Machine Ready condition;
KubeadmControlPlane will always add readinessGates for the condition it is setting on the Machine:
APIServerPodHealthy, SchedulerPodHealthy, ControllerManagerPodHealthy, and if etcd is managed by CKP also
EtcdPodHealthy, EtcdMemberHealthy.
This field can be used e.g. to instruct the machine controller to include in the computation for Machine’s ready
computation a condition, managed by an external controllers, reporting the status of special software/hardware installed on the Machine.
NOTE: This field is considered only for computing v1beta2 conditions.
MaxItems: 32
Optional: {}
nodeDrainTimeout DurationnodeDrainTimeout is the total amount of time that the controller will spend on draining a controlplane node
The default value is 0, meaning that the node can be drained without any time limitations.
NOTE: NodeDrainTimeout is different from kubectl drain --timeout
Optional: {}
nodeVolumeDetachTimeout DurationnodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes
to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
Optional: {}
nodeDeletionTimeout DurationnodeDeletionTimeout defines how long the machine controller will attempt to delete the Node that the Machine
hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely.
If no value is provided, the default value for this property of the Machine resource will be used.
Optional: {}
taints MachineTaint arraytaints are the node taints that Cluster API will manage.
This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes,
e.g. the node controller might add the node.kubernetes.io/not-ready taint.
Only those taints defined in this list will be added or removed by core Cluster API controllers.
There can be at most 64 taints.
A pod would have to tolerate all existing taints to run on the corresponding node.
NOTE: This list is implemented as a “map” type, meaning that individual elements can be managed by different owners.
MaxItems: 64
MinItems: 1
Optional: {}

KubeadmControlPlaneSpec

KubeadmControlPlaneSpec defines the desired state of KubeadmControlPlane.

Appears in:

FieldDescriptionDefaultValidation
replicas integerreplicas is the number of desired machines. Defaults to 1. When stacked etcd is used only
odd numbers are permitted, as per etcd best practice.
This is a pointer to distinguish between explicit zero and not specified.
Optional: {}
version stringversion defines the desired Kubernetes version.
Please note that if kubeadmConfigSpec.ClusterConfiguration.imageRepository is not set
we don’t allow upgrades to versions >= v1.22.0 for which kubeadm uses the old registry (k8s.gcr.io).
Please use a newer patch version with the new registry instead. The default registries of kubeadm are:
* registry.k8s.io (new registry): >= v1.22.17, >= v1.23.15, >= v1.24.9, >= v1.25.0
* k8s.gcr.io (old registry): all older versions
MaxLength: 256
MinLength: 1
Required: {}
machineTemplate KubeadmControlPlaneMachineTemplatemachineTemplate contains information about how machines
should be shaped when creating or updating a control plane.
Required: {}
kubeadmConfigSpec KubeadmConfigSpeckubeadmConfigSpec is a KubeadmConfigSpec
to use for initializing and joining machines to the control plane.
Required: {}
rolloutBefore RolloutBeforerolloutBefore is a field to indicate a rollout should be performed
if the specified criteria is met.
Optional: {}
rolloutStrategy RolloutStrategyrolloutStrategy is the RolloutStrategy to use to replace control plane machines with
new ones.
{ rollingUpdate:map[maxSurge:1] type:RollingUpdate }Optional: {}
remediationStrategy RemediationStrategyremediationStrategy is the RemediationStrategy that controls how control plane machine remediation happens.Optional: {}
machineNamingStrategy MachineNamingStrategymachineNamingStrategy allows changing the naming pattern used when creating Machines.
InfraMachines & KubeadmConfigs will use the same name as the corresponding Machines.
Optional: {}

KubeadmControlPlaneStatus

KubeadmControlPlaneStatus defines the observed state of KubeadmControlPlane.

Appears in:

FieldDescriptionDefaultValidation
selector stringselector is the label selector in string format to avoid introspection
by clients, and is used to provide the CRD-based integration for the
scale subresource and additional integrations for things like kubectl
describe.. The string will be in the same format as the query-param syntax.
More info about label selectors: http://kubernetes.io/docs/user-guide/labels#label-selectors
MaxLength: 4096
MinLength: 1
Optional: {}
replicas integerreplicas is the total number of non-terminated machines targeted by this control plane
(their labels match the selector).
Optional: {}
version stringversion represents the minimum Kubernetes version for the control plane machines
in the cluster.
MaxLength: 256
MinLength: 1
Optional: {}
updatedReplicas integerupdatedReplicas is the total number of non-terminated machines targeted by this control plane
that have the desired template spec.
Optional: {}
readyReplicas integerreadyReplicas is the total number of fully running and ready control plane machines.Optional: {}
unavailableReplicas integerunavailableReplicas is the total number of unavailable machines targeted by this control plane.
This is the total number of machines that are still required for
the deployment to have 100% available capacity. They may either
be machines that are running but not yet ready or machines
that still have not been created.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
initialized booleaninitialized denotes that the KubeadmControlPlane API Server is initialized and thus
it can accept requests.
NOTE: this field is part of the Cluster API contract and it is used to orchestrate provisioning.
The value of this field is never updated after provisioning is completed. Please use conditions
to check the operational state of the control plane.
Optional: {}
ready booleanready denotes that the KubeadmControlPlane API Server became ready during initial provisioning
to receive requests.
NOTE: this field is part of the Cluster API contract and it is used to orchestrate provisioning.
The value of this field is never updated after provisioning is completed. Please use conditions
to check the operational state of the control plane.
Optional: {}
failureReason KubeadmControlPlaneStatusErrorfailureReason indicates that there is a terminal problem reconciling the
state, and will be set to a token value suitable for
programmatic interpretation.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
Optional: {}
failureMessage stringfailureMessage indicates that there is a terminal problem reconciling the
state, and will be set to a descriptive error message.
Deprecated: This field is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.
MaxLength: 10240
MinLength: 1
Optional: {}
observedGeneration integerobservedGeneration is the latest generation observed by the controller.Optional: {}
conditions Conditionsconditions defines current service state of the KubeadmControlPlane.Optional: {}
lastRemediation LastRemediationStatuslastRemediation stores info about last remediation performed.Optional: {}
versions StatusVersion arrayversions is the aggregated Kubernetes versions in this KubeadmControlPlane.MaxItems: 100
MinItems: 1
Optional: {}
v1beta2 KubeadmControlPlaneV1Beta2Statusv1beta2 groups all the fields that will be added or modified in KubeadmControlPlane’s status with the V1Beta2 version.Optional: {}

KubeadmControlPlaneTemplate

KubeadmControlPlaneTemplate is the Schema for the kubeadmcontrolplanetemplates API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringcontrolplane.cluster.x-k8s.io/v1beta1
kind stringKubeadmControlPlaneTemplate
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
spec KubeadmControlPlaneTemplateSpecspec is the desired state of KubeadmControlPlaneTemplate.Optional: {}

KubeadmControlPlaneTemplateList

KubeadmControlPlaneTemplateList contains a list of KubeadmControlPlaneTemplate.

FieldDescriptionDefaultValidation
apiVersion stringcontrolplane.cluster.x-k8s.io/v1beta1
kind stringKubeadmControlPlaneTemplateList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items KubeadmControlPlaneTemplate arrayitems is the list of KubeadmControlPlaneTemplates.

KubeadmControlPlaneTemplateMachineTemplate

KubeadmControlPlaneTemplateMachineTemplate defines the template for Machines in a KubeadmControlPlaneTemplate object. NOTE: KubeadmControlPlaneTemplateMachineTemplate is similar to KubeadmControlPlaneMachineTemplate but omits ObjectMeta and InfrastructureRef fields. These fields do not make sense on the KubeadmControlPlaneTemplate, because they are calculated by the Cluster topology reconciler during reconciliation and thus cannot be configured on the KubeadmControlPlaneTemplate.

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
nodeDrainTimeout DurationnodeDrainTimeout is the total amount of time that the controller will spend on draining a controlplane node
The default value is 0, meaning that the node can be drained without any time limitations.
NOTE: NodeDrainTimeout is different from kubectl drain --timeout
Optional: {}
nodeVolumeDetachTimeout DurationnodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes
to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations.
Optional: {}
nodeDeletionTimeout DurationnodeDeletionTimeout defines how long the machine controller will attempt to delete the Node that the Machine
hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely.
If no value is provided, the default value for this property of the Machine resource will be used.
Optional: {}
taints MachineTaint arraytaints are the node taints that Cluster API will manage.
This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes,
e.g. the node controller might add the node.kubernetes.io/not-ready taint.
Only those taints defined in this list will be added or removed by core Cluster API controllers.
There can be at most 64 taints.
A pod would have to tolerate all existing taints to run on the corresponding node.
NOTE: This list is implemented as a “map” type, meaning that individual elements can be managed by different owners.
MaxItems: 64
MinItems: 1
Optional: {}

KubeadmControlPlaneTemplateResource

KubeadmControlPlaneTemplateResource describes the data needed to create a KubeadmControlPlane from a template.

Appears in:

FieldDescriptionDefaultValidation
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
spec KubeadmControlPlaneTemplateResourceSpecspec is the desired state of KubeadmControlPlaneTemplateResource.Required: {}

KubeadmControlPlaneTemplateResourceSpec

KubeadmControlPlaneTemplateResourceSpec defines the desired state of KubeadmControlPlane. NOTE: KubeadmControlPlaneTemplateResourceSpec is similar to KubeadmControlPlaneSpec but omits Replicas and Version fields. These fields do not make sense on the KubeadmControlPlaneTemplate, because they are calculated by the Cluster topology reconciler during reconciliation and thus cannot be configured on the KubeadmControlPlaneTemplate.

Appears in:

FieldDescriptionDefaultValidation
machineTemplate KubeadmControlPlaneTemplateMachineTemplatemachineTemplate contains information about how machines
should be shaped when creating or updating a control plane.
Optional: {}
kubeadmConfigSpec KubeadmConfigSpeckubeadmConfigSpec is a KubeadmConfigSpec
to use for initializing and joining machines to the control plane.
Required: {}
rolloutBefore RolloutBeforerolloutBefore is a field to indicate a rollout should be performed
if the specified criteria is met.
Optional: {}
rolloutStrategy RolloutStrategyrolloutStrategy is the RolloutStrategy to use to replace control plane machines with
new ones.
{ rollingUpdate:map[maxSurge:1] type:RollingUpdate }Optional: {}
remediationStrategy RemediationStrategyremediationStrategy is the RemediationStrategy that controls how control plane machine remediation happens.Optional: {}
machineNamingStrategy MachineNamingStrategymachineNamingStrategy allows changing the naming pattern used when creating Machines.
InfraMachines & KubeadmConfigs will use the same name as the corresponding Machines.
Optional: {}

KubeadmControlPlaneTemplateSpec

KubeadmControlPlaneTemplateSpec defines the desired state of KubeadmControlPlaneTemplate.

Appears in:

FieldDescriptionDefaultValidation
template KubeadmControlPlaneTemplateResourcetemplate defines the desired state of KubeadmControlPlaneTemplate.Required: {}

KubeadmControlPlaneV1Beta2Status

KubeadmControlPlaneV1Beta2Status Groups all the fields that will be added or modified in KubeadmControlPlane with the V1Beta2 version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a KubeadmControlPlane’s current state.
Known condition types are Available, CertificatesAvailable, EtcdClusterAvailable, MachinesReady, MachinesUpToDate,
ScalingUp, ScalingDown, Remediating, Deleting, Paused.
MaxItems: 32
Optional: {}
readyReplicas integerreadyReplicas is the number of ready replicas for this KubeadmControlPlane. A machine is considered ready when Machine’s Ready condition is true.Optional: {}
availableReplicas integeravailableReplicas is the number of available replicas targeted by this KubeadmControlPlane. A machine is considered available when Machine’s Available condition is true.Optional: {}
upToDateReplicas integerupToDateReplicas is the number of up-to-date replicas targeted by this KubeadmControlPlane. A machine is considered up-to-date when Machine’s UpToDate condition is true.Optional: {}

LastRemediationStatus

LastRemediationStatus stores info about last remediation performed. NOTE: if for any reason information about last remediation are lost, RetryCount is going to restart from 0 and thus more remediations than expected might happen.

Appears in:

FieldDescriptionDefaultValidation
machine stringmachine is the machine name of the latest machine being remediated.MaxLength: 253
MinLength: 1
Required: {}
retryCount integerretryCount used to keep track of remediation retry for the last remediated machine.
A retry happens when a machine that was created as a replacement for an unhealthy machine also fails.
Required: {}

MachineNamingStrategy

MachineNamingStrategy allows changing the naming pattern used when creating Machines. InfraMachines & KubeadmConfigs will use the same name as the corresponding Machines.

Appears in:

FieldDescriptionDefaultValidation
template stringtemplate defines the template to use for generating the names of the Machine objects.
If not defined, it will fallback to \{\{ .kubeadmControlPlane.name \}\}-\{\{ .random \}\}.
If the generated name string exceeds 63 characters, it will be trimmed to 58 characters and will
get concatenated with a random suffix of length 5.
Length of the template string must not exceed 256 characters.
The template allows the following variables .cluster.name, .kubeadmControlPlane.name and .random.
The variable .cluster.name retrieves the name of the cluster object that owns the Machines being created.
The variable .kubeadmControlPlane.name retrieves the name of the KubeadmControlPlane object that owns the Machines being created.
The variable .random is substituted with random alphanumeric string, without vowels, of length 5. This variable is required
part of the template. If not provided, validation will fail.
MaxLength: 256
MinLength: 1
Optional: {}

RemediationStrategy

RemediationStrategy allows to define how control plane machine remediation happens.

Appears in:

FieldDescriptionDefaultValidation
maxRetry integermaxRetry is the Max number of retries while attempting to remediate an unhealthy machine.
A retry happens when a machine that was created as a replacement for an unhealthy machine also fails.
For example, given a control plane with three machines M1, M2, M3:
M1 become unhealthy; remediation happens, and M1-1 is created as a replacement.
If M1-1 (replacement of M1) has problems while bootstrapping it will become unhealthy, and then be
remediated; such operation is considered a retry, remediation-retry #1.
If M1-2 (replacement of M1-1) becomes unhealthy, remediation-retry #2 will happen, etc.
A retry could happen only after RetryPeriod from the previous retry.
If a machine is marked as unhealthy after MinHealthyPeriod from the previous remediation expired,
this is not considered a retry anymore because the new issue is assumed unrelated from the previous one.
If not set, the remedation will be retried infinitely.
Optional: {}
retryPeriod DurationretryPeriod is the duration that KCP should wait before remediating a machine being created as a replacement
for an unhealthy machine (a retry).
If not set, a retry will happen immediately.
Optional: {}
minHealthyPeriod DurationminHealthyPeriod defines the duration after which KCP will consider any failure to a machine unrelated
from the previous one. In this case the remediation is not considered a retry anymore, and thus the retry
counter restarts from 0. For example, assuming MinHealthyPeriod is set to 1h (default)
M1 become unhealthy; remediation happens, and M1-1 is created as a replacement.
If M1-1 (replacement of M1) has problems within the 1hr after the creation, also
this machine will be remediated and this operation is considered a retry - a problem related
to the original issue happened to M1 -.
If instead the problem on M1-1 is happening after MinHealthyPeriod expired, e.g. four days after
m1-1 has been created as a remediation of M1, the problem on M1-1 is considered unrelated to
the original issue happened to M1.
If not set, this value is defaulted to 1h.
Optional: {}

RollingUpdate

RollingUpdate is used to control the desired behavior of rolling update.

Appears in:

FieldDescriptionDefaultValidation
maxSurge IntOrStringmaxSurge is the maximum number of control planes that can be scheduled above or under the
desired number of control planes.
Value can be an absolute number 1 or 0.
Defaults to 1.
Example: when this is set to 1, the control plane can be scaled
up immediately when the rolling update starts.
Optional: {}

RolloutBefore

RolloutBefore describes when a rollout should be performed on the KCP machines.

Appears in:

FieldDescriptionDefaultValidation
certificatesExpiryDays integercertificatesExpiryDays indicates a rollout needs to be performed if the
certificates of the machine will expire within the specified days.
Optional: {}

RolloutStrategy

RolloutStrategy describes how to replace existing machines with new ones.

Appears in:

FieldDescriptionDefaultValidation
type RolloutStrategyTypetype of rollout. Currently the only supported strategy is
“RollingUpdate”.
Default is RollingUpdate.
Enum: [RollingUpdate]
Optional: {}
rollingUpdate RollingUpdaterollingUpdate is the rolling update config params. Present only if
RolloutStrategyType = RollingUpdate.
Optional: {}

RolloutStrategyType

Underlying type: string

RolloutStrategyType defines the rollout strategies for a KubeadmControlPlane.

Validation:

  • Enum: [RollingUpdate]

Appears in:

FieldDescription
RollingUpdateRollingUpdateStrategyType replaces the old control planes by new one using rolling update
i.e. gradually scale up or down the old control planes and scale up or down the new one.

ipam.cluster.x-k8s.io/v1alpha1

Package v1alpha1 contains API Schema definitions for the exp v1alpha1 IPAM API.

Deprecated: This package is deprecated and is going to be removed when support for v1beta1 will be dropped.

Resource Types

IPAddress

IPAddress is the Schema for the ipaddress API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringipam.cluster.x-k8s.io/v1alpha1
kind stringIPAddress
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
spec IPAddressSpecspec is the desired state of IPAddress.Optional: {}

IPAddressClaim

IPAddressClaim is the Schema for the ipaddressclaim API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringipam.cluster.x-k8s.io/v1alpha1
kind stringIPAddressClaim
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
spec IPAddressClaimSpecspec is the desired state of IPAddressClaim.Optional: {}
status IPAddressClaimStatusstatus is the observed state of IPAddressClaim.Optional: {}

IPAddressClaimList

IPAddressClaimList is a list of IPAddressClaims.

FieldDescriptionDefaultValidation
apiVersion stringipam.cluster.x-k8s.io/v1alpha1
kind stringIPAddressClaimList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items IPAddressClaim arrayitems is the list of IPAddressClaims.

IPAddressClaimSpec

IPAddressClaimSpec is the desired state of an IPAddressClaim.

Appears in:

FieldDescriptionDefaultValidation
poolRef TypedLocalObjectReferencepoolRef is a reference to the pool from which an IP address should be created.Required: {}

IPAddressClaimStatus

IPAddressClaimStatus is the observed status of a IPAddressClaim.

Appears in:

FieldDescriptionDefaultValidation
addressRef LocalObjectReferenceaddressRef is a reference to the address that was created for this claim.Optional: {}
conditions Conditionsconditions summarises the current state of the IPAddressClaimOptional: {}

IPAddressList

IPAddressList is a list of IPAddress.

FieldDescriptionDefaultValidation
apiVersion stringipam.cluster.x-k8s.io/v1alpha1
kind stringIPAddressList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items IPAddress arrayitems is the list of IPAddresses.

IPAddressSpec

IPAddressSpec is the desired state of an IPAddress.

Appears in:

FieldDescriptionDefaultValidation
claimRef LocalObjectReferenceclaimRef is a reference to the claim this IPAddress was created for.Required: {}
poolRef TypedLocalObjectReferencepoolRef is a reference to the pool that this IPAddress was created from.Required: {}
address stringaddress is the IP address.MaxLength: 39
MinLength: 1
Required: {}
prefix integerprefix is the prefix of the address.Required: {}
gateway stringgateway is the network gateway of the network the address is from.MaxLength: 39
MinLength: 1
Optional: {}

ipam.cluster.x-k8s.io/v1beta1

Package v1beta1 contains API Schema definitions for the v1beta1 IPAM API.

Deprecated: This package is deprecated and is going to be removed when support for v1beta1 will be dropped.

Resource Types

IPAddress

IPAddress is the Schema for the ipaddress API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringipam.cluster.x-k8s.io/v1beta1
kind stringIPAddress
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
spec IPAddressSpecspec is the desired state of IPAddress.Optional: {}

IPAddressClaim

IPAddressClaim is the Schema for the ipaddressclaim API.

Appears in:

FieldDescriptionDefaultValidation
apiVersion stringipam.cluster.x-k8s.io/v1beta1
kind stringIPAddressClaim
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
spec IPAddressClaimSpecspec is the desired state of IPAddressClaim.Optional: {}
status IPAddressClaimStatusstatus is the observed state of IPAddressClaim.Optional: {}

IPAddressClaimList

IPAddressClaimList is a list of IPAddressClaims.

FieldDescriptionDefaultValidation
apiVersion stringipam.cluster.x-k8s.io/v1beta1
kind stringIPAddressClaimList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items IPAddressClaim arrayitems is the list of IPAddressClaims.

IPAddressClaimSpec

IPAddressClaimSpec is the desired state of an IPAddressClaim.

Appears in:

FieldDescriptionDefaultValidation
clusterName stringclusterName is the name of the Cluster this object belongs to.MaxLength: 63
MinLength: 1
Optional: {}
poolRef TypedLocalObjectReferencepoolRef is a reference to the pool from which an IP address should be created.Required: {}

IPAddressClaimStatus

IPAddressClaimStatus is the observed status of a IPAddressClaim.

Appears in:

FieldDescriptionDefaultValidation
addressRef LocalObjectReferenceaddressRef is a reference to the address that was created for this claim.Optional: {}
conditions Conditionsconditions summarises the current state of the IPAddressClaimOptional: {}
v1beta2 IPAddressClaimV1Beta2Statusv1beta2 groups all the fields that will be added or modified in IPAddressClaim’s status with the V1Beta2 version.Optional: {}

IPAddressClaimV1Beta2Status

IPAddressClaimV1Beta2Status groups all the fields that will be added or modified in IPAddressClaimStatus with the V1Beta2 version. See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.

Appears in:

FieldDescriptionDefaultValidation
conditions Condition arrayconditions represents the observations of a IPAddressClaim’s current state.MaxItems: 32
Optional: {}

IPAddressList

IPAddressList is a list of IPAddress.

FieldDescriptionDefaultValidation
apiVersion stringipam.cluster.x-k8s.io/v1beta1
kind stringIPAddressList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.Optional: {}
items