Skip to content

Commit 0d39bea

Browse files
author
Arvind Thirumurugan
committed
make metriccollector cluster scoped
Signed-off-by: Arvind Thirumurugan <[email protected]>
1 parent a256cc0 commit 0d39bea

File tree

4 files changed

+61
-70
lines changed

4 files changed

+61
-70
lines changed

apis/placement/v1beta1/metriccollector_types.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ import (
2424
)
2525

2626
// +genclient
27+
// +genclient:nonNamespaced
2728
// +kubebuilder:object:root=true
28-
// +kubebuilder:resource:scope="Namespaced",shortName=mc,categories={fleet,fleet-metrics}
29+
// +kubebuilder:resource:scope="Cluster",shortName=mc,categories={fleet,fleet-metrics}
2930
// +kubebuilder:subresource:status
3031
// +kubebuilder:storageversion
3132
// +kubebuilder:printcolumn:JSONPath=`.metadata.generation`,name="Gen",type=string

config/crd/bases/placement.kubernetes-fleet.io_metriccollectors.yaml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ spec:
1717
shortNames:
1818
- mc
1919
singular: metriccollector
20-
scope: Namespaced
20+
scope: Cluster
2121
versions:
2222
- additionalPrinterColumns:
2323
- jsonPath: .metadata.generation
@@ -69,8 +69,15 @@ spec:
6969
Example: http://prometheus.test-ns.svc.cluster.local:9090
7070
pattern: ^https?://.*$
7171
type: string
72+
reportNamespace:
73+
description: |-
74+
ReportNamespace is the namespace in the hub cluster where the MetricCollectorReport will be created.
75+
This should be the fleet-member-{clusterName} namespace.
76+
Example: fleet-member-cluster-1
77+
type: string
7278
required:
7379
- prometheusUrl
80+
- reportNamespace
7481
type: object
7582
status:
7683
description: The observed status of MetricCollector.

pkg/controllers/approvalrequest/controller.go

Lines changed: 39 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323
"fmt"
2424
"time"
2525

26-
corev1 "k8s.io/api/core/v1"
2726
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
2827
"k8s.io/apimachinery/pkg/api/errors"
2928
"k8s.io/apimachinery/pkg/api/meta"
@@ -199,41 +198,15 @@ func (r *Reconciler) ensureMetricCollectorResources(
199198
clusterNames []string,
200199
updateRunName, stageName string,
201200
) error {
202-
// Generate names - namespace is derived from updateRun name
203-
namespaceName := fmt.Sprintf("mc-%s", updateRunName)
204-
metricCollectorName := fmt.Sprintf("mc-%s", stageName)
201+
// Generate names
202+
metricCollectorName := fmt.Sprintf("mc-%s-%s", updateRunName, stageName)
205203
crpName := fmt.Sprintf("crp-mc-%s-%s", updateRunName, stageName)
206204
roName := fmt.Sprintf("ro-mc-%s-%s", updateRunName, stageName)
207205

208-
// Create Namespace on hub
209-
namespace := &corev1.Namespace{
210-
ObjectMeta: metav1.ObjectMeta{
211-
Name: namespaceName,
212-
Labels: map[string]string{
213-
"app": "metric-collector",
214-
"update-run": updateRunName,
215-
},
216-
},
217-
}
218-
219-
existingNS := &corev1.Namespace{}
220-
err := r.Client.Get(ctx, types.NamespacedName{Name: namespaceName}, existingNS)
221-
if err != nil {
222-
if errors.IsNotFound(err) {
223-
if err := r.Client.Create(ctx, namespace); err != nil {
224-
return fmt.Errorf("failed to create Namespace: %w", err)
225-
}
226-
klog.V(2).InfoS("Created Namespace", "namespace", namespaceName)
227-
} else {
228-
return fmt.Errorf("failed to get Namespace: %w", err)
229-
}
230-
}
231-
232-
// Create MetricCollector resource (template) in the namespace on hub
206+
// Create MetricCollector resource (cluster-scoped) on hub
233207
metricCollector := &placementv1beta1.MetricCollector{
234208
ObjectMeta: metav1.ObjectMeta{
235-
Name: metricCollectorName,
236-
Namespace: namespaceName,
209+
Name: metricCollectorName,
237210
Labels: map[string]string{
238211
"app": "metric-collector",
239212
"approval-request": approvalReq.GetName(),
@@ -250,7 +223,7 @@ func (r *Reconciler) ensureMetricCollectorResources(
250223

251224
// Create or update MetricCollector
252225
existingMC := &placementv1beta1.MetricCollector{}
253-
err = r.Client.Get(ctx, types.NamespacedName{Name: metricCollectorName, Namespace: namespaceName}, existingMC)
226+
err := r.Client.Get(ctx, types.NamespacedName{Name: metricCollectorName}, existingMC)
254227
if err != nil {
255228
if errors.IsNotFound(err) {
256229
if err := r.Client.Create(ctx, metricCollector); err != nil {
@@ -289,18 +262,18 @@ func (r *Reconciler) ensureMetricCollectorResources(
289262
})
290263
}
291264

292-
resourceOverride := &placementv1beta1.ResourceOverride{
265+
// Create ClusterResourceOverride with rules for each cluster
266+
clusterResourceOverride := &placementv1beta1.ClusterResourceOverride{
293267
ObjectMeta: metav1.ObjectMeta{
294-
Name: roName,
295-
Namespace: namespaceName,
268+
Name: roName,
296269
Labels: map[string]string{
297270
"approval-request": approvalReq.GetName(),
298271
"update-run": updateRunName,
299272
"stage": stageName,
300273
},
301274
},
302-
Spec: placementv1beta1.ResourceOverrideSpec{
303-
ResourceSelectors: []placementv1beta1.ResourceSelector{
275+
Spec: placementv1beta1.ClusterResourceOverrideSpec{
276+
ClusterResourceSelectors: []placementv1beta1.ResourceSelectorTerm{
304277
{
305278
Group: "placement.kubernetes-fleet.io",
306279
Version: "v1beta1",
@@ -314,21 +287,22 @@ func (r *Reconciler) ensureMetricCollectorResources(
314287
},
315288
}
316289

317-
existingRO := &placementv1beta1.ResourceOverride{}
318-
err = r.Client.Get(ctx, types.NamespacedName{Name: roName, Namespace: namespaceName}, existingRO)
290+
// Create or update ClusterResourceOverride
291+
existingCRO := &placementv1beta1.ClusterResourceOverride{}
292+
err = r.Client.Get(ctx, types.NamespacedName{Name: roName}, existingCRO)
319293
if err != nil {
320294
if errors.IsNotFound(err) {
321-
if err := r.Client.Create(ctx, resourceOverride); err != nil {
322-
return fmt.Errorf("failed to create ResourceOverride: %w", err)
295+
if err := r.Client.Create(ctx, clusterResourceOverride); err != nil {
296+
return fmt.Errorf("failed to create ClusterResourceOverride: %w", err)
323297
}
324-
klog.V(2).InfoS("Created ResourceOverride", "resourceOverride", roName)
298+
klog.V(2).InfoS("Created ClusterResourceOverride", "clusterResourceOverride", roName)
325299
} else {
326-
return fmt.Errorf("failed to get ResourceOverride: %w", err)
300+
return fmt.Errorf("failed to get ClusterResourceOverride: %w", err)
327301
}
328302
}
329303

330304
// Create ClusterResourcePlacement with PickFixed policy
331-
// CRP resource selector selects the namespace containing the MetricCollector
305+
// CRP resource selector selects the MetricCollector directly
332306
crp := &placementv1beta1.ClusterResourcePlacement{
333307
ObjectMeta: metav1.ObjectMeta{
334308
Name: crpName,
@@ -341,10 +315,10 @@ func (r *Reconciler) ensureMetricCollectorResources(
341315
Spec: placementv1beta1.PlacementSpec{
342316
ResourceSelectors: []placementv1beta1.ResourceSelectorTerm{
343317
{
344-
Group: "",
345-
Version: "v1",
346-
Kind: "Namespace",
347-
Name: namespaceName,
318+
Group: "placement.kubernetes-fleet.io",
319+
Version: "v1beta1",
320+
Kind: "MetricCollector",
321+
Name: metricCollectorName,
348322
},
349323
},
350324
Policy: &placementv1beta1.PlacementPolicy{
@@ -386,6 +360,8 @@ func (r *Reconciler) handleDelete(ctx context.Context, approvalReqObj placementv
386360
updateRunName := spec.TargetUpdateRun
387361
stageName := spec.TargetStage
388362
crpName := fmt.Sprintf("crp-mc-%s-%s", updateRunName, stageName)
363+
metricCollectorName := fmt.Sprintf("mc-%s-%s", updateRunName, stageName)
364+
croName := fmt.Sprintf("ro-mc-%s-%s", updateRunName, stageName)
389365

390366
crp := &placementv1beta1.ClusterResourcePlacement{}
391367
if err := r.Client.Get(ctx, types.NamespacedName{Name: crpName}, crp); err == nil {
@@ -395,14 +371,22 @@ func (r *Reconciler) handleDelete(ctx context.Context, approvalReqObj placementv
395371
klog.V(2).InfoS("Deleted ClusterResourcePlacement", "crp", crpName)
396372
}
397373

398-
// Delete the namespace (this will delete MetricCollector and ResourceOverride)
399-
namespaceName := fmt.Sprintf("mc-%s", updateRunName)
400-
namespace := &corev1.Namespace{}
401-
if err := r.Client.Get(ctx, types.NamespacedName{Name: namespaceName}, namespace); err == nil {
402-
if err := r.Client.Delete(ctx, namespace); err != nil && !errors.IsNotFound(err) {
403-
return ctrl.Result{}, fmt.Errorf("failed to delete Namespace: %w", err)
374+
// Delete ClusterResourceOverride
375+
cro := &placementv1beta1.ClusterResourceOverride{}
376+
if err := r.Client.Get(ctx, types.NamespacedName{Name: croName}, cro); err == nil {
377+
if err := r.Client.Delete(ctx, cro); err != nil && !errors.IsNotFound(err) {
378+
return ctrl.Result{}, fmt.Errorf("failed to delete ClusterResourceOverride: %w", err)
379+
}
380+
klog.V(2).InfoS("Deleted ClusterResourceOverride", "clusterResourceOverride", croName)
381+
}
382+
383+
// Delete MetricCollector
384+
metricCollector := &placementv1beta1.MetricCollector{}
385+
if err := r.Client.Get(ctx, types.NamespacedName{Name: metricCollectorName}, metricCollector); err == nil {
386+
if err := r.Client.Delete(ctx, metricCollector); err != nil && !errors.IsNotFound(err) {
387+
return ctrl.Result{}, fmt.Errorf("failed to delete MetricCollector: %w", err)
404388
}
405-
klog.V(2).InfoS("Deleted Namespace", "namespace", namespaceName)
389+
klog.V(2).InfoS("Deleted MetricCollector", "metricCollector", metricCollectorName)
406390
}
407391

408392
// Remove finalizer

pkg/controllers/metriccollector/controller.go

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -57,20 +57,20 @@ type Reconciler struct {
5757
// Reconcile reconciles a MetricCollector object
5858
func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
5959
startTime := time.Now()
60-
klog.V(2).InfoS("MetricCollector reconciliation starts", "metricCollector", req.NamespacedName)
60+
klog.V(2).InfoS("MetricCollector reconciliation starts", "metricCollector", req.Name)
6161
defer func() {
6262
latency := time.Since(startTime).Milliseconds()
63-
klog.V(2).InfoS("MetricCollector reconciliation ends", "metricCollector", req.NamespacedName, "latency", latency)
63+
klog.V(2).InfoS("MetricCollector reconciliation ends", "metricCollector", req.Name, "latency", latency)
6464
}()
6565

66-
// Fetch the MetricCollector instance
66+
// Fetch the MetricCollector instance (cluster-scoped)
6767
mc := &placementv1beta1.MetricCollector{}
68-
if err := r.MemberClient.Get(ctx, req.NamespacedName, mc); err != nil {
68+
if err := r.MemberClient.Get(ctx, client.ObjectKey{Name: req.Name}, mc); err != nil {
6969
if errors.IsNotFound(err) {
70-
klog.V(2).InfoS("MetricCollector not found, ignoring", "metricCollector", req.NamespacedName)
70+
klog.V(2).InfoS("MetricCollector not found, ignoring", "metricCollector", req.Name)
7171
return ctrl.Result{}, nil
7272
}
73-
klog.ErrorS(err, "Failed to get MetricCollector", "metricCollector", req.NamespacedName)
73+
klog.ErrorS(err, "Failed to get MetricCollector", "metricCollector", req.Name)
7474
return ctrl.Result{}, err
7575
}
7676

@@ -85,7 +85,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
8585
mc.Status.ObservedGeneration = mc.Generation
8686

8787
if collectErr != nil {
88-
klog.ErrorS(collectErr, "Failed to collect metrics", "metricCollector", req.NamespacedName)
88+
klog.ErrorS(collectErr, "Failed to collect metrics", "metricCollector", req.Name)
8989
meta.SetStatusCondition(&mc.Status.Conditions, metav1.Condition{
9090
Type: placementv1beta1.MetricCollectorConditionTypeReady,
9191
Status: metav1.ConditionTrue,
@@ -101,7 +101,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
101101
Message: fmt.Sprintf("Failed to collect metrics: %v", collectErr),
102102
})
103103
} else {
104-
klog.V(2).InfoS("Successfully collected metrics", "metricCollector", req.NamespacedName, "workloads", len(collectedMetrics))
104+
klog.V(2).InfoS("Successfully collected metrics", "metricCollector", req.Name, "workloads", len(collectedMetrics))
105105
meta.SetStatusCondition(&mc.Status.Conditions, metav1.Condition{
106106
Type: placementv1beta1.MetricCollectorConditionTypeReady,
107107
Status: metav1.ConditionTrue,
@@ -119,13 +119,13 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
119119
}
120120

121121
if err := r.MemberClient.Status().Update(ctx, mc); err != nil {
122-
klog.ErrorS(err, "Failed to update MetricCollector status", "metricCollector", req.NamespacedName)
122+
klog.ErrorS(err, "Failed to update MetricCollector status", "metricCollector", req.Name)
123123
return ctrl.Result{}, err
124124
}
125125

126126
// Sync MetricCollectorReport to hub cluster
127127
if err := r.syncReportToHub(ctx, mc); err != nil {
128-
klog.ErrorS(err, "Failed to sync MetricCollectorReport to hub", "metricCollector", req.NamespacedName)
128+
klog.ErrorS(err, "Failed to sync MetricCollectorReport to hub", "metricCollector", req.Name)
129129
meta.SetStatusCondition(&mc.Status.Conditions, metav1.Condition{
130130
Type: placementv1beta1.MetricCollectorConditionTypeReported,
131131
Status: metav1.ConditionFalse,
@@ -145,7 +145,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
145145

146146
// Update status with reporting condition
147147
if err := r.MemberClient.Status().Update(ctx, mc); err != nil {
148-
klog.ErrorS(err, "Failed to update MetricCollector status with reporting condition", "metricCollector", req.NamespacedName)
148+
klog.ErrorS(err, "Failed to update MetricCollector status with reporting condition", "metricCollector", req.Name)
149149
return ctrl.Result{}, err
150150
}
151151

@@ -167,8 +167,7 @@ func (r *Reconciler) syncReportToHub(ctx context.Context, mc *placementv1beta1.M
167167
Name: mc.Name,
168168
Namespace: reportNamespace,
169169
Labels: map[string]string{
170-
"metriccollector-name": mc.Name,
171-
"metriccollector-namespace": mc.Namespace,
170+
"metriccollector-name": mc.Name,
172171
},
173172
},
174173
}

0 commit comments

Comments
 (0)