Skip to content

Commit 4448ff5

Browse files
authored
Merge pull request #420 from mars1024/subnet-metrics
add subnet metrics and unregister metrics during deletion
2 parents b847fd2 + 7343222 commit 4448ff5

File tree

4 files changed

+172
-7
lines changed

4 files changed

+172
-7
lines changed

pkg/constants/finalizers.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,10 @@
1616

1717
package constants
1818

19-
const FinalizerIPAllocated = "networking.alibaba.com/ip-allocated"
20-
const FinalizerManagerRuntimeRegistered = "multicluster.alibaba.com/manager-runtime-registered"
19+
const (
20+
FinalizerIPAllocated = "networking.alibaba.com/ip-allocated"
21+
22+
FinalizerManagerRuntimeRegistered = "multicluster.alibaba.com/manager-runtime-registered"
23+
24+
FinalizerMetricsRegistered = "networking.alibaba.com/metrics-registered"
25+
)

pkg/controllers/networking/networkstatus_controller.go

+53-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"sigs.k8s.io/controller-runtime/pkg/builder"
3131
"sigs.k8s.io/controller-runtime/pkg/client"
3232
"sigs.k8s.io/controller-runtime/pkg/controller"
33+
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
3334
"sigs.k8s.io/controller-runtime/pkg/event"
3435
"sigs.k8s.io/controller-runtime/pkg/handler"
3536
ctrllog "sigs.k8s.io/controller-runtime/pkg/log"
@@ -85,6 +86,17 @@ func (r *NetworkStatusReconciler) Reconcile(ctx context.Context, req ctrl.Reques
8586
return ctrl.Result{}, wrapError("unable to fetch Network", client.IgnoreNotFound(err))
8687
}
8788

89+
if network.DeletionTimestamp != nil {
90+
cleanMetrics(network.Name)
91+
return ctrl.Result{}, wrapError("unable to remove finalizer", r.removeFinalizer(ctx, network))
92+
93+
}
94+
95+
// make sure metrics will be un-registered before deletion
96+
if err = r.addFinalizer(ctx, network); err != nil {
97+
return ctrl.Result{}, wrapError("unable to add finalizer to network", err)
98+
}
99+
88100
nodeSelector := network.Spec.NodeSelector
89101
switch networkingv1.GetNetworkType(network) {
90102
case networkingv1.NetworkTypeGlobalBGP:
@@ -187,15 +199,54 @@ func updateUsageMetrics(networkName string, networkStatus *networkingv1.NetworkS
187199
}
188200
}
189201

202+
func cleanMetrics(networkName string) {
203+
_ = metrics.IPUsageGauge.DeleteLabelValues(networkName, metrics.IPv4, metrics.IPTotalUsageType)
204+
_ = metrics.IPUsageGauge.DeleteLabelValues(networkName, metrics.IPv4, metrics.IPUsedUsageType)
205+
_ = metrics.IPUsageGauge.DeleteLabelValues(networkName, metrics.IPv4, metrics.IPAvailableUsageType)
206+
207+
_ = metrics.IPUsageGauge.DeleteLabelValues(networkName, metrics.IPv6, metrics.IPTotalUsageType)
208+
_ = metrics.IPUsageGauge.DeleteLabelValues(networkName, metrics.IPv6, metrics.IPUsedUsageType)
209+
_ = metrics.IPUsageGauge.DeleteLabelValues(networkName, metrics.IPv6, metrics.IPAvailableUsageType)
210+
211+
_ = metrics.IPUsageGauge.DeleteLabelValues(networkName, metrics.DualStack, metrics.IPAvailableUsageType)
212+
}
213+
214+
func (r *NetworkStatusReconciler) addFinalizer(ctx context.Context, network *networkingv1.Network) error {
215+
if controllerutil.ContainsFinalizer(network, constants.FinalizerMetricsRegistered) {
216+
return nil
217+
}
218+
219+
patch := client.MergeFrom(network.DeepCopy())
220+
controllerutil.AddFinalizer(network, constants.FinalizerMetricsRegistered)
221+
return retry.RetryOnConflict(retry.DefaultRetry, func() error {
222+
return r.Patch(ctx, network, patch)
223+
})
224+
}
225+
226+
func (r *NetworkStatusReconciler) removeFinalizer(ctx context.Context, network *networkingv1.Network) error {
227+
if !controllerutil.ContainsFinalizer(network, constants.FinalizerMetricsRegistered) {
228+
return nil
229+
}
230+
231+
patch := client.MergeFrom(network.DeepCopy())
232+
controllerutil.RemoveFinalizer(network, constants.FinalizerMetricsRegistered)
233+
return retry.RetryOnConflict(retry.DefaultRetry, func() error {
234+
return r.Patch(ctx, network, patch)
235+
})
236+
}
237+
190238
// SetupWithManager sets up the controller with the Manager.
191239
func (r *NetworkStatusReconciler) SetupWithManager(mgr ctrl.Manager) (err error) {
192240
return ctrl.NewControllerManagedBy(mgr).
193241
Named(ControllerNetworkStatus).
194242
For(&networkingv1.Network{},
195243
builder.WithPredicates(
196-
&predicate.GenerationChangedPredicate{},
197244
&utils.IgnoreDeletePredicate{},
198-
&utils.NetworkSpecChangePredicate{},
245+
&predicate.ResourceVersionChangedPredicate{},
246+
predicate.Or(
247+
&utils.NetworkSpecChangePredicate{},
248+
&utils.TerminatingPredicate{},
249+
),
199250
)).
200251
Watches(&source.Kind{Type: &networkingv1.Subnet{}},
201252
handler.EnqueueRequestsFromMapFunc(func(object client.Object) []reconcile.Request {

pkg/controllers/networking/subnetstatus_controller.go

+98-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"fmt"
2222
"reflect"
2323

24+
"github.com/prometheus/client_golang/prometheus"
2425
corev1 "k8s.io/api/core/v1"
2526
"k8s.io/apimachinery/pkg/types"
2627
"k8s.io/client-go/tools/record"
@@ -29,6 +30,7 @@ import (
2930
"sigs.k8s.io/controller-runtime/pkg/builder"
3031
"sigs.k8s.io/controller-runtime/pkg/client"
3132
"sigs.k8s.io/controller-runtime/pkg/controller"
33+
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
3234
"sigs.k8s.io/controller-runtime/pkg/event"
3335
"sigs.k8s.io/controller-runtime/pkg/handler"
3436
ctrllog "sigs.k8s.io/controller-runtime/pkg/log"
@@ -37,9 +39,11 @@ import (
3739
"sigs.k8s.io/controller-runtime/pkg/source"
3840

3941
networkingv1 "github.com/alibaba/hybridnet/pkg/apis/networking/v1"
42+
"github.com/alibaba/hybridnet/pkg/constants"
4043
"github.com/alibaba/hybridnet/pkg/controllers/concurrency"
4144
"github.com/alibaba/hybridnet/pkg/controllers/utils"
4245
ipamtypes "github.com/alibaba/hybridnet/pkg/ipam/types"
46+
"github.com/alibaba/hybridnet/pkg/metrics"
4347
)
4448

4549
const ControllerSubnetStatus = "SubnetStatus"
@@ -78,6 +82,17 @@ func (r *SubnetStatusReconciler) Reconcile(ctx context.Context, req ctrl.Request
7882
return ctrl.Result{}, wrapError("unable to fetch Subnet", client.IgnoreNotFound(err))
7983
}
8084

85+
if subnet.DeletionTimestamp != nil {
86+
cleanSubnetMetrics(subnet.Spec.Network, subnet.Name)
87+
return ctrl.Result{}, wrapError("unable to remove finalizer", r.removeFinalizer(ctx, subnet))
88+
89+
}
90+
91+
// make sure metrics will be un-registered before deletion
92+
if err = r.addFinalizer(ctx, subnet); err != nil {
93+
return ctrl.Result{}, wrapError("unable to add finalizer to subnet", err)
94+
}
95+
8196
// fetch subnet usage from manager
8297
var usage *ipamtypes.Usage
8398
if usage, err = r.IPAMManager.GetSubnetUsage(subnet.Spec.Network, subnet.Name); err != nil {
@@ -99,6 +114,9 @@ func (r *SubnetStatusReconciler) Reconcile(ctx context.Context, req ctrl.Request
99114
return ctrl.Result{}, nil
100115
}
101116

117+
// update metrics
118+
updateSubnetUsageMetrics(subnet.Spec.Network, subnet.Name, &subnet.Status)
119+
102120
// patch subnet status
103121
subnetPatch := client.MergeFrom(subnet.DeepCopy())
104122
subnet.Status = *subnetStatus
@@ -114,15 +132,93 @@ func (r *SubnetStatusReconciler) Reconcile(ctx context.Context, req ctrl.Request
114132
return ctrl.Result{}, nil
115133
}
116134

135+
func updateSubnetUsageMetrics(networkName, subnetName string, subnetStatus *networkingv1.SubnetStatus) {
136+
if subnetStatus.Total > 0 {
137+
metrics.SubnetIPUsageGauge.With(
138+
prometheus.Labels{
139+
"subnetName": subnetName,
140+
"networkName": networkName,
141+
"usageType": metrics.IPTotalUsageType,
142+
},
143+
).Set(float64(subnetStatus.Total))
144+
145+
metrics.SubnetIPUsageGauge.With(
146+
prometheus.Labels{
147+
"subnetName": subnetName,
148+
"networkName": networkName,
149+
"usageType": metrics.IPUsedUsageType,
150+
},
151+
).Set(float64(subnetStatus.Used))
152+
153+
metrics.SubnetIPUsageGauge.With(
154+
prometheus.Labels{
155+
"subnetName": subnetName,
156+
"networkName": networkName,
157+
"usageType": metrics.IPAvailableUsageType,
158+
},
159+
).Set(float64(subnetStatus.Available))
160+
}
161+
}
162+
163+
func cleanSubnetMetrics(networkName, subnetName string) {
164+
_ = metrics.SubnetIPUsageGauge.Delete(
165+
prometheus.Labels{
166+
"subnetName": subnetName,
167+
"networkName": networkName,
168+
"usageType": metrics.IPTotalUsageType,
169+
})
170+
171+
_ = metrics.SubnetIPUsageGauge.Delete(
172+
prometheus.Labels{
173+
"subnetName": subnetName,
174+
"networkName": networkName,
175+
"usageType": metrics.IPUsedUsageType,
176+
})
177+
178+
_ = metrics.SubnetIPUsageGauge.Delete(
179+
prometheus.Labels{
180+
"subnetName": subnetName,
181+
"networkName": networkName,
182+
"usageType": metrics.IPAvailableUsageType,
183+
})
184+
}
185+
186+
func (r *SubnetStatusReconciler) addFinalizer(ctx context.Context, subnet *networkingv1.Subnet) error {
187+
if controllerutil.ContainsFinalizer(subnet, constants.FinalizerMetricsRegistered) {
188+
return nil
189+
}
190+
191+
patch := client.MergeFrom(subnet.DeepCopy())
192+
controllerutil.AddFinalizer(subnet, constants.FinalizerMetricsRegistered)
193+
return retry.RetryOnConflict(retry.DefaultRetry, func() error {
194+
return r.Patch(ctx, subnet, patch)
195+
})
196+
}
197+
198+
func (r *SubnetStatusReconciler) removeFinalizer(ctx context.Context, subnet *networkingv1.Subnet) error {
199+
if !controllerutil.ContainsFinalizer(subnet, constants.FinalizerMetricsRegistered) {
200+
return nil
201+
}
202+
203+
patch := client.MergeFrom(subnet.DeepCopy())
204+
controllerutil.RemoveFinalizer(subnet, constants.FinalizerMetricsRegistered)
205+
return retry.RetryOnConflict(retry.DefaultRetry, func() error {
206+
return r.Patch(ctx, subnet, patch)
207+
})
208+
}
209+
117210
// SetupWithManager sets up the controller with the Manager.
118211
func (r *SubnetStatusReconciler) SetupWithManager(mgr ctrl.Manager) error {
119212
return ctrl.NewControllerManagedBy(mgr).
120213
Named(ControllerSubnetStatus).
121214
For(&networkingv1.Subnet{},
122215
builder.WithPredicates(
123-
&predicate.GenerationChangedPredicate{},
124216
&utils.IgnoreDeletePredicate{},
125-
&utils.SubnetSpecChangePredicate{},
217+
&predicate.ResourceVersionChangedPredicate{},
218+
predicate.Or(
219+
&utils.SubnetSpecChangePredicate{},
220+
&utils.TerminatingPredicate{},
221+
),
126222
)).
127223
Watches(&source.Kind{Type: &networkingv1.IPInstance{}},
128224
handler.EnqueueRequestsFromMapFunc(func(object client.Object) []reconcile.Request {

pkg/metrics/metrics.go

+14-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ import (
2222
)
2323

2424
func init() {
25-
metrics.Registry.MustRegister(IPUsageGauge,
25+
metrics.Registry.MustRegister(
26+
IPUsageGauge,
27+
SubnetIPUsageGauge,
2628
IPAllocationPeriodSummary,
2729
RemoteClusterStatusCheckDuration,
2830
)
@@ -52,6 +54,17 @@ var IPUsageGauge = prometheus.NewGaugeVec(
5254
},
5355
)
5456

57+
var SubnetIPUsageGauge = prometheus.NewGaugeVec(
58+
prometheus.GaugeOpts{
59+
Name: "subnet_ip_usage",
60+
Help: "the usage of IPs in different subnets",
61+
},
62+
[]string{
63+
"subnetName",
64+
"networkName",
65+
"usageType",
66+
})
67+
5568
const (
5669
IPStatefulAllocateType = "stateful"
5770
IPNormalAllocateType = "normal"

0 commit comments

Comments
 (0)