sigs.k8s.io/cluster-api@v1.6.3/docs/proposals/20230407-flexible-managed-k8s-endpoints.md (about)

     1  <!-- START doctoc generated TOC please keep comment here to allow auto update -->
     2  <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
     3  **Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*
     4  
     5  - [Flexible Managed Kubernetes Endpoints](#flexible-managed-kubernetes-endpoints)
     6    - [Glossary](#glossary)
     7    - [Summary](#summary)
     8    - [Motivation](#motivation)
     9      - [Goals](#goals)
    10      - [Non-Goals](#non-goals)
    11      - [Future Work](#future-work)
    12    - [Proposal](#proposal)
    13      - [User Stories](#user-stories)
    14        - [Story 1](#story-1)
    15        - [Story 2](#story-2)
    16        - [Story 3](#story-3)
    17        - [Story 4](#story-4)
    18        - [Story 5](#story-5)
    19        - [Story 6](#story-6)
    20        - [Story 7](#story-7)
    21      - [Design](#design)
    22        - [Core Cluster API changes](#core-cluster-api-changes)
    23        - [Infra Providers API changes](#infra-providers-api-changes)
    24        - [Core Cluster API Controllers changes](#core-cluster-api-controllers-changes)
    25        - [Provider controller changes](#provider-controller-changes)
    26      - [Guidelines for infra providers implementation](#guidelines-for-infra-providers-implementation)
    27    - [Background work](#background-work)
    28      - [EKS in CAPA](#eks-in-capa)
    29        - [AKS in CAPZ](#aks-in-capz)
    30        - [GKE in CAPG](#gke-in-capg)
    31        - [Learnings from original Proposal: Two kinds with a Managed Control Plane & Managed Infra Cluster adhering to the current CAPI contracts](#learnings-from-original-proposal-two-kinds-with-a-managed-control-plane--managed-infra-cluster-adhering-to-the-current-capi-contracts)
    32      - [Two New Flows](#two-new-flows)
    33        - [Flow 1: `<Infra>Cluster` and `<Infra>ControlPlane`, with `ControlPlaneEndpoint` reported via `<Infra>ControlPlane`](#flow-1-infracluster-and-infracontrolplane-with-controlplaneendpoint-reported-via-infracontrolplane)
    34        - [Flow 2: Change CAPI to make `<Infra>Cluster` optional](#flow-2-change-capi-to-make-infracluster-optional)
    35        - [Alternative Option: Introduce a new Managed Kubernetes provider type (with contract)](#alternative-option-introduce-a-new-managed-kubernetes-provider-type-with-contract)
    36    - [Recommendations](#recommendations)
    37    - [Implementation History](#implementation-history)
    38  
    39  <!-- END doctoc generated TOC please keep comment here to allow auto update -->
    40  
    41  ---
    42  title: Flexible Managed Kubernetes Endpoints
    43  authors:
    44    - "@jackfrancis"
    45  reviewers:
    46    - "@richardcase"
    47    - "@pydctw"
    48    - "@mtougeron"
    49    - "@CecileRobertMichon"
    50    - "@fabriziopandini"
    51    - "@sbueringer"
    52    - "@killianmuldoon"
    53    - "@mboersma"
    54    - "@nojnhuh"
    55  creation-date: 2023-04-07
    56  last-updated: 2023-04-07
    57  status: provisional
    58  see-also:
    59    - "/docs/proposals/20220725-managed-kubernetes.md"
    60  ---
    61  
    62  # Flexible Managed Kubernetes Endpoints
    63  
    64  ## Glossary
    65  
    66  Refer to the [Cluster API Book Glossary](https://cluster-api.sigs.k8s.io/reference/glossary.html).
    67  
    68  The following terms will be used in this document.
    69  
    70  - Managed Kubernetes
    71    - Managed Kubernetes refers to any Kubernetes Cluster provisioning and maintenance abstraction, usually exposed as an API, that is natively available in a Cloud provider. For example: [EKS](https://aws.amazon.com/eks/), [OKE](https://www.oracle.com/cloud/cloud-native/container-engine-kubernetes/), [AKS](https://azure.microsoft.com/en-us/products/kubernetes-service), [GKE](https://cloud.google.com/kubernetes-engine), [IBM Cloud Kubernetes Service](https://www.ibm.com/cloud/kubernetes-service), [DOKS](https://www.digitalocean.com/products/kubernetes), and many more throughout the Kubernetes Cloud Native ecosystem.
    72  - `ControlPlane Provider`
    73    - When we say `ControlPlane Provider` we refer to a solution that implements a solution for the management of a Kubernetes [control plane](https://kubernetes.io/docs/concepts/#kubernetes-control-plane) according to the Cluster API contract. Please note that in the context of managed Kubernetes, the `ControlPlane Provider` usually wraps the corresponding abstraction for a specific Cloud provider. Concrete example for Microsoft Azure is the `AzureManagedControlPlane`, for AWS the `AWSManagedControlPlane`, for Google the `GCPManagedControlPlane` etc.
    74  - _Kubernetes Cluster Infrastructure_
    75    - When we refer to _Kubernetes Cluster Infrastructure_ (abbr. _Cluster Infrastructure_) we refer to the **infrastructure that supports a Kubernetes cluster**, like e.g. VPC, security groups, load balancers etc. Please note that in the context of Managed Kubernetes some of those components are going to be provided by the corresponding abstraction for a specific Cloud provider (EKS, OKE, AKS etc), and thus Cluster API should not take care of managing a subset or all those components.
    76  - `<Infra>Cluster`
    77    - When we say `<Infra>Cluster` we refer to any provider that provides Kubernetes Cluster Infrastructure for a specific Cloud provider. Concrete example for Microsoft Azure is the `AzureCluster` and the `AzureManagedCluster`, for AWS the `AWSCluster` and the `AWSManagedCluster`, for Google Cloud the `GCPCluster` and the `GCPManagedCluster`).
    78  - e.g.
    79    - This just means "For example:"!
    80  
    81  ## Summary
    82  
    83  This proposal aims to address the lesson learned by running Managed Kubernetes solution on top of Cluster API, and make this use case simpler and more straight forward both for Cluster API users and for the maintainers of the Cluster API providers.
    84  
    85  More specifically we would like to introduce first class support for two scenarios:
    86  
    87  - Permit omitting the `<Infra>Cluster` entirely, thus making it simpler to use with Cluster API all the Managed Kubernetes implementations which do not require any additional Kubernetes Cluster Infrastructure (network settings, security groups, etc) on top of what is provided out of the box by the managed Kubernetes primitive offered by a Cloud provider.
    88  - Allow the `ControlPlane Provider` component to take ownership of the responsibility of creating the control plane endpoint, thus making it simpler to use with Cluster API all the Managed Kubernetes implementations which are taking care out of the box of this piece of Cluster Infrastructure.
    89  
    90  The above capabilities can be used alone or in combination depending on the requirements of a specific Managed Kubernetes or on the specific architecture/set of Cloud components being implemented.
    91  
    92  ## Motivation
    93  
    94  The implementation of Managed Kubernetes scenarios by Cluster API providers occurred after the architectural design of Cluster API, and thus that design process did not consider these Managed Kubernetes scenarios as a user story. In practice, Cluster API's specification has allowed Managed Kubernetes solutions to emerge that aid running fleets of clusters at scale, with CAPA's `AWSManagedCluster` and `AzureManagedCluster` being notable examples. However, because these Managed Kubernetes solutions arrived after the Cluster API contract was defined, providers have not settled on a consistent rendering of how a "Service-Managed Kubernetes" specification fits into a "Cluster API-Managed Kubernetes" surface area.
    95  
    96  One particular part of the existing Cluster API surface area that is inconsistent with most Managed Kubernetes user experiences is the accounting of the [Kubernetes API server](https://kubernetes.io/docs/concepts/overview/components/#kube-apiserver). In the canonical "self-managed" user story that Cluster API addresses, it is the provider implementation of Cluster API (e.g., CAPA) that is responsible for scaffolding the necessary _Kubernetes Cluster Infrastructure_ that is required in order to create the Kubernetes API server (e.g., a Load Balancer and a public IP address). This provider responsibility is declared in the `<Infra>Cluster` resource, and carried out via its controllers; and then finally this reconciliation is synchronized with the parent `Cluster` Cluster API resource.
    97  
    98  Because there exist Managed Kubernetes scenarios that handle a subset or all _Kubernetes Cluster Infrastructure_ responsibilities themselves, Cluster API's requirement of a `<Infra>Cluster` resource leads to undesirable implementation decisions, because in these scenarios there is no actual work for a Cluster API provider to do to scaffold _Kubernetes Cluster Infrastructure_.
    99  
   100  Finally, for Managed Kubernetes scenarios that _do_ include additional, user-exposed infra (e.g., GKE and EKS as of this writing), we want to make it easier to account for the representation of the Managed Kubernetes API server endpoint, which is not always best owned by a `<Infra>Cluster` resource.
   101  
   102  ### Goals
   103  
   104  - Build upon [the existing Cluster API Managed Kubernetes proposal](https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20220725-managed-kubernetes.md). Any net new recommendations and/or proposals will be a continuation of the existing proposal, and consistent with its original conclusions.
   105  - Identify and document API changes and controllers changes required to omit the `<Infra>Cluster` entirely, where this is applicable.
   106  - Identify and document API changes and controllers changes required to allow the `ControlPlane Provider` component to take ownership of the responsibility of creating the control plane endpoint.
   107  - Ensure any changes to the current behavioral contract are backwards-compatible.
   108  
   109  ### Non-Goals
   110  
   111  - Introduce new "Managed Kubernetes" data types in Cluster API.
   112  - Invalidate [the existing Cluster API Managed Kubernetes proposal and concluding recommendations](https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20220725-managed-kubernetes.md).
   113  
   114  ### Future Work
   115  
   116  - Detailed documentation that references the flavors of Managed Kubernetes scenarios and how they can be implemented in Cluster API, with provider examples.
   117  
   118  ## Proposal
   119  
   120  ### User Stories
   121  
   122  #### Story 1
   123  
   124  As a cluster operator, I want to use Cluster API to provision and manage the lifecycle of a control plane that utilizes my service provider's managed Kubernetes control plane (i.e. EKS, AKS, GKE), so that I don’t have to worry about the management/provisioning of control plane nodes, and so I can take advantage of any value add services offered by my cloud provider.
   125  
   126  #### Story 2
   127  
   128  As a cluster operator, I want to be able to provision both "unmanaged" and "managed" Kubernetes clusters from the same management cluster, so that I can support different requirements and use cases as needed whilst using a single operating model.
   129  
   130  #### Story 3
   131  
   132  As a Cluster API provider implementor, I want to be able to return the control plane endpoint created by the `ControlPlane Provider`, so that it fits naturally with how most of the native Managed Kubernetes implementations works.
   133  
   134  #### Story 4
   135  
   136  As a Cluster API provider developer, I want guidance on how to incorporate a managed Kubernetes service into my provider, so that its usage is compatible with Cluster API architecture/features and its usage is consistant with other providers.
   137  
   138  #### Story 5
   139  
   140  As a Cluster API provider developer, I want to enable the ClusterClass feature for a Managed Kubernetes service, so that users can take advantage of an improved UX with ClusterClass-based clusters.
   141  
   142  #### Story 6
   143  
   144  As a cluster operator, I want to use Cluster API to provision and manage the lifecycle of worker nodes that utilizes my cloud providers' managed instances (if they support them), so that I don't have to worry about the management of these instances.
   145  
   146  #### Story 7
   147  
   148  As a service provider I want to be able to offer Managed Kubernetes clusters by using CAPI referencing my own managed control plane implementation that satisfies Cluster API contracts.
   149  
   150  ### Design
   151  
   152  Below we are documenting API changes and controllers changes required to omit the `<Infra>Cluster` entirely and to allow the `ControlPlane Provider` component  to take ownership of the responsibility of creating the control plane endpoint.
   153  
   154  #### Core Cluster API changes
   155  
   156  This proposal does not introduce any breaking changes for the existing "core" API. More specifically:
   157  
   158  The existing Cluster API types are already able to omit the `<Infra>Cluster`:
   159  
   160  - The `infrastructureRef` field on the Cluster object is already a pointer and thus it could be set to nil, and in fact we are already creating Clusters without `infrastructureRef` when we use a cluster class).
   161  - The `infrastructure.Ref` field on the ClusterClass objects already a pointer and thus it could be set to nil, but in this case it is required to change the validation webhook to allow the user to not specify it; on top of that, when validating inline patches, we should reject patches targeting the infrastructure template objects if not specified.
   162  
   163  In order to allow the `ControlPlane Provider` component to take ownership of the responsibility of creating the control plane endpoint we are going to introduce a new `ClusterEndpoint` CRD, below some example:
   164  
   165  ```yaml
   166  apiVersion: cluster.x-k8s.io/v1beta1
   167  kind: ClusterEndpoint
   168  metadata:
   169     labels:
   170        cluster.x-k8s.io/cluster-name: my-cluster
   171  spec:
   172    cluster: my-cluster
   173    host: "my-cluster-1234567890.region.elb.amazonaws.com"
   174    port: 1234
   175    type: ExternalControlPlaneEndpoint
   176  ```
   177  
   178  ```yaml
   179  apiVersion: cluster.x-k8s.io/v1beta1
   180  kind: ClusterEndpoint
   181  metadata:
   182     labels:
   183        cluster.x-k8s.io/cluster-name: my-cluster-2
   184  spec:
   185    cluster: my-cluster-2
   186    host: "10.40.85.102"
   187    port: 1234
   188    type: ExternalControlPlaneEndpoint
   189  ```
   190  
   191  This is how the type specification would look:
   192  
   193  ```go
   194  // ClusterEndpointType describes the type of cluster endpoint.
   195  type ClusterEndpointType string
   196  
   197  // ClusterEndpoint represents a reachable Kubernetes API endpoint serving a particular cluster function.
   198  type ClusterEndpoint struct {
   199    metav1.TypeMeta   `json:",inline"`
   200  	metav1.ObjectMeta `json:"metadata,omitempty"`
   201  
   202    Spec ClusterEndpointSpec   `json:"spec,omitempty"`
   203  }
   204  
   205  // ClusterEndpointSpec defines the desired state of the Cluster endpoint.
   206  type ClusterEndpointSpec struct {
   207  	// The Host is the DNS record or the IP address that the endpoint is reachable on.
   208  	Host string `json:"host"`
   209  
   210  	// The port on which the endpoint is serving.
   211  	Port int32 `json:"port"`
   212  
   213    // Cluster is a reference to the cluster name that this endpoint is reachable on.
   214    Cluster string `json:"cluster"`
   215  
   216    // Type describes the function that this cluster endpoint serves.
   217    // +kubebuilder:validation:Enum=apiserver
   218    Type ClusterEndpointType `json:"type"`
   219  }
   220  ```
   221  
   222  The `<Infra>Cluster` object which is currently using the `spec.controlPlaneEndpoint` for the same scope will continue to work because "core" Cluster API controllers will continue to recognize when this field is set and take care of generating the `ClusterEndpoint` automatically; however this mechanism should be considered as a temporary machinery to migrate to the new CRD, and it will be removed in future versions of Cluster API. In addition, once the legacy behavior is removed, we will deprecate and eventually remove the `spec.controlPlaneEndpoint` field from the `Cluster` CustomResourceDefinition, and recommend that providers do the same for their `<Infra>Cluster` CustomResourceDefinitions as well.
   223  
   224  Future Notes:
   225  
   226  - A future `type` field can be introduced to enable CAPI to extend the usage of this CRD to address https://github.com/kubernetes-sigs/cluster-api/issues/5295 in a future iteration
   227  - The current implementation originates from the `Cluster.spec.ControlPlaneEndpoint` field, which defines the info we need for this proposal; but in future iterations we might consider to support more addressed or more ports for each ClusterEndpoint, similarly what is implemented in the core v1 Endpoint type.
   228  
   229  #### Infra Providers API changes
   230  
   231  This proposal does not introduce any breaking changes for the provider's API.
   232  
   233  However, Infra providers will be made aware that `spec.controlPlaneEndpoint` will be scheduled for deprecation in `<Infra>Cluster` resources in a future CAPI API version, with corresponding warning messages in controller logs. We will recommend that they remove it in a future API version of their provider.
   234  
   235  #### Core Cluster API Controllers changes
   236  
   237  - All the controllers working with ClusterClass objects must take into account that the `infrastructure.Ref` field could be omitted; most notably:
   238    - The ClusterClass controller must ignore nil `infrastructure.Ref` fields while adding owner references to all the objects referenced by a ClusterClass.
   239    - The Topology controller must skip the generation of the `<Infra>Cluster` objects when the `infrastructure.Ref` field in a ClusterClass is empty.
   240  
   241  - All the controllers working with Cluster objects must take into account that the `infrastructureRef` field could be omitted; most notably:
   242    - The Cluster controller must use skip reconciling this external reference when the `infrastructureRef` is missing; also, the `status.InfrastructureReady` field must be automatically set to true in this case.
   243  
   244  - A controller (details TBD) will reconcile the new `ClusterEndpoint` CR. Please note that:
   245    - The value from the `ClusterEndpoint` CRD must surface on the `spec.ControlPlaneEndpoint` field on the `Cluster` object.
   246    - If both are present, the value from the `ClusterEndpoint` CRD must take precedence on the value from `<Infra>Cluster` objects still using the `spec.controlPlaneEndpoint`.
   247  
   248  - The Cluster controller must implement the temporary machinery to migrate to the new CRD existing Clusters and to deal with `<Infra>Cluster` objects still using the `spec.controlPlaneEndpoint` field as a way to communicate the ClusterAddress to "core" Cluster API controllers:
   249    - If there is the `spec.ControlPlaneEndpoint` on the `Cluster` object but not a corresponding `ClusterEndpoint` CR, the CR must be created.
   250  
   251  #### Provider controller changes
   252  
   253  - All the `<Infra>Cluster` controllers who are responsible for creating a control plane endpoint
   254    - As soon as the `spec.controlPlaneEndpoint` field in the `<Infra>Cluster` object will removed, the `<Infra>Cluster` controller must instead create a `ClusterEndpoint` CR to communicate the control plane endpoint to the Cluster API core controllers
   255      - NOTE: technically it is possible to start creating the `ClusterEndpoint` CR *before* the removal of the `spec.controlPlaneEndpoint` field, because the new CR will take precedence on the value read from the field, but this is up to the infra provider maintainers.
   256    - The `ClusterEndpoint` CR must have an owner reference to the `<Infra>Cluster` object from which it is originated.
   257  
   258  - All the `ControlPlane Provider` controllers who are responsible for creating a control plane endpoint
   259    - Must no longer wait for the `spec.ControlPlaneEndpoint` field on the `Cluster` object to be set before starting to provision the control plane.
   260    - As soon as the Managed Kubernetes Service-provided control plane endpoint is available, the controller must create a `ClusterEndpoint` CR to communicate this to the control plane endpoint to the Cluster API core controllers
   261    - The `ClusterEndpoint` CR must have an owner reference to the `ControlPlane` object from which is originated.
   262  
   263  ### Guidelines for infra providers implementation
   264  
   265  Let's consider following scenarios for an hypothetical `cluster-api-provider-foo` infra provider:
   266  
   267  _Scenario 1._
   268  
   269  If the `Foo` cloud provider has a `FKS` managed Kubernetes offering that is taking care of _the entire Kubernetes Cluster infrastructure_, the maintainers of the `cluster-api-provider-foo` provider:
   270  - Must not implement a `FKSCluster` CRD and the corresponding `FKSClusterTemplate` CRD (nor the related controllers)
   271  - Must implement a `FKRControlControlplane provider`, a `FKRControlControlplane` CRD, the corresponding `FKRControlControlplane` and related controllers
   272  - The `FKRControlControlplane` controller:
   273    - Must not wait for `spec.ControlPlaneEndpoint` field on the `Cluster` object to be set before starting to provision the `FKS` managed Kubernetes instance.
   274    - As soon as the control plane endpoint is available, Must create a `ClusterEndpoint` CR to communicate the control plane endpoint to the Cluster API core controllers; the `ClusterEndpoint` CR must have an owner reference to the `FKRControlControlplane` object from which is originated.
   275    - Must set the `status.Ready` field on the `FKRControlControlplane` object when the provisioning is complete
   276  
   277  _Scenario 2._
   278  
   279  If the `Foo` cloud provider has a `FKS` managed Kubernetes offering that is taking care of _only of a subset of the Kubernetes Cluster infrastructure_, or it is required to provision some additional pieces of infrastructure on top of what provisioned out of the box, e.g. a SSH bastion host, the maintainers of the `cluster-api-provider-foo` provider:
   280  - Must implement a `FKSCluster` CRD and the corresponding `FKSClusterTemplate` CRD and the related controllers
   281    - The `FKSCluster` controller
   282      - Must create only the additional piece of the _Kubernetes Cluster infrastructure_ not provisioned by the `FKS` managed Kubernetes instance (in this example a SSH bastion host)
   283      - Must not create a `ClusterEndpoint` CR (nor set the `spec.controlPlaneEndpoint` field in the `FKSCluster` object), because provisioning the control plane endpoint is not responsibility of this controller.
   284      - Must set the `status.Ready` field on the `FKSCluster` object when the provisioning is complete
   285  - Must implement a `FKRControlControlplane provider`, a `FKRControlControlplane` CRD, the corresponding `FKRControlControlplane` and related controllers
   286    - The `FKRControlControlplane` controller:
   287      - Must wait for `status.InfrastructureReady` field on the `Cluster` object to be set to true before starting to provision the control plane.
   288      - Must not wait for `spec.ControlPlaneEndpoint` field on the `Cluster` object to be set before starting to provision the control plane.
   289      - As soon as the control plane endpoint is available, Must create a `ClusterEndpoint` CR to communicate the control plane endpoint to the Cluster API core controllers; the `ClusterEndpoint` CR must have an owner reference to the `FKRControlControlplane` object from which is originated.
   290      - Must set the `status.Ready` field on the `FKRControlControlplane` object when the provisioning is complete
   291  
   292  _Scenario 3._
   293  
   294  If the `Foo` cloud provider has a `FKS` managed Kubernetes offering that is not taking care of the control plane endpoint e.g. because it requires an existing `FooElasticIP`, a `FooElacticLoadBalancer` to be provisioned before creating the `FKS` managed Kubernetes cluster, the maintainers of the `cluster-api-provider-foo` provider:
   295  - Must implement a `FKSCluster` CRD and the corresponding `FKSClusterTemplate` CRD and the related controllers; those controllers must create a `ClusterEndpoint` CR as soon as the control plane endpoint is available
   296    - The `FKSCluster` controller
   297      - Must create only the additional piece of the _Kubernetes Cluster infrastructure_ not provisioned by the `FKS` managed Kubernetes instance (in this example `FooElasticIP`, a `FooElacticLoadBalancer`)
   298      - As soon as the control plane endpoint is available, Must create a `ClusterEndpoint` CR; the `ClusterEndpoint` CR must have an owner reference to the `FKSCluster` object from which is originated.
   299      - Must set the `status.Ready` field on the `FKSCluster` object when the provisioning is complete
   300  - Must implement a `FKRControlControlplane provider`, a `FKRControlControlplane` CRD, the corresponding `FKRControlControlplane` and related controllers
   301    - The `FKRControlControlplane` controller:
   302      - Must wait for `status.InfrastructureReady` field on the `Cluster` object to be set to true before starting to provision the `FKS` managed Kubernetes instance.
   303      - Must wait for `spec.ControlPlaneEndpoint` field on the `Cluster` object to be set before starting to provision the `FKS` managed Kubernetes instance.
   304      - Must set the `status.Ready` field on the `FKRControlControlplane` object when the provisioning is complete
   305  
   306  Please note that this scenario is equivalent to what is implemented for a non managed Kubernetes `FooCluster`, backed by Cluster API managed `FooMachines`, with the only difference that in this case it possible to rely on `KCP` as `ControlControlplane provider`, and thus point 2 of the above list do not apply.
   307  
   308  ## Implementation History
   309  
   310  - [x] 01/11/2023: Compile a Google Doc to organize thoughts prior to CAEP [link here](https://docs.google.com/document/d/1rqzZfsO6k_RmOHUxx47cALSr_6SeTG89e9C44-oHHdQ/)
   311  
   312  [managedKubernetesRecommendation]: https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20220725-managed-kubernetes.md#option-3-two-kinds-with-a-managed-control-plane-and-managed-infra-cluster-with-better-separation-of-responsibilities