Skip to content

Commit a461bb5

Browse files
committed
Update with feedback
Signed-off-by: Marvin Beckers <[email protected]>
1 parent 120cef5 commit a461bb5

File tree

1 file changed

+31
-26
lines changed

1 file changed

+31
-26
lines changed

designs/multi-cluster.md

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Author: @sttts @embik
44

55
Initial implementation: @vincepri
66

7-
Last Updated on: 12/04/2024
7+
Last Updated on: 2025-01-06
88

99
## Table of Contents
1010

@@ -38,7 +38,7 @@ objects. This proposal is about adding native support for multi-cluster use-case
3838
to controller-runtime.
3939

4040
With this change, it will be possible to implement pluggable cluster providers
41-
that automatically start and stop watches (and thus, cluster-aware reconcilers) when
41+
that automatically start and stop sources (and thus, cluster-aware reconcilers) when
4242
the cluster provider adds ("engages") or removes ("disengages") a cluster.
4343

4444
## Motivation
@@ -56,24 +56,28 @@ This change is important because:
5656

5757
### Goals
5858

59-
- Provide an interface for plugging in a "cluster provider", which provides a dynamic set of clusters that should be reconciled by registered controllers.
60-
- Provide a way to natively write controllers that
61-
1. (UNIFORM MULTI-CLUSTER CONTROLLER) operate on multiple clusters in a uniform way,
59+
- Allow 3rd-parties to implement an (optional) multi-cluster provider Go interface that controller-runtime will use (if configured on the manager) to dynamically attach and detach registered controllers to clusters that come and go.
60+
- With that, provide a way to natively write controllers for these patterns:
61+
1. use the cluster provider Go interface that can be implemented by 3rd parties outside of controller-runtime to adapt an existing multi-cluster-compatible code-base to a concrete environment.
62+
2. (UNIFORM MULTI-CLUSTER CONTROLLERS) operate on multiple clusters in a uniform way,
6263
i.e. reconciling the same resources on multiple clusters, **optionally**
6364
- sourcing information from one central hub cluster
6465
- sourcing information cross-cluster.
6566

66-
Example: distributed `ReplicaSet` controller, reconciling `ReplicaSets` on multiple clusters.
67-
2. (AGGREGATING MULTI-CLUSTER CONTROLLER) operate on one central hub cluster aggregating information from multiple clusters.
67+
Example: distributed `ReplicaSet` controller, reconciling `ReplicaSets` on multiple clusters.
68+
3. (AGGREGATING MULTI-CLUSTER CONTROLLERS) operate on one central hub cluster aggregating information from multiple clusters.
6869

6970
Example: distributed `Deployment` controller, aggregating `ReplicaSets` across multiple clusters back into a central `Deployment` object.
70-
- Allow clusters to dynamically join and leave the set of clusters a controller operates on.
71-
- Allow logical clusters where a set of clusters is actually backed by one physical informer store.
72-
- Allow 3rd-parties to plug in their multi-cluster adapter (in source code) into
73-
an existing multi-cluster-compatible code-base.
71+
72+
#### Low-Level Requirements
73+
74+
- Allow event sources to be cross-cluster such that:
75+
1. Multi-cluster events can trigger reconciliation in the one central hub cluster.
76+
2. Central hub cluster events can trigger reconciliation on multiple clusters.
77+
- Allow reconcilers to look up objects through (informer) indexes from specific other clusters.
7478
- Minimize the amount of changes to make a controller-runtime controller
7579
multi-cluster-compatible, in a way that 3rd-party projects have no reason to
76-
object these kind of changes.
80+
object to these kind of changes.
7781

7882
Here we call a controller to be multi-cluster-compatible if the reconcilers get
7983
reconcile requests in cluster `X` and do all reconciliation in cluster `X`. This
@@ -231,9 +235,16 @@ if err != nil {
231235
client := cl.GetClient()
232236
```
233237

234-
Due to the BYO `request` type, controllers need to be built like this:
238+
Due to the BYO `request` type, controllers using the `For` builder function need to be built/changed like this:
235239

236240
```golang
241+
// previous
242+
builder.TypedControllerManagedBy[reconcile.Request](mgr).
243+
Named("single-cluster-controller").
244+
For(&corev1.Pod{}).
245+
Complete(reconciler)
246+
247+
// new
237248
builder.TypedControllerManagedBy[ClusterRequest](mgr).
238249
Named("multi-cluster-controller").
239250
Watches(&corev1.Pod{}, &ClusterRequestEventHandler{}).
@@ -243,7 +254,7 @@ builder.TypedControllerManagedBy[ClusterRequest](mgr).
243254
With `ClusterRequest` and `ClusterRequestEventHandler` being BYO types. `reconciler`
244255
can be e.g. of type `reconcile.TypedFunc[ClusterRequest]`.
245256

246-
`ClusterRequest` will likely often look like this:
257+
`ClusterRequest` will likely often look like this (but since it is a BYO type, it could store other information as well):
247258

248259
```golang
249260
type ClusterRequest struct {
@@ -252,18 +263,12 @@ type ClusterRequest struct {
252263
}
253264
```
254265

255-
Controllers that use `For` or `Owns` cannot be converted to multi-cluster controllers
256-
without changing to `Watches` as the BYO `request` type cannot be used with them:
257-
258-
```golang
259-
// pkg/builder/controller.go
260-
if reflect.TypeFor[request]() != reflect.TypeOf(reconcile.Request{}) {
261-
return fmt.Errorf("For() can only be used with reconcile.Request, got %T", *new(request))
262-
}
263-
```
266+
Controllers that use `Owns` cannot be converted to multi-cluster controllers
267+
without a BYO type re-implementation of `handler.EnqueueRequestForOwner` matching
268+
the BYO type, which is considered out of scope for now.
264269

265-
With the described changes (use `GetCluster(ctx, clusterName)` and making `reconciler`
266-
a `TypedFunc[ClusterRequest`) an existing controller will automatically act as
270+
With the described changes (use `GetCluster(ctx, clusterName)`, making `reconciler`
271+
a `TypedFunc[ClusterRequest]` and migrating to `Watches`) an existing controller will automatically act as
267272
*uniform multi-cluster controller*. It will reconcile resources from cluster `X`
268273
in cluster `X`.
269274

@@ -273,7 +278,7 @@ the controller.
273278

274279
Controllers that should be triggered by events on the hub cluster can continue
275280
to use `For` and `Owns` and explicitly pass the intention to engage only with the
276-
"default" cluster:
281+
"default" cluster (this is only necessary if a cluster provider is plugged in):
277282

278283
```golang
279284
builder.NewControllerManagedBy(mgr).

0 commit comments

Comments
 (0)