Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrate kubelet custom metrics to stability framework part 1 #84907

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion pkg/kubelet/metrics/collectors/BUILD
Expand Up @@ -13,7 +13,7 @@ go_library(
"//pkg/kubelet/metrics:go_default_library",
"//pkg/kubelet/server/stats:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
"//staging/src/k8s.io/component-base/metrics:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
],
)
Expand Down
28 changes: 17 additions & 11 deletions pkg/kubelet/metrics/collectors/log_metrics.go
Expand Up @@ -17,14 +17,13 @@ limitations under the License.
package collectors

import (
"github.com/prometheus/client_golang/prometheus"
"k8s.io/component-base/metrics"
"k8s.io/klog"

statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
)

var (
descLogSize = prometheus.NewDesc(
descLogSize = metrics.NewDesc(
"kubelet_container_log_filesystem_used_bytes",
"Bytes used by the container's logs on the filesystem.",
[]string{
Expand All @@ -33,28 +32,35 @@ var (
"pod",
"container",
}, nil,
metrics.ALPHA,
"",
)
)

type logMetricsCollector struct {
metrics.BaseStableCollector

podStats func() ([]statsapi.PodStats, error)
}

// NewLogMetricsCollector implements the prometheus.Collector interface and
// Check if logMetricsCollector implements necessary interface
var _ metrics.StableCollector = &logMetricsCollector{}

// NewLogMetricsCollector implements the metrics.StableCollector interface and
// exposes metrics about container's log volume size.
func NewLogMetricsCollector(podStats func() ([]statsapi.PodStats, error)) prometheus.Collector {
func NewLogMetricsCollector(podStats func() ([]statsapi.PodStats, error)) metrics.StableCollector {
return &logMetricsCollector{
podStats: podStats,
}
}

// Describe implements the prometheus.Collector interface.
func (c *logMetricsCollector) Describe(ch chan<- *prometheus.Desc) {
// DescribeWithStability implements the metrics.StableCollector interface.
func (c *logMetricsCollector) DescribeWithStability(ch chan<- *metrics.Desc) {
ch <- descLogSize
}

// Collect implements the prometheus.Collector interface.
func (c *logMetricsCollector) Collect(ch chan<- prometheus.Metric) {
// CollectWithStability implements the metrics.StableCollector interface.
func (c *logMetricsCollector) CollectWithStability(ch chan<- metrics.Metric) {
podStats, err := c.podStats()
if err != nil {
klog.Errorf("failed to get pod stats: %v", err)
Expand All @@ -64,9 +70,9 @@ func (c *logMetricsCollector) Collect(ch chan<- prometheus.Metric) {
for _, ps := range podStats {
for _, c := range ps.Containers {
if c.Logs != nil && c.Logs.UsedBytes != nil {
ch <- prometheus.MustNewConstMetric(
ch <- metrics.NewLazyConstMetric(
descLogSize,
prometheus.GaugeValue,
metrics.GaugeValue,
float64(*c.Logs.UsedBytes),
ps.PodRef.UID,
ps.PodRef.Namespace,
Expand Down
12 changes: 9 additions & 3 deletions pkg/kubelet/metrics/collectors/log_metrics_test.go
Expand Up @@ -25,18 +25,24 @@ import (
)

func TestNoMetricsCollected(t *testing.T) {
// Refresh Desc to share with different registry
descLogSize = descLogSize.GetRawDesc()

collector := &logMetricsCollector{
podStats: func() ([]statsapi.PodStats, error) {
return []statsapi.PodStats{}, nil
},
}

if err := testutil.CollectAndCompare(collector, strings.NewReader(""), ""); err != nil {
if err := testutil.CustomCollectAndCompare(collector, strings.NewReader(""), ""); err != nil {
t.Fatal(err)
}
}

func TestMetricsCollected(t *testing.T) {
// Refresh Desc to share with different registry
descLogSize = descLogSize.GetRawDesc()

size := uint64(18)
collector := &logMetricsCollector{
podStats: func() ([]statsapi.PodStats, error) {
Expand All @@ -60,8 +66,8 @@ func TestMetricsCollected(t *testing.T) {
},
}

err := testutil.CollectAndCompare(collector, strings.NewReader(`
# HELP kubelet_container_log_filesystem_used_bytes Bytes used by the container's logs on the filesystem.
err := testutil.CustomCollectAndCompare(collector, strings.NewReader(`
# HELP kubelet_container_log_filesystem_used_bytes [ALPHA] Bytes used by the container's logs on the filesystem.
# TYPE kubelet_container_log_filesystem_used_bytes gauge
kubelet_container_log_filesystem_used_bytes{container="containerName1",namespace="some-namespace",pod="podName1",uid="UID_some_id"} 18
`), "kubelet_container_log_filesystem_used_bytes")
Expand Down
62 changes: 34 additions & 28 deletions pkg/kubelet/metrics/collectors/volume_stats.go
Expand Up @@ -17,58 +17,68 @@ limitations under the License.
package collectors

import (
"github.com/prometheus/client_golang/prometheus"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/klog"
"k8s.io/component-base/metrics"
stats "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
"k8s.io/kubernetes/pkg/kubelet/metrics"
kubeletmetrics "k8s.io/kubernetes/pkg/kubelet/metrics"
serverstats "k8s.io/kubernetes/pkg/kubelet/server/stats"
)

var (
volumeStatsCapacityBytesDesc = prometheus.NewDesc(
prometheus.BuildFQName("", metrics.KubeletSubsystem, metrics.VolumeStatsCapacityBytesKey),
volumeStatsCapacityBytesDesc = metrics.NewDesc(
metrics.BuildFQName("", kubeletmetrics.KubeletSubsystem, kubeletmetrics.VolumeStatsCapacityBytesKey),
"Capacity in bytes of the volume",
[]string{"namespace", "persistentvolumeclaim"}, nil,
metrics.ALPHA, "",
)
volumeStatsAvailableBytesDesc = prometheus.NewDesc(
prometheus.BuildFQName("", metrics.KubeletSubsystem, metrics.VolumeStatsAvailableBytesKey),
volumeStatsAvailableBytesDesc = metrics.NewDesc(
metrics.BuildFQName("", kubeletmetrics.KubeletSubsystem, kubeletmetrics.VolumeStatsAvailableBytesKey),
"Number of available bytes in the volume",
[]string{"namespace", "persistentvolumeclaim"}, nil,
metrics.ALPHA, "",
)
volumeStatsUsedBytesDesc = prometheus.NewDesc(
prometheus.BuildFQName("", metrics.KubeletSubsystem, metrics.VolumeStatsUsedBytesKey),
volumeStatsUsedBytesDesc = metrics.NewDesc(
metrics.BuildFQName("", kubeletmetrics.KubeletSubsystem, kubeletmetrics.VolumeStatsUsedBytesKey),
"Number of used bytes in the volume",
[]string{"namespace", "persistentvolumeclaim"}, nil,
metrics.ALPHA, "",
)
volumeStatsInodesDesc = prometheus.NewDesc(
prometheus.BuildFQName("", metrics.KubeletSubsystem, metrics.VolumeStatsInodesKey),
volumeStatsInodesDesc = metrics.NewDesc(
metrics.BuildFQName("", kubeletmetrics.KubeletSubsystem, kubeletmetrics.VolumeStatsInodesKey),
"Maximum number of inodes in the volume",
[]string{"namespace", "persistentvolumeclaim"}, nil,
metrics.ALPHA, "",
)
volumeStatsInodesFreeDesc = prometheus.NewDesc(
prometheus.BuildFQName("", metrics.KubeletSubsystem, metrics.VolumeStatsInodesFreeKey),
volumeStatsInodesFreeDesc = metrics.NewDesc(
metrics.BuildFQName("", kubeletmetrics.KubeletSubsystem, kubeletmetrics.VolumeStatsInodesFreeKey),
"Number of free inodes in the volume",
[]string{"namespace", "persistentvolumeclaim"}, nil,
metrics.ALPHA, "",
)
volumeStatsInodesUsedDesc = prometheus.NewDesc(
prometheus.BuildFQName("", metrics.KubeletSubsystem, metrics.VolumeStatsInodesUsedKey),
volumeStatsInodesUsedDesc = metrics.NewDesc(
metrics.BuildFQName("", kubeletmetrics.KubeletSubsystem, kubeletmetrics.VolumeStatsInodesUsedKey),
"Number of used inodes in the volume",
[]string{"namespace", "persistentvolumeclaim"}, nil,
metrics.ALPHA, "",
)
)

type volumeStatsCollector struct {
metrics.BaseStableCollector

statsProvider serverstats.Provider
}

// NewVolumeStatsCollector creates a volume stats prometheus collector.
func NewVolumeStatsCollector(statsProvider serverstats.Provider) prometheus.Collector {
// Check if volumeStatsCollector implements necessary interface
var _ metrics.StableCollector = &volumeStatsCollector{}

// NewVolumeStatsCollector creates a volume stats metrics.StableCollector.
func NewVolumeStatsCollector(statsProvider serverstats.Provider) metrics.StableCollector {
return &volumeStatsCollector{statsProvider: statsProvider}
}

// Describe implements the prometheus.Collector interface.
func (collector *volumeStatsCollector) Describe(ch chan<- *prometheus.Desc) {
// DescribeWithStability implements the metrics.StableCollector interface.
func (collector *volumeStatsCollector) DescribeWithStability(ch chan<- *metrics.Desc) {
ch <- volumeStatsCapacityBytesDesc
ch <- volumeStatsAvailableBytesDesc
ch <- volumeStatsUsedBytesDesc
Expand All @@ -77,20 +87,16 @@ func (collector *volumeStatsCollector) Describe(ch chan<- *prometheus.Desc) {
ch <- volumeStatsInodesUsedDesc
}

// Collect implements the prometheus.Collector interface.
func (collector *volumeStatsCollector) Collect(ch chan<- prometheus.Metric) {
// CollectWithStability implements the metrics.StableCollector interface.
func (collector *volumeStatsCollector) CollectWithStability(ch chan<- metrics.Metric) {
podStats, err := collector.statsProvider.ListPodStats()
if err != nil {
return
}
addGauge := func(desc *prometheus.Desc, pvcRef *stats.PVCReference, v float64, lv ...string) {
addGauge := func(desc *metrics.Desc, pvcRef *stats.PVCReference, v float64, lv ...string) {
lv = append([]string{pvcRef.Namespace, pvcRef.Name}, lv...)
metric, err := prometheus.NewConstMetric(desc, prometheus.GaugeValue, v, lv...)
if err != nil {
klog.Warningf("Failed to generate metric: %v", err)
return
}
ch <- metric

ch <- metrics.NewLazyConstMetric(desc, metrics.GaugeValue, v, lv...)
}
allPVCs := sets.String{}
for _, podStat := range podStats {
Expand Down
14 changes: 7 additions & 7 deletions pkg/kubelet/metrics/collectors/volume_stats_test.go
Expand Up @@ -34,17 +34,17 @@ func TestVolumeStatsCollector(t *testing.T) {
// Fixed metadata on type and help text. We prepend this to every expected
// output so we only have to modify a single place when doing adjustments.
const metadata = `
# HELP kubelet_volume_stats_available_bytes Number of available bytes in the volume
# HELP kubelet_volume_stats_available_bytes [ALPHA] Number of available bytes in the volume
# TYPE kubelet_volume_stats_available_bytes gauge
# HELP kubelet_volume_stats_capacity_bytes Capacity in bytes of the volume
# HELP kubelet_volume_stats_capacity_bytes [ALPHA] Capacity in bytes of the volume
# TYPE kubelet_volume_stats_capacity_bytes gauge
# HELP kubelet_volume_stats_inodes Maximum number of inodes in the volume
# HELP kubelet_volume_stats_inodes [ALPHA] Maximum number of inodes in the volume
# TYPE kubelet_volume_stats_inodes gauge
# HELP kubelet_volume_stats_inodes_free Number of free inodes in the volume
# HELP kubelet_volume_stats_inodes_free [ALPHA] Number of free inodes in the volume
# TYPE kubelet_volume_stats_inodes_free gauge
# HELP kubelet_volume_stats_inodes_used Number of used inodes in the volume
# HELP kubelet_volume_stats_inodes_used [ALPHA] Number of used inodes in the volume
# TYPE kubelet_volume_stats_inodes_used gauge
# HELP kubelet_volume_stats_used_bytes Number of used bytes in the volume
# HELP kubelet_volume_stats_used_bytes [ALPHA] Number of used bytes in the volume
# TYPE kubelet_volume_stats_used_bytes gauge
`

Expand Down Expand Up @@ -132,7 +132,7 @@ func TestVolumeStatsCollector(t *testing.T) {
mockStatsProvider := new(statstest.StatsProvider)
mockStatsProvider.On("ListPodStats").Return(podStats, nil)
mockStatsProvider.On("ListPodStatsAndUpdateCPUNanoCoreUsage").Return(podStats, nil)
if err := testutil.CollectAndCompare(&volumeStatsCollector{statsProvider: mockStatsProvider}, strings.NewReader(want), metrics...); err != nil {
if err := testutil.CustomCollectAndCompare(&volumeStatsCollector{statsProvider: mockStatsProvider}, strings.NewReader(want), metrics...); err != nil {
t.Errorf("unexpected collecting result:\n%s", err)
}
}
4 changes: 2 additions & 2 deletions pkg/kubelet/metrics/metrics.go
Expand Up @@ -499,7 +499,7 @@ var (
var registerMetrics sync.Once

// Register registers all metrics.
func Register(containerCache kubecontainer.RuntimeCache, collectors ...metrics.Collector) {
func Register(containerCache kubecontainer.RuntimeCache, collectors ...metrics.StableCollector) {
// Register the metrics.
registerMetrics.Do(func() {
legacyregistry.MustRegister(NodeName)
Expand Down Expand Up @@ -540,7 +540,7 @@ func Register(containerCache kubecontainer.RuntimeCache, collectors ...metrics.C
legacyregistry.MustRegister(ConfigError)
}
for _, collector := range collectors {
legacyregistry.RawMustRegister(collector)
legacyregistry.CustomMustRegister(collector)
}
})
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/kubelet/pluginmanager/metrics/BUILD
Expand Up @@ -7,8 +7,8 @@ go_library(
visibility = ["//visibility:public"],
deps = [
"//pkg/kubelet/pluginmanager/cache:go_default_library",
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
"//staging/src/k8s.io/component-base/metrics:go_default_library",
"//staging/src/k8s.io/component-base/metrics/legacyregistry:go_default_library",
],
)

Expand Down
30 changes: 15 additions & 15 deletions pkg/kubelet/pluginmanager/metrics/metrics.go
Expand Up @@ -19,8 +19,8 @@ package metrics
import (
"sync"

"github.com/prometheus/client_golang/prometheus"
"k8s.io/klog"
"k8s.io/component-base/metrics"
"k8s.io/component-base/metrics/legacyregistry"
"k8s.io/kubernetes/pkg/kubelet/pluginmanager/cache"
)

Expand All @@ -32,11 +32,13 @@ const (
var (
registerMetrics sync.Once

totalPluginsDesc = prometheus.NewDesc(
totalPluginsDesc = metrics.NewDesc(
pluginManagerTotalPlugins,
"Number of plugins in Plugin Manager",
[]string{"socket_path", "state"},
nil,
metrics.ALPHA,
"",
)
)

Expand All @@ -55,35 +57,33 @@ func (pc pluginCount) add(state, pluginName string) {
// Register registers Plugin Manager metrics.
func Register(asw cache.ActualStateOfWorld, dsw cache.DesiredStateOfWorld) {
registerMetrics.Do(func() {
prometheus.MustRegister(&totalPluginsCollector{asw, dsw})
legacyregistry.CustomMustRegister(&totalPluginsCollector{asw: asw, dsw: dsw})
})
}

type totalPluginsCollector struct {
metrics.BaseStableCollector

asw cache.ActualStateOfWorld
dsw cache.DesiredStateOfWorld
}

var _ prometheus.Collector = &totalPluginsCollector{}
var _ metrics.StableCollector = &totalPluginsCollector{}

// Describe implements the prometheus.Collector interface.
func (c *totalPluginsCollector) Describe(ch chan<- *prometheus.Desc) {
// DescribeWithStability implements the metrics.StableCollector interface.
func (c *totalPluginsCollector) DescribeWithStability(ch chan<- *metrics.Desc) {
ch <- totalPluginsDesc
}

// Collect implements the prometheus.Collector interface.
func (c *totalPluginsCollector) Collect(ch chan<- prometheus.Metric) {
// CollectWithStability implements the metrics.StableCollector interface.
func (c *totalPluginsCollector) CollectWithStability(ch chan<- metrics.Metric) {
for stateName, pluginCount := range c.getPluginCount() {
for socketPath, count := range pluginCount {
metric, err := prometheus.NewConstMetric(totalPluginsDesc,
prometheus.GaugeValue,
ch <- metrics.NewLazyConstMetric(totalPluginsDesc,
metrics.GaugeValue,
float64(count),
socketPath,
stateName)
if err != nil {
klog.Warningf("Failed to create metric : %v", err)
}
ch <- metric
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/kubelet/pluginmanager/metrics/metrics_test.go
Expand Up @@ -42,7 +42,7 @@ func TestMetricCollection(t *testing.T) {
t.Fatalf("AddOrUpdatePlugin failed. Expected: <no error> Actual: <%v>", err)
}

metricCollector := &totalPluginsCollector{asw, dsw}
metricCollector := &totalPluginsCollector{asw: asw, dsw: dsw}

// Check if getPluginCount returns correct data
count := metricCollector.getPluginCount()
Expand Down
3 changes: 1 addition & 2 deletions pkg/kubelet/volumemanager/metrics/BUILD
Expand Up @@ -9,9 +9,8 @@ go_library(
"//pkg/kubelet/volumemanager/cache:go_default_library",
"//pkg/volume:go_default_library",
"//pkg/volume/util:go_default_library",
"//staging/src/k8s.io/component-base/metrics:go_default_library",
"//staging/src/k8s.io/component-base/metrics/legacyregistry:go_default_library",
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
],
)

Expand Down