@@ -18,17 +18,22 @@ import (
1818 "k8s.io/apimachinery/pkg/runtime/serializer"
1919 utilruntime "k8s.io/apimachinery/pkg/util/runtime"
2020 clientgoscheme "k8s.io/client-go/kubernetes/scheme"
21+ "k8s.io/client-go/rest"
22+ "k8s.io/client-go/tools/clientcmd"
2123 ctrl "sigs.k8s.io/controller-runtime"
2224 "sigs.k8s.io/controller-runtime/pkg/client"
2325 "sigs.k8s.io/controller-runtime/pkg/cluster"
2426 "sigs.k8s.io/controller-runtime/pkg/healthz"
2527 "sigs.k8s.io/controller-runtime/pkg/log/zap"
2628 "sigs.k8s.io/controller-runtime/pkg/manager"
29+ metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
2730 "sigs.k8s.io/controller-runtime/pkg/webhook"
2831 mcmanager "sigs.k8s.io/multicluster-runtime/pkg/manager"
2932 "sigs.k8s.io/multicluster-runtime/pkg/multicluster"
3033 mcsingle "sigs.k8s.io/multicluster-runtime/providers/single"
3134
35+ karmadaclusterv1alpha1 "github.com/karmada-io/api/cluster/v1alpha1"
36+ karmadapolicyv1alpha1 "github.com/karmada-io/api/policy/v1alpha1"
3237 computev1alpha "go.datum.net/compute/api/v1alpha"
3338 "go.datum.net/compute/internal/config"
3439 "go.datum.net/compute/internal/controller"
5156 gitCommit = "unknown"
5257 gitTreeState = "unknown"
5358 buildDate = "unknown"
59+
60+ // downstreamRestConfig holds the REST config for the downstream control plane.
61+ // It is populated from --downstream-kubeconfig when set, and is nil when the
62+ // flag is omitted (e.g. in non-federation deployments).
63+ downstreamRestConfig * rest.Config
5464)
5565
5666func init () {
@@ -61,6 +71,8 @@ func init() {
6171 utilruntime .Must (computev1alpha .AddToScheme (scheme ))
6272 utilruntime .Must (networkingv1alpha .AddToScheme (scheme ))
6373 utilruntime .Must (quotav1alpha1 .AddToScheme (scheme ))
74+ utilruntime .Must (karmadapolicyv1alpha1 .Install (scheme ))
75+ utilruntime .Must (karmadaclusterv1alpha1 .Install (scheme ))
6476
6577 // +kubebuilder:scaffold:scheme
6678}
@@ -71,12 +83,27 @@ func main() {
7183 var leaderElectionNamespace string
7284 var probeAddr string
7385 var serverConfigFile string
86+ var downstreamKubeconfig string
87+ var downstreamContext string
88+ var enableManagementControllers bool
89+ var enableCellControllers bool
7490
7591 flag .StringVar (& probeAddr , "health-probe-bind-address" , ":8081" , "The address the probe endpoint binds to." )
7692 flag .BoolVar (& enableLeaderElection , "leader-elect" , false ,
7793 "Enable leader election for controller manager. " +
7894 "Enabling this will ensure there is only one active controller manager." )
7995 flag .StringVar (& leaderElectionNamespace , "leader-elect-namespace" , "" , "The namespace to use for leader election." )
96+ flag .StringVar (& downstreamKubeconfig , "downstream-kubeconfig" , "" ,
97+ "Path to the kubeconfig file for the downstream control plane. " +
98+ "When omitted, downstream federation features are disabled." )
99+ flag .StringVar (& downstreamContext , "downstream-context" , "" ,
100+ "Context to use from the downstream kubeconfig. When omitted, the current context is used." )
101+ flag .BoolVar (& enableManagementControllers , "enable-management-controllers" , true ,
102+ "Enable management-plane controllers (WorkloadDeploymentFederator, InstanceProjector). " +
103+ "Disable when running a cell-only operator instance." )
104+ flag .BoolVar (& enableCellControllers , "enable-cell-controllers" , true ,
105+ "Enable cell controllers (WorkloadDeploymentReconciler, InstanceReconciler). " +
106+ "Disable when running a management-only operator instance." )
80107
81108 opts := zap.Options {
82109 Development : true ,
@@ -89,6 +116,23 @@ func main() {
89116
90117 ctrl .SetLogger (zap .New (zap .UseFlagOptions (& opts )))
91118
119+ // Load the downstream REST config when --downstream-kubeconfig is provided.
120+ // When the flag is omitted, downstreamRestConfig remains nil and federation
121+ // features will be skipped at controller setup time.
122+ if downstreamKubeconfig != "" {
123+ loader := clientcmd .NewNonInteractiveDeferredLoadingClientConfig (
124+ & clientcmd.ClientConfigLoadingRules {ExplicitPath : downstreamKubeconfig },
125+ & clientcmd.ConfigOverrides {CurrentContext : downstreamContext },
126+ )
127+ var err error
128+ downstreamRestConfig , err = loader .ClientConfig ()
129+ if err != nil {
130+ setupLog .Error (err , "unable to load downstream kubeconfig" , "path" , downstreamKubeconfig )
131+ os .Exit (1 )
132+ }
133+ setupLog .Info ("downstream kubeconfig loaded" , "path" , downstreamKubeconfig )
134+ }
135+
92136 setupLog .Info ("starting compute" ,
93137 "version" , version ,
94138 "gitCommit" , gitCommit ,
@@ -180,17 +224,63 @@ func main() {
180224 setupLog .Error (err , "unable to create controller" , "controller" , "Workload" )
181225 os .Exit (1 )
182226 }
183- if err = (& controller.WorkloadDeploymentReconciler {}).SetupWithManager (mgr ); err != nil {
184- setupLog .Error (err , "unable to create controller" , "controller" , "WorkloadDeployment" )
185- os .Exit (1 )
227+
228+ // Build a single downstream client shared across all controllers that need
229+ // to read or write to the downstream control plane. Nil when federation is disabled.
230+ var downstreamClient client.Client
231+ if downstreamRestConfig != nil {
232+ downstreamClient , err = client .New (downstreamRestConfig , client.Options {Scheme : scheme })
233+ if err != nil {
234+ setupLog .Error (err , "unable to create downstream client" )
235+ os .Exit (1 )
236+ }
186237 }
187- if err = (& controller.WorkloadDeploymentScheduler {}).SetupWithManager (mgr ); err != nil {
188- setupLog .Error (err , "unable to create controller" , "controller" , "WorkloadDeploymentScheduler" )
189- os .Exit (1 )
238+
239+ if enableCellControllers {
240+ if err = (& controller.WorkloadDeploymentReconciler {}).SetupWithManager (mgr ); err != nil {
241+ setupLog .Error (err , "unable to create controller" , "controller" , "WorkloadDeployment" )
242+ os .Exit (1 )
243+ }
190244 }
191- if err = (& controller.InstanceReconciler {}).SetupWithManager (mgr , deploymentCluster ); err != nil {
192- setupLog .Error (err , "unable to create controller" , "controller" , "Instance" )
193- os .Exit (1 )
245+
246+ if enableCellControllers {
247+ instanceReconciler := & controller.InstanceReconciler {DownstreamClient : downstreamClient }
248+ if err = instanceReconciler .SetupWithManager (mgr , deploymentCluster ); err != nil {
249+ setupLog .Error (err , "unable to create controller" , "controller" , "Instance" )
250+ os .Exit (1 )
251+ }
252+ }
253+
254+ // WorkloadDeploymentFederator and InstanceProjector are management-plane
255+ // controllers that run on the control-plane cluster. They require a downstream
256+ // control plane to be configured (--downstream-kubeconfig provided).
257+ if enableManagementControllers && downstreamRestConfig != nil {
258+ federator := & controller.WorkloadDeploymentFederator {DownstreamClient : downstreamClient }
259+ if err = federator .SetupWithManager (mgr ); err != nil {
260+ setupLog .Error (err , "unable to create controller" , "controller" , "WorkloadDeploymentFederator" )
261+ os .Exit (1 )
262+ }
263+
264+ // InstanceProjector: runs in the Control Plane Cell, watches Instances
265+ // written back to the downstream control plane by POP-cell operators, and
266+ // projects them into the corresponding project namespaces via the
267+ // multicluster manager.
268+ downstreamMgr , err := manager .New (downstreamRestConfig , manager.Options {
269+ Scheme : scheme ,
270+ Metrics : metricsserver.Options {BindAddress : "0" },
271+ })
272+ if err != nil {
273+ setupLog .Error (err , "unable to create downstream manager for InstanceProjector" )
274+ os .Exit (1 )
275+ }
276+ if err = (& controller.InstanceProjector {
277+ DownstreamClient : downstreamClient ,
278+ MCManager : mgr ,
279+ }).SetupWithManager (downstreamMgr ); err != nil {
280+ setupLog .Error (err , "unable to create controller" , "controller" , "InstanceProjector" )
281+ os .Exit (1 )
282+ }
283+ runnables = append (runnables , downstreamMgr )
194284 }
195285
196286 if serverConfig .WebhookServer != nil {
@@ -284,6 +374,7 @@ func initializeClusterDiscovery(
284374 }
285375
286376 discoveryManager , err := manager .New (discoveryRestConfig , manager.Options {
377+ Metrics : metricsserver.Options {BindAddress : "0" },
287378 Client : client.Options {
288379 Cache : & client.CacheOptions {
289380 Unstructured : true ,
0 commit comments