What happened:
Cluster scoped metric like kube_node_created is duplicated as many times as the number of namespace when using --namespaces=...
So, warning log like below is shown in the Prometheus.
ts=2026-02-26T05:56:38.676Z caller=scrape.go:1754 level=warn component="scrape manager" scrape_pool=serviceMonitor/<namespace>/kube-state-metrics/0 target=http://<pod IP>:8080/metrics msg="Error on ingesting samples with different value but same timestamp" num_dropped=7440
What you expected to happen:
Cluster scoped metric isn't duplicated as many times as the number of namespace.
How to reproduce it (as minimally and precisely as possible):
-
deploy kube-state-metrics with --namespaces cli options
a. kube-prometheus-stack Helm chart values
kube-state-metrics:
....
namespaces:
- namespaceA
- namespaceB
- namespaceC
=> pass 3 namespace
-
check metrics via kube-state-metrics' /metrics API
# HELP kube_namespace_created [STABLE] Unix creation timestamp
# TYPE kube_namespace_created gauge
kube_namespace_created{namespace="namespaceA"} 1.715672771e+09
kube_namespace_created{namespace="namespaceA"} 1.715672771e+09
kube_namespace_created{namespace="namespaceA"} 1.715672771e+09
# HELP kube_namespace_status_phase [STABLE] kubernetes namespace status phase.
# TYPE kube_namespace_status_phase gauge
... (same above)
=> kube_namespace_created metric is repeated as many times as the number of namespace (for this example, repeat 3 times)
Anything else we need to know?:
Only cluster scope metric is duplicated.
a. kube-prometheus-stack Helm chart values
kube-state-metrics:
....
collectors:
- configmaps
- cronjobs
- daemonsets
- deployments
- endpointslices
- ingresses
- jobs
- namespaces
- nodes
- persistentvolumeclaims
- persistentvolumes
- poddisruptionbudgets
- pods
- replicasets
- replicationcontrollers
- secrets
- services
- statefulsets
- storageclasses
- volumeattachments
b. duplicated metric list
kube_namespace_created
kube_namespace_status_phase
kube_node_created
kube_node_info
kube_node_labels
kube_node_spec_unschedulable
kube_node_status_allocatable
kube_node_status_capacity
kube_node_status_addresses
kube_persistentvolume_claim_ref
kube_persistentvolume_status_phase
kube_persistentvolume_info
kube_persistentvolume_capacity_bytes
kube_persistentvolume_created
kube_persistentvolume_volume_mode
kube_storageclass_info
kube_storageclass_created
kube_volumeattachment_labels
kube_volumeattachment_info
kube_volumeattachment_created
kube_volumeattachment_spec_source_persistentvolume
kube_volumeattachment_status_attached
kube_volumeattachment_status_attachment_metadata
=> I checked this from prometheus log like below after setting prometheus' log level as debug
ts=2026-02-26T06:16:38.660Z caller=scrape.go:1793 level=debug component="scrape manager" scrape_pool=serviceMonitor/<namespace>/kube-state-metrics/0 target=http://<pod IP>:8080/metrics msg="Duplicate sample for timestamp" series="kube_namespace_created{namespace=\"namespaceA\"}"
...
ts=2026-02-26T06:16:38.754Z caller=scrape.go:1754 level=warn component="scrape manager" scrape_pool=serviceMonitor/<namespace>/kube-state-metrics/0 target=http://<pod IP>:8080/metrics msg="Error on ingesting samples with different value but same timestamp" num_dropped=7440
So I'm not sure if it's right, but I think, below logic is reason of duplicated metric for cluster scope.
https://github.com/kubernetes/kube-state-metrics/blob/v2.13.0/internal/store/builder.go
// WithGenerateStoresFunc configures a custom generate store function
func (b *Builder) WithGenerateStoresFunc(f ksmtypes.BuildStoresFunc) {
b.buildStoresFunc = f
}
// DefaultGenerateStoresFunc returns default buildStores function
func (b *Builder) DefaultGenerateStoresFunc() ksmtypes.BuildStoresFunc {
return b.buildStores
}
...
func (b *Builder) buildNamespaceStores() []cache.Store {
return b.buildStoresFunc(namespaceMetricFamilies(b.allowAnnotationsList["namespaces"], b.allowLabelsList["namespaces"]), &v1.Namespace{}, createNamespaceListWatch, b.useAPIServerCache)
}
...
func (b *Builder) buildStores(...) []cache.Store {
...
if b.namespaces.IsAllNamespaces() {
store := metricsstore.NewMetricsStore(
familyHeaders,
composedMetricGenFuncs,
)
if b.fieldSelectorFilter != "" {
klog.InfoS("FieldSelector is used", "fieldSelector", b.fieldSelectorFilter)
}
listWatcher := listWatchFunc(b.kubeClient, v1.NamespaceAll, b.fieldSelectorFilter)
b.startReflector(expectedType, store, listWatcher, useAPIServerCache)
return []cache.Store{store}
}
stores := make([]cache.Store, 0, len(b.namespaces))
for _, ns := range b.namespaces {
store := metricsstore.NewMetricsStore(
familyHeaders,
composedMetricGenFuncs,
)
if b.fieldSelectorFilter != "" {
klog.InfoS("FieldSelector is used", "fieldSelector", b.fieldSelectorFilter)
}
listWatcher := listWatchFunc(b.kubeClient, ns, b.fieldSelectorFilter)
b.startReflector(expectedType, store, listWatcher, useAPIServerCache)
stores = append(stores, store)
}
return stores
}
builder.buildStoresFunc is set as buildStores function.
so when building namespace store using buildNamespaceStores(), namespace store is created as many times as the number of namespace, because --namespaces options is used not all namespace.
I solved it for now by not passing namespaces list.
But I want to use namespaces options to exclude namespace that isn't need to scrape for metric.
So, I hope this problem is solved.
Environment:
- kube-state-metrics version: 2.13.0
- Kubernetes version (use
kubectl version): 1.34
- Cloud provider or hardware configuration:
- Other info:
- kube-prometheus-stack version: 65.0.0
- prometheus: 2.54.1
What happened:
Cluster scoped metric like
kube_node_createdis duplicated as many times as the number of namespace when using--namespaces=...So, warning log like below is shown in the Prometheus.
What you expected to happen:
Cluster scoped metric isn't duplicated as many times as the number of namespace.
How to reproduce it (as minimally and precisely as possible):
deploy kube-state-metrics with --namespaces cli options
a. kube-prometheus-stack Helm chart values
=> pass 3 namespace
check metrics via kube-state-metrics' /metrics API
=>
kube_namespace_createdmetric is repeated as many times as the number of namespace (for this example, repeat 3 times)Anything else we need to know?:
Only cluster scope metric is duplicated.
a. kube-prometheus-stack Helm chart values
b. duplicated metric list
=> I checked this from prometheus log like below after setting prometheus' log level as debug
So I'm not sure if it's right, but I think, below logic is reason of duplicated metric for cluster scope.
https://github.com/kubernetes/kube-state-metrics/blob/v2.13.0/internal/store/builder.go
builder.buildStoresFunc is set as buildStores function.
so when building namespace store using buildNamespaceStores(), namespace store is created as many times as the number of namespace, because --namespaces options is used not all namespace.
I solved it for now by not passing namespaces list.
But I want to use namespaces options to exclude namespace that isn't need to scrape for metric.
So, I hope this problem is solved.
Environment:
kubectl version): 1.34