To build controllers that interact with multiple Kubernetes clusters, use the cluster.Cluster interface to manage cluster-specific dependencies (like Client, Cache, and Scheme) separately from the main manager.Manager. The manager.Manager now embeds the Cluster interface, allowing you to add additional clusters to a single manager.
Key steps for multi-cluster setup:
- Create a primary manager for the main cluster.
- Create additional
cluster.Cluster instances for secondary clusters. - Add the secondary clusters to the manager using
mgr.Add(clusterInstance). - Use the specific cluster's methods (e.g.,
cluster.GetClient()) within your reconciler to perform actions on that specific cluster.
// Example: Reconciler using two different clusters
type secretMirrorReconciler struct {
referenceClusterClient, mirrorClusterClient client.Client
}
func NewSecretMirrorReconciler(mgr manager.Manager, mirrorCluster cluster.Cluster) error {
return ctrl.NewControllerManagedBy(mgr).
// Watch Secrets in the reference cluster (the one the manager is tied to)
For(&corev1.Secret{}).
// Watch Secrets in the mirror cluster using its specific cache
Watches(
source.NewKindWithCache(&corev1.Secret{}, mirrorCluster.GetCache()),
&handler.EnqueueRequestForObject{},
).
Complete(&secretMirrorReconciler{
referenceClusterClient: mgr.GetClient(),
mirrorClusterClient: mirrorCluster.GetClient(),
})
}
func main() {
// 1. Setup primary manager
mgr, err := manager.New(cfg1, manager.Options{})
// 2. Setup secondary cluster
mirrorCluster, err := cluster.New(cfg2)
// 3. Add secondary cluster to manager
if err := mgr.Add(mirrorCluster); err != nil {
panic(err)
}
// 4. Initialize reconciler with both clients
if err := NewSecretMirrorReconciler(mgr, mirrorCluster); err != nil {
panic(err)
}
// 5. Start everything
if err := mgr.Start(signals.SetupSignalHandler()); err != nil {
panic(err)
}
}