sigs.k8s.io/cluster-api@v1.7.1/docs/book/src/clusterctl/commands/alpha-topology-plan.md (about)

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