sigs.k8s.io/cluster-api@v1.6.3/docs/book/src/clusterctl/commands/alpha-topology-plan.md (about) 1 # clusterctl alpha topology plan 2 3 The `clusterctl alpha topology plan` command can be used to get a plan of how a Cluster topology evolves given 4 file(s) containing resources to be applied to a Cluster. 5 6 The input file(s) could contain a new/modified Cluster, a new/modified ClusterClass and/or new/modified templates, 7 depending on the use case you are going to plan for (see more details below). 8 9 The topology plan output would provide details about objects that will be created, updated and deleted of a target cluster; 10 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). 11 12 ```bash 13 clusterctl alpha topology plan -f input.yaml -o output/ 14 ``` 15 16 <aside class="note"> 17 18 <h1>Running without a management cluster</h1> 19 20 This command can be used with or without a management cluster. In case the command is used without a management cluster 21 the input should have all the objects needed. 22 23 </aside> 24 25 <aside class="note"> 26 27 <h1>Limitations: Server Side Apply</h1> 28 29 The topology controllers uses [Server Side Apply](https://kubernetes.io/docs/reference/using-api/server-side-apply/) 30 to support use cases where other controllers are co-authoring the same objects, but this kind of interactions can't be recreated 31 in a dry-run scenario. 32 33 As a consequence Dry-Run can give some false positives/false negatives when trying to have a preview of 34 changes to a set of existing topology owned objects. In other worlds this limitation impacts all the use cases described 35 below except for "Designing a new ClusterClass". 36 37 More specifically: 38 - DryRun doesn't consider OpenAPI schema extension like +ListMap this can lead to false positives when topology 39 dry run is simulating a change to an existing slice (DryRun always reverts external changes, like server side apply when +ListMap=atomic). 40 - DryRun doesn't consider existing metadata.managedFields, and this can lead to false negatives when topology dry run 41 is simulating a change where a field is dropped from a template (DryRun always preserve dropped fields, like 42 server side apply when the field has more than one manager). 43 44 </aside> 45 46 <aside class="note"> 47 48 <h1>Limitations: RuntimeSDK</h1> 49 50 Please note that `clusterctl` doesn't support Runtime SDK yet. This means that ClusterClasses with external patches are not yet supported. 51 52 </aside> 53 54 ## Example use cases 55 56 ### Designing a new ClusterClass 57 58 When designing a new ClusterClass users might want to preview the Cluster generated using such ClusterClass. 59 The `clusterctl alpha topology plan command` can be used to do so: 60 61 ```bash 62 clusterctl alpha topology plan -f example-cluster-class.yaml -f example-cluster.yaml -o output/ 63 ``` 64 65 `example-cluster-class.yaml` holds the definitions of the ClusterClass and all the associated templates. 66 <details> 67 <summary>View <code>example-cluster-class.yaml</code></summary> 68 69 ```yaml 70 apiVersion: cluster.x-k8s.io/v1beta1 71 kind: ClusterClass 72 metadata: 73 name: example-cluster-class 74 namespace: default 75 spec: 76 controlPlane: 77 ref: 78 apiVersion: controlplane.cluster.x-k8s.io/v1beta1 79 kind: KubeadmControlPlaneTemplate 80 name: example-cluster-control-plane 81 namespace: default 82 machineInfrastructure: 83 ref: 84 kind: DockerMachineTemplate 85 apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 86 name: "example-cluster-control-plane" 87 namespace: default 88 infrastructure: 89 ref: 90 apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 91 kind: DockerClusterTemplate 92 name: example-cluster 93 namespace: default 94 workers: 95 machineDeployments: 96 - class: "default-worker" 97 template: 98 bootstrap: 99 ref: 100 apiVersion: bootstrap.cluster.x-k8s.io/v1beta1 101 kind: KubeadmConfigTemplate 102 name: example-docker-worker-bootstraptemplate 103 infrastructure: 104 ref: 105 apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 106 kind: DockerMachineTemplate 107 name: example-docker-worker-machinetemplate 108 --- 109 apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 110 kind: DockerClusterTemplate 111 metadata: 112 name: example-cluster 113 namespace: default 114 spec: 115 template: 116 spec: {} 117 --- 118 kind: KubeadmControlPlaneTemplate 119 apiVersion: controlplane.cluster.x-k8s.io/v1beta1 120 metadata: 121 name: "example-cluster-control-plane" 122 namespace: default 123 spec: 124 template: 125 spec: 126 machineTemplate: 127 nodeDrainTimeout: 1s 128 kubeadmConfigSpec: 129 clusterConfiguration: 130 controllerManager: 131 extraArgs: { enable-hostpath-provisioner: 'true' } 132 apiServer: 133 certSANs: [ localhost, 127.0.0.1 ] 134 initConfiguration: 135 nodeRegistration: {} # node registration parameters are automatically injected by CAPD according to the kindest/node image in use. 136 joinConfiguration: 137 nodeRegistration: {} # node registration parameters are automatically injected by CAPD according to the kindest/node image in use. 138 --- 139 apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 140 kind: DockerMachineTemplate 141 metadata: 142 name: "example-cluster-control-plane" 143 namespace: default 144 spec: 145 template: 146 spec: 147 extraMounts: 148 - containerPath: "/var/run/docker.sock" 149 hostPath: "/var/run/docker.sock" 150 --- 151 apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 152 kind: DockerMachineTemplate 153 metadata: 154 name: "example-docker-worker-machinetemplate" 155 namespace: default 156 spec: 157 template: 158 spec: {} 159 --- 160 apiVersion: bootstrap.cluster.x-k8s.io/v1beta1 161 kind: KubeadmConfigTemplate 162 metadata: 163 name: "example-docker-worker-bootstraptemplate" 164 namespace: default 165 spec: 166 template: 167 spec: 168 joinConfiguration: 169 nodeRegistration: {} # node registration parameters are automatically injected by CAPD according to the kindest/node image in use. 170 ``` 171 172 </details> 173 174 `example-cluster.yaml` holds the definition of `example-cluster` Cluster. 175 <details> 176 <summary>View <code>example-cluster.yaml</code></summary> 177 178 ```yaml 179 apiVersion: cluster.x-k8s.io/v1beta1 180 kind: Cluster 181 metadata: 182 name: "example-cluster" 183 namespace: "default" 184 labels: 185 cni: kindnet 186 spec: 187 clusterNetwork: 188 services: 189 cidrBlocks: ["10.128.0.0/12"] 190 pods: 191 cidrBlocks: ["192.168.0.0/16"] 192 serviceDomain: "cluster.local" 193 topology: 194 class: example-cluster-class 195 version: v1.21.2 196 controlPlane: 197 metadata: {} 198 replicas: 1 199 workers: 200 machineDeployments: 201 - class: "default-worker" 202 name: "md-0" 203 replicas: 1 204 ``` 205 206 </details> 207 208 Produces an output similar to this: 209 ```bash 210 The following ClusterClasses will be affected by the changes: 211 * default/example-cluster-class 212 213 The following Clusters will be affected by the changes: 214 * default/example-cluster 215 216 Changes for Cluster "default/example-cluster": 217 218 NAMESPACE KIND NAME ACTION 219 default DockerCluster example-cluster-rnx2q created 220 default DockerMachineTemplate example-cluster-control-plane-dfnvz created 221 default DockerMachineTemplate example-cluster-md-0-infra-qz9qk created 222 default KubeadmConfigTemplate example-cluster-md-0-bootstrap-m29vz created 223 default KubeadmControlPlane example-cluster-b2lhc created 224 default MachineDeployment example-cluster-md-0-pqscg created 225 default Secret example-cluster-shim created 226 default Cluster example-cluster modified 227 228 Created objects are written to directory "output/created" 229 Modified objects are written to directory "output/modified" 230 ``` 231 232 The contents of the output directory are similar to this: 233 ```bash 234 output 235 ├── created 236 │ ├── DockerCluster_default_example-cluster-rnx2q.yaml 237 │ ├── DockerMachineTemplate_default_example-cluster-control-plane-dfnvz.yaml 238 │ ├── DockerMachineTemplate_default_example-cluster-md-0-infra-qz9qk.yaml 239 │ ├── KubeadmConfigTemplate_default_example-cluster-md-0-bootstrap-m29vz.yaml 240 │ ├── KubeadmControlPlane_default_example-cluster-b2lhc.yaml 241 │ ├── MachineDeployment_default_example-cluster-md-0-pqscg.yaml 242 │ └── Secret_default_example-cluster-shim.yaml 243 └── modified 244 ├── Cluster_default_example-cluster.diff 245 ├── Cluster_default_example-cluster.jsonpatch 246 ├── Cluster_default_example-cluster.modified.yaml 247 └── Cluster_default_example-cluster.original.yaml 248 ``` 249 250 ### Plan changes to Cluster topology 251 252 When making changes to a Cluster topology the `clusterctl alpha topology plan` can be used to analyse how the underlying objects will be affected. 253 254 ```bash 255 clusterctl alpha topology plan -f modified-example-cluster.yaml -o output/ 256 ``` 257 258 The `modified-example-cluster.yaml` scales up the control plane to 3 replicas and adds additional labels to the machine deployment. 259 <details> 260 <summary>View <code>modified-example-cluster.yaml</code></summary> 261 262 ```yaml 263 apiVersion: cluster.x-k8s.io/v1beta1 264 kind: Cluster 265 metadata: 266 name: "example-cluster" 267 namespace: default 268 labels: 269 cni: kindnet 270 spec: 271 clusterNetwork: 272 services: 273 cidrBlocks: ["10.128.0.0/12"] 274 pods: 275 cidrBlocks: ["192.168.0.0/16"] 276 serviceDomain: "cluster.local" 277 topology: 278 class: example-cluster-class 279 version: v1.21.2 280 controlPlane: 281 metadata: {} 282 # Scale up the control plane from 1 -> 3. 283 replicas: 3 284 workers: 285 machineDeployments: 286 - class: "default-worker" 287 # Apply additional labels. 288 metadata: 289 labels: 290 test-label: md-0-label 291 name: "md-0" 292 replicas: 1 293 ``` 294 </details> 295 296 Produces an output similar to this: 297 ```bash 298 Detected a cluster with Cluster API installed. Will use it to fetch missing objects. 299 No ClusterClasses will be affected by the changes. 300 The following Clusters will be affected by the changes: 301 * default/example-cluster 302 303 Changes for Cluster "default/example-cluster": 304 305 NAMESPACE KIND NAME ACTION 306 default KubeadmControlPlane example-cluster-l7kx8 modified 307 default MachineDeployment example-cluster-md-0-j58ln modified 308 309 Modified objects are written to directory "output/modified" 310 ``` 311 312 ### Rebase a Cluster to a different ClusterClass 313 314 The command can be used to plan if a Cluster can be successfully rebased to a different ClusterClass. 315 316 Rebasing a Cluster to a different ClusterClass: 317 ```bash 318 # Rebasing from `example-cluster-class` to `another-cluster-class`. 319 clusterctl alpha topology plan -f rebase-example-cluster.yaml -o output/ 320 ``` 321 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. 322 323 <details> 324 <summary>View <code>rebase-example-cluster.yaml</code></summary> 325 326 ```yaml 327 apiVersion: cluster.x-k8s.io/v1beta1 328 kind: Cluster 329 metadata: 330 name: "example-cluster" 331 namespace: "default" 332 labels: 333 cni: kindnet 334 spec: 335 clusterNetwork: 336 services: 337 cidrBlocks: ["10.128.0.0/12"] 338 pods: 339 cidrBlocks: ["192.168.0.0/16"] 340 serviceDomain: "cluster.local" 341 topology: 342 # ClusterClass changed from 'example-cluster-class' -> 'another-cluster-class'. 343 class: another-cluster-class 344 version: v1.21.2 345 controlPlane: 346 metadata: {} 347 replicas: 1 348 workers: 349 machineDeployments: 350 - class: "default-worker" 351 name: "md-0" 352 replicas: 1 353 ``` 354 </details> 355 356 If the target ClusterClass is compatible with the original ClusterClass the output be similar to: 357 ```bash 358 Detected a cluster with Cluster API installed. Will use it to fetch missing objects. 359 No ClusterClasses will be affected by the changes. 360 The following Clusters will be affected by the changes: 361 * default/example-cluster 362 363 Changes for Cluster "default/example-cluster": 364 365 NAMESPACE KIND NAME ACTION 366 default DockerCluster example-cluster-7t7pl modified 367 default DockerMachineTemplate example-cluster-control-plane-lt6kw modified 368 default DockerMachineTemplate example-cluster-md-0-infra-cjxs4 modified 369 default KubeadmConfigTemplate example-cluster-md-0-bootstrap-m9sg8 modified 370 default KubeadmControlPlane example-cluster-l7kx8 modified 371 372 Modified objects are written to directory "output/modified" 373 ``` 374 375 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: 376 ```bash 377 Detected a cluster with Cluster API installed. Will use it to fetch missing objects. 378 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" 379 ``` 380 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. 381 382 ### Testing the effects of changing a ClusterClass 383 384 When planning for a change on a ClusterClass you might want to understand what effects the change will have on existing clusters. 385 386 ```bash 387 clusterctl alpha topology plan -f modified-first-cluster-class.yaml -o output/ 388 ``` 389 When multiple clusters are affected, only the list of Clusters and ClusterClasses is presented. 390 ```bash 391 Detected a cluster with Cluster API installed. Will use it to fetch missing objects. 392 The following ClusterClasses will be affected by the changes: 393 * default/first-cluster-class 394 395 The following Clusters will be affected by the changes: 396 * default/first-cluster 397 * default/second-cluster 398 399 No target cluster identified. Use --cluster to specify a target cluster to get detailed changes. 400 ``` 401 402 To get the full list of changes for the "first-cluster": 403 ```bash 404 clusterctl alpha topology plan -f modified-first-cluster-class.yaml -o output/ -c "first-cluster" 405 ``` 406 Output will be similar to the full summary output provided in other examples. 407 408 ## How does `topology plan` work? 409 410 The topology plan operation is composed of the following steps: 411 * Set the namespace on objects in the input with missing namespace. 412 * Run the Defaulting and Validation webhooks on the Cluster and ClusterClass objects in the input. 413 * Dry run the topology reconciler on the target cluster. 414 * Capture all changes observed during reconciliation. 415 416 ## Reference 417 418 ### `--file`, `-f` (REQUIRED) 419 420 The input file(s) with the target changes. Supports multiple input files. 421 422 The objects in the input should follow these rules: 423 * All the objects in the input should belong to the same namespace. 424 * Should not have multiple Clusters. 425 * Should not have multiple ClusterClasses. 426 427 <aside class="note warning"> 428 429 <h1>Object namespaces</h1> 430 431 If some of the objects have a defined namespace and some do not, the objects are considered as belonging to different namespaces 432 which is not allowed. 433 434 </aside> 435 436 <aside class="note warning"> 437 438 <h1>Defaulting and Validation</h1> 439 440 All templates in the inputs should be fully valid and have all the default values set. `topology plan` will not run any defaulting 441 or validation on these objects. Defaulting and validation is only run on Cluster and ClusterClass objects. 442 443 </aside> 444 445 <aside class="note warning"> 446 447 <h1>API Versions and Contract compatibility</h1> 448 449 All the objects in the input of the same `Group.Kind` should have the same `apiVersion`. 450 Example: Two `InfraMachineTemplate`s with `apiVersion`s `infrastructure.cluster.x-k8s.io/v1beta1` and `infrastructure.cluster.x-k8s.io/v1alpha4` are not allowed. 451 452 The API version of resource in the input should be compatible with the current version of Cluster API contract. 453 454 </aside> 455 456 ### `--output-directory`, `-o` (REQUIRED) 457 458 Information about the objects that are created and updated is written to this directory. 459 460 For objects that are modified the following files are written to disk: 461 * Original object 462 * Final object 463 * JSON patch between the original and the final objects 464 * Diff of the original and final objects 465 466 ### `--cluster`, `-c` (Optional) 467 468 When multiple clusters are affected by the input, `--cluster` can be used to specify a target cluster. 469 470 If only one cluster is affected or if a Cluster is in the input it defaults as the target cluster. 471 472 ### `--namespace`, `-n` (Optional) 473 474 Namespace used for objects with missing namespaces in the input. 475 476 If not provided, the namespace defined in kubeconfig is used. If a kubeconfig is not available the value `default` is used.