mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-28 22:17:14 +00:00
kubelet/metrics: add cri_metrics
that pulls metrics from the CRI Signed-off-by: Peter Hunt <pehunt@redhat.com>
This commit is contained in:
parent
6298ce68e2
commit
1a7388c2ef
129
pkg/kubelet/metrics/collectors/cri_metrics.go
Normal file
129
pkg/kubelet/metrics/collectors/cri_metrics.go
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2022 The Kubernetes 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 collectors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"k8s.io/component-base/metrics"
|
||||||
|
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type criMetricsCollector struct {
|
||||||
|
metrics.BaseStableCollector
|
||||||
|
// The descriptors structure will be populated by one call to ListMetricDescriptors from the runtime.
|
||||||
|
// They will be saved in this map, where the key is the Name and the value is the Desc.
|
||||||
|
descriptors map[string]*metrics.Desc
|
||||||
|
listPodSandboxMetricsFn func(context.Context) ([]*runtimeapi.PodSandboxMetrics, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if criMetricsCollector implements necessary interface
|
||||||
|
var _ metrics.StableCollector = &criMetricsCollector{}
|
||||||
|
|
||||||
|
// NewCRIMetricsCollector implements the metrics.Collector interface
|
||||||
|
func NewCRIMetricsCollector(ctx context.Context, listPodSandboxMetricsFn func(context.Context) ([]*runtimeapi.PodSandboxMetrics, error), listMetricDescriptorsFn func(context.Context) ([]*runtimeapi.MetricDescriptor, error)) metrics.StableCollector {
|
||||||
|
descs, err := listMetricDescriptorsFn(ctx)
|
||||||
|
if err != nil {
|
||||||
|
klog.ErrorS(err, "Error reading MetricDescriptors")
|
||||||
|
return &criMetricsCollector{
|
||||||
|
listPodSandboxMetricsFn: listPodSandboxMetricsFn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c := &criMetricsCollector{
|
||||||
|
listPodSandboxMetricsFn: listPodSandboxMetricsFn,
|
||||||
|
descriptors: make(map[string]*metrics.Desc, len(descs)),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, desc := range descs {
|
||||||
|
c.descriptors[desc.Name] = criDescToProm(desc)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describe implements the metrics.DescribeWithStability interface.
|
||||||
|
func (c *criMetricsCollector) DescribeWithStability(ch chan<- *metrics.Desc) {
|
||||||
|
for _, desc := range c.descriptors {
|
||||||
|
ch <- desc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect implements the metrics.CollectWithStability interface.
|
||||||
|
// TODO(haircommander): would it be better if these were processed async?
|
||||||
|
func (c *criMetricsCollector) CollectWithStability(ch chan<- metrics.Metric) {
|
||||||
|
podMetrics, err := c.listPodSandboxMetricsFn(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
klog.ErrorS(err, "Failed to get pod metrics")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, podMetric := range podMetrics {
|
||||||
|
for _, metric := range podMetric.GetMetrics() {
|
||||||
|
promMetric, err := c.criMetricToProm(metric)
|
||||||
|
if err == nil {
|
||||||
|
ch <- promMetric
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, ctrMetric := range podMetric.GetContainerMetrics() {
|
||||||
|
for _, metric := range ctrMetric.GetMetrics() {
|
||||||
|
promMetric, err := c.criMetricToProm(metric)
|
||||||
|
if err == nil {
|
||||||
|
ch <- promMetric
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func criDescToProm(m *runtimeapi.MetricDescriptor) *metrics.Desc {
|
||||||
|
// Labels in the translation are variableLabels, as opposed to constant labels.
|
||||||
|
// This is because the values of the labels will be different for each container.
|
||||||
|
return metrics.NewDesc(m.Name, m.Help, m.LabelKeys, nil, metrics.INTERNAL, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criMetricsCollector) criMetricToProm(m *runtimeapi.Metric) (metrics.Metric, error) {
|
||||||
|
desc, ok := c.descriptors[m.Name]
|
||||||
|
if !ok {
|
||||||
|
err := fmt.Errorf("error converting CRI Metric to prometheus format")
|
||||||
|
klog.V(5).ErrorS(err, "Descriptor not present in pre-populated list of descriptors", "descriptor name", m.Name)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
typ := criTypeToProm[m.MetricType]
|
||||||
|
|
||||||
|
pm, err := metrics.NewConstMetric(desc, typ, float64(m.GetValue().Value), m.LabelValues...)
|
||||||
|
if err != nil {
|
||||||
|
klog.ErrorS(err, "Error getting CRI prometheus metric", "descriptor", desc.String())
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// If Timestamp is 0, then the runtime did not cache the result.
|
||||||
|
// In this case, a cached result is a metric that was collected ahead of time,
|
||||||
|
// as opposed to on-demand.
|
||||||
|
// If the metric was requested as needed, then Timestamp==0.
|
||||||
|
if m.Timestamp == 0 {
|
||||||
|
return pm, nil
|
||||||
|
}
|
||||||
|
return metrics.NewLazyMetricWithTimestamp(time.Unix(0, m.Timestamp), pm), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var criTypeToProm = map[runtimeapi.MetricType]metrics.ValueType{
|
||||||
|
runtimeapi.MetricType_COUNTER: metrics.CounterValue,
|
||||||
|
runtimeapi.MetricType_GAUGE: metrics.GaugeValue,
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user