Naadir Jeewa
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    --- title: Cluster API OS Independent Machine Bootstrapper authors: - "@randomvariable" - "@yastij" reviewers: - "@moshloop" - "@marcelmue" - "@jsturtevant" - "@fabriziopandini" - "@binchenx" - "@alexeldeib" - "@vincepri" creation-date: 2021-02-22 last-updated: 2021-02-22 status: provisional see-also: - "/docs/proposals/2021022-kubelet-authentication-plugin.md" --- # Cluster API Machine Bootstrapper ## Table of Contents - [Cluster API Machine Bootstrapper](#cluster-api-machine-bootstrapper) - [Table of Contents](#table-of-contents) - [Glossary](#glossary) - [Summary](#summary) - [Motivation](#motivation) - [Goals](#goals) - [Non-Goals/Future Work](#non-goalsfuture-work) - [Proposal](#proposal) - [User Stories](#user-stories) - [Requirements Specification](#requirements-specification) - [Implementation details](#implementation-details) - [Deployment Model](#deployment-model) - [Core plugins](#core-plugins) - [Phased development](#phased-development) - [Plugin architecture](#plugin-architecture) - [Security Model](#security-model) - [Userdata storage](#userdata-storage) - [Types](#types) - [Additions to core Bootstrap type used in Machine* types](#additions-to-core-bootstrap-type-used-in-machine-types) - [Bootstrap template ConfigMap/Secret format:](#bootstrap-template-configmapsecret-format) - [Variables](#variables) - [Custom supported functions](#custom-supported-functions) - [MachineConfig types](#machineconfig-types) - [Common types](#common-types) - [Serialized data format](#serialized-data-format) - [Remote configuration](#remote-configuration) - [Encrypted configuration](#encrypted-configuration) - [Example of combining](#example-of-combining) - [Risks and Mitigations](#risks-and-mitigations) - [Alternatives](#alternatives) - [Single MachineConfiguration type](#single-machineconfiguration-type) - [MachineConfiguration as a separate non-bootstrap resource](#machineconfiguration-as-a-separate-non-bootstrap-resource) - [Upgrade Strategy](#upgrade-strategy) - [Additional Details](#additional-details) - [Test Plan [optional]](#test-plan-optional) - [Graduation Criteria [optional]](#graduation-criteria-optional) - [Version Skew Strategy [optional]](#version-skew-strategy-optional) - [Implementation History](#implementation-history) ## Glossary * OS Distribution: An OS Distribution refers to a packaged version of an Operating System, in order to primarily distinguish between different Linux distributions such as CentOS vs. Ubuntu vs. Talos, as opposed to differences between Operating Systems as a whole (e.g. Linux and Windows). * Machineadm : Is a binary CLI that is executed on machines to perform Kubernetes Cluster API bootstrap. * CABPK: Cluster API Bootstrap Provider Kubeadm is the bootstrap controller that exists from v1alpha2 onwards and generates cloud-init bootstrap data to execute kubeadm for a machine provisioned by Cluster API * Cloud-Init: Is a first-boot bootstrapper written by Canonical and is widely used across Ubuntu, Amazon Linux 2, and VMware PhotonOS * Cloudbase-Init: A Cloud-Init API compatible bootstrapper for the Windows operating system. * First-boot bootstrapper: Run when a machine is booted for the first time, and retrieve configuration information from an infrastructure provider specified endpoint, e.g. IMDS or Guestinfo. ## Summary Cluster API through v1alpha3 has used a combination of kubeadm, shell scripts and cloud-init to provision nodes. This proposal is for a node bootstrapper to combine these functions into a component that configures a machine and runs kubeadm, and be able to be consumed by multiple bootstrap providers such as cloud-init, Ignition and Talos. ## Motivation Cluster API’s reliance on cloud-init has frequently caused problems: changes in patch releases have caused breaking changes for Cluster API providers, such as vSphere and AWS. It has also made it difficult for other vendors, not using cloud-init, to easily use the core Cluster API providers, examples include OpenShift and FlatCar Linux which both use Ignition, and Talos with their own system. Furthermore, certain providers, such as Cluster API Provider AWS are utilising time-limited hacks within cloud-init to secure bootstrap userdata, and this is not sustainable for the health of the project over time. Use of an agnostic bootstrapper (machineadm) benefits end users in that they won’t need to closely monitor changes within each system that may have negative side effects on Cluster API. In addition, separating out the processes required to bootstrap a Kubernetes node from the bootstrap mechanism allows for Cluster API Kubeadm Bootstrap Provider (CABPK) to become an independent component. ### Goals * To produce a minimal on-machine bootstrapping mechanism to run kubeadm, and configure cluster related components. * To produce interfaces to plug new bootstrapping mechanisms. * To define new super-types (bootstrapper agnostic) for cluster and control plane configuration, which are not directly coupled to the kubeadm types. * To work closely with other efforts within Cluster API for the introduction of the types, like the one outlined in #2769. * To have Kubeadm Control Plane Provider and Kubeadm Bootstrap Provider adopt these types in v1alpha4 (release blocking). ### Non-Goals/Future Work - To support any on the fly mutability of components or resources at the present time. This proposal will be amended in the future to cover mutability use cases after the initial implementations are completed. ## Proposal ### User Stories <table> <thead> <tr> <th>ID</th><th>Title</th><th>Description</th></tr> </thead> <tbody> <tr> <td>U1</td><td>Non cloud-init bootstrap processes</td> <td> Ignition is a user-data processing Linux bootstrapping system used by Flat Car Linux, RHEL Atomic Host and Fedora CoreOS. (cluster-api/3761) </td> </tr> <tr> <td>U2</td><td>System preparation</td> <td> Although Flatcar Container Linux is being added to Image Builder, Flatcar is intended to also be used as an immutable distribution, with all additions being done at first boot. Flatcar users should be able to use standard Flatcar images with Cluster API. </td> </tr> <tr> <td>U3</td><td>Active Directory</td> <td> As a platform operator of a Windows environment, I may require their Kubernetes nodes to be domain joined such that the application workloads operate with appropriate Kerberos credentials to connect to services in the infrastructure. For Windows or Linux hosts joining an Active Directory, they must effectively be given a set of bootstrap credentials to join the directory and persist a Kerberos keytab for the host. </td> </tr> <tr> <td>U4</td><td>CIS Benchmark Compliance</td> <td> As a platform operator, I require Kubernetes clusters to pass the CIS Benchmark in order to meet organisational level security compliance requirements. </td> </tr> <tr> <td>U5</td><td>DISA STIG Compliance</td> <td> As a platform operator in a US, UK, Canadian, Australian or New Zealand secure government environment, I require my Kubernetes clusters to not break compliance with the DISA STIG. <br/><br/> Identified checks are CNTR-K8-000150. </td> </tr> <tr> <td>U6</td><td>Kubeadm UX</td> <td> As a cluster operator, I would like the bootstrap configuration of clusters or machines to be shielded from changes happening in kubeadm (e.g. v1beta1 and v1beta2 type migration)</td> </tr> <tr> <td>U7</td><td>Existing Clusters</td> <td> As a cluster operator with existing clusters, I would like to be able to, after enabling the necessary flags or feature gates, to create new clusters or machines using nodeadm. </td> </tr> <tr> <td>U8</td><td>Air-gapped</td> <td> As a cluster operator, I need Cluster API to operate independently of an internet connection in order to be able to provision clusters in an air-gapped environment, i.e. where the data center is not connected to the public internet. </td> </tr> <tr> <td>U9</td><td>Advanced control plane configuration files </td> <td> As a cluster operator, I need to configure components of my control plane, such as audit logging policies, KMS encryption, authentication webhooks to meet organisational requirements. </td> </tr> <tr> <td>U10</td><td>ContainerD Configuration</td> <td> Options such as proxy configuration, registry mirrors, custom certs, cgroup hierachy (image-builder/471) need to often be customised, and it isn’t always suitable to do at an image level. Cluster operators in an organisation often resort to prekubeadmcommand bash scripts to configure containerd and restart the service. </td> </tr> <tr> <td>U11</td><td>API Server Auth Reconfiguration</td> <td> As a cluster operator, I need to reconfigure the API server such that I can deploy a new static pod for authentication and insert an updated API server configuration. </td> </tr> <tr> <td>U12</td><td>Improving bootstrap reporting</td> <td> SRE teams often need to diagnose failed nodes, and having better information about why a node may have failed to join, or better indication of success would be helpful. (cluster-api/3716) </td> </tr> </tbody> </table> ### Requirements Specification We define three modalities of the node bootstrapper: <table> <thead> <tr><th>Mode</th><th>Description</th> </thead> <tbody> <tr> <td>Provisioning</td> <td> Expected to run as part of machine bootstrapping e.g. (part of cloud-* SystemD units or Windows OOBE). Only supported when used with Cluster API bootstrapping. Typically executes cluster creation or node join procedures, configuring kubelet etc... </td> </tr> <tr> <td>Preparation</td> <td> Could be run as part of machine bootstrapping prior to “provisioning”, and “prepares” a machine for use with Kubernetes. We largely keep this out of scope for the initial implementation unless there is a trivial implementation. </td> </tr> <tr> <td>Post</td> <td> Parts of the use cases above require ongoing management of a host. We list these as requirements, but are largely not in scope for the machine bootstrapper and should be dealt with by external systems. </td> </tr> </tbody> </table> <table> <thead> <tr><th>ID</th><th>Requirement</th><th>Mode</th><th>Related Stories</th> </thead> <tbody> <tr> <td>R1</td> <td> The machine bootstrapper MUST be able to execute kubeadm and report its outcome. Provisioning </td> <td>Provisioning</td><td>U1</td> </tr> <tr> <td>R2</td> <td> The machine bootstrapper MUST allow the configuration of Linux sysctl parameters </td> <td>Preparation</td><td>U2,U4</td> </tr> <tr> <td>R3</td> <td> The machine bootstrapper COULD allow the application of custom static pods on the control plane </td> <td>Provisioning</td><td>U4,U9</td> </tr> <tr> <td>R4</td> <td> The machine bootstrapper MUST not directly expose the kubeadm API to the end user </td> <td>Provisioning</td><td>U6</td> </tr> <tr> <td>R5</td> <td> The machine bootstrapper MUST be able to be used in conjunction with an OS provided bootstrapping tool, not limited to Cloud-Init, Ignition, Talos and Windows Answer File. </td> <td>Provisioning</td><td>U1</td> </tr> <tr> <td>R6</td> <td> The machine bootstrapper/authenticator binary MUST provide cryptographic verification in situations where it is downloaded post-boot. </td> <td>Preparation</td><td>U2</td> </tr> <tr> <td>R7</td> <td> The machine bootstrapper MUST not be reliant on the use of static pods to operate</td> <td>All</td><td>U5</td> </tr> <tr> <td>R8</td> <td> The machine bootstrapper MUST enable a Windows node to be domain joined. The machine bootstrapper WILL NOT manage the group membership of a Windows node in order to enable Group Managed Service Accounts </td> <td>Provisioning</td><td>U3</td> </tr> <tr> <td>R9</td> <td> The node bootstrapping system MUST be opt-in and not affect the operation of existing clusters when Cluster API is upgraded. </td> <td>Provisioning</td><td>U7</td> </tr> <tr> <td>R10</td> <td> The machine bootstrapper system SHOULD allow the agent to be downloaded from the management cluster </td> <td>Preparation</td><td>U8</td> </tr> <tr> <td>R11</td> <td> The machine bootstrapper MUST be able to operate without connectivity to the internet (using proper configuration parameters), or to the management cluster. </td> <td>Provisioning</td><td>U7</td> </tr> <tr> <td>R12</td> <td> When the machine bootstrapper is downloaded on boot the location MUST be configurable</td> <td>Preparation</td><td>U8</td> </tr> <tr> <td>R13</td> <td> When the machine bootstrapper is downloaded from the public internet, it MUST be downloadable from a location not subject to frequent rate limiting (e.g. a GCS bucket).</td> <td>Preparation</td><td>U9</td> </tr> <tr> <td>R14</td> <td> The machine bootstrapper MUST be able to configure containerd given a structured configuration input..</td> <td>Provisioning</td><td>U10</td> </tr> <tr> <td>R15</td> <td> The machine bootstrapper MUST publish a documented contract for operating system maintainers to integrate with the machine bootstrapper. </td> <td>All</td><td>U1</td> </tr> </tbody> </table> ### Implementation details #### Deployment Model <table> <thead> <tr><th>Component</th><th>Location</th><th>Description</th> </thead> <tbody> <tr> <td>machineadm-bootstrap-controller</td><td>cluster-api repo</td> <td> The core machine bootstrapper contains the controllerst hat reconciles MachineConfig to produce machineadm yaml </td> <tr> <td>machineadm-bootstrap-controller</td><td>cluster-api repo</td> <td> The core machine bootstrapper contains the controllerst hat reconciles MachineConfig to produce machineadm yaml </td> </tr> <tr> <td>machineadm cli</td><td>cluster-api repo</td> <td> The core CLI that reads machineadm.yaml and orchestrates the bootstrapping workflow </td> </tr> <tr> <td>machineadm core plugins</td><td>cluster-api repo</td> <td> A controller that ships with the infrastructure provider that can reconcile the storage of machineadm configurations with infrastructure APIs (e.g. Amazon S3/Minio, GCS, custom server etc...). </td> </tr> <tr> <td>machineadm remote configuration plugin</td><td>infrastructure provider repo</td> <td> An infrastructure plugin for the node bootstrapper will be created within infrastructure providers that would be responsible for infrastructure-specific logic to pull files machineadm files from a given location and upload bootstrap data. </td> </tr> <tr> <td>machineadm encryption plugin</td><td>infrastructure provider repo</td> <td> An infrastructure plugin for the node bootstrapper will be created within infrastructure providers that would be responsible for infrastructure-specific logic to use an external key management service. </td> </tr> <tr> <td>machineadm infrastructure controller</td><td>infrastructure provider repo</td> <td> A controller that ships with the infrastructure provider that can reconcile the storage of machineadm configurations with infrastructure APIs (e.g. Amazon S3/Minio, GCS, custom server etc...). </td> </tr> </tbody> </table> ##### Core plugins <table> <thead> <tr><th>Component</th><th>Description</th> </thead> <tbody> <tr> <td>machineadm-container-runtime-plugin-containerd</td> <td> A plugin that configures containerd runtimes. </td> <tr> <td>machineadm-timesync-plugin-systemd</td> <td> A plugin that configures systemd-timesyncd. </td> <tr> <td>machineadm-timesync-plugin-ntpd</td> <td> A plugin that configures ntpd. </td> <tr> <td>machineadm-timesync-plugin-chronyd</td> <td> A plugin that configures chronyd. </td> </tbody> </table> ### Phased development With reference to the modalities described in the requirements specification, we propose 3 phases of development: | Phase | What gets implemented | | ----------------- | ------------------------------- | | Phase 1 - Alpha 1 | Provisioning Modality | | Phase 2 - Alpha 2 | Preparation and Post Modalities | | Phase 3 & GA | API Stabilisation | ### Plugin architecture Machineadm will use the [go-plugin][go-plugin] architecture used by Hashicorp. Machineadm will expect plugins to use consistent filename formats depending on what type of plugin it is (and will be documented in the type). Plugins can either be "on path", in a directory supported in the PATH variable, or: * Linux: stored in `/usr/libexec/machineadm` or `/usr/local/libexec/machineadm` * Windows: stored in `"C:\Program Files\machineadm\plugins"` ### Security Model #### Userdata storage Machineadm's security model is intended such that secrets associated with machine configuration are stored on the management Kubernetes cluster and are secured to the level that the backing API server and etcd are secured. For machine bootstrapping, secrets are intended to be delivered by an infrastructure provider to a suitable secure location, and to also provide a mechanism for the machine to report back status. Examples include: * Amazon S3 or S3-compatible API such as Minio * AWS Secrets Manager and AWS Systems Manager Parameter Store When using external storage, we assume security is configured appropriately (e.g. Amazon Identity and Access Management), and is outside of the system boundary of machineadm bootstrap controller. In addition, some providers may require a secondary mechanism to encrypt data. For example, a deployment of an S3 compatible API may not support the same levels of fine-grained IAM access supported by EC2. A provider may then want to further encrypt the data. In this case we will additionally support a data block for in-band binary data (see [#encrypted-configuration](#encrypted-configuration)) that can be decrypted with a key derivation algorithm and a passphrase from an external source. We do not assume a KMS can directly encrypt the entire machine configuration as most systems have byte limits of around 64KB. Instead we assume the use of envelope encryption where a KMS encrypts a random string that is itself used as a key for encryption/data of data. We furthermore protect the KMS issued random string by deriving a key from it using SHA-512 PBKDF2-HMAC hashed to 50,000 rounds, with the result used for AES-256-GCM. This provides FIPS compliance with a suitable level of encryption given the resultant data will be applied as plain text to the machine configuration. The passphrase may either be stored at a remote location only the machine can access, or itself may be encrypted by an external Key Management Service, in which case machineadm is using envelope encryption. For example. the AWS provider could call `kms::GenerateDataKey` that generates a random string and associated ciphertext for the string encrypted by the Customer Managed Key. The provider could then use the random string as the passphrase for key derivation and throw away the plaintext passphrase, encoding the KMS encrypted value in a URI understood by the machineadm plugin, e.g. `kms://ZW5jcnlwdGVk@arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab`, where the base64 value before @ represents the encrypted passphrase to be handed to kms::Decrypt. In terms of why we provide support for both external data and in-band data with encryption is that some infrastructure APIs have limited userdata storage: For example, AWS and Azure are both limited to 64 kilobytes for userdata. When users want to configure things such as system certificates, these are generally incompressible and may exceed the capacity of that infrastructure. In these scenarios, external data stores are required to allow high levels of customization. ### Types #### Additions to core Bootstrap type used in Machine* types ```go // Bootstrap capsulates fields to configure the Machine’s bootstrapping mechanism. type Bootstrap struct { // NOTE: NO CHANGES TO EXISTING FIELDS // NEW FIELD: // InfrastructureRef is a reference to an infrastructure provide specific resource // that holds details of how to store and retrieve bootstrap data securely, // and how a bootstrapper can report status. InfrastructureRef *corev1.ObjectReference `json:"infrastructureRef,omitempty"` } ``` #### Bootstrap template ConfigMap/Secret format: Bootstrap templates will be simple go template strings that will form the final user data block. For the purposes of machineadm, the OS bootstrapper must write the file to disk somewhere, and execute machineadm with administrative credentials against the provided file. The following variables and functions are supported: ##### Variables * `machine_config`: The contents of the final infrastructure customized bootstrap configuration document. ##### Custom supported functions * `base64`: Base64 encodes the input. * `gzipBase64`: gzip compresses the input and then base64 encodes it. An example using cloud-init is presented below: ```yaml apiVersion: v1 kind: ConfigMap metadata: name: cloud-init-machineadm-bootstrap-template data: template: | #cloud-config write_files: - encoding: gz+b64 content: {{ machine_config | gzipBase64 }}. owner: root:root path: /tmp/machineadm_config.yaml permissions: '0644' runcmd: - /usr/bin/machineadm --bootstrap --path /tmp/machineadm_config.yaml ``` #### MachineConfig types It is important to note that we have in effect two representations of the MachineConfig: First, we have the MachineBootstrap Kubernetes resource that may reference other Kubernetes resources such as secrets for inclusion in the machine configuration. Secondly, we have the "serialized" MachineConfiguration which is the "fully realized" configuration, that inlines all of the referenced data and is stored as its own Kubernetes secret for handoff to the infrastructure provider for secure storage. ##### Common types ```go // MachineBootstrapConfig is a resource that defines the configuration // of a machine type MachineBootstrapConfig struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` Spec MachineBootstrapConfigSpec `json:"spec,omitempty"` Status MachineBootstrapConfigStatus `json:"status,omitempty"` } // MachineBootstrapConfigSpec defines the desired state of a MachineBootstrapConfig type MachineBootstrapConfigSpec struct { PluginRefs []corev1.ObjectReference `json:"pluginRefs"` } // MachineBootstrapConfigTemplate is a resource that defines the configuration // of a machine type MachineBootstrapConfigTemplate struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` Spec MachineBootstrapConfigTemplateSpec `json:"spec,omitempty"` } // MachineBootstrapConfigTemplateSpec defines the desired state of a MachineBootstrapConfigTemplate type MachineBootstrapConfigTemplateSpec struct { MachineBootstrapConfigSpec `json:",inline"` // PluginTemplateRefs is a list of machine bootstrap plugin template refs // which will be instantiated for each machine. PluginTemplateRefs []corev1.ObjectReference `json:"pluginTemplateRefs,omitempty"` } // MachineBootstrapConfigStatus defines the observed state of KubeadmConfig type MachineBootstrapConfigStatus struct { // Ready indicates the BootstrapData field is ready to be consumed Ready bool `json:"ready,omitempty"` // DataSecretName is the name of the secret that stores the bootstrap data script. // +optional DataSecretName *string `json:"dataSecretName,omitempty"` // FailureReason will be set on non-retryable errors // +optional FailureReason string `json:"failureReason,omitempty"` // FailureMessage will be set on non-retryable errors // +optional FailureMessage string `json:"failureMessage,omitempty"` // ObservedGeneration is the latest generation observed by the controller. // +optional ObservedGeneration int64 `json:"observedGeneration,omitempty"` PluginConditions []PluginConditions // Conditions defines current service state of the KubeadmConfig. // +optional Conditions clusterv1.Conditions `json:"conditions,omitempty"` } type PluginConditions struct { SecretReady bool Reason string } // PluginStatus defines the status of a machineadm plugin type PluginStatus struct { // FailureReason will be set on non-retryable errors // +optional FailureReason string `json:"failureReason,omitempty"` // FailureMessage will be set on non-retryable errors // +optional FailureMessage string `json:"failureMessage,omitempty"` // Conditions defines current service state of the cluster. // +optional Conditions Conditions `json:"conditions,omitempty"` // Ready defines if the control plane is ready. // +optional Ready bool `json:"ready,omitempty"` SecretName string `json:"secretName,omitempty"` BeforePlugins []string `json:"beforePlugins,omitempty"` AfterPlugins []string `json:"afterPlugins,omitempty"` } ``` #### Serialized data format `machineadm_config.yaml` will be a multi-part YAML docment supporting multiple data types, read and processed in order. ##### Remote configuration ```go // RemoteConfig is a resource for fetching a remote machine configuration type RemoteConfig struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` Spec RemoteConfigSpec `json:"spec,omitempty"` } type RemoteConfigSpec struct { // Provider is the infrastructure provider plugin that fetches the remote config. // This must be present on the host as // machineadm-remote-configuration-provider-x // +kubebuilder:validation:Required Provider string `json:"provider"` // URI is the location of the provider-specific remote config for retrieval // s3://us-west-2.cluster-api.contoso.com/bootstrap/test-cluster-machine-ufjdhad.yaml // +kubebuilder:validation:Required URI string `json:"uri"` } ``` ##### Encrypted configuration In-line serialized encrypted data for machineadm is a fully versioned type. The reason for this is to allow changes due to security reviews, CVEs, support for different types of encryption, such that we are not locked in to a particular implementation, as is currently the case with Kubernetes API Server KMS encryption providers. ```go // EncryptedConfig is a resource representing in-line encrypted // data that can be decrypted with an infrastructure plugin type EncryptedConfig struct { metav1.TypeMeta `json:",inline"` Spec EncryptedDataSpec `json:"spec,omitempty"` } // EncryptedConfigSpec stores an encrypted block of data as Ciphertext decryptable with a given key derivation algorithm // and passphrase. type EncryptedConfigSpec struct { // Provider is the infrastructure provider plugin that fetches the passphrase. This must be present on the host as // machineadm-plugin-encryption-provider-x // +kubebuilder:validation:Required Provider string `json:"provider"` // PassphraseURI is the location of the provider-specific passphrase // for retrieval, e.g. kms://ZW5jcnlwdGVk@arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab // +kubebuilder:validation:Required PassphraseURI string `json:"passphraseURI"` // Ciphertext is the base64 encoded encrypted ciphertext Ciphertext string `json:"ciphertext"` // +kubebuilder:validation:Required // Salt is base64 encoded random data added to the hashing algorithm to safeguard the // passphrase Salt string `json:"salt"` // IV, or Initialization Vector is the base64 encoded fixed-size input to a cryptographic algorithm // providing the random seed that was used for encryption. IV string `json:"iv"` // CipherAlgorithm is the encryption algorithm used for the ciphertext // +kubebuilder:validation:Required // +kubebuilder:default:=aes-256-gcm CipherAlgorithm string `json:"cipherAlgorithm"` // DigestAlgorithm is the digest algorithm used for key derivation. // +kubebuilder:validation:Required // +kubebuilder:default:=sha-512 DigestAlgorithm string `json:"digestAlgorithm"` // Iterations is the number of hashing iterations that was used for key derivation. // +kubebuilder:default:=50000 Iterations string `json:"iterations"` // KeyDerivationAlgorithm states the key derivation algorithm used to derive the encryption key // from the passphrase // +kubebuilder:validation:Required // +kubebuilder:default:=pbkdf2 KeyDerivationAlgorithm string `json:"keyDerivationAlgorithm"` } ``` ##### Example of combining ### Risks and Mitigations - What are the risks of this proposal and how do we mitigate? Think broadly. - How will UX be reviewed and by whom? - How will security be reviewed and by whom? - Consider including folks that also work outside the SIG or subproject. ## Alternatives ### Single MachineConfiguration type We could alternatively have a single MachineConfiguration type that includes all of the common use cases within it. The problem with this is that it leads to a large versioned API surface that would need to be supported for a long time. Breaking out separate configuration components into smaller types allows for extensibility, and faster revisioning of types where needed. ### MachineConfiguration as a separate non-bootstrap resource Another option that was considered was to preserve KubeadmBootstrapConfig, and have the MachineConfiguration resources wholly attached to the Machine object. This would theoretically allow the continued usage of KubeadmControlPlane, but changes the Machine contract, and would need to be considered in version upgrades for Machine resources. ## Upgrade Strategy TODO If applicable, how will the component be upgraded? Make sure this is in the test plan. Consider the following in developing an upgrade strategy for this enhancement: - What changes (in invocations, configurations, API use, etc.) is an existing cluster required to make on upgrade in order to keep previous behavior? - What changes (in invocations, configurations, API use, etc.) is an existing cluster required to make on upgrade in order to make use of the enhancement? ## Additional Details ### Test Plan [optional] TODO **Note:** *Section not required until targeted at a release.* Consider the following in developing a test plan for this enhancement: - Will there be e2e and integration tests, in addition to unit tests? - How will it be tested in isolation vs with other components? No need to outline all of the test cases, just the general strategy. Anything that would count as tricky in the implementation and anything particularly challenging to test should be called out. All code is expected to have adequate tests (eventually with coverage expectations). Please adhere to the [Kubernetes testing guidelines][testing-guidelines] when drafting this test plan. [testing-guidelines]: https://git.k8s.io/community/contributors/devel/sig-testing/testing.md ### Graduation Criteria [optional] **Note:** *Section not required until targeted at a release.* Define graduation milestones. These may be defined in terms of API maturity, or as something else. Initial proposal should keep this high-level with a focus on what signals will be looked at to determine graduation. Consider the following in developing the graduation criteria for this enhancement: - [Maturity levels (`alpha`, `beta`, `stable`)][maturity-levels] - [Deprecation policy][deprecation-policy] Clearly define what graduation means by either linking to the [API doc definition](https://kubernetes.io/docs/concepts/overview/kubernetes-api/#api-versioning), or by redefining what graduation means. In general, we try to use the same stages (alpha, beta, GA), regardless how the functionality is accessed. [maturity-levels]: https://git.k8s.io/community/contributors/devel/sig-architecture/api_changes.md#alpha-beta-and-stable-versions [deprecation-policy]: https://kubernetes.io/docs/reference/using-api/deprecation-policy/ ### Version Skew Strategy [optional] If applicable, how will the component handle version skew with other components? What are the guarantees? Make sure this is in the test plan. Consider the following in developing a version skew strategy for this enhancement: - Does this enhancement involve coordinating behavior in the control plane and in the kubelet? How does an n-2 kubelet without this feature available behave when this feature is used? - Will any other components on the node change? For example, changes to CSI, CRI or CNI may require updating that component before the kubelet. ## Implementation History - [ ] MM/DD/YYYY: Proposed idea in an issue or [community meeting] - [ ] MM/DD/YYYY: Compile a Google Doc following the CAEP template (link here) - [ ] MM/DD/YYYY: First round of feedback from community - [ ] MM/DD/YYYY: Present proposal at a [community meeting] - [ ] MM/DD/YYYY: Open proposal PR <!-- Links --> [community meeting]: https://docs.google.com/document/d/1Ys-DOR5UsgbMEeciuG0HOgDQc8kZsaWIWJeKJ1-UfbY [go-plugin]: https://github.com/hashicorp/go-plugin [kmip]: https://en.wikipedia.org/wiki/Key_Management_Interoperability_Protocol

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully