clusterctl alpha topology plan
The clusterctl alpha topology plan
command can be used to get a plan of how a Cluster topology evolves given
file(s) containing resources to be applied to a Cluster.
The input file(s) could contain a new/modified Cluster, a new/modified ClusterClass and/or new/modified templates, depending on the use case you are going to plan for (see more details below).
The topology plan output would provide details about objects that will be created, updated and deleted of a target cluster; If instead the command detects that the change impacts many Clusters, the users will be required to select one to focus on (see flags below).
clusterctl alpha topology plan -f input.yaml -o output/
Example use cases
Designing a new ClusterClass
When designing a new ClusterClass users might want to preview the Cluster generated using such ClusterClass.
The clusterctl alpha topology plan command
can be used to do so:
clusterctl alpha topology plan -f example-cluster-class.yaml -f example-cluster.yaml -o output/
example-cluster-class.yaml
holds the definitions of the ClusterClass and all the associated templates.
View example-cluster-class.yaml
apiVersion: cluster.x-k8s.io/v1beta1
kind: ClusterClass
metadata:
name: example-cluster-class
namespace: default
spec:
controlPlane:
ref:
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: KubeadmControlPlaneTemplate
name: example-cluster-control-plane
namespace: default
machineInfrastructure:
ref:
kind: DockerMachineTemplate
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
name: "example-cluster-control-plane"
namespace: default
infrastructure:
ref:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: DockerClusterTemplate
name: example-cluster
namespace: default
workers:
machineDeployments:
- class: "default-worker"
template:
bootstrap:
ref:
apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
kind: KubeadmConfigTemplate
name: example-docker-worker-bootstraptemplate
infrastructure:
ref:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: DockerMachineTemplate
name: example-docker-worker-machinetemplate
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: DockerClusterTemplate
metadata:
name: example-cluster
namespace: default
spec:
template:
spec: {}
---
kind: KubeadmControlPlaneTemplate
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
metadata:
name: "example-cluster-control-plane"
namespace: default
spec:
template:
spec:
machineTemplate:
nodeDrainTimeout: 1s
kubeadmConfigSpec:
clusterConfiguration:
controllerManager:
extraArgs: { enable-hostpath-provisioner: 'true' }
apiServer:
certSANs: [ localhost, 127.0.0.1 ]
initConfiguration:
nodeRegistration:
criSocket: unix:///var/run/containerd/containerd.sock
kubeletExtraArgs:
cgroup-driver: cgroupfs
eviction-hard: 'nodefs.available<0%,nodefs.inodesFree<0%,imagefs.available<0%'
joinConfiguration:
nodeRegistration:
criSocket: unix:///var/run/containerd/containerd.sock
kubeletExtraArgs:
cgroup-driver: cgroupfs
eviction-hard: 'nodefs.available<0%,nodefs.inodesFree<0%,imagefs.available<0%'
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: DockerMachineTemplate
metadata:
name: "example-cluster-control-plane"
namespace: default
spec:
template:
spec:
extraMounts:
- containerPath: "/var/run/docker.sock"
hostPath: "/var/run/docker.sock"
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: DockerMachineTemplate
metadata:
name: "example-docker-worker-machinetemplate"
namespace: default
spec:
template:
spec: {}
---
apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
kind: KubeadmConfigTemplate
metadata:
name: "example-docker-worker-bootstraptemplate"
namespace: default
spec:
template:
spec:
joinConfiguration:
nodeRegistration:
kubeletExtraArgs:
cgroup-driver: cgroupfs
eviction-hard: 'nodefs.available<0%,nodefs.inodesFree<0%,imagefs.available<0%'
example-cluster.yaml
holds the definition of example-cluster
Cluster.
View example-cluster.yaml
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
name: "example-cluster"
namespace: "default"
labels:
cni: kindnet
spec:
clusterNetwork:
services:
cidrBlocks: ["10.128.0.0/12"]
pods:
cidrBlocks: ["192.168.0.0/16"]
serviceDomain: "cluster.local"
topology:
class: example-cluster-class
version: v1.21.2
controlPlane:
metadata: {}
replicas: 1
workers:
machineDeployments:
- class: "default-worker"
name: "md-0"
replicas: 1
Produces an output similar to this:
The following ClusterClasses will be affected by the changes:
* default/example-cluster-class
The following Clusters will be affected by the changes:
* default/example-cluster
Changes for Cluster "default/example-cluster":
NAMESPACE KIND NAME ACTION
default DockerCluster example-cluster-rnx2q created
default DockerMachineTemplate example-cluster-control-plane-dfnvz created
default DockerMachineTemplate example-cluster-md-0-infra-qz9qk created
default KubeadmConfigTemplate example-cluster-md-0-bootstrap-m29vz created
default KubeadmControlPlane example-cluster-b2lhc created
default MachineDeployment example-cluster-md-0-pqscg created
default Secret example-cluster-shim created
default Cluster example-cluster modified
Created objects are written to directory "output/created"
Modified objects are written to directory "output/modified"
The contents of the output directory are similar to this:
output
├── created
│ ├── DockerCluster_default_example-cluster-rnx2q.yaml
│ ├── DockerMachineTemplate_default_example-cluster-control-plane-dfnvz.yaml
│ ├── DockerMachineTemplate_default_example-cluster-md-0-infra-qz9qk.yaml
│ ├── KubeadmConfigTemplate_default_example-cluster-md-0-bootstrap-m29vz.yaml
│ ├── KubeadmControlPlane_default_example-cluster-b2lhc.yaml
│ ├── MachineDeployment_default_example-cluster-md-0-pqscg.yaml
│ └── Secret_default_example-cluster-shim.yaml
└── modified
├── Cluster_default_example-cluster.diff
├── Cluster_default_example-cluster.jsonpatch
├── Cluster_default_example-cluster.modified.yaml
└── Cluster_default_example-cluster.original.yaml
Plan changes to Cluster topology
When making changes to a Cluster topology the clusterctl alpha topology plan
can be used to analyse how the underlying objects will be affected.
clusterctl alpha topology plan -f modified-example-cluster.yaml -o output/
The modified-example-cluster.yaml
scales up the control plane to 3 replicas and adds additional labels to the machine deployment.
View modified-example-cluster.yaml
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
name: "example-cluster"
namespace: default
labels:
cni: kindnet
spec:
clusterNetwork:
services:
cidrBlocks: ["10.128.0.0/12"]
pods:
cidrBlocks: ["192.168.0.0/16"]
serviceDomain: "cluster.local"
topology:
class: example-cluster-class
version: v1.21.2
controlPlane:
metadata: {}
# Scale up the control plane from 1 -> 3.
replicas: 3
workers:
machineDeployments:
- class: "default-worker"
# Apply additional labels.
metadata:
labels:
test-label: md-0-label
name: "md-0"
replicas: 1
Produces an output similar to this:
Detected a cluster with Cluster API installed. Will use it to fetch missing objects.
No ClusterClasses will be affected by the changes.
The following Clusters will be affected by the changes:
* default/example-cluster
Changes for Cluster "default/example-cluster":
NAMESPACE KIND NAME ACTION
default KubeadmControlPlane example-cluster-l7kx8 modified
default MachineDeployment example-cluster-md-0-j58ln modified
Modified objects are written to directory "output/modified"
Rebase a Cluster to a different ClusterClass
The command can be used to plan if a Cluster can be successfully rebased to a different ClusterClass.
Rebasing a Cluster to a different ClusterClass:
# Rebasing from `example-cluster-class` to `another-cluster-class`.
clusterctl alpha topology plan -f rebase-example-cluster.yaml -o output/
The example-cluster
Cluster is rebased from example-cluster-class
to another-cluster-class
. In this example another-cluster-class
is assumed to be available in the management cluster.
View rebase-example-cluster.yaml
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
name: "example-cluster"
namespace: "default"
labels:
cni: kindnet
spec:
clusterNetwork:
services:
cidrBlocks: ["10.128.0.0/12"]
pods:
cidrBlocks: ["192.168.0.0/16"]
serviceDomain: "cluster.local"
topology:
# ClusterClass changed from 'example-cluster-class' -> 'another-cluster-class'.
class: another-cluster-class
version: v1.21.2
controlPlane:
metadata: {}
replicas: 1
workers:
machineDeployments:
- class: "default-worker"
name: "md-0"
replicas: 1
If the target ClusterClass is compatible with the original ClusterClass the output be similar to:
Detected a cluster with Cluster API installed. Will use it to fetch missing objects.
No ClusterClasses will be affected by the changes.
The following Clusters will be affected by the changes:
* default/example-cluster
Changes for Cluster "default/example-cluster":
NAMESPACE KIND NAME ACTION
default DockerCluster example-cluster-7t7pl modified
default DockerMachineTemplate example-cluster-control-plane-lt6kw modified
default DockerMachineTemplate example-cluster-md-0-infra-cjxs4 modified
default KubeadmConfigTemplate example-cluster-md-0-bootstrap-m9sg8 modified
default KubeadmControlPlane example-cluster-l7kx8 modified
Modified objects are written to directory "output/modified"
Instead, if the command detects that the rebase operation would lead to a non-functional cluster (ClusterClasses are incompatible), the output will be similar to:
Detected a cluster with Cluster API installed. Will use it to fetch missing objects.
Error: failed defaulting and validation on input objects: failed to run defaulting and validation on Clusters: failed validation of cluster.x-k8s.io/v1beta1, Kind=Cluster default/example-cluster: Cluster.cluster.x-k8s.io "example-cluster" is invalid: spec.topology.workers.machineDeployments[0].class: Invalid value: "default-worker": MachineDeploymentClass with name "default-worker" does not exist in ClusterClass "another-cluster-class"
In this example rebasing will lead to a non-functional Cluster because the ClusterClass is missing a worker class that is used by the Cluster.
Testing the effects of changing a ClusterClass
When planning for a change on a ClusterClass you might want to understand what effects the change will have on existing clusters.
clusterctl alpha topology plan -f modified-first-cluster-class.yaml -o output/
When multiple clusters are affected, only the list of Clusters and ClusterClasses is presented.
Detected a cluster with Cluster API installed. Will use it to fetch missing objects.
The following ClusterClasses will be affected by the changes:
* default/first-cluster-class
The following Clusters will be affected by the changes:
* default/first-cluster
* default/second-cluster
No target cluster identified. Use --cluster to specify a target cluster to get detailed changes.
To get the full list of changes for the “first-cluster”:
clusterctl alpha topology plan -f modified-first-cluster-class.yaml -o output/ -c "first-cluster"
Output will be similar to the full summary output provided in other examples.
How does topology plan
work?
The topology plan operation is composed of the following steps:
- Set the namespace on objects in the input with missing namespace.
- Run the Defaulting and Validation webhooks on the Cluster and ClusterClass objects in the input.
- Dry run the topology reconciler on the target cluster.
- Capture all changes observed during reconciliation.
Reference
--file
, -f
(REQUIRED)
The input file(s) with the target changes. Supports multiple input files.
The objects in the input should follow these rules:
- All the objects in the input should belong to the same namespace.
- Should not have multiple Clusters.
- Should not have multiple ClusterClasses.
--output-directory
, -o
(REQUIRED)
Information about the objects that are created and updated is written to this directory.
For objects that are modified the following files are written to disk:
- Original object
- Final object
- JSON patch between the original and the final objects
- Diff of the original and final objects
--cluster
, -c
(Optional)
When multiple clusters are affected by the input, --cluster
can be used to specify a target cluster.
If only one cluster is affected or if a Cluster is in the input it defaults as the target cluster.
--namespace
, -n
(Optional)
Namespace used for objects with missing namespaces in the input.
If not provided, the namespace defined in kubeconfig is used. If a kubeconfig is not available the value default
is used.