Skip to content

docs(customresourcestate): document full VPA CRS replacement config - #3042

Open
locker95 wants to merge 1 commit into
kubernetes:mainfrom
locker95:docs/vpa-crm-replacement-config
Open

docs(customresourcestate): document full VPA CRS replacement config#3042
locker95 wants to merge 1 commit into
kubernetes:mainfrom
locker95:docs/vpa-crm-replacement-config

Conversation

@locker95

@locker95 locker95 commented Jul 25, 2026

Copy link
Copy Markdown

What this PR does / why we need it:
The VerticalPodAutoscaler section of the Custom Resource State docs only showed how to re-create annotation metrics after the built-in VPA collector was removed in v2.9.0. Users upgrading needed a full replacement config (labels, update mode, resource policy, and recommendation metrics) and clear notes about naming/RBAC differences.

This PR turns that section into a migration-focused guide with:

  • RBAC requirements for VPA + CRDs
  • Differences from the pre-v2.9 built-in collector
  • A complete CustomResourceStateMetrics config covering the former built-in metrics
  • Old → CRS metric name mapping
  • Example series output

How does this change affect the cardinality of KSM:
Does not change cardinality (documentation only).

Which issue(s) this PR fixes:
Fixes #2041

Summary by CodeRabbit

  • Documentation
    • Updated Custom Resource State Metrics guidance for VerticalPodAutoscaler (VPA), including a complete replacement configuration after the prior collector change.
    • Added RBAC guidance and refreshed YAML examples.
    • Documented behavioral differences vs the previous built-in collector (metric naming, CPU/memory split, quantity parsing, and label/annotation handling).
    • Added metric name mapping, target recommendation examples, and links to related configuration references.

@kubernetes-prow kubernetes-prow Bot added the do-not-merge/invalid-commit-message Indicates that a PR should not merge because it has an invalid commit message. label Jul 25, 2026
@kubernetes-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: locker95
Once this PR has been reviewed and has the lgtm label, please assign bhope for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubernetes-prow

Copy link
Copy Markdown
Contributor

This issue is currently awaiting triage.

If kube-state-metrics contributors determine this is a relevant issue, they will accept it by applying the triage/accepted label and provide further guidance.

The triage/accepted label can be added by org members by writing /triage accepted in a comment.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@kubernetes-prow kubernetes-prow Bot added the needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. label Jul 25, 2026
@kubernetes-prow

Copy link
Copy Markdown
Contributor

Welcome @locker95!

It looks like this is your first PR to kubernetes/kube-state-metrics 🎉. Please refer to our pull request process documentation to help your PR have a smooth ride to approval.

You will be prompted by a bot to use commands during the review process. Do not be afraid to follow the prompts! It is okay to experiment. Here is the bot commands documentation.

You can also check if kubernetes/kube-state-metrics has its own contribution guidelines.

You may want to refer to our testing guide if you run into trouble with your tests not passing.

If you are having difficulty getting your pull request seen, please follow the recommended escalation practices. Also, for tips and tricks in the contribution process you may want to read the Kubernetes contributor cheat sheet. We want to make sure your contribution gets all the attention it needs!

Thank you, and welcome to Kubernetes. 😃

@github-project-automation github-project-automation Bot moved this to Needs Triage in SIG Instrumentation Jul 25, 2026
@kubernetes-prow kubernetes-prow Bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Jul 25, 2026
@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 75844bd4-d66d-4cdb-a0de-2b8c86e13e16

📥 Commits

Reviewing files that changed from the base of the PR and between e9ee50b and b6d06b7.

📒 Files selected for processing (1)
  • docs/metrics/extend/customresourcestate-metrics.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/metrics/extend/customresourcestate-metrics.md

📝 Walkthrough

Walkthrough

The documentation adds a complete VPA Custom Resource State Metrics replacement configuration, explains differences from the removed built-in collector, documents required RBAC, and maps legacy metric names to CPU- and memory-specific CRS names.

Changes

VPA CRS documentation

Layer / File(s) Summary
VPA CRS replacement configuration
docs/metrics/extend/customresourcestate-metrics.md
Documents collector differences and RBAC requirements, then provides a complete VPA CRS YAML example with revised CPU and memory metric definitions.
Legacy metric mapping and validation
docs/metrics/extend/customresourcestate-metrics.md
Maps pre-v2.9.0 built-in metric names to CRS names using metricNamePrefix: "kube" and adds a Prometheus series example with related references.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Suggested reviewers: rexagod, catherinef-dev

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the documentation change to provide a full VPA CRS replacement config.
Linked Issues check ✅ Passed The docs add a complete VPA CRS replacement example and supporting guidance requested by issue #2041.
Out of Scope Changes check ✅ Passed The added RBAC, metric mapping, and example output all support the VPA replacement-guide objective.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/metrics/extend/customresourcestate-metrics.md`:
- Around line 354-366: Update the RBAC example in the custom resource state
documentation to retain only the required VerticalPodAutoscaler list/watch rule
for the fixed GVK configuration. Remove the CustomResourceDefinitions rule from
the copy-paste YAML and add it to an explanatory note stating that CRD
list/watch permissions are needed only when wildcard GVK discovery is
configured.
- Around line 336-344: Revise the introductory text to describe the
configuration as a replacement rather than a drop-in replacement. Explicitly
state that CPU and memory recommendations now use separate metric families,
annotations and labels change from Gauge to Info, and existing dashboards or
alerts querying the former families require query migration.
- Around line 345-346: Update the quantity-parsing note near the CRS metrics
conversion documentation to remove the unresolved edge-case caveat. State
explicitly that supported VPA quantity strings have no known
CRS-versus-old-collector conversion differences, while retaining the existing
supported conversion description.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0e67c318-dcc8-4a97-aa65-f789d2052afe

📥 Commits

Reviewing files that changed from the base of the PR and between 5df57ce and e9ee50b.

📒 Files selected for processing (1)
  • docs/metrics/extend/customresourcestate-metrics.md

Comment on lines +336 to +344
The configuration below is intended as a drop-in replacement for the metrics that existed before v2.9.0.
A few differences remain:

* CRS always adds `customresource_group`, `customresource_kind`, and `customresource_version` labels.
* Resource recommendation gauges are exposed as separate `_cpu` / `_memory` metric names.
The old collector used a single metric name with `resource` and `unit` labels.
Both `resource` and `unit` are still present via `commonLabels` so queries can filter the same way.
Using one metric name for both CPU and memory is possible (see [Same Metrics with Different Labels](#same-metrics-with-different-labels)),
but produces two `# HELP` lines for the same series name, which some scrapers reject.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Don’t describe this as a drop-in replacement.

The configuration restores equivalent data, but not metric compatibility: CPU and memory recommendations use separate metric families, and annotations/labels change from Gauge to Info. Existing dashboards and alerts still querying the former families require migration. Reword this as a replacement configuration and call out the query changes explicitly. (raw.githubusercontent.com)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/metrics/extend/customresourcestate-metrics.md` around lines 336 - 344,
Revise the introductory text to describe the configuration as a replacement
rather than a drop-in replacement. Explicitly state that CPU and memory
recommendations now use separate metric families, annotations and labels change
from Gauge to Info, and existing dashboards or alerts querying the former
families require query migration.

Comment on lines +345 to +346
* Quantity parsing is handled by CRS (for example `100m` CPU and memory sizes).
Values should match the old collector for common cases, but edge cases may differ.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate file =="
git ls-files | rg 'docs/metrics/extend/customresourcestate-metrics.md|customresourcestate-metrics' || true

echo "== nearby lines =="
sed -n '310,370p' docs/metrics/extend/customresourcestate-metrics.md 2>/dev/null || true

echo "== search quantity parsing mentions =="
rg -n "quantity|Quantity parsing|250m|512Gi|VPA|customresourcestate-metrics|cpu|memory" docs/metrics/extend/customresourcestate-metrics.md 2>/dev/null || true

Repository: kubernetes/kube-state-metrics

Length of output: 12844


🌐 Web query:

kubernetes/kube-state-metrics docs metrics extend customresourcestate-metrics resource quantity parsing Kubernetes quantity parsing

💡 Result:

In kube-state-metrics (KSM), Custom Resource State metrics support the parsing of Kubernetes quantities (e.g., "250m", "512Gi") into float64 values [1]. This functionality is part of KSM's implicit type conversion logic for CustomResourceState metrics [1]. When configuring Custom Resource State metrics, KSM automatically attempts to parse string values retrieved from custom resources into floats [1]. The supported string-to-float parsing logic includes the following: - Quantities: Strings such as "250m" (millicores) or "512Gi" (binary gigabytes) are parsed into their corresponding numerical float64 representation [1]. - Percentages: Strings ending with a "%" character are also parsed into floats [1]. - Other Formats: Standard numerical formats are supported; additionally, "true"/"yes" are mapped to 1.0, and "false"/"no"/"unknown" are mapped to 0.0 [1]. This feature was specifically introduced to ensure that custom resources could be monitored similarly to core Kubernetes resources, supporting use cases like Vertical Pod Autoscaler (VPA) deprecation [2]. If you are encountering issues with specific parsing (such as distinguishing between a resource quantity and a duration string), note that KSM explicitly handles quantities using Kubernetes' standard quantity parsing libraries [1]. However, there is no native "valueType" configuration for duration parsing in the general sense; KSM has faced requests to support time.ParseDuration explicitly [3], and users requiring specific conversions should ensure their configuration correctly maps the intended path to the value [1]. For further details on configuring these metrics, consult the official KSM documentation on Custom Resource State metrics [1].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== docs section around quantity details =="
sed -n '620,680p' docs/metrics/extend/customresourcestate-metrics.md || true

echo "== find quantity conversion references in repo =="
rg -n "quantity" --glob '*.go' --glob '*.md' . | head -n 120 || true

echo "== inspect implementation references =="
rg -n "api/resource|ParseQuantity|Quantity|quantities|strconv|parseFloat|vpa|verticalpodautoscaler" --glob '*.go' . | head -n 240 || true

Repository: kubernetes/kube-state-metrics

Length of output: 11665


🌐 Web query:

kubernetes/apimachinery pkg api resource quantity parse decimal milli 250m 100m values

💡 Result:

In the Kubernetes apimachinery library, the k8s.io/apimachinery/pkg/api/resource package handles the parsing and representation of resource quantities [1][2]. The resource.Quantity type provides a fixed-point representation for numerical values, which is commonly used for CPU and memory resource specifications [3]. When parsing strings like "250m" or "100m", the system interprets the "m" suffix as a decimal SI unit representing "milli" (1/1000) [3][4]. Key characteristics of this parsing mechanism include: - Interpretation of Units: The "m" suffix is part of the DecimalSI format [3]. Therefore, "250m" is equivalent to 0.25 (or 250/1000) and "100m" is equivalent to 0.1 (or 100/1000) [5][6]. - Internal Representation: The ParseQuantity function in quantity.go processes these strings by identifying the numeric part and the suffix, then calculating a mantissa and exponent to store the value accurately [2][7]. - Precision Constraints: Kubernetes enforces that quantities cannot have more than 3 decimal places [3]. Values exceeding this precision are rounded up (e.g., 0.1m would be rounded up to 1m) [3]. - Interchangeability: Because "m" signifies 1/1000, "100m" is functionally identical to the decimal representation "0.1" [5][4]. Using the "m" suffix is a standard practice to avoid potential parsing ambiguities associated with floating-point numbers in YAML manifests [6]. When writing Go code using this library, you can parse these strings using resource.ParseQuantity(str), which returns a Quantity object and an error if the format is invalid [2][7]. You can subsequently access these values using methods like MilliValue() or AsInt64() [3][8].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== vpa store implementation in current repo =="
for f in $(git ls-files | rg 'internal/store/.*verticalpodautoscaler|verticalpodautoscaler.*go'); do
  echo "--- $f"
  wc -l "$f"
  rg -n "resource.Quantity|MilliValue|AsInt64|As Milli|containerRecommendations|VPA|verticalPodAutoscaler" "$f" || true
done

echo "== old VPA store around conversion =="
sed -n '1,340p' internal/store/verticalpodautoscaler.go 2>/dev/null || true

Repository: kubernetes/kube-state-metrics

Length of output: 252


🌐 Web query:

"k8s.io/apimachinery/pkg/api/resource" "MustParse" "Quantity" "MilliValue" "AsInt64"

💡 Result:

In the Kubernetes apimachinery library (k8s.io/apimachinery/pkg/api/resource), the MustParse, MilliValue, and AsInt64 functions are used to parse and manipulate Quantity objects, which represent fixed-point numbers [1][2][3]. MustParse The MustParse function parses a string into a Quantity object [1][2]. If the string is invalid, it panics [1][3]. It is primarily intended for use in tests or scenarios where the input is guaranteed to be a valid quantity string [1][2]. Example: q:= resource.MustParse("5300m") [4] MilliValue The MilliValue function returns the value of the quantity in milli-units (e.g., 1 core = 1000m) [1][2]. It calculates the result as ceil(q * 1000) [1][3]. Because this calculation can potentially overflow an int64, it is recommended to verify the quantity's size if overflow is a concern [1][2]. Example: milli:= q.MilliValue // Returns 5300 for "5300m" [4] AsInt64 The AsInt64 function attempts to return the underlying value of the quantity as an int64 [1][5]. It returns two values: the int64 representation and a boolean indicating if the conversion was successful (i.e., if a "fast conversion" was possible) [1][2]. If the function returns false, the quantity cannot be represented as a simple int64, and the caller must instead use the inf.Dec form (via AsDec) to handle the value [1][5]. Example: val, ok:= q.AsInt64 [2]

Citations:


🌐 Web query:

"resource.ParseQuantity" "strconv.ParseFloat" "MilliValue" verticalpodautoscaler kube-state-metrics

💡 Result:

The terms provided are related to how Kubernetes handles resource quantities and how metrics for resources like Vertical Pod Autoscalers (VPA) are processed. resource.ParseQuantity and MilliValue resource.ParseQuantity is a function in the Kubernetes apimachinery library used to convert strings (e.g., "500m", "2Gi") into a Quantity object, which is a fixed-point representation of a number [1][2][3]. Because Kubernetes avoids floating-point numbers to ensure precision, ParseQuantity handles parsing logic to maintain this fixed-point state [3]. MilliValue is a method on the Quantity object that returns the value in milli-units (e.g., millicores or millibytes) as an int64 [1][2][4]. It essentially computes ceil(q * 1000) [1][5]. Because this calculation can overflow an int64 for very large quantities, the official documentation and source code warn that callers should verify the number is small enough—typically by checking against MaxMilliValue or using Value—before calling MilliValue [2][5]. strconv.ParseFloat While Kubernetes primarily avoids floating-point math for its internal resource representation to ensure deterministic behavior, strconv.ParseFloat may be used in peripheral tooling, logging, or specific metric calculations where values are converted to standard IEEE 754 floating-point numbers for display or intermediate analysis. However, it is not used for core Quantity operations within the apimachinery library [3]. verticalpodautoscaler and kube-state-metrics In earlier versions of kube-state-metrics, Vertical Pod Autoscalers (VPA) were supported as built-in resources. However, as of version 2.7.0, built-in support for VPA was removed [6][7]. Users are now encouraged to use the Custom Resource State (CRS) configuration feature to generate metrics for VPAs [8][6][7]. This involves configuring kube-state-metrics to monitor the VPA custom resource and extract specific fields (like recommendations or bounds) into Prometheus metrics [8][9]. If you are working with these metrics, ensure your configurations correctly resolve the paths to VPA status fields to avoid errors, such as nil-pointer dereferences when fields are missing [10].

Citations:


🌐 Web query:

kubernetes/kube-state-metrics pkg/customresourcestate/registry_factory.go 751 761 strconv.ParseFloat resource mustParseQuantity

💡 Result:

In the context of the kube-state-metrics codebase, specifically within the pkg/customresourcestate/registry_factory.go file, the functions strconv.ParseFloat and mustParseQuantity are utilized for converting raw data retrieved from Custom Resource (CR) fields into numeric formats suitable for metric values [1][2]. These conversions typically occur during the generation of metrics, such as Gauges, where the values extracted from the Kubernetes API object via defined paths need to be cast to types compatible with the Prometheus metric format [1][2]. Specifically: 1. strconv.ParseFloat: This Go standard library function is used to parse string representations of floating-point numbers into float64 values [1]. 2. mustParseQuantity: This is a function from the Kubernetes apimachinery resource package (k8s.io/apimachinery/pkg/api/resource) [3]. It is used to parse Kubernetes Quantity objects—which can represent complex values like memory (e.g., 5Gi) or CPU (e.g., 500m)—into their underlying numeric representation [3][4]. The mustParse variant typically panics if the input string is invalid, making it suitable for scenarios where input validity is guaranteed by configuration or prior checks [3]. The code around lines 750-760 in various versions of registry_factory.go has historically been the site of logic for handling these conversions, as well as managing edge cases where paths might not exist or values might be nil [1][2]. If these conversion functions encounter unexpected types or nil values resulting from a failed path traversal, it can lead to errors or, in older/buggy implementations, application panics [1][2]. Current development practices in the project emphasize checking for path existence and handling nil values gracefully before attempting these conversions to prevent such crashes [1][2].

Citations:


🌐 Web query:

Kubernetes Quantity DecimalSI BinarySI 100m 250m FloatValue

💡 Result:

In Kubernetes, a Quantity is a fixed-point representation of a number used primarily for resource requests and limits [1]. It is designed to avoid the inaccuracies inherent in floating-point arithmetic [1]. Technical details regarding Quantities include: Internal Representation Quantities are never internally represented by floating-point numbers [1]. They use a fixed-point system that maintains precision [1]. While methods exist to convert a Quantity to a float64 (such as AsApproximateFloat64 or AsFloat64Slow), these are provided for external consumption and may involve a trade-off between performance and precision [2][3]. Suffix Formats When a Quantity is parsed, it remembers its suffix format and will use that same format when serialized [1]. There are three primary suffix formats: 1. DecimalSI: Uses powers of 10 (e.g., m, k, M, G, T, P, E), where 1k = 1000 [4][1]. 2. BinarySI: Uses powers of 2 (e.g., Ki, Mi, Gi, Ti, Pi, Ei), where 1Ki = 1024 [4][1]. 3. DecimalExponent: Uses scientific notation with the 'e' or 'E' suffix (e.g., 12e6) [5][1]. Examples - 100m: Represents 100 milli-units (e.g., 0.1 of a core) using DecimalSI [4]. - 250m: Represents 250 milli-units (e.g., 0.25 of a core) using DecimalSI [4]. Constraint Notes No quantity can represent a number greater than 2^63-1 in magnitude, nor can it have more than 3 decimal places [4][1]. Values exceeding these constraints are typically rounded or capped [4][1]. When serializing, Kubernetes will put the value into a "canonical form" that eliminates fractional digits where possible and uses the largest possible exponent or suffix [1]. If a BinarySI quantity represents a small value (between -1 and +1), it may be serialized as DecimalSI to avoid rounding issues [6].

Citations:


🌐 Web query:

kubernetes/kubernetes pkg/apimachinery/api/resource/quantity.go FormatAsFloat AsApproximateFloat64

💡 Result:

In Kubernetes, the k8s.io/apimachinery/pkg/api/resource package provides the Quantity type, which is used for fixed-point representation of numbers (like CPU and memory limits/requests) [1][2]. The Quantity struct provides two primary methods for retrieving its value as a float64: 1. AsApproximateFloat64: This method returns an approximate float64 representation of the quantity [3][4]. It is optimized for performance, though it may lose precision [3][4]. If the quantity's value exceeds the range of a float64, it returns +Inf or -Inf [3][4]. Internally, it calculates the value using the quantity's base and exponent, using math.Pow10 to adjust the magnitude [3][4]. 2. AsFloat64Slow: This method provides a more precise float64 representation of the quantity but is significantly slower than AsApproximateFloat64() [3][4]. It is recommended when precision is more important than performance [3]. The FormatAsFloat function does not exist as a standard method on the Quantity struct in the k8s.io/apimachinery package; it is likely you are referring to AsApproximateFloat64(). Historical Note: A known issue (Issue #103748) previously caused AsApproximateFloat64() to return incorrect, very small values when used with quantities employing BinarySI formatting (e.g., "2.5Gi") [5]. This was resolved in PR #103751, ensuring that the approximate float calculation correctly handles binary-scaled quantities [6].

Citations:


Remove the unresolved quantity-conversion caveat.

The supported conversion is described below for strings that parse as quantities. If there are no known CRS vs. old VPA converter value differences for supported VPA quantities, state that explicitly here so users can trust the migration values.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/metrics/extend/customresourcestate-metrics.md` around lines 345 - 346,
Update the quantity-parsing note near the CRS metrics conversion documentation
to remove the unresolved edge-case caveat. State explicitly that supported VPA
quantity strings have no known CRS-versus-old-collector conversion differences,
while retaining the existing supported conversion description.

Comment on lines +354 to +366
##### RBAC

kube-state-metrics needs permission to list and watch VerticalPodAutoscalers.
When CRS is enabled, list/watch on CustomResourceDefinitions is also commonly required
(the upstream Helm chart adds these when custom resource state is enabled):

```yaml
# Using --resource=verticalpodautoscalers, we get the following output:
# HELP kube_verticalpodautoscaler_annotations Kubernetes annotations converted to Prometheus labels.
# TYPE kube_verticalpodautoscaler_annotations gauge
# kube_verticalpodautoscaler_annotations{namespace="default",verticalpodautoscaler="hamster-vpa",target_api_version="apps/v1",target_kind="Deployment",target_name="hamster"} 1
# A similar result can be achieved by specifying the following in --custom-resource-state-config:
kind: CustomResourceStateMetrics
spec:
resources:
- groupVersionKind:
group: autoscaling.k8s.io
kind: "VerticalPodAutoscaler"
version: "v1"
labelsFromPath:
verticalpodautoscaler: [metadata, name]
namespace: [metadata, namespace]
target_api_version: [apiVersion]
target_kind: [spec, targetRef, kind]
target_name: [spec, targetRef, name]
metrics:
- name: "annotations"
help: "Kubernetes annotations converted to Prometheus labels."
each:
type: Gauge
gauge:
path: [metadata, annotations]
# This will output the following metric:
# HELP kube_customresource_autoscaling_annotations Kubernetes annotations converted to Prometheus labels.
# TYPE kube_customresource_autoscaling_annotations gauge
# kube_customresource_autoscaling_annotations{customresource_group="autoscaling.k8s.io", customresource_kind="VerticalPodAutoscaler", customresource_version="v1", namespace="default",target_api_version="autoscaling.k8s.io/v1",target_kind="Deployment",target_name="hamster",verticalpodautoscaler="hamster-vpa"} 123
- apiGroups: ["autoscaling.k8s.io"]
resources: ["verticalpodautoscalers"]
verbs: ["list", "watch"]
- apiGroups: ["apiextensions.k8s.io"]
resources: ["customresourcedefinitions"]
verbs: ["list", "watch"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Make CRD RBAC conditional on wildcard GVK discovery.

This configuration pins the GVK to autoscaling.k8s.io/v1/VerticalPodAutoscaler, so its ListWatch targets the VPA resource directly. CRD list/watch access is needed for wildcard version/kind discovery, not this fixed-GVK example; including it in the default copy-paste RBAC grants unnecessary cluster-wide read access. Keep VPA permissions required here and move the CRD rule into a note for wildcard configurations. (raw.githubusercontent.com)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/metrics/extend/customresourcestate-metrics.md` around lines 354 - 366,
Update the RBAC example in the custom resource state documentation to retain
only the required VerticalPodAutoscaler list/watch rule for the fixed GVK
configuration. Remove the CustomResourceDefinitions rule from the copy-paste
YAML and add it to an explanatory note stating that CRD list/watch permissions
are needed only when wildcard GVK discovery is configured.

Replace the annotations-only VerticalPodAutoscaler example with a
migration-focused guide: RBAC, known differences from the pre-v2.9
collector, a complete CustomResourceStateMetrics config covering the
former built-in metrics, a name mapping table, and sample series.

Signed-off-by: Dean Chen <862469039@qq.com>
@locker95
locker95 force-pushed the docs/vpa-crm-replacement-config branch from e9ee50b to b6d06b7 Compare July 27, 2026 18:26
@kubernetes-prow kubernetes-prow Bot removed the do-not-merge/invalid-commit-message Indicates that a PR should not merge because it has an invalid commit message. label Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

Status: Needs Triage

Development

Successfully merging this pull request may close these issues.

Missing replacement config for VPA collector in CRM

1 participant