diff --git a/.chloggen/fix_k8s_node_cpu_util.yaml b/.chloggen/fix_k8s_node_cpu_util.yaml new file mode 100644 index 000000000000..8904f13e1519 --- /dev/null +++ b/.chloggen/fix_k8s_node_cpu_util.yaml @@ -0,0 +1,27 @@ +# Use this changelog template to create an entry for release notes. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: bug_fix + +# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver) +component: kubeletstatsreceiver + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Fixes `k8s.node.cpu.utilization` so as to be properly reported as a ratio against the Node's capacity + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [27885] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: + +# If your change doesn't affect end users or the exported elements of any package, +# you should instead start your pull request title with [chore] or use the "Skip Changelog" label. +# Optional: The change log or logs in which this entry should be included. +# e.g. '[user]' or '[user, api]' +# Include 'user' if the change is relevant to end users. +# Include 'api' if there is a change to a library API. +# Default: '[user]' +change_logs: [] diff --git a/receiver/kubeletstatsreceiver/README.md b/receiver/kubeletstatsreceiver/README.md index a250ba5dff37..7fb4930c7f4f 100644 --- a/receiver/kubeletstatsreceiver/README.md +++ b/receiver/kubeletstatsreceiver/README.md @@ -218,11 +218,11 @@ receivers: - pod ``` -### Collect `k8s.{container,pod}.{cpu,memory}.node.utilization` as ratio of total node's capacity +### Collect `k8s.{container,pod}.{cpu,memory}.node.utilization` and `k8s.node.cpu.utilization` as ratio of total node's capacity In order to calculate the `k8s.container.cpu.node.utilization`, `k8s.pod.cpu.node.utilization`, -`k8s.container.memory.node.utilization` and `k8s.pod.memory.node.utilization` metrics, the -information of the node's capacity must be retrieved from the k8s API. In this, the `k8s_api_config` needs to be set. +`k8s.container.memory.node.utilization`, `k8s.pod.memory.node.utilization` and `k8s.pod.memory.node.utilization` metrics, +the information of the node's capacity must be retrieved from the k8s API. In this, the `k8s_api_config` needs to be set. In addition, the node name must be identified properly. The `K8S_NODE_NAME` env var can be set using the downward API inside the collector pod spec as follows: @@ -253,6 +253,8 @@ receivers: enabled: true k8s.pod.memory.node.utilization: enabled: true + k8s.node.cpu.utilization: + enabled: true ``` ### Optional parameters diff --git a/receiver/kubeletstatsreceiver/internal/kubelet/accumulator.go b/receiver/kubeletstatsreceiver/internal/kubelet/accumulator.go index 5cdf803080ab..d49aa615efc4 100644 --- a/receiver/kubeletstatsreceiver/internal/kubelet/accumulator.go +++ b/receiver/kubeletstatsreceiver/internal/kubelet/accumulator.go @@ -56,7 +56,7 @@ func (a *metricDataAccumulator) nodeStats(s stats.NodeStats) { currentTime := pcommon.NewTimestampFromTime(a.time) addUptimeMetric(a.mbs.NodeMetricsBuilder, metadata.NodeUptimeMetrics.Uptime, s.StartTime, currentTime) - addCPUMetrics(a.mbs.NodeMetricsBuilder, metadata.NodeCPUMetrics, s.CPU, currentTime, resources{}, 0) + addCPUMetrics(a.mbs.NodeMetricsBuilder, metadata.NodeCPUMetrics, s.CPU, currentTime, resources{}, a.metadata.nodeCapacity.CPUCapacity) addMemoryMetrics(a.mbs.NodeMetricsBuilder, metadata.NodeMemoryMetrics, s.Memory, currentTime, resources{}, 0) addFilesystemMetrics(a.mbs.NodeMetricsBuilder, metadata.NodeFilesystemMetrics, s.Fs, currentTime) addNetworkMetrics(a.mbs.NodeMetricsBuilder, metadata.NodeNetworkMetrics, s.Network, currentTime) diff --git a/receiver/kubeletstatsreceiver/internal/kubelet/cpu.go b/receiver/kubeletstatsreceiver/internal/kubelet/cpu.go index b1a767983ead..b60d44ab43c3 100644 --- a/receiver/kubeletstatsreceiver/internal/kubelet/cpu.go +++ b/receiver/kubeletstatsreceiver/internal/kubelet/cpu.go @@ -35,7 +35,10 @@ func addCPUUtilizationMetrics( currentTime pcommon.Timestamp, r resources, nodeCPULimit float64) { - cpuMetrics.Utilization(mb, currentTime, usageCores) + + if cpuMetrics.Utilization != nil { + cpuMetrics.Utilization(mb, currentTime, usageCores) + } if nodeCPULimit > 0 { cpuMetrics.NodeUtilization(mb, currentTime, usageCores/nodeCPULimit) diff --git a/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics.go b/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics.go index 02aef00983ad..3dc066bb0fea 100644 --- a/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics.go +++ b/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics.go @@ -3096,9 +3096,6 @@ func NewMetricsBuilder(mbc MetricsBuilderConfig, settings receiver.Settings, opt if mbc.Metrics.ContainerCPUUtilization.Enabled { settings.Logger.Warn("[WARNING] `container.cpu.utilization` should not be enabled: WARNING: This metric will be disabled in a future release. Use metric container.cpu.usage instead.") } - if mbc.Metrics.K8sNodeCPUUtilization.Enabled { - settings.Logger.Warn("[WARNING] `k8s.node.cpu.utilization` should not be enabled: WARNING: This metric will be disabled in a future release. Use metric k8s.node.cpu.usage instead.") - } if mbc.Metrics.K8sPodCPUUtilization.Enabled { settings.Logger.Warn("[WARNING] `k8s.pod.cpu.utilization` should not be enabled: This metric will be disabled in a future release. Use metric k8s.pod.cpu.usage instead.") } diff --git a/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics_test.go b/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics_test.go index 1fd14d7c86f2..c34ac6513b06 100644 --- a/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics_test.go +++ b/receiver/kubeletstatsreceiver/internal/metadata/generated_metrics_test.go @@ -66,10 +66,6 @@ func TestMetricsBuilder(t *testing.T) { assert.Equal(t, "[WARNING] `container.cpu.utilization` should not be enabled: WARNING: This metric will be disabled in a future release. Use metric container.cpu.usage instead.", observedLogs.All()[expectedWarnings].Message) expectedWarnings++ } - if test.metricsSet == testDataSetDefault || test.metricsSet == testDataSetAll { - assert.Equal(t, "[WARNING] `k8s.node.cpu.utilization` should not be enabled: WARNING: This metric will be disabled in a future release. Use metric k8s.node.cpu.usage instead.", observedLogs.All()[expectedWarnings].Message) - expectedWarnings++ - } if test.metricsSet == testDataSetDefault || test.metricsSet == testDataSetAll { assert.Equal(t, "[WARNING] `k8s.pod.cpu.utilization` should not be enabled: This metric will be disabled in a future release. Use metric k8s.pod.cpu.usage instead.", observedLogs.All()[expectedWarnings].Message) expectedWarnings++ diff --git a/receiver/kubeletstatsreceiver/internal/metadata/metrics.go b/receiver/kubeletstatsreceiver/internal/metadata/metrics.go index 5f23d5264185..bba2379cc956 100644 --- a/receiver/kubeletstatsreceiver/internal/metadata/metrics.go +++ b/receiver/kubeletstatsreceiver/internal/metadata/metrics.go @@ -28,9 +28,10 @@ type CPUMetrics struct { } var NodeCPUMetrics = CPUMetrics{ - Time: (*MetricsBuilder).RecordK8sNodeCPUTimeDataPoint, - Usage: (*MetricsBuilder).RecordK8sNodeCPUUsageDataPoint, - Utilization: (*MetricsBuilder).RecordK8sNodeCPUUtilizationDataPoint, + Time: (*MetricsBuilder).RecordK8sNodeCPUTimeDataPoint, + Usage: (*MetricsBuilder).RecordK8sNodeCPUUsageDataPoint, + //Utilization: (*MetricsBuilder).RecordK8sNodeCPUUtilizationDataPoint, + NodeUtilization: (*MetricsBuilder).RecordK8sNodeCPUUtilizationDataPoint, } var PodCPUMetrics = CPUMetrics{ diff --git a/receiver/kubeletstatsreceiver/metadata.yaml b/receiver/kubeletstatsreceiver/metadata.yaml index f382515cf634..1f197cd1c124 100644 --- a/receiver/kubeletstatsreceiver/metadata.yaml +++ b/receiver/kubeletstatsreceiver/metadata.yaml @@ -92,8 +92,6 @@ metrics: k8s.node.cpu.utilization: enabled: true description: "Node CPU utilization" - warnings: - if_enabled: "WARNING: This metric will be disabled in a future release. Use metric k8s.node.cpu.usage instead." unit: "1" gauge: value_type: double diff --git a/receiver/kubeletstatsreceiver/scraper.go b/receiver/kubeletstatsreceiver/scraper.go index 582bbbfae57c..aad4ac35b3b2 100644 --- a/receiver/kubeletstatsreceiver/scraper.go +++ b/receiver/kubeletstatsreceiver/scraper.go @@ -83,7 +83,8 @@ func newKubletScraper( nodeLimits: &kubelet.NodeCapacity{}, } - if metricsConfig.Metrics.K8sContainerCPUNodeUtilization.Enabled || + if metricsConfig.Metrics.K8sNodeCPUUtilization.Enabled || + metricsConfig.Metrics.K8sContainerCPUNodeUtilization.Enabled || metricsConfig.Metrics.K8sPodCPUNodeUtilization.Enabled || metricsConfig.Metrics.K8sContainerMemoryNodeUtilization.Enabled || metricsConfig.Metrics.K8sPodMemoryNodeUtilization.Enabled { diff --git a/receiver/kubeletstatsreceiver/scraper_test.go b/receiver/kubeletstatsreceiver/scraper_test.go index 649766adff75..1afb3daf12b3 100644 --- a/receiver/kubeletstatsreceiver/scraper_test.go +++ b/receiver/kubeletstatsreceiver/scraper_test.go @@ -102,6 +102,7 @@ func TestScraperWithCPUNodeUtilization(t *testing.T) { metricGroupsToCollect: map[kubelet.MetricGroup]bool{ kubelet.ContainerMetricGroup: true, kubelet.PodMetricGroup: true, + kubelet.NodeMetricGroup: true, }, k8sAPIClient: client, } @@ -117,6 +118,9 @@ func TestScraperWithCPUNodeUtilization(t *testing.T) { K8sPodCPUNodeUtilization: metadata.MetricConfig{ Enabled: true, }, + K8sNodeCPUUtilization: metadata.MetricConfig{ + Enabled: true, + }, }, ResourceAttributes: metadata.DefaultResourceAttributesConfig(), }, @@ -140,7 +144,7 @@ func TestScraperWithCPUNodeUtilization(t *testing.T) { require.Eventually(t, func() bool { md, err = r.Scrape(context.Background()) require.NoError(t, err) - return numContainers+numPods == md.DataPointCount() + return numContainers+numPods+1 == md.DataPointCount() }, 10*time.Second, 100*time.Millisecond, "metrics not collected") diff --git a/receiver/kubeletstatsreceiver/testdata/scraper/test_scraper_cpu_util_nodelimit_expected.yaml b/receiver/kubeletstatsreceiver/testdata/scraper/test_scraper_cpu_util_nodelimit_expected.yaml index aecca73d94f7..ab70e5c05545 100644 --- a/receiver/kubeletstatsreceiver/testdata/scraper/test_scraper_cpu_util_nodelimit_expected.yaml +++ b/receiver/kubeletstatsreceiver/testdata/scraper/test_scraper_cpu_util_nodelimit_expected.yaml @@ -1,4 +1,22 @@ resourceMetrics: + - resource: + attributes: + - key: k8s.node.name + value: + stringValue: minikube + scopeMetrics: + - metrics: + - description: Node CPU utilization + gauge: + dataPoints: + - asDouble: 0.020717166125 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: k8s.node.cpu.utilization + unit: "1" + scope: + name: otelcol/kubeletstatsreceiver + version: latest - resource: attributes: - key: k8s.namespace.name