mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-27 16:17:34 +00:00
* Feat: poll multi-cluster metrics and export to prometheus Signed-off-by: zhukunshuai <jookunshuai@gmail.com> * pass context to polling loop Signed-off-by: zhukunshuai <jookunshuai@gmail.com> * move metrics definition to montitor/metrics/multicluster.go Signed-off-by: zhukunshuai <jookunshuai@gmail.com> * remove pod usage metric and make reviewable Signed-off-by: zhukunshuai <jookunshuai@gmail.com> * revert the change of GetClusterMetricsFromMetricsAPI Signed-off-by: zhukunshuai <jookunshuai@gmail.com> * revert the change of GetClusterMetricsFromMetricsAPI Signed-off-by: zhukunshuai <jookunshuai@gmail.com> * Separate the polling logic into a function Signed-off-by: zhukunshuai <jookunshuai@gmail.com> * add start menber function Signed-off-by: zhukunshuai <jookunshuai@gmail.com> * make refreshPeriod a menber var Signed-off-by: zhukunshuai <jookunshuai@gmail.com> * fix typo Signed-off-by: zhukunshuai <jookunshuai@gmail.com>
125 lines
4.3 KiB
Go
125 lines
4.3 KiB
Go
/*
|
|
Copyright 2022 The KubeVela Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package multicluster
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/oam-dev/kubevela/pkg/monitor/metrics"
|
|
|
|
"k8s.io/klog/v2"
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
)
|
|
|
|
// metricsMap records the metrics of clusters
|
|
var metricsMap map[string]*ClusterMetrics
|
|
|
|
// ClusterMetricsMgr manage metrics of clusters
|
|
type ClusterMetricsMgr struct {
|
|
kubeClient client.Client
|
|
refreshPeriod time.Duration
|
|
}
|
|
|
|
// ClusterMetricsHelper is the interface that provides operations for cluster metrics
|
|
type ClusterMetricsHelper interface {
|
|
Refresh() error
|
|
}
|
|
|
|
// NewClusterMetricsMgr will create a cluster metrics manager
|
|
func NewClusterMetricsMgr(ctx context.Context, kubeClient client.Client, refreshPeriod time.Duration) (*ClusterMetricsMgr, error) {
|
|
mgr := &ClusterMetricsMgr{
|
|
kubeClient: kubeClient,
|
|
refreshPeriod: refreshPeriod,
|
|
}
|
|
go mgr.Start(ctx)
|
|
return mgr, nil
|
|
}
|
|
|
|
// Refresh will re-collect cluster metrics and refresh cache
|
|
func (cmm *ClusterMetricsMgr) Refresh() ([]VirtualCluster, error) {
|
|
clusters, _ := ListVirtualClusters(context.Background(), cmm.kubeClient)
|
|
m := make(map[string]*ClusterMetrics)
|
|
|
|
// retrieves metrics by cluster-gateway
|
|
for _, cluster := range clusters {
|
|
isConnected := true
|
|
clusterInfo, err := GetClusterInfo(context.Background(), cmm.kubeClient, cluster.Name)
|
|
if err != nil {
|
|
klog.Warningf("failed to get cluster info of cluster-(%s)", cluster.Name)
|
|
isConnected = false
|
|
}
|
|
clusterUsageMetrics, err := GetClusterMetricsFromMetricsAPI(context.Background(), cmm.kubeClient, cluster.Name)
|
|
if err != nil {
|
|
klog.Warningf("failed to request metrics api of cluster-(%s)", cluster.Name)
|
|
}
|
|
cm := &ClusterMetrics{
|
|
IsConnected: isConnected,
|
|
ClusterInfo: clusterInfo,
|
|
ClusterUsageMetrics: clusterUsageMetrics,
|
|
}
|
|
m[cluster.Name] = cm
|
|
cluster.Metrics = cm
|
|
}
|
|
metricsMap = m
|
|
return clusters, nil
|
|
}
|
|
|
|
// Start will start polling cluster api to collect metrics
|
|
func (cmm *ClusterMetricsMgr) Start(ctx context.Context) {
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
klog.Warning("Stop cluster metrics polling loop.")
|
|
return
|
|
default:
|
|
clusters, _ := cmm.Refresh()
|
|
for _, cluster := range clusters {
|
|
exportMetrics(cluster.Metrics, cluster.Name)
|
|
}
|
|
time.Sleep(cmm.refreshPeriod)
|
|
}
|
|
}
|
|
}
|
|
|
|
// exportMetrics will report ClusterMetrics with a clusterName label
|
|
func exportMetrics(m *ClusterMetrics, clusterName string) {
|
|
if m == nil {
|
|
return
|
|
}
|
|
metrics.ClusterIsConnectedGauge.WithLabelValues(clusterName).Set(func() float64 {
|
|
if m.IsConnected {
|
|
return 1
|
|
}
|
|
return 0
|
|
}())
|
|
if m.ClusterInfo != nil {
|
|
metrics.ClusterWorkerNumberGauge.WithLabelValues(clusterName).Set(float64(m.ClusterInfo.WorkerNumber))
|
|
metrics.ClusterMasterNumberGauge.WithLabelValues(clusterName).Set(float64(m.ClusterInfo.MasterNumber))
|
|
metrics.ClusterMemoryCapacityGauge.WithLabelValues(clusterName).Set(m.ClusterInfo.MemoryCapacity.AsApproximateFloat64())
|
|
metrics.ClusterCPUCapacityGauge.WithLabelValues(clusterName).Set(float64(m.ClusterInfo.CPUCapacity.MilliValue()))
|
|
metrics.ClusterPodCapacityGauge.WithLabelValues(clusterName).Set(m.ClusterInfo.PodCapacity.AsApproximateFloat64())
|
|
metrics.ClusterMemoryAllocatableGauge.WithLabelValues(clusterName).Set(m.ClusterInfo.MemoryAllocatable.AsApproximateFloat64())
|
|
metrics.ClusterCPUAllocatableGauge.WithLabelValues(clusterName).Set(float64(m.ClusterInfo.CPUAllocatable.MilliValue()))
|
|
metrics.ClusterPodAllocatableGauge.WithLabelValues(clusterName).Set(m.ClusterInfo.PodAllocatable.AsApproximateFloat64())
|
|
}
|
|
if m.ClusterUsageMetrics != nil {
|
|
metrics.ClusterMemoryUsageGauge.WithLabelValues(clusterName).Set(m.ClusterUsageMetrics.MemoryUsage.AsApproximateFloat64())
|
|
metrics.ClusterCPUUsageGauge.WithLabelValues(clusterName).Set(float64(m.ClusterUsageMetrics.CPUUsage.MilliValue()))
|
|
}
|
|
}
|