Skip to content

Commit 7f4d55f

Browse files
feat(metrics): provide metrics for tenant quotas
Signed-off-by: Lukas Boettcher <1340215+lukasboettcher@users.noreply.github.com>
1 parent 0571e41 commit 7f4d55f

File tree

4 files changed

+115
-0
lines changed

4 files changed

+115
-0
lines changed

controllers/tenant/cleanup.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright 2020-2023 Project Capsule Authors.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package tenant
5+
6+
import (
7+
"context"
8+
9+
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
10+
11+
capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2"
12+
"github.com/projectcapsule/capsule/pkg/metrics"
13+
)
14+
15+
func (r *Manager) handleMetricsCleanup(ctx context.Context, tenant *capsulev1beta2.Tenant) (err error) {
16+
metricsFinalizer := "capsule.clastix.io/metrics-cleanup"
17+
18+
// examine DeletionTimestamp to determine if object is under deletion
19+
if tenant.ObjectMeta.DeletionTimestamp.IsZero() { //nolint:nestif
20+
// The object is not being deleted, so if it does not have our finalizer,
21+
// then lets add the finalizer and update the object. This is equivalent
22+
// to registering our finalizer.
23+
if !controllerutil.ContainsFinalizer(tenant, metricsFinalizer) {
24+
controllerutil.AddFinalizer(tenant, metricsFinalizer)
25+
26+
if err := r.Update(ctx, tenant); err != nil {
27+
return err
28+
}
29+
}
30+
} else {
31+
// The object is being deleted
32+
if controllerutil.ContainsFinalizer(tenant, metricsFinalizer) {
33+
// our finalizer is present, so handle the removal of the metrics
34+
r.Log.Info("Removing ResourceQuota metrics because Tenant " + tenant.Name + " is being deleted")
35+
36+
// remove all metrics of the deleted tenant
37+
metrics.TenantResourceUsage.DeletePartialMatch(map[string]string{"tenant": tenant.Name})
38+
metrics.TenantResourceLimit.DeletePartialMatch(map[string]string{"tenant": tenant.Name})
39+
40+
// remove our finalizer from the list and update it.
41+
controllerutil.RemoveFinalizer(tenant, metricsFinalizer)
42+
43+
if err := r.Update(ctx, tenant); err != nil {
44+
return err
45+
}
46+
}
47+
}
48+
49+
return nil
50+
}

controllers/tenant/manager.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,15 @@ func (r Manager) Reconcile(ctx context.Context, request ctrl.Request) (result ct
133133
return
134134
}
135135

136+
// Handle cleanup of metrics if the tenant was deleted
137+
r.Log.Info("Setting up metrics cleanup")
138+
139+
if err = r.handleMetricsCleanup(ctx, instance); err != nil {
140+
r.Log.Error(err, "Cannot setup metrics cleanup")
141+
142+
return
143+
}
144+
136145
r.Log.Info("Tenant reconciling completed")
137146

138147
return ctrl.Result{}, err

controllers/tenant/resourcequotas.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323

2424
capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2"
2525
"github.com/projectcapsule/capsule/pkg/api"
26+
"github.com/projectcapsule/capsule/pkg/metrics"
2627
"github.com/projectcapsule/capsule/pkg/utils"
2728
)
2829

@@ -51,6 +52,18 @@ func (r *Manager) syncResourceQuotas(ctx context.Context, tenant *capsulev1beta2
5152
if typeLabel, err = utils.GetTypeLabel(&corev1.ResourceQuota{}); err != nil {
5253
return err
5354
}
55+
56+
// Remove prior metrics, to avoid cleaning up for metrics of deleted ResourceQuotas
57+
metrics.TenantResourceUsage.DeletePartialMatch(map[string]string{"tenant": tenant.Name})
58+
metrics.TenantResourceLimit.DeletePartialMatch(map[string]string{"tenant": tenant.Name})
59+
60+
// Expose the namespace quota and usage as metrics for the tenant
61+
metrics.TenantResourceUsage.WithLabelValues(tenant.Name, "namespaces", "").Set(float64(tenant.Status.Size))
62+
63+
if tenant.Spec.NamespaceOptions != nil && tenant.Spec.NamespaceOptions.Quota != nil {
64+
metrics.TenantResourceLimit.WithLabelValues(tenant.Name, "namespaces", "").Set(float64(*tenant.Spec.NamespaceOptions.Quota))
65+
}
66+
5467
//nolint:nestif
5568
if tenant.Spec.ResourceQuota.Scope == api.ResourceQuotaScopeTenant {
5669
group := new(errgroup.Group)
@@ -102,6 +115,19 @@ func (r *Manager) syncResourceQuotas(ctx context.Context, tenant *capsulev1beta2
102115

103116
r.Log.Info("Computed " + name.String() + " quota for the whole Tenant is " + quantity.String())
104117

118+
// Expose usage and limit metrics for the resource (name) of the ResourceQuota (index)
119+
metrics.TenantResourceUsage.WithLabelValues(
120+
tenant.Name,
121+
name.String(),
122+
strconv.Itoa(index),
123+
).Set(float64(quantity.MilliValue()) / 1000)
124+
125+
metrics.TenantResourceLimit.WithLabelValues(
126+
tenant.Name,
127+
name.String(),
128+
strconv.Itoa(index),
129+
).Set(float64(hardQuota.MilliValue()) / 1000)
130+
105131
switch quantity.Cmp(resourceQuota.Hard[name]) {
106132
case 0:
107133
// The Tenant is matching exactly the Quota:

pkg/metrics/metrics.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2020-2023 Project Capsule Authors.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package metrics
5+
6+
import (
7+
"github.com/prometheus/client_golang/prometheus"
8+
"sigs.k8s.io/controller-runtime/pkg/metrics"
9+
)
10+
11+
var (
12+
metricsPrefix = "capsule_"
13+
14+
TenantResourceUsage = prometheus.NewGaugeVec(prometheus.GaugeOpts{
15+
Name: metricsPrefix + "tenant_resource_usage",
16+
Help: "Current resource usage for a given resource in a tenant",
17+
}, []string{"tenant", "resource", "resourcequotaindex"})
18+
19+
TenantResourceLimit = prometheus.NewGaugeVec(prometheus.GaugeOpts{
20+
Name: metricsPrefix + "tenant_resource_limit",
21+
Help: "Current resource limit for a given resource in a tenant",
22+
}, []string{"tenant", "resource", "resourcequotaindex"})
23+
)
24+
25+
func init() {
26+
metrics.Registry.MustRegister(
27+
TenantResourceUsage,
28+
TenantResourceLimit,
29+
)
30+
}

0 commit comments

Comments
 (0)