-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Description
What happened:
Starting from version 2.8.0, if Prometheus is started with --enable-feature=native-histograms flag it fails to scrape KSM, instead erroring with the error:
proto: wrong wireType = 0 for field Metric
What you expected to happen:
KSM should be able to be scraped by Prometheus
How to reproduce it (as minimally and precisely as possible):
I can reproduce this just on minikube with the standard helm prometheus, chart https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus
helm install prometheus prometheus-community/prometheus --set server.extraFlags={"enable-feature=native-histograms"\,"log.level=debug"} --version=19.7.2
This deploys kube-state-metrics version: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.8.0
And Prometheus version: quay.io/prometheus/prometheus:v2.41.0
With the --enable-feature=native-histograms set.
Anything else we need to know?:
The problem was introduced in this PR #1974
I think the issue, is that when you enable Native Histograms, Prometheus is sending headers with a content type of:
content type: %v application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited
Which we're then mirroring in our headers:
resHeader.Set("Content-Type", string(contentType))But we're not actually changing our response so we're replying with invalid protobuf hence the error from Prometheus.
I did this as a simple workaround and it fixed the issue:
if contentType == expfmt.FmtProtoDelim {
resHeader.Set("Content-Type", `text/plain; version=`+"0.0.4")
} else {
resHeader.Set("Content-Type", string(contentType))
}However I'm not sure this is the right approach, is it intended that kube-state-metrics always responds with content headers that match the request? Or was this just a change for Open Metrics? In which case perhaps the header should only get changed if the contentType == expfmt.FmtOpenMetric? e.g reverse the logic, only change the headers if we detect open metrics headers:
if contentType == expfmt.FmtOpenMetrics {
resHeader.Set("Content-Type", string(contentType))
} else {
resHeader.Set("Content-Type", `text/plain; version=`+"0.0.4")
}That way the code would behave the same as it did prior to 2.8.0 if the open metrics headers are not present.
Environment:
- kube-state-metrics version: 2.8.0
- Kubernetes version (use
kubectl version): 1.26.1 - Cloud provider or hardware configuration: n/a
- Other info: