sigs.k8s.io/cluster-api@v1.7.1/docs/proposals/20190610-machine-states-preboot-bootstrapping.md (about)

     1  ---
     2  title: Machine States & Preboot Bootstrapping
     3  authors:
     4    - "@ncdc"
     5    - "@vincepri"
     6  reviewers:
     7    - "@davidewatson"
     8    - "@detiber"
     9    - "@justinsb"
    10    - "@timothysc"
    11    - "@vincepri"
    12  creation-date: 2019-06-10
    13  last-updated: 2019-09-06
    14  status: implemented
    15  ---
    16  
    17  # Machine States & Preboot Bootstrapping
    18  
    19  ## Table of Contents
    20  
    21  <!-- START doctoc generated TOC please keep comment here to allow auto update -->
    22  <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
    23  
    24  - [Glossary](#glossary)
    25  - [Summary](#summary)
    26  - [Motivation](#motivation)
    27    - [Goals](#goals)
    28    - [Non-Goals/Future Work](#non-goalsfuture-work)
    29  - [Proposal](#proposal)
    30    - [Data model changes](#data-model-changes)
    31  - [States and transitions](#states-and-transitions)
    32    - [Pending](#pending)
    33      - [Transition Conditions](#transition-conditions)
    34      - [Expectations](#expectations)
    35    - [Provisioning](#provisioning)
    36      - [Transition Conditions](#transition-conditions-1)
    37      - [Expectations](#expectations-1)
    38    - [Provisioned](#provisioned)
    39      - [Transition Conditions](#transition-conditions-2)
    40      - [Expectations](#expectations-2)
    41    - [Running](#running)
    42      - [Transition Conditions](#transition-conditions-3)
    43      - [Expectations](#expectations-3)
    44    - [Deleting](#deleting)
    45      - [Transition Conditions](#transition-conditions-4)
    46      - [Expectations](#expectations-4)
    47    - [Deleted](#deleted)
    48      - [Transition Conditions](#transition-conditions-5)
    49      - [Expectations](#expectations-5)
    50    - [Failed](#failed)
    51      - [Transition Conditions](#transition-conditions-6)
    52      - [Expectations](#expectations-6)
    53    - [Sequence diagram: User creates a machine with Kubeadm bootstrapper.](#sequence-diagram-user-creates-a-machine-with-kubeadm-bootstrapper)
    54    - [User Stories](#user-stories)
    55    - [Implementation Details/Notes/Constraints](#implementation-detailsnotesconstraints)
    56      - [Machine Controller Role](#machine-controller-role)
    57      - [Machine Controller dynamic watchers](#machine-controller-dynamic-watchers)
    58      - [Object References, Templates, MachineSets and MachineDeployments](#object-references-templates-machinesets-and-machinedeployments)
    59      - [Controllers and the single responsibility approach](#controllers-and-the-single-responsibility-approach)
    60      - [Remote references and accessing a workload cluster](#remote-references-and-accessing-a-workload-cluster)
    61      - [The “Phase” field and its role](#the-phase-field-and-its-role)
    62      - [Showing a status summary to users](#showing-a-status-summary-to-users)
    63    - [Risks and Mitigations](#risks-and-mitigations)
    64      - [State transitions are inflexible](#state-transitions-are-inflexible)
    65      - [Machine Controller can access any machine or cluster in any namespace](#machine-controller-can-access-any-machine-or-cluster-in-any-namespace)
    66      - [Certificates and tokens are exposed in plaintext](#certificates-and-tokens-are-exposed-in-plaintext)
    67      - [Bootstrap data cannot be merged](#bootstrap-data-cannot-be-merged)
    68      - [MachineClass is deprecated and will be revisited later](#machineclass-is-deprecated-and-will-be-revisited-later)
    69  - [Design Details](#design-details)
    70    - [Test Plan](#test-plan)
    71    - [Graduation Criteria](#graduation-criteria)
    72    - [Upgrade / Downgrade Strategy](#upgrade--downgrade-strategy)
    73    - [Version Skew Strategy](#version-skew-strategy)
    74  - [Implementation History](#implementation-history)
    75  - [Drawbacks](#drawbacks)
    76  - [Alternatives](#alternatives)
    77      - [Object References, Templates, MachineSets and MachineDeployments](#object-references-templates-machinesets-and-machinedeployments-1)
    78  
    79  <!-- END doctoc generated TOC please keep comment here to allow auto update -->
    80  
    81  ## Glossary
    82  
    83  - **[Cluster API](../book/src/reference/glossary.md#cluster-api)**: Unless otherwise specified, this refers to the project as a whole.
    84  - **Cluster API Manager**: The controller-runtime's Manager that runs controllers.
    85  - **[Machine](../book/src/reference/glossary.md#machine)**: The Kubernetes Custom Resource Definition offered by Cluster API.
    86  - **[Server/Instance/Host](../book/src/reference/glossary.md#server)**: The infrastructure that backs a Machine.
    87  - **Bootstrapping**: The process of turning a server into a Kubernetes node.
    88  
    89  ## Summary
    90  
    91  This proposal outlines splitting up the Machine data model into two new providers/controllers along with the generic Machine controller. The two new providers are the Infrastructure provider and the Bootstrap provider. The infrastructure provider handles provisioning infrastructure (cloud, bare metal, virtual) and the bootstrap provider handles turning a server into a Kubernetes node. This change will improve separation of concerns for the Machine controller and gives more degrees of freedom to the user.
    92  
    93  In Cluster API v1alpha1, users can create Machine custom resources. When a Machine resource is created, Cluster API components react by provisioning infrastructure (typically a physical or virtual machine) and then bootstrapping Kubernetes on the provisioned server, making it a Kubernetes Node. Cluster API’s current architecture mandates that a single “provider” handle both the infrastructure provisioning and the Kubernetes bootstrapping.
    94  
    95  ## Motivation
    96  - A singular provider that combines infrastructure provisioning and Kubernetes bootstrapping is too restrictive. Many current v1alpha1 providers target single cloud providers. If a user wants to install a specific Kubernetes distribution (Kubernetes, OpenShift, Rancher, etc.), it is left to the provider to add support for it. In practical terms, we are not able to guarantee that a user can install the same distribution regardless of infrastructure environment.
    97  - The Machine custom resource contains fields for provider-specific configuration and status. These are represented as opaque [RawExtensions](https://godoc.org/k8s.io/apimachinery/pkg/runtime#RawExtension), meaning their contents are not directly processed as part of the Machine’s validation.
    98  - The strict relationship between the Machine controller with provider-specific Actuator doesn't allow reconciling machines with providerSpec of different cloud providers in the same cluster (i.e. hybrid cluster). Separation of provider-specific bits from the Machine controller increases flexibility of the cluster api plane and moves the responsibility for their interpretation and reconciliation into dedicated controllers.
    99  - Both users and developers are confused by the code organization split. The Cluster API repository currently offers controllers for Cluster, Machine, MachineSet, MachineDeployment, Node. Some of these controllers are meant to be vendored and run as part of a provider's Manager; while some others are generic (MachineDeployment, MachineSet, Node) and meant to be run as part of the Cluster API Manager. As outlined in this proposal, we'd like to streamline the relationship between where the code lives and where it runs. In particular, we'd like to make the Machine type and its controller generic, which will allow for it to be part of the Cluster API Manager.
   100  
   101  ### Goals
   102  1. To use Kubernetes Controllers to manage the lifecycle of Machines.
   103  1. To make bootstrap implementations reusable across any infrastructure provider.
   104  1. To support pre-boot (e.g. cloud-init, bash scripts, or similar) bootstrapping.
   105  1. To support bootstrapping different Kubernetes distributions on the same infrastructure provider.
   106  1. To validate provider-specific content as early as possible (create, update).
   107  
   108  ### Non-Goals/Future Work
   109  1. To modify the Cluster object.
   110  1. To fully implement machine state lifecycle hooks. This must be part of a future proposal that builds on these proposed changes.
   111  1. To setup OS configuration, install software or any other features related to image building.
   112  1. To support post-boot configuration of Machine.
   113  1. To revisit MachineClass role and functionality.
   114  1. To customize the image beyond the settings required to run kubelet, that is an implementation constraint of the bootstrap provider.
   115  
   116  ## Proposal
   117  In this section we outline the proposed API changes; describe states, transitions, and sequence diagrams for the most important scenarios; and provide a kubeadm-based example.
   118  
   119  ### Data model changes
   120  The Machine Spec and Status fields undergo some breaking changes which remove or add new fields. We introduce a Bootstrap Controller which encapsulates the integration point between a Machine and its path to become a Kubernetes Node.
   121  
   122  ```go
   123  type MachineSpec struct
   124  ```
   125  - **To remove**
   126      - **ProviderSpec [optional]** _Superseded by InfrastructureRef_
   127          - Type: `*runtime.RawExtension`
   128          - Description: ProviderSpec details Provider-specific configuration to use during node creation.
   129      - **Versions [optional]**  _Superseded by Version_
   130          - Type: `MachineVersionInfo`
   131          - Description: Versions of key software to use. This field is optional at cluster creation time, and omitting the field indicates that the cluster installation tool should select defaults for the user. These defaults may differ based on the cluster installer, but the tool should populate the values it uses when persisting Machine objects. A Machine spec missing this field at runtime is invalid.
   132  - **To add**
   133      - **Bootstrap**
   134          - Type: `Bootstrap`
   135          - Description: Bootstrap is a reference to a local struct which encapsulates fields to configure the Machine’s bootstrapping mechanism.
   136      - **InfrastructureRef [required]**
   137          - Type: `corev1.ObjectReference`
   138          - Description: InfrastructureRef is a required reference to a Custom Resource Definition offered by an infrastructure provider.
   139      - **Version [optional]**
   140          - Type: `string`
   141          - Description: Version defines the desired Kubernetes version. This field is meant to be optionally used by bootstrap providers.
   142  
   143  ```go
   144  type MachineStatus struct
   145  ```
   146  
   147  - **To remove**
   148      - **ProviderStatus [optional]**
   149          - Type: `*runtime.RawExtension`
   150          - Description: ProviderStatus details a Provider-specific status. It is recommended that providers maintain their own versioned API types that should be serialized/deserialized from this field.
   151      - **Versions [optional]**  _Superseded by Version_
   152          - Type: `*MachineVersionInfo`
   153          - Description: Versions specifies the current versions of software on the corresponding Node (if it exists). This is provided for a few reasons [...].
   154  - **To add**
   155      - **Version [optional]**
   156          - Type: `*string`
   157          - Description: Version specifies the current version of Kubernetes running on the corresponding Node. This is meant to be a means of bubbling up status from the Node to the Machine. It is entirely optional, but useful for end-user UX if it’s present.
   158      - **BootstrapReady [optional]**
   159          - Type: `bool`
   160          - Description: True when the bootstrap provider status is ready.
   161      - **InfrastructureReady [optional]**
   162          - Type: `bool`
   163          - Description: True when the infrastructure provider status is ready.
   164  
   165  ```go
   166  type Bootstrap struct
   167  ```
   168  - **To add**
   169      - **ConfigRef [optional]**
   170          - Type: `*corev1.ObjectReference`
   171          - Description: ConfigRef is a reference to a bootstrap provider-specific resource that holds configuration details. The reference is optional to allow users/operators to specify Bootstrap.Data without the need of a controller.
   172      - **Data [optional]**
   173          - Type: `*string`
   174          - Description: Data contains the bootstrap data, such as cloud-init details scripts. If nil, the Machine should remain in the Pending state.
   175  
   176  ## States and transitions
   177  The Cluster API Machine Controller is responsible for managing the lifecycle of a Machine, including its state transitions. This is the only controller that should be writing updates to Machines.
   178  
   179  ---
   180  ### Pending
   181  ```go
   182  // MachinePhasePending is the first state a Machine is assigned by
   183  // Cluster API Machine controller after being created.
   184  MachinePhasePending = MachinePhaseType("pending")
   185  ```
   186  
   187  #### Transition Conditions
   188  - `Machine.Status.Phase` is empty string
   189  
   190  #### Expectations
   191  - When `Machine.Spec.Bootstrap.Data` is:
   192      - `<nil>`, expect the field to be set by an external controller.
   193      - `""` (empty string), expect the bootstrap step to be ignored.
   194      - `"..."` (populated by user or from the bootstrap provider), expect the contents to be used by a bootstrap (pre-Running transition) or infrastructure (Provisioning state) provider.
   195  
   196  ---
   197  ### Provisioning
   198  ```go
   199  // MachinePhaseProvisioning is the state when the
   200  // Machine infrastructure is being created.
   201  MachinePhaseProvisioning = MachinePhaseType("provisioning")
   202  ```
   203  
   204  #### Transition Conditions
   205  - `Machine.Spec.Bootstrap.ConfigRef`->`Status.Ready` is true
   206  - `Machine.Spec.Bootstrap.Data` is not `<nil>`
   207  
   208  #### Expectations
   209  - Machine’s infrastructure to be in the process of being provisioned.
   210  
   211  ---
   212  ### Provisioned
   213  ```go
   214  // MachinePhaseProvisioned is the state when its
   215  // infrastructure has been created and configured.
   216  MachinePhaseProvisioned = MachinePhaseType("provisioned")
   217  ```
   218  
   219  #### Transition Conditions
   220  - `Machine.Spec.InfrastructureRef`->`Status.Ready` is true
   221  - `Machine.Spec.ProviderID` is synced from `Machine.Spec.InfrastructureRef` -> `Spec.ProviderID`
   222  - (optional) `Machine.Status.Addresses` is synced from `Machine.Spec.InfrastructureRef` -> `Status.Addresses`
   223  
   224  #### Expectations
   225  - Machine’s infrastructure has been created and the compute resource is available to be configured.
   226  
   227  ---
   228  ### Running
   229  ```go
   230  // MachinePhaseRunning is the Machine state when it has
   231  // become a Kubernetes Node in a Ready state.
   232  MachinePhaseRunning = MachinePhaseType("running")
   233  ```
   234  
   235  #### Transition Conditions
   236  - A Kubernetes Node is found with the same `Machine.Spec.ProviderID` and its state is “Ready”
   237  
   238  #### Expectations
   239  - Machine controller should set `Machine.Status.NodeRef`.
   240  
   241  ---
   242  ### Deleting
   243  ```go
   244  // MachinePhaseDeleting is the Machine state when a delete
   245  // request has been sent to the API Server,
   246  // but its infrastructure has not yet been fully deleted.
   247  MachinePhaseDeleting = MachinePhaseType("deleting")
   248  ```
   249  
   250  #### Transition Conditions
   251  - `Machine.ObjectMeta.DeletionTimestamp` is not zero.
   252  
   253  #### Expectations
   254  - Node associated should be drained and cordoned.
   255  - Machine’s related resources should be deleted first using cascading deletion.
   256  
   257  ---
   258  ### Deleted
   259  ```go
   260  // MachinePhaseDeleted is the Machine state when the object
   261  // and the related infrastructure is deleted and
   262  // ready to be garbage collected by the API Server.
   263  MachinePhaseDeleted = MachinePhaseType("deleted")
   264  ```
   265  
   266  #### Transition Conditions
   267  - `Machine.ObjectMeta.DeletionTimestamp` is not zero.
   268  - (optional) `Machine.Bootstrap.ConfigRef` -> `ObjectMeta.DeletionTimestamp` is not zero.
   269  - `Machine.Spec.InfrastructureRef`-> `ObjectMeta.DeletionTimestamp` is not zero.
   270  
   271  #### Expectations
   272  - Machine controller should remove finalizer.
   273  
   274  ---
   275  ### Failed
   276  ```go
   277  // MachinePhaseFailed is the Machine state when the system
   278  // might require user intervention.
   279  MachinePhaseFailed = MachinePhaseType("failed")
   280  ```
   281  
   282  #### Transition Conditions
   283  - `Machine.ErrorReason` and/or `Machine.ErrorMessage` is populated.
   284  
   285  #### Expectations
   286  - User intervention.
   287  
   288  ---
   289  ![Figure 1](../book/src/images/bootstrap-controller.png)
   290  
   291  ### Sequence diagram: User creates a machine with Kubeadm bootstrapper.
   292  In this scenario, we go through each step from “kubectl apply” to seeing the Node in “Running” state. The user has chosen to create a Machine with the following: no custom user data, Machine.Bootstrap is a Kubeadm bootstrap provider, and Machine.InfrastructureRef is an AWS infrastructure provider.
   293  
   294  ![Figure 2](./images/machine-states-preboot/Figure2.png)
   295  
   296  Figure 2 is a simplified diagram of the configuration of a Machine using a Kubeadm bootstrap provider. Machine.Spec.Bootstrap.ConfigRef points to a bootstrap provider-specific custom resource; in this example, a KubeadmBootstrapConfig called controlplane-0.
   297  
   298  ![Figure 3](./images/machine-states-preboot/Figure3.png)
   299  
   300  In this diagram, we have two main entities: API Server and Cluster API Machine Controller. When a Machine is created, the Kubernetes API Server validates it, persists it, and emits a watch event. The Cluster API Machine Controller receives the watch event and reconciles the Machine.
   301  
   302  The reconciliation loop starts by checking the Machine’s Bootstrap fields. For the purpose of this example, we expect the Machine.Spec.Bootstrap.Data field to be nil and for the ConfigRef’s associated resource to have a non-Ready status. The Machine Controller sets Machine.Status.Phase to “Pending” and sends the update to the API Server.
   303  
   304  The Machine Controller also establishes a watch for the bootstrap and infrastructure specific resources (KubeadmBootstrapConfig, AWSInfrastructureConfig). In addition, the controller sets an OwnerReference on KubeadmBootstrapConfig and AWSInfrastructureConfig.
   305  
   306  ![Figure 4](./images/machine-states-preboot/Figure4.png)
   307  
   308  After the Machine Controller updates the Machine, it must wait for the machine to be “provisionable” - in this case, the Machine must have its Spec.Bootstrap.Data specified. Any value besides nil is acceptable. Some environments may not require any bootstrap data, in which case this would be designated by the empty string. Other environments that do require bootstrap data would use a non-empty string.
   309  
   310  In this example, we have a Kubeadm Bootstrap Provider that runs a controller watching for KubeadmBootstrapConfig and Machine WatchEvents. Upon receiving a Machine event, a reconcile request is enqueued for the associated KubeadmBootstrapConfig. Next, it retrieves the Machine, Cluster, and generates a cloud-init based bootstrap configuration which is then stored in KubeadmBootstrapConfig.Status.BootstrapData. It also sets KubeadmBootstrapConfig.Status.Ready to `true`. A non-nil value in KubeadmBootstrapConfig.Status.BootstrapData is indicative to the Cluster API Machine Controller that the bootstrap provider has completed its work.
   311  
   312  ![Figure 5](./images/machine-states-preboot/Figure5.png)
   313  
   314  The Cluster API Machine Controller receives an event for the updated KubeadmBootstrapConfig resource and enqueues a reconciliation request for the associated Machine. The Machine Controller sees the populated KubeadmBootstrapConfig.Status.BootstrapData field and copies it to Machine.Spec.Bootstrap.Data. The Machine Controller also updates Machine.Status.Phase to Provisioning and sends the updated Machine to the API Server.
   315  
   316  ![Figure 6](./images/machine-states-preboot/Figure6.png)
   317  
   318  With this latest Machine update, the API Server emits another watch event. A machine infrastructure provider controller watches for updates to Machine objects to determine when it can reconcile its own objects and start provisioning. For this example, we’ll use an AWS infrastructure provider that bootstraps using cloud-init. As shown in Figure 6, it watches for AWSInfrastructureConfig and Machine WatchEvents. Once it receives the event on the Machine, it enqueues a reconciliation request for the associated AWSInfrastructureConfig (via Machine.InfrastructureRef). When the controller sees the Machine’s non-nil bootstrap data, it asks AWS to create an EC2 instance, using the Machine’s bootstrap data as the cloud-init data for the virtual machine. After the EC2 instance is up and running, the AWS controller sets AWSInfrastructureConfig.Status.Ready to `true`, populates the AWSInfrastructureConfig.Status.Addresses field, and sends the updated AWSInfrastructureConfig to the API Server.
   319  
   320  ![Figure 7](./images/machine-states-preboot/Figure7.png)
   321  
   322  The Cluster API Controller manager receives an event for the updated AWSInfrastructureConfig resource and enqueues a reconciliation request for the associated Machine. The Machine Controller understands that the infrastructure is ready by checking that the AWSInfrastructureConfig.Status.Addresses field has been populated and proceeds to wait for a Kubernetes Node matching the Machine.ProviderID in “Ready” state. After a Node is found, the Machine Controller sets Machine.Status.NodeRef, Machine.Status.Phase to “Ready” and updates the Machine object.
   323  
   324  ![Figure 8](./images/machine-states-preboot/Figure8.png)
   325  
   326  The Machine has now become a Kubernetes Node and ready to be used.
   327  
   328  ### User Stories
   329  
   330  - As a Kubernetes operator, I’d like to provide custom bootstrap data without the use of a Kubernetes controller.
   331  
   332  - As a Kubernetes operator, I’d like to monitor the progress of fulfilling a Machine and understand what errors, if any, have been reported by the controllers involved.
   333  
   334  - As an infrastructure provider author, I would like to build the fewest number of components possible to support the full cluster-api.
   335  
   336  - As an infrastructure provider author, I would like to take advantage of the kubernetes API to provide validation for provider-specific data needed to provision a machine.
   337  
   338  - As an infrastructure provider author, I would like to build a controller to manage provisioning machines using tools of my own choosing.
   339  
   340  - As an infrastructure provider author, I would like to build a controller to manage provisioning machines without being restricted to a CRUD API.
   341  
   342  - As an infrastructure provider consumer, I would like to have validation for the provider-specific data I need to give the system to have it provision a machine.
   343  
   344  ### Implementation Details/Notes/Constraints
   345  
   346  #### Machine Controller Role
   347  The Machine Controller lives within Cluster API manager alongside MachineSet and MachineDeployment controllers. This controller should be the only controller having write permissions to Machine objects. The controller responsibility focuses on state transitions and operations including but not limited to:
   348  - Manage Machines finalizers.
   349  - Set Machine OwnerReferences (e.g. to Cluster, MachineSet).
   350  - Setting Machine.Status.Phase based on the transition conditions described above.
   351  - Pull data from provider custom resources into the right places (e.g. Machine.Spec.Bootstrap.Data from Machine.Spec.Bootstrap.ConfigRef -> Status.BootstrapData).
   352  - Update Status fields from provider custom resources.
   353  
   354  #### Machine Controller dynamic watchers
   355  The Machine Controller needs to watch for updates to bootstrap and infrastructure provider specific resources so it can copy bootstrap data/status and infrastructure provider status information to the Machine status. To achieve this, we can use controller-runtime’s `source.Informer` type and client-go’s `dynamicinformer.DynamicSharedInformerFactory`.
   356  
   357  When the Machine Controller reconciles a Machine and sees a reference to a provider-specific resource, such as a KubeadmBootstrapConfig or an AWSMachineConfig, it can:
   358  - Get a dynamic informer for the provider-specific resource.
   359  - Invoke c.Watch() (where c is a `controller.Controller` instance) with a `source.Informer` for the dynamic informer and a `handler.EnqueueRequestForOwner` configured with Machine as the OwnerType.
   360  
   361  #### Object References, Templates, MachineSets and MachineDeployments
   362  With providerSpec and providerStatus no longer inlined in the Machine resource, we need a way to ensure we can continue to provide at least unique status information for a Machine per bootstrap configuration and per infrastructure configuration.
   363  
   364  Each Machine needs a reference to a unique Bootstrap provider-specific resource, and a reference to a unique Infrastructure provider-specific resource. This is easy to do when creating a single Machine, but not so obvious when a MachineSet is creating multiple Machine replicas.
   365  
   366  For the MachineSet, the references to the Bootstrap and Infrastructure resources are references to templates. When the MachineSet Controller creates a new Machine replica, it retrieves the Bootstrap and Infrastructure resources referenced by the MachineSet’s Machine spec template and creates copies for that Machine to use exclusively.
   367  
   368  #### Controllers and the single responsibility approach
   369  Each controller internal or external to Cluster API in v1alpha2 should follow a single responsibility approach. In the scenario above we go through some of these details: a controller should only modify its own custom resources, but it can watch or read other objects. By following this principle, we aim to reduce or completely eliminate the problem of having controllers modifying and fighting for updates to the same resource.
   370  
   371  #### Remote references and accessing a workload cluster
   372  Part of the workflow shown above is the ability for the Machine Controller to access the Workload Cluster’s API Server. As part of this proposal, we want to standardize how the Machine Controller gains access to a cluster using a Kubernetes Secret. The Secret should be living within the associated Cluster namespace and following a preset naming convention (e.g. `<cluster-name>-kubeconfig`) and RBAC should be configured appropriately.
   373  
   374  For the purpose of this proposal, the secret-based access to the Workload Cluster is going to require that the Workload Cluster’s API server be accessible from the management cluster with direct https. Features such as tunneling or other forms of access are left to a later proposal.
   375  
   376  #### The “Phase” field and its role
   377  The Phase field is a high-level indicator of the status of the Machine as it is provisioned, from the API user’s perspective. The value should not be interpreted by any software components as a reliable indication of the actual state of the Machine, and controllers should not use the Phase value when making decisions about what action to take. Controllers should always look at the actual state of the Machine’s fields to make those decisions.
   378  
   379  #### Showing a status summary to users
   380  One of the project’s goals is to improve the user experience by providing more information on a Machine status. In this proposal we add new fields (Machine.Status.InfrastructurePhase and Machine.Status.BootstrapPhase) to the Machine Status which the Machine Controller synchronizes from the referenced custom objects.
   381  
   382  ### Risks and Mitigations
   383  
   384  #### State transitions are inflexible
   385  To determine state transitions, we adopt a simple approach that relies on the values from a specific set of fields. As outlined in the state description tables above, a transition can happen if and only if the whole set of conditions is true. Some might argue that it’d be more ideal to adopt a more complex yet powerful system that would allow controllers to dynamically specify conditions that need to be met for a state transition to happen. Although desirable, this particular feature adds a lot of complexity to the system, therefore we propose to tackle related use cases and implementation work in a future community proposal.
   386  
   387  #### Machine Controller can access any machine or cluster in any namespace
   388  The Cluster API Machine controller, given the design outlined above, can access any Machine in any namespace and gain access (via secret-based kubeconfig) to any Workload Cluster API Server. To overcome the security concerns, we allow users or cluster operators to optionally restrict the Cluster API manager, to watch and operate on objects within a single namespace, based on prefix, or a list using command line flags and providing RBAC examples.
   389  
   390  #### Certificates and tokens are exposed in plaintext
   391  Sensitive data is exposed in multiple places and could pose a security risk. The behavior won’t change from v1alpha1 and will be tackled in a future proposal.
   392  
   393  #### Bootstrap data cannot be merged
   394  Cluster API doesn’t provide an out of the box experience for merging user-supplied user-data with one or more bootstrap providers. While there are some use cases (e.g. installing software tools, configuring kernel params) that would require support for this feature, we’d like to keep v1alpha2 scoped to a single source of truth and put aside the complications that might arise supporting such request. Bootstrap providers may allow for such feature by providing additional fields in their own custom resources.
   395  
   396  #### MachineClass is deprecated and will be revisited later
   397  MachineClass has served as a templating mechanisms for Machines. In v1alpha2 templating is left to MachineSet and MachineDeployment references and the functionality from MachineClass is being removed in favor of the new approach. In future revisions MachineClass might be revisited to support other use cases and tools like cluster autoscaler.
   398  
   399  ## Design Details
   400  
   401  ### Test Plan
   402  TODO @release
   403  
   404  ### Graduation Criteria
   405  TODO @release
   406  
   407  ### Upgrade / Downgrade Strategy
   408  TODO @release
   409  
   410  ### Version Skew Strategy
   411  TODO @release
   412  
   413  ## Implementation History
   414  
   415  - [x] 05/29/2019: Discuss v1alpha2 scope reduction at the [community meeting](https://docs.google.com/document/d/1Ys-DOR5UsgbMEeciuG0HOgDQc8kZsaWIWJeKJ1-UfbY/edit#heading=h.s8py1oplak7i)
   416  - [x] 06/04/2019: Compile a Google Doc following the CAEP template [link](https://docs.google.com/document/d/18JOgoK9EF3miEd2FWvIggruA-41jL8fLcEhiVzzwzjQ/edit?ts=5cfa7379#)
   417  - [x] 06/05/2019: Present the proposal at the [community meeting](https://docs.google.com/document/d/1Ys-DOR5UsgbMEeciuG0HOgDQc8kZsaWIWJeKJ1-UfbY/edit#heading=h.pj3kmzqnc2qa)
   418  - [x] 06/06/2019: Ask community for feedback
   419  - [x] 06/10/2019: Open proposal PR
   420  
   421  ## Drawbacks
   422  
   423  ## Alternatives
   424  
   425  #### Object References, Templates, MachineSets and MachineDeployments
   426  For each reference have a template reference as well.
   427  Alongside Machine.Bootstrap.ConfigRef and Machine.InfrastructureRef we can add two more fields: Machine.Bootstrap.ConfigTemplateRef and Machine.InfrastructureTemplateRef. The Machine Controller is responsible, in pre-pending phase, for turning templates in new instances and fill in Machine.Bootstrap.ConfigRef and Machine.InfrastructureRef. MachineDeployments and MachineSets should only permit the use of template references.