Skip to content

Commit 5c3d5bb

Browse files
vinceprisbueringer
andauthored
[release-1.7] 🌱 Allow control plane provider to set endpoint (#10800)
* Allow control plane provider to set endpoint Signed-off-by: Vince Prignano <[email protected]> * Update cluster_controller_phases_test.go Co-authored-by: Stefan Büringer <[email protected]> --------- Signed-off-by: Vince Prignano <[email protected]> Co-authored-by: Stefan Büringer <[email protected]>
1 parent e7e568c commit 5c3d5bb

File tree

5 files changed

+318
-7
lines changed

5 files changed

+318
-7
lines changed

docs/book/src/developer/architecture/controllers/cluster.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ provisions EC2 instances that will become a Kubernetes cluster through some boot
2222

2323
The cluster controller will set an OwnerReference on the infrastructureCluster. This controller should normally take no action during reconciliation until it sees the OwnerReference.
2424

25-
An infrastructureCluster controller is expected to eventually have its `spec.controlPlaneEndpoint` set by the user/controller.
25+
An infrastructureCluster controller is expected to either supply a controlPlaneEndpoint (via its own `spec.controlPlaneEndpoint` field),
26+
or rely on `spec.controlPlaneEndpoint` in its parent [Cluster](./cluster.md) object.
27+
28+
If an endpoint is not provided, the implementer should exit reconciliation until it sees `cluster.spec.controlPlaneEndpoint` populated.
2629

2730
The Cluster controller bubbles up `spec.controlPlaneEndpoint` and `status.ready` into `status.infrastructureReady` from the infrastructureCluster.
2831

@@ -50,6 +53,9 @@ is a map, defined as `map[string]FailureDomainSpec`. A unique key must be used f
5053
- `controlPlane` (bool): indicates if failure domain is appropriate for running control plane instances.
5154
- `attributes` (`map[string]string`): arbitrary attributes for users to apply to a failure domain.
5255

56+
Note: once any of `failureReason` or `failureMessage` surface on the cluster who is referencing the infrastructureCluster object,
57+
they cannot be restored anymore (it is considered a terminal error; the only way to recover is to delete and recreate the cluster).
58+
5359
Example:
5460
```yaml
5561
kind: MyProviderCluster

docs/book/src/developer/architecture/controllers/control-plane.md

+35-4
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,14 @@ Kubernetes control plane consisting of the following services:
4141

4242
The Cluster controller will set an OwnerReference on the Control Plane. The Control Plane controller should normally take no action during reconciliation until it sees the ownerReference.
4343

44-
A Control Plane controller implementation should exit reconciliation until it sees `cluster.spec.controlPlaneEndpoint` populated.
44+
A Control Plane controller implementation must either supply a controlPlaneEndpoint (via its own `spec.controlPlaneEndpoint` field),
45+
or rely on `spec.controlPlaneEndpoint` in its parent [Cluster](./cluster.md) object.
4546

46-
The Cluster controller bubbles up `status.ready` into `status.controlPlaneReady` and `status.initialized` into a `controlPlaneInitialized` condition from the Control Plane CR.
47+
If an endpoint is not provided, the implementer should exit reconciliation until it sees `cluster.spec.controlPlaneEndpoint` populated.
48+
49+
A Control Plane controller can optionally provide a `controlPlaneEndpoint`
4750

48-
The `ImplementationControlPlane` *must* rely on the existence of
49-
`status.controlplaneEndpoint` in its parent [Cluster](./cluster.md) object.
51+
The Cluster controller bubbles up `status.ready` into `status.controlPlaneReady` and `status.initialized` into a `controlPlaneInitialized` condition from the Control Plane CR.
5052

5153
### CRD contracts
5254

@@ -110,6 +112,35 @@ documentation][scale].
110112
deletion. A duration of 0 will retry deletion indefinitely. It defaults to 10 seconds on the
111113
Machine.
112114

115+
#### Optional `spec` fields for implementations providing endpoints
116+
117+
The `ImplementationControlPlane` object may provide a `spec.controlPlaneEndpoint` field to inform the Cluster
118+
controller where the endpoint is located.
119+
120+
Implementers might opt to choose the `APIEndpoint` struct exposed by Cluster API types, or the following:
121+
122+
<table>
123+
<tr>
124+
<th> Field </th>
125+
<th> Type </th>
126+
<th> Description </th>
127+
</tr>
128+
<tr>
129+
<td><code>host</code></td>
130+
<td>String</td>
131+
<td>
132+
The hostname on which the API server is serving.
133+
</td>
134+
</tr>
135+
<tr>
136+
<td><code>port</code></td>
137+
<td>Integer</td>
138+
<td>
139+
The port on which the API server is serving.
140+
</td>
141+
</tr>
142+
</table>
143+
113144
#### Required `status` fields
114145

115146
The `ImplementationControlPlane` object **must** have a `status` object.

docs/proposals/20230407-flexible-managed-k8s-endpoints.md

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ More specifically we would like to introduce first class support for two scenari
7676

7777
- 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.
7878
- 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.
79+
- Note: In May 2024 [this pull request](https://github.com/kubernetes-sigs/cluster-api/pull/10667) added the ability for the control plane provider to provide the endpoint the same way the infrastructure cluster would.
7980

8081
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.
8182

internal/controllers/cluster/cluster_controller_phases.go

+16-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ func (r *Reconciler) reconcileInfrastructure(ctx context.Context, cluster *clust
199199

200200
// Get and parse Spec.ControlPlaneEndpoint field from the infrastructure provider.
201201
if !cluster.Spec.ControlPlaneEndpoint.IsValid() {
202-
if err := util.UnstructuredUnmarshalField(infraConfig, &cluster.Spec.ControlPlaneEndpoint, "spec", "controlPlaneEndpoint"); err != nil {
202+
if err := util.UnstructuredUnmarshalField(infraConfig, &cluster.Spec.ControlPlaneEndpoint, "spec", "controlPlaneEndpoint"); err != nil && err != util.ErrUnstructuredFieldNotFound {
203203
return ctrl.Result{}, errors.Wrapf(err, "failed to retrieve Spec.ControlPlaneEndpoint from infrastructure provider for Cluster %q in namespace %q",
204204
cluster.Name, cluster.Namespace)
205205
}
@@ -218,6 +218,8 @@ func (r *Reconciler) reconcileInfrastructure(ctx context.Context, cluster *clust
218218

219219
// reconcileControlPlane reconciles the Spec.ControlPlaneRef object on a Cluster.
220220
func (r *Reconciler) reconcileControlPlane(ctx context.Context, cluster *clusterv1.Cluster) (ctrl.Result, error) {
221+
log := ctrl.LoggerFrom(ctx)
222+
221223
if cluster.Spec.ControlPlaneRef == nil {
222224
return ctrl.Result{}, nil
223225
}
@@ -274,6 +276,19 @@ func (r *Reconciler) reconcileControlPlane(ctx context.Context, cluster *cluster
274276
}
275277
}
276278

279+
if !ready {
280+
log.V(3).Info("Control Plane provider is not ready yet")
281+
return ctrl.Result{}, nil
282+
}
283+
284+
// Get and parse Spec.ControlPlaneEndpoint field from the control plane provider.
285+
if !cluster.Spec.ControlPlaneEndpoint.IsValid() {
286+
if err := util.UnstructuredUnmarshalField(controlPlaneConfig, &cluster.Spec.ControlPlaneEndpoint, "spec", "controlPlaneEndpoint"); err != nil && err != util.ErrUnstructuredFieldNotFound {
287+
return ctrl.Result{}, errors.Wrapf(err, "failed to retrieve Spec.ControlPlaneEndpoint from control plane provider for Cluster %q in namespace %q",
288+
cluster.Name, cluster.Namespace)
289+
}
290+
}
291+
277292
return ctrl.Result{}, nil
278293
}
279294

0 commit comments

Comments
 (0)