@@ -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,26 @@ 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. When omitted, downstream federation features are disabled." )
98+ flag .StringVar (& downstreamContext , "downstream-context" , "" ,
99+ "Context to use from the downstream kubeconfig. When omitted, the current context is used." )
100+ flag .BoolVar (& enableManagementControllers , "enable-management-controllers" , true ,
101+ "Enable management-plane controllers (WorkloadDeploymentFederator, InstanceProjector). " +
102+ "Disable when running a cell-only operator instance." )
103+ flag .BoolVar (& enableCellControllers , "enable-cell-controllers" , true ,
104+ "Enable cell controllers (WorkloadDeploymentReconciler, InstanceReconciler). " +
105+ "Disable when running a management-only operator instance." )
80106
81107 opts := zap.Options {
82108 Development : true ,
@@ -89,6 +115,23 @@ func main() {
89115
90116 ctrl .SetLogger (zap .New (zap .UseFlagOptions (& opts )))
91117
118+ // Load the downstream REST config when --downstream-kubeconfig is provided.
119+ // When the flag is omitted, downstreamRestConfig remains nil and federation
120+ // features will be skipped at controller setup time.
121+ if downstreamKubeconfig != "" {
122+ loader := clientcmd .NewNonInteractiveDeferredLoadingClientConfig (
123+ & clientcmd.ClientConfigLoadingRules {ExplicitPath : downstreamKubeconfig },
124+ & clientcmd.ConfigOverrides {CurrentContext : downstreamContext },
125+ )
126+ var err error
127+ downstreamRestConfig , err = loader .ClientConfig ()
128+ if err != nil {
129+ setupLog .Error (err , "unable to load downstream kubeconfig" , "path" , downstreamKubeconfig )
130+ os .Exit (1 )
131+ }
132+ setupLog .Info ("downstream kubeconfig loaded" , "path" , downstreamKubeconfig )
133+ }
134+
92135 setupLog .Info ("starting compute" ,
93136 "version" , version ,
94137 "gitCommit" , gitCommit ,
@@ -180,17 +223,62 @@ func main() {
180223 setupLog .Error (err , "unable to create controller" , "controller" , "Workload" )
181224 os .Exit (1 )
182225 }
183- if err = (& controller.WorkloadDeploymentReconciler {}).SetupWithManager (mgr ); err != nil {
184- setupLog .Error (err , "unable to create controller" , "controller" , "WorkloadDeployment" )
185- os .Exit (1 )
226+
227+ // Build a single downstream client shared across all controllers that need
228+ // to read or write to the downstream control plane. Nil when federation is disabled.
229+ var downstreamClient client.Client
230+ if downstreamRestConfig != nil {
231+ downstreamClient , err = client .New (downstreamRestConfig , client.Options {Scheme : scheme })
232+ if err != nil {
233+ setupLog .Error (err , "unable to create downstream client" )
234+ os .Exit (1 )
235+ }
186236 }
187- if err = (& controller.WorkloadDeploymentScheduler {}).SetupWithManager (mgr ); err != nil {
188- setupLog .Error (err , "unable to create controller" , "controller" , "WorkloadDeploymentScheduler" )
189- os .Exit (1 )
237+
238+ if enableCellControllers {
239+ if err = (& controller.WorkloadDeploymentReconciler {}).SetupWithManager (mgr ); err != nil {
240+ setupLog .Error (err , "unable to create controller" , "controller" , "WorkloadDeployment" )
241+ os .Exit (1 )
242+ }
190243 }
191- if err = (& controller.InstanceReconciler {}).SetupWithManager (mgr , deploymentCluster ); err != nil {
192- setupLog .Error (err , "unable to create controller" , "controller" , "Instance" )
193- os .Exit (1 )
244+
245+ if enableCellControllers {
246+ instanceReconciler := & controller.InstanceReconciler {DownstreamClient : downstreamClient }
247+ if err = instanceReconciler .SetupWithManager (mgr , deploymentCluster ); err != nil {
248+ setupLog .Error (err , "unable to create controller" , "controller" , "Instance" )
249+ os .Exit (1 )
250+ }
251+ }
252+
253+ // WorkloadDeploymentFederator and InstanceProjector are management-plane
254+ // controllers that run on the control-plane cluster. They require a downstream
255+ // control plane to be configured (--downstream-kubeconfig provided).
256+ if enableManagementControllers && downstreamRestConfig != nil {
257+ if err = (& controller.WorkloadDeploymentFederator {DownstreamClient : downstreamClient }).SetupWithManager (mgr ); err != nil {
258+ setupLog .Error (err , "unable to create controller" , "controller" , "WorkloadDeploymentFederator" )
259+ os .Exit (1 )
260+ }
261+
262+ // InstanceProjector: runs in the Control Plane Cell, watches Instances
263+ // written back to the downstream control plane by POP-cell operators, and
264+ // projects them into the corresponding project namespaces via the
265+ // multicluster manager.
266+ downstreamMgr , err := manager .New (downstreamRestConfig , manager.Options {
267+ Scheme : scheme ,
268+ Metrics : metricsserver.Options {BindAddress : "0" },
269+ })
270+ if err != nil {
271+ setupLog .Error (err , "unable to create downstream manager for InstanceProjector" )
272+ os .Exit (1 )
273+ }
274+ if err = (& controller.InstanceProjector {
275+ DownstreamClient : downstreamClient ,
276+ MCManager : mgr ,
277+ }).SetupWithManager (downstreamMgr ); err != nil {
278+ setupLog .Error (err , "unable to create controller" , "controller" , "InstanceProjector" )
279+ os .Exit (1 )
280+ }
281+ runnables = append (runnables , downstreamMgr )
194282 }
195283
196284 if serverConfig .WebhookServer != nil {
@@ -284,6 +372,7 @@ func initializeClusterDiscovery(
284372 }
285373
286374 discoveryManager , err := manager .New (discoveryRestConfig , manager.Options {
375+ Metrics : metricsserver.Options {BindAddress : "0" },
287376 Client : client.Options {
288377 Cache : & client.CacheOptions {
289378 Unstructured : true ,
0 commit comments