diff --git a/pkg/kubelet/server/metrics/metrics.go b/pkg/kubelet/server/metrics/metrics.go index e9a2b5fca76..d6e1a39c782 100644 --- a/pkg/kubelet/server/metrics/metrics.go +++ b/pkg/kubelet/server/metrics/metrics.go @@ -26,6 +26,9 @@ import ( const ( kubeletSubsystem = "kubelet" + + CAdvisorMetricsProvider MetricsProviderType = "cadvisor" + CRIMetricsProvider MetricsProviderType = "cri" ) var ( @@ -76,6 +79,15 @@ var ( }, []string{"metric_source"}, ) + MetricsProvider = metrics.NewGaugeVec( + &metrics.GaugeOpts{ + Subsystem: kubeletSubsystem, + Name: "metrics_provider", + Help: "Metrics provider used by kubelet to collect container stats. Values can be 'cadvisor' and 'cri'", + StabilityLevel: metrics.ALPHA, + }, + []string{"provider"}, + ) ) var registerMetrics sync.Once @@ -87,6 +99,7 @@ func Register() { legacyregistry.MustRegister(HTTPRequestsDuration) legacyregistry.MustRegister(HTTPInflightRequests) legacyregistry.MustRegister(VolumeStatCalDuration) + legacyregistry.MustRegister(MetricsProvider) }) } @@ -99,3 +112,11 @@ func SinceInSeconds(start time.Time) float64 { func CollectVolumeStatCalDuration(metricSource string, start time.Time) { VolumeStatCalDuration.WithLabelValues(metricSource).Observe(SinceInSeconds(start)) } + +type MetricsProviderType string + +// SetMetricsProvider sets the metrics provider. +func SetMetricsProvider(provider MetricsProviderType) { + MetricsProvider.Reset() + MetricsProvider.WithLabelValues(string(provider)).Set(1) +} diff --git a/pkg/kubelet/server/metrics/metrics_test.go b/pkg/kubelet/server/metrics/metrics_test.go new file mode 100644 index 00000000000..cc68afa68f3 --- /dev/null +++ b/pkg/kubelet/server/metrics/metrics_test.go @@ -0,0 +1,65 @@ +/* +Copyright 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 metrics + +import ( + "strings" + "testing" + + "k8s.io/component-base/metrics/legacyregistry" + "k8s.io/component-base/metrics/testutil" +) + +func TestSetMetricsProvider(t *testing.T) { + Register() + MetricsProvider.Reset() + + tests := []struct { + name string + provider MetricsProviderType + want string + }{ + { + name: "cadvisor provider", + provider: CAdvisorMetricsProvider, + want: ` +# HELP kubelet_metrics_provider [ALPHA] Metrics provider used by kubelet to collect container stats. Values can be 'cadvisor' and 'cri' +# TYPE kubelet_metrics_provider gauge +kubelet_metrics_provider{provider="cadvisor"} 1 +`, + }, + { + name: "cri provider", + provider: CRIMetricsProvider, + want: ` +# HELP kubelet_metrics_provider [ALPHA] Metrics provider used by kubelet to collect container stats. Values can be 'cadvisor' and 'cri' +# TYPE kubelet_metrics_provider gauge +kubelet_metrics_provider{provider="cri"} 1 +`, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + SetMetricsProvider(tt.provider) + + if err := testutil.GatherAndCompare(legacyregistry.DefaultGatherer, strings.NewReader(tt.want), "kubelet_metrics_provider"); err != nil { + t.Errorf("unexpected metric output: %v", err) + } + }) + } +} diff --git a/pkg/kubelet/server/server.go b/pkg/kubelet/server/server.go index 0ee72e1643e..114cda5b715 100644 --- a/pkg/kubelet/server/server.go +++ b/pkg/kubelet/server/server.go @@ -476,6 +476,7 @@ func (s *Server) InstallAuthNotRequiredHandlers(ctx context.Context) { r.RawMustRegister(metrics.NewPrometheusMachineCollector(prometheusHostAdapter{s.host}, includedMetrics)) if utilfeature.DefaultFeatureGate.Enabled(features.PodAndContainerStatsFromCRI) { r.CustomRegister(collectors.NewCRIMetricsCollector(context.TODO(), s.host.ListPodSandboxMetrics, s.host.ListMetricDescriptors)) + servermetrics.SetMetricsProvider(servermetrics.CRIMetricsProvider) } else { cadvisorOpts := cadvisorv2.RequestOptions{ IdType: cadvisorv2.TypeName, @@ -483,6 +484,7 @@ func (s *Server) InstallAuthNotRequiredHandlers(ctx context.Context) { Recursive: true, } r.RawMustRegister(metrics.NewPrometheusCollector(prometheusHostAdapter{s.host}, containerPrometheusLabelsFunc(s.host), includedMetrics, clock.RealClock{}, cadvisorOpts)) + servermetrics.SetMetricsProvider(servermetrics.CAdvisorMetricsProvider) } s.restfulCont.Handle(cadvisorMetricsPath, compbasemetrics.HandlerFor(r, compbasemetrics.HandlerOpts{ErrorHandling: compbasemetrics.ContinueOnError}),