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.