kube-state-metrics

GitHub

Add-on agent to generate and expose cluster-level metrics.

RAW Doc

README

Documentation

This documentation is intended to be a complete reflection of the current state of the exposed metrics of kube-state-metrics.

Any contribution to improving this documentation or adding sample usages will be appreciated.

Table of Contents

* Metrics Stages
* Exposed Metrics
* PromQL Queries
* Join Metrics
* CLI arguments

Metrics Stages

Stages about metrics are grouped into three categories:

| Stage | Description |
| ------------ | -------------------------------------------------------------------------------------------------------------------------- |
| EXPERIMENTAL | Metrics which normally correspond to the Kubernetes API object alpha status or spec fields and can be changed at any time. |
| STABLE | Metrics which should have very few backwards-incompatible changes outside of major version updates. |
| DEPRECATED | Metrics which will be removed once the deprecation timeline is met. |

Opt-in Metrics

As of v2.3.0, kube-state-metrics supports additional opt-in metrics via the CLI flag --metric-opt-in-list. See the metric documentation to identify which metrics need to be specified.

Exposed Metrics

Per group of metrics there is one file for each metrics.
See each file for specific documentation about the exposed metrics:

Default Resources

* CertificateSigningRequest Metrics
* ConfigMap Metrics
* CronJob Metrics
* DaemonSet Metrics
* Deployment Metrics
* Endpoint Metrics
* Horizontal Pod Autoscaler Metrics
* Ingress Metrics
* Job Metrics
* Lease Metrics
* LimitRange Metrics
* MutatingAdmissionPolicy Metrics
* MutatingAdmissionPolicyBinding Metrics
* MutatingWebhookConfiguration Metrics
* Namespace Metrics
* NetworkPolicy Metrics
* Node Metrics
* PersistentVolume Metrics
* PersistentVolumeClaim Metrics
* Pod Disruption Budget Metrics
* Pod Metrics
* ReplicaSet Metrics
* ReplicationController Metrics
* ResourceQuota Metrics
* Secret Metrics
* Service Metrics
* StatefulSet Metrics
* StorageClass Metrics
* ValidatingAdmissionPolicy Metrics
* ValidatingAdmissionPolicyBinding Metrics
* ValidatingWebhookConfiguration Metrics
* VolumeAttachment Metrics

Optional Resources

* ClusterRole Metrics
* ClusterRoleBinding Metrics
* EndpointSlice Metrics
* IngressClass Metrics
* Role Metrics
* RoleBinding Metrics
* ServiceAccount Metrics

PromQL Queries

For practical PromQL query examples and alerting rules:

* StatefulSet Queries & Alerts

Join Metrics

When an additional, not provided by default label is needed, a Prometheus matching operator
can be used to extend single metrics output.

This example adds label_release to the set of default labels of the kube_pod_status_ready metric
and allows you select or group the metrics by Helm release label:

promql
kube_pod_status_ready * on (namespace, pod) group_left(label_release) kube_pod_labels

Another useful example would be to query the memory usage of pods by its phase, such as Running:

promql
sum(kube_pod_container_resource_requests{resource="memory"}) by (namespace, pod, node)
* on (namespace, pod) group_left() (sum(kube_pod_status_phase{phase="Running"}) by (pod, namespace) == 1)

Metrics from Custom Resources

NOTE

custom-resource-state is feature-frozen in favor of resource-state-metrics. Once resource-state-metrics is stable, custom-resource-state will be deprecated.

See Custom Resource State Metrics for experimental support for custom resources.

CLI Arguments

Additionally, options for kube-state-metrics can be passed when executing as a CLI, or in a kubernetes / openshift environment. More information can be found here: CLI Arguments

Protecting /metrics endpoints

Kube-State-Metrics' metrics can contain sensitive information about the state of the cluster, which you as an operator might want to additionally protect from unauthorized access.
In order to achieve this, you need to enable the --auth-filter flag on kube-state-metrics.
With this, kube-state-metrics will only accept authenticated and authorized requests to the /metrics endpoints.
Kube-state-metrics uses Kubernetes' RBAC mechanisms for this, so this means that every scrape will trigger a request against the API Server for TokenReview and SubjectAccessReview.
The clients scraping the endpoint, need to use a token which can be provided by a ServiceAccount that can be set up the following way:

A ClusterRole providing access like this:

yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: metrics-reader
rules:
- nonResourceURLs:
- "/metrics"
verbs:
- get

and a matching ClusterRoleBinding

yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: metrics-reader-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: metrics-reader
subjects:
- kind: ServiceAccount
name: YOUR_SERVICE_ACCOUNT
namespace: NAMESPACE_OF_THE_SERVICE_ACCOUNT

Your client can then use either this ServiceAccount to gather metrics or you can create a token, that can be used to fetch data like this:

bash
TOKEN=$(kubectl create token YOUR_SERVICE_ACCOUNT -n NAMESPACE_OF_THE_SERVICE_ACCOUNT)
curl -H "Authorization: Bearer $TOKEN" KUBE_STATE_METRICS_URL:8080/metrics

---

Design/Metrics Best Practices

Kube-State-Metrics - Timeseries best practices

---

Author: Manuel RΓΌger (<[email protected]>)

Date: October 17th 2024

---

Introduction

Kube-State-Metrics' goal is to provide insights into the state of Kubernetes objects by exposing them as metrics.
This document provides guidelines with the goal to create a good user experience when using these metrics.

Please be aware that this document is introduced in a later stage of the project and there might be metrics that do not follow these best practices.
Feel encouraged to report these metrics and provide a pull request to improve them.

General best practices

We follow Prometheus best practices in terms of naming and labeling.

Best practices for kube-state-metrics

Avoid pre-computation

kube-state-metrics should expose metrics on an individual object level and avoid any sort of pre-computation unless it is required due to for example high cardinality on objects.
We prefer not to add metrics that can be derived from existing raw metrics. For example, we would not want to expose a metric called kube_pod_total as it can be computed with count(kube_pod_info).
This way kube-state-metrics allows the user to have full control on how they want to use the metrics and gives them flexibility to do specific computation.

Static object properties

An object usually has a stable set of properties that do not change during its lifecycle in Kubernetes.
This includes properties like name, namespace, uid etc. that have a 1:1 relationship with the object.
It is a good practice to group those together into an _info metric.
If there is a 1:n relationship (e.g. a list of ports), it should be in a separate metric to avoid generating too many metrics.

Dynamic object properties

An object can also have a dynamic set of properties, which are usually part of the status field.
These change during the lifecycle of the object.
For example a pod can be in different states like "Pending", "Running" etc.
These should be part of a "State Set" that includes labels that identify the object as well as the dynamic property.

Linked properties

If an object contains a substructure that links multiple properties together (e.g. endpoint address and port), those should be reported in the same metric.

Optional properties

Some Kubernetes objects have optional fields. In case there is an optional value, the label should still be exposed, ideally as an empty string.

Timestamps

Timestamps like creation time or modification time should be exposed as a value. The metric should end with _timestamp_seconds. The date value is represented in UNIX epoch seconds.

Cardinality

Some object properties can cause cardinality issues if they can contain a lot of different values or are linked together with multiple properties that also can change a lot.
In this case it is better to limit the number of values that can be exposed within kube-state-metrics by allowing only a few of them and have a default for others.
If for example the Kubernetes object contains a status field that contains an error message that can change a lot, it would be better to have a boolean error="true" label in case there is an error.
If there are some error messages that are worth exposing, those could be exposed and for any other message, a default value could be provided.

Stability

We follow the stability framework derived from Kubernetes, in which we expose experimental and stable metrics.
Experimental metrics are recently introduced or expose alpha/beta resources in the Kubernetes API.
They can change anytime and should be used with caution.
They can be promoted to a stable metric once the object stabilized in the Kubernetes API or they were part of two consecutive releases and haven't observed any changes in them.

Stable metrics are considered frozen with the exception of new labels being added.
A stable metric or a label on a stable metric can be deprecated in release Major.Minor and the earliest point it will be removed is the release Major.Minor+2.

---

Design/Metrics Store Performance Optimization

Kube-State-Metrics - Performance Optimization Proposal

---

Author: Max Inden (<[email protected]>)

Date: 23. July 2018

Target release: v1.5.0

---

Glossary

* kube-state-metrics: β€œSimple service that listens to the Kubernetes API server
and generates metrics about the state of the objects”

* Time series: A single line in a /metrics response e.g.
β€œmetric_name{label="value"} 1”

Problem Statement

There has been repeated reports of two issues running kube-state-metrics on
production Kubernetes clusters. First kube-state-metrics takes a long time
(β€œ10s - 20s”) to respond on its /metrics endpoint, leading to Prometheus
instances dropping the scrape interval request and marking the given time series
as stale. Second kube-state-metrics uses a lot of memory and thereby being
out-of-memory killed due to low set Kubernetes resource limits.

Goal

The goal of this proposal can be split into the following sub-goals ordered by
their priority:

1. Decrease response time on /metrics endpoint

2. Decrease overall runtime memory usage

Status Quo

Instead of requesting the needed information from the Kubernetes API-Server on
demand (on scrape), kube-state-metrics uses the Kubernetes client-go cache tool
to keep a full in memory representation of all Kubernetes objects of a given
cluster. Using the cache speeds up the performance critical path of replying to
a scrape request, and reduces the load on the Kubernetes API-Server by only
sending deltas whenever they occur. Kube-state-metrics does not make use of all
properties and sub-objects of these Kubernetes objects that it stores in its
cache.

On a scrape request by e.g. Prometheus on the /metrics endpoint
kube-state-metrics calculates the configured time series on demand based on the
objects in its cache and converts them to the Prometheus string representation.

Proposal

Instead of a full representation of all Kubernetes objects with all its
properties in memory via the Kubernetes client-go cache, use a map, addressable
by the Kubernetes object uuid, containing all time series of that object as a
single multi-line string.

go
var cache = map[uuid][]byte{}

Kube-state-metrics listens on add, update and delete events via Kubernetes
client-go reflectors. On add and update events kube-state-metrics generates all
time series related to the Kubernetes object based on the event’s payload,
concatenates the time series to a single byte slice and sets / replaces the byte
slice in the store at the uuid of the Kubernetes object. One can precompute the
length of a time series byte slice before allocation as the sum of the length of
the metric name, label keys and values as well as the metric value in string
representation. On delete events kube-state-metrics deletes the uuid entry of
the given Kubernetes object in the cache map.

On a scrape request on the /metrics endpoint, kube-state-metrics iterates over
the cache map and concatenates all time series string blobs into a single
string, which is finally passed on as a response.

text
/ Detailed source-code truncated for AI context efficiency. /

<details>
<summary>Code to reproduce diagram</summary>

Build via text-diagram

text
object pod_reflector pod_store pod_collector metrics_endpoint

note left of pod_reflector: new pod p1
pod_reflector -> pod_store: Add(p1)
note right of pod_store: generateMetrics(p1)
pod_store -> pod_reflector: nil

note right of metrics_endpoint: GET /metrics
metrics_endpoint -> pod_collector: Collect()
pod_collector -> pod_store: GetAll()
pod_store -> pod_collector: []string{metrics}
pod_collector -> metrics_endpoint: concat(metrics)

</details>

FAQ / Follow up improvements

* If kube-state-metrics only listens on add, update and delete events, how is it
aware of already existing Kubernetes objects created before kube-state-metrics
was started? Leveraging Kubernetes client-go, reflectors can initialize all
existing objects before any add, update or delete events. To ensure no events
are missed in the long run, periodic resyncs via Kubernetes client-go can be
triggered. This extra confidence is not a must and should be compared to its
costs, as Kubernetes client-go already gives decent guarantees on event
delivery.

* What about metadata (HELP and description) in the /metrics output? As a first
iteration they would be skipped until we have a better idea on the design.

* How can the cache map be concurrently accessed? The core golang map
implementation is not thread-safe. As a first iteration a simple mutex should
be sufficient. Golang's sync.Map might be considered.

* To solve the problem of out of order events send by the Kubernetes API-Server
to kube-state-metrics, to each blob of time series inside the cache map it can
keep the Kubernetes resource version. On add and update events, first compare
the resource version of the event with than the resource version in the cache.
Only move forward if the former is higher than the latter.

* In case the memory consumption of the time series string blobs is a problem
the following optimization can be considered: Among the time series strings,
multiple sub-strings will be heavily duplicated like the metric name. Instead
of saving unstructured strings inside the cache map, one can structure them,
using pointers to deduplicate e.g. metric names.

* Kube-state-metrics does not make use of all properties of all Kubernetes
objects. Instead of unmarshalling unused properties, their json struct tags or
their Protobuf representation could be removed.

---

Developer/Cli Arguments

Command line arguments

kube-state-metrics can be configured through command line arguments.

Those arguments can be passed during startup when running locally:

kube-state-metrics --telemetry-port=8081 --kubeconfig=<KUBE-CONFIG> --apiserver=<APISERVER> ...

Or configured in the args section of your deployment configuration in a Kubernetes / Openshift context:

yaml
spec:
template:
spec:
containers:
- args:
- '--telemetry-port=8081'
- '--kubeconfig=<KUBE-CONFIG>'
- '--apiserver=<APISERVER>'

Available options

text
/ Detailed source-code truncated for AI context efficiency. /

---

Developer/Guide

Developer Guide

This developer guide documentation is intended to assist all contributors in various code contributions.
Any contribution to improving this documentation will be appreciated.

Table of Contents

* Add New Kubernetes Resource Metric Collector
* Add New Metrics

Add New Kubernetes Resource Metric Collector

The following steps are needed to introduce a new resource and its respective resource metrics.

* Reference your new resource(s) to the docs/README.md.
* Reference your new resource(s) in the docs/developer/cli-arguments.md as part of the --resources flag.
* Create a new <name-of-resource>.md in the docs directory to provide documentation on the resource(s) and metrics you implemented. Follow the formatting of all other resources.
* Add the resource(s) you are representing to the jsonnet/kube-state-metrics/kube-state-metrics.libsonnet under the appropriate apiGroup using the verbs: list and watch.
* Run make examples/standard, this should re-generate examples/standard/cluster-role.yaml with the resource(s) added to jsonnet/kube-state-metrics/kube-state-metrics.libsonnet.
* Reference and add build functions for the new resource(s) in internal/store/builder.go.
* Reference the new resource in pkg/options/resource.go.
* Add a sample Kubernetes manifest to be used by tests in the tests/manifests/ directory.
* Lastly, and most importantly, actually implement your new resource(s) and its test binary in internal/store. Follow the formatting and structure of other resources.

Add New Metrics

* Make metrics experimental first when introducing them, refer #1910 for more information.

| Metric stability level | |
|------------------------|--------------------|
| EXPERIMENTAL | basemetrics.ALPHA |
| STABLE | basemetrics.STABLE |

---

Metrics/Workload/Cronjob Metrics

CronJob Metrics

| Metric name | Metric type | Description | Labels/tags | Status |
| ---------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| kube_cronjob_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via --metric-annotations-allowlist | cronjob=&lt;cronjob-name&gt; <br> namespace=&lt;cronjob-namespace&gt; <br> annotation_CRONJOB_ANNOTATION=&lt;CRONJOB_ANNOTATION&gt; | EXPERIMENTAL |
| kube_cronjob_info | Gauge | | cronjob=&lt;cronjob-name&gt; <br> namespace=&lt;cronjob-namespace&gt; <br> schedule=&lt;schedule&gt; <br> concurrency_policy=&lt;concurrency-policy&gt; <br> timezone=&lt;timezone&gt; | STABLE |
| kube_cronjob_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | cronjob=&lt;cronjob-name&gt; <br> namespace=&lt;cronjob-namespace&gt; <br> label_CRONJOB_LABEL=&lt;CRONJOB_LABEL&gt; | STABLE |
| kube_cronjob_created | Gauge | | cronjob=&lt;cronjob-name&gt; <br> namespace=&lt;cronjob-namespace&gt; | STABLE |
| kube_cronjob_next_schedule_time | Gauge | | cronjob=&lt;cronjob-name&gt; <br> namespace=&lt;cronjob-namespace&gt; | STABLE |
| kube_cronjob_schedule_invalid | Gauge | | cronjob=&lt;cronjob-name&gt; <br> namespace=&lt;cronjob-namespace&gt; | EXPERIMENTAL |
| kube_cronjob_status_active | Gauge | | cronjob=&lt;cronjob-name&gt; <br> namespace=&lt;cronjob-namespace&gt; | STABLE |
| kube_cronjob_status_last_schedule_time | Gauge | | cronjob=&lt;cronjob-name&gt; <br> namespace=&lt;cronjob-namespace&gt; | STABLE |
| kube_cronjob_status_last_successful_time | Gauge | | cronjob=&lt;cronjob-name&gt; <br> namespace=&lt;cronjob-namespace&gt; | STABLE |
| kube_cronjob_spec_suspend | Gauge | | cronjob=&lt;cronjob-name&gt; <br> namespace=&lt;cronjob-namespace&gt; | STABLE |
| kube_cronjob_spec_starting_deadline_seconds | Gauge | | cronjob=&lt;cronjob-name&gt; <br> namespace=&lt;cronjob-namespace&gt; | STABLE |
| kube_cronjob_metadata_resource_version | Gauge | | cronjob=&lt;cronjob-name&gt; <br> namespace=&lt;cronjob-namespace&gt; | STABLE |
| kube_cronjob_spec_successful_job_history_limit | Gauge | | cronjob=&lt;cronjob-name&gt; <br> namespace=&lt;cronjob-namespace&gt; | EXPERIMENTAL |
| kube_cronjob_spec_failed_job_history_limit | Gauge | | cronjob=&lt;cronjob-name&gt; <br> namespace=&lt;cronjob-namespace&gt; | EXPERIMENTAL |

---

Metrics/Workload/Daemonset Metrics

DaemonSet Metrics

| Metric name | Metric type | Description | Labels/tags | Status |
| ---------------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| kube_daemonset_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via --metric-annotations-allowlist | daemonset=&lt;daemonset-name&gt; <br> namespace=&lt;daemonset-namespace&gt; <br> annotation_DAEMONSET_ANNOTATION=&lt;DAEMONSET_ANNOTATION&gt; | EXPERIMENTAL |
| kube_daemonset_created | Gauge | | daemonset=&lt;daemonset-name&gt; <br> namespace=&lt;daemonset-namespace&gt; | STABLE |
| kube_daemonset_status_current_number_scheduled | Gauge | | daemonset=&lt;daemonset-name&gt; <br> namespace=&lt;daemonset-namespace&gt; | STABLE |
| kube_daemonset_status_desired_number_scheduled | Gauge | | daemonset=&lt;daemonset-name&gt; <br> namespace=&lt;daemonset-namespace&gt; | STABLE |
| kube_daemonset_status_number_available | Gauge | | daemonset=&lt;daemonset-name&gt; <br> namespace=&lt;daemonset-namespace&gt; | STABLE |
| kube_daemonset_status_number_misscheduled | Gauge | | daemonset=&lt;daemonset-name&gt; <br> namespace=&lt;daemonset-namespace&gt; | STABLE |
| kube_daemonset_status_number_ready | Gauge | | daemonset=&lt;daemonset-name&gt; <br> namespace=&lt;daemonset-namespace&gt; | STABLE |
| kube_daemonset_status_number_unavailable | Gauge | | daemonset=&lt;daemonset-name&gt; <br> namespace=&lt;daemonset-namespace&gt; | STABLE |
| kube_daemonset_status_observed_generation | Gauge | | daemonset=&lt;daemonset-name&gt; <br> namespace=&lt;daemonset-namespace&gt; | STABLE |
| kube_daemonset_status_updated_number_scheduled | Gauge | | daemonset=&lt;daemonset-name&gt; <br> namespace=&lt;daemonset-namespace&gt; | STABLE |
| kube_daemonset_metadata_generation | Gauge | | daemonset=&lt;daemonset-name&gt; <br> namespace=&lt;daemonset-namespace&gt; | STABLE |
| kube_daemonset_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | daemonset=&lt;daemonset-name&gt; <br> namespace=&lt;daemonset-namespace&gt; <br> label_DAEMONSET_LABEL=&lt;DAEMONSET_LABEL&gt; | STABLE |
| kube_daemonset_deletion_timestamp | Gauge | Unix deletion timestamp | daemonset=&lt;daemonset-name&gt; <br> namespace=&lt;daemonset-namespace&gt; | EXPERIMENTAL |

---

Metrics/Workload/Deployment Metrics

Deployment Metrics

| Metric name | Metric type | Description | Labels/tags | Status |
| ----------------------------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| kube_deployment_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via --metric-annotations-allowlist | deployment=&lt;deployment-name&gt; <br> namespace=&lt;deployment-namespace&gt; <br> annotation_DEPLOYMENT_ANNOTATION=&lt;DEPLOYMENT_ANNOTATION&gt; | EXPERIMENTAL |
| kube_deployment_status_replicas | Gauge | The number of replicas per deployment. | deployment=&lt;deployment-name&gt; <br> namespace=&lt;deployment-namespace&gt; | STABLE |
| kube_deployment_status_replicas_ready | Gauge | The number of ready replicas per deployment. | deployment=&lt;deployment-name&gt; <br> namespace=&lt;deployment-namespace&gt; | STABLE |
| kube_deployment_status_replicas_available | Gauge | The number of available replicas per deployment. | deployment=&lt;deployment-name&gt; <br> namespace=&lt;deployment-namespace&gt; | STABLE |
| kube_deployment_status_replicas_unavailable | Gauge | The number of unavailable replicas per deployment. | deployment=&lt;deployment-name&gt; <br> namespace=&lt;deployment-namespace&gt; | STABLE |
| kube_deployment_status_replicas_updated | Gauge | The number of updated replicas per deployment. | deployment=&lt;deployment-name&gt; <br> namespace=&lt;deployment-namespace&gt; | STABLE |
| kube_deployment_status_terminating_replicas | Gauge | The number of terminating replicas per deployment. | deployment=&lt;deployment-name&gt; <br> namespace=&lt;deployment-namespace&gt; | ALPHA |
| kube_deployment_status_observed_generation | Gauge | The generation observed by the deployment controller. | deployment=&lt;deployment-name&gt; <br> namespace=&lt;deployment-namespace&gt; | STABLE |
| kube_deployment_status_condition | Gauge | The current status conditions of a deployment. | deployment=&lt;deployment-name&gt; <br> namespace=&lt;deployment-namespace&gt; <br> reason=&lt;deployment-transition-reason&gt; <br> condition=&lt;deployment-condition&gt; <br> status=&lt;true\|false\|unknown&gt; | STABLE |
| kube_deployment_spec_replicas | Gauge | Number of desired pods for a deployment. | deployment=&lt;deployment-name&gt; <br> namespace=&lt;deployment-namespace&gt; | STABLE |
| kube_deployment_spec_paused | Gauge | Whether the deployment is paused and will not be processed by the deployment controller. | deployment=&lt;deployment-name&gt; <br> namespace=&lt;deployment-namespace&gt; | STABLE |
| kube_deployment_spec_strategy_rollingupdate_max_unavailable | Gauge | Maximum number of unavailable replicas during a rolling update of a deployment. | deployment=&lt;deployment-name&gt; <br> namespace=&lt;deployment-namespace&gt; | STABLE |
| kube_deployment_spec_strategy_rollingupdate_max_surge | Gauge | Maximum number of replicas that can be scheduled above the desired number of replicas during a rolling update of a deployment. | deployment=&lt;deployment-name&gt; <br> namespace=&lt;deployment-namespace&gt; | STABLE |
| kube_deployment_metadata_generation | Gauge | Sequence number representing a specific generation of the desired state. | deployment=&lt;deployment-name&gt; <br> namespace=&lt;deployment-namespace&gt; | STABLE |
| kube_deployment_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | deployment=&lt;deployment-name&gt; <br> namespace=&lt;deployment-namespace&gt; <br> label_DEPLOYMENT_LABEL=&lt;DEPLOYMENT_LABEL&gt; | STABLE |
| kube_deployment_created | Gauge | Unix creation timestamp | deployment=&lt;deployment-name&gt; <br> namespace=&lt;deployment-namespace&gt; | STABLE |
| kube_deployment_deletion_timestamp | Gauge | Unix deletion timestamp | deployment=&lt;deployment-name&gt; <br> namespace=&lt;deployment-namespace&gt; | EXPIREMENTAL |
| kube_deployment_owner | Gauge | Information about the Deployment's owner. | deployment=&lt;deployment-name&gt; <br> namespace=&lt;deployment-namespace&gt; <br> owner_kind=&lt;owner-kind&gt; <br> owner_name=&lt;owner-name&gt; | ALPHA |

---

Metrics/Workload/Horizontalpodautoscaler Metrics

Horizontal Pod Autoscaler Metrics

| Metric name | Metric type | Description | Labels/tags | Status |
| ---------------------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| kube_horizontalpodautoscaler_info | Gauge | | horizontalpodautoscaler=&lt;hpa-name&gt; <br> namespace=&lt;hpa-namespace&gt; <br> scaletargetref_api_version=&lt;hpa-target-api-version&gt; <br> scaletargetref_kind=&lt;hpa-target-kind&gt; <br> scaletargetref_name=&lt;hpa-target-name&gt; | EXPERIMENTAL |
| kube_horizontalpodautoscaler_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via --metric-annotations-allowlist | horizontalpodautoscaler=&lt;hpa-name&gt; <br> namespace=&lt;hpa-namespace&gt; | EXPERIMENTAL |
| kube_horizontalpodautoscaler_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | horizontalpodautoscaler=&lt;hpa-name&gt; <br> namespace=&lt;hpa-namespace&gt; | STABLE |
| kube_horizontalpodautoscaler_metadata_generation | Gauge | | horizontalpodautoscaler=&lt;hpa-name&gt; <br> namespace=&lt;hpa-namespace&gt; | STABLE |
| kube_horizontalpodautoscaler_spec_max_replicas | Gauge | | horizontalpodautoscaler=&lt;hpa-name&gt; <br> namespace=&lt;hpa-namespace&gt; | STABLE |
| kube_horizontalpodautoscaler_spec_min_replicas | Gauge | | horizontalpodautoscaler=&lt;hpa-name&gt; <br> namespace=&lt;hpa-namespace&gt; | STABLE |
| kube_horizontalpodautoscaler_spec_target_metric | Gauge | | horizontalpodautoscaler=&lt;hpa-name&gt; <br> namespace=&lt;hpa-namespace&gt; <br> metric_name=&lt;metric-name&gt; <br> metric_target_type=&lt;value\|utilization\|average&gt; <br> container=&lt;container-name&gt; | EXPERIMENTAL |
| kube_horizontalpodautoscaler_spec_behavior_scale_down_tolerance | Gauge | The tolerance on the ratio between the current and desired metric value below which no scale down occurs. | horizontalpodautoscaler=&lt;hpa-name&gt; <br> namespace=&lt;hpa-namespace&gt; | EXPERIMENTAL |
| kube_horizontalpodautoscaler_spec_behavior_scale_up_tolerance | Gauge | The tolerance on the ratio between the current and desired metric value below which no scale up occurs. | horizontalpodautoscaler=&lt;hpa-name&gt; <br> namespace=&lt;hpa-namespace&gt; | EXPERIMENTAL |
| kube_horizontalpodautoscaler_status_target_metric | Gauge | | horizontalpodautoscaler=&lt;hpa-name&gt; <br> namespace=&lt;hpa-namespace&gt; <br> metric_name=&lt;metric-name&gt; <br> metric_target_type=&lt;value\|utilization\|average&gt; <br> container=&lt;container-name&gt; | STABLE |
| kube_horizontalpodautoscaler_status_condition | Gauge | | horizontalpodautoscaler=&lt;hpa-name&gt; <br> namespace=&lt;hpa-namespace&gt; <br> condition=&lt;hpa-condition&gt; <br> status=&lt;true\|false\|unknown&gt; | STABLE |
| kube_horizontalpodautoscaler_status_current_replicas | Gauge | | horizontalpodautoscaler=&lt;hpa-name&gt; <br> namespace=&lt;hpa-namespace&gt; | STABLE |
| kube_horizontalpodautoscaler_status_desired_replicas | Gauge | | horizontalpodautoscaler=&lt;hpa-name&gt; <br> namespace=&lt;hpa-namespace&gt; | STABLE |
| kube_horizontalpodautoscaler_created | Gauge | | horizontalpodautoscaler=&lt;hpa-name&gt; <br> namespace=&lt;hpa-namespace&gt; | EXPERIMENTAL |
| kube_horizontalpodautoscaler_deletion_timestamp | Gauge | | horizontalpodautoscaler=&lt;hpa-name&gt; <br> namespace=&lt;hpa-namespace&gt; | EXPERIMENTAL |

---

Metrics/Workload/Job Metrics

Job Metrics

| Metric name | Metric type | Description | Labels/tags | Status |
| ------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| kube_job_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via --metric-annotations-allowlist | job_name=&lt;job-name&gt; <br> namespace=&lt;job-namespace&gt; <br> annotation_JOB_ANNOTATION=&lt;JOB_ANNOTATION&gt; | EXPERIMENTAL |
| kube_job_info | Gauge | | job_name=&lt;job-name&gt; <br> namespace=&lt;job-namespace&gt; | STABLE |
| kube_job_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | job_name=&lt;job-name&gt; <br> namespace=&lt;job-namespace&gt; <br> label_JOB_LABEL=&lt;JOB_LABEL&gt; | STABLE |
| kube_job_owner | Gauge | | job_name=&lt;job-name&gt; <br> namespace=&lt;job-namespace&gt; <br> owner_kind=&lt;owner kind&gt; <br> owner_name=&lt;owner name&gt; <br> owner_is_controller=&lt;whether owner is controller&gt; | STABLE |
| kube_job_spec_parallelism | Gauge | | job_name=&lt;job-name&gt; <br> namespace=&lt;job-namespace&gt; | STABLE |
| kube_job_spec_completions | Gauge | | job_name=&lt;job-name&gt; <br> namespace=&lt;job-namespace&gt; | STABLE |
| kube_job_spec_active_deadline_seconds | Gauge | | job_name=&lt;job-name&gt; <br> namespace=&lt;job-namespace&gt; | STABLE |
| kube_job_status_active | Gauge | | job_name=&lt;job-name&gt; <br> namespace=&lt;job-namespace&gt; | STABLE |
| kube_job_status_succeeded | Gauge | | job_name=&lt;job-name&gt; <br> namespace=&lt;job-namespace&gt; | STABLE |
| kube_job_status_failed | Gauge | | job_name=&lt;job-name&gt; <br> namespace=&lt;job-namespace&gt; <br> reason=&lt;failure reason&gt; | STABLE |
| kube_job_status_start_time | Gauge | | job_name=&lt;job-name&gt; <br> namespace=&lt;job-namespace&gt; | STABLE |
| kube_job_status_completion_time | Gauge | | job_name=&lt;job-name&gt; <br> namespace=&lt;job-namespace&gt; | STABLE |
| kube_job_complete | Gauge | | job_name=&lt;job-name&gt; <br> namespace=&lt;job-namespace&gt; <br> condition=&lt;true\|false\|unknown&gt; | STABLE |
| kube_job_failed | Gauge | | job_name=&lt;job-name&gt; <br> namespace=&lt;job-namespace&gt; <br> condition=&lt;true\|false\|unknown&gt; | STABLE |
| kube_job_created | Gauge | | job_name=&lt;job-name&gt; <br> namespace=&lt;job-namespace&gt; | STABLE |
| kube_job_status_suspended | Gauge | | job_name=&lt;job-name&gt; <br> namespace=&lt;job-namespace&gt; | EXPERIMENTAL |
| kube_job_status_ready | Gauge | The number of ready pods that belong to this Job. | job_name=&lt;job-name&gt; <br> namespace=&lt;job-namespace&gt; | EXPERIMENTAL |

---

Metrics/Workload/Pod Metrics

Pod Metrics

Note: For pod resource requests and limits, kube-scheduler exposes kube_pod_resource_request and kube_pod_resource_limit on its /metrics/resources endpoint. These are computed from the pod's effective resource requirements and already account for pod-level resources (pod.spec.resources, beta and enabled by default since Kubernetes 1.34), so they are recommended over the container-level metrics below. kube-state-metrics does not expose a separate metric for pod-level resources. These metrics are defined in KEP-1748.

| Metric name | Metric type | Description | Unit (where applicable) | Labels/tags | Status | Opt-in |
| ----------------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | ------ |
| kube_pod_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via --metric-annotations-allowlist | | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> annotation_POD_ANNOTATION=&lt;POD_ANNOTATION&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_info | Gauge | Information about pod | | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> host_ip=&lt;host-ip&gt; <br> pod_ip=&lt;pod-ip&gt; <br> node=&lt;node-name&gt;<br> created_by_kind=&lt;created_by_kind&gt;<br> created_by_name=&lt;created_by_name&gt;<br> uid=&lt;pod-uid&gt;<br> priority_class=&lt;priority_class&gt;<br> host_network=&lt;host_network&gt; | STABLE | - |
| kube_pod_ips | Gauge | Pod IP addresses | | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> ip=&lt;pod-ip-address&gt; <br> ip_family=&lt;4 OR 6&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_start_time | Gauge | Start time in unix timestamp for a pod | seconds | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_completion_time | Gauge | Completion time in unix timestamp for a pod | seconds | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_owner | Gauge | Information about the Pod's owner | | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> owner_kind=&lt;owner kind&gt; <br> owner_name=&lt;owner name&gt; <br> owner_is_controller=&lt;whether owner is controller&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> label_POD_LABEL=&lt;POD_LABEL&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_nodeselectors | Gauge | Describes the Pod nodeSelectors | | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> nodeselector_NODE_SELECTOR=&lt;NODE_SELECTOR&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | Opt-in |
| kube_pod_status_phase | Gauge | The pods current phase | | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> phase=&lt;Pending\|Running\|Succeeded\|Failed\|Unknown&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_status_qos_class | Gauge | The pods current qosClass | | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> qos_class=&lt;BestEffort\|Burstable\|Guaranteed&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_status_ready | Gauge | Describes whether the pod is ready to serve requests | | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> condition=&lt;true\|false\|unknown&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_status_scheduled | Gauge | Describes the status of the scheduling process for the pod | | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> condition=&lt;true\|false\|unknown&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_container_info | Gauge | Information about a container in a pod | | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> image=&lt;image-name&gt; <br> image_id=&lt;image-id&gt; <br> image_spec=&lt;image-spec&gt; <br> container_id=&lt;containerid&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_container_status_waiting | Gauge | Describes whether the container is currently in waiting state | | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_container_status_waiting_reason | Gauge | Describes the reason the container is currently in waiting state | | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> reason=&lt;container-waiting-reason&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_container_status_running | Gauge | Describes whether the container is currently in running state | | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_container_state_started | Gauge | Start time in unix timestamp for a pod container | seconds | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_container_status_terminated | Gauge | Describes whether the container is currently in terminated state | | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_container_status_terminated_reason | Gauge | Describes the reason the container is currently in terminated state | | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> reason=&lt;container-terminated-reason&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_container_status_last_terminated_reason | Gauge | Describes the last reason the container was in terminated state | | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> reason=&lt;last-terminated-reason&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_container_status_last_terminated_exitcode | Gauge | Describes the exit code for the last container in terminated state. | | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_container_status_last_terminated_timestamp | Gauge | Last terminated time for a pod container in unix timestamp. | | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_container_status_ready | Gauge | Describes whether the containers readiness check succeeded | | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_status_initialized_time | Gauge | Time when the pod is initialized. | seconds | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_status_ready_time | Gauge | Time when pod passed readiness probes. | seconds | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_status_container_ready_time | Gauge | Time when the container of the pod entered Ready state. | seconds | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_container_status_restarts_total | Counter | The number of container restarts per container | | container=&lt;container-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> pod=&lt;pod-name&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_container_resource_requests | Gauge | The number of requested request resource by a container. It is recommended to use the kube_pod_resource_request metric exposed by kube-scheduler instead, as it is more precise. | cpu=&lt;core&gt; <br> memory=&lt;bytes&gt; | resource=&lt;resource-name&gt; <br> unit=&lt;resource-unit&gt; <br> container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> node=&lt; node-name&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_container_resource_limits | Gauge | The number of requested limit resource by a container. It is recommended to use the kube_pod_resource_limit metric exposed by kube-scheduler instead, as it is more precise. | cpu=&lt;core&gt; <br> memory=&lt;bytes&gt; | resource=&lt;resource-name&gt; <br> unit=&lt;resource-unit&gt; <br> container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> node=&lt; node-name&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_overhead_cpu_cores | Gauge | The pod overhead in regards to cpu cores associated with running a pod | core | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_overhead_memory_bytes | Gauge | The pod overhead in regards to memory associated with running a pod | bytes | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_runtimeclass_name_info | Gauge | The runtimeclass associated with the pod | | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_created | Gauge | Unix creation timestamp | seconds | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_deletion_timestamp | Gauge | Unix deletion timestamp | seconds | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_restart_policy | Gauge | Describes the restart policy in use by this pod | | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> type=&lt;Always\|Never\|OnFailure&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_init_container_info | Gauge | Information about an init container in a pod | | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> image=&lt;image-name&gt; <br> image_id=&lt;image-id&gt; <br> image_spec=&lt;image-spec&gt; <br> container_id=&lt;containerid&gt; <br> uid=&lt;pod-uid&gt; <br> restart_policy=&lt;restart-policy&gt; | STABLE | - |
| kube_pod_init_container_state_started | Gauge | Start time in unix timestamp for a pod init container | seconds | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_init_container_status_waiting | Gauge | Describes whether the init container is currently in waiting state | | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_init_container_status_waiting_reason | Gauge | Describes the reason the init container is currently in waiting state | | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> reason=&lt;container-waiting-reason&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_init_container_status_running | Gauge | Describes whether the init container is currently in running state | | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_init_container_status_terminated | Gauge | Describes whether the init container is currently in terminated state | | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_init_container_status_terminated_reason | Gauge | Describes the reason the init container is currently in terminated state | | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> reason=&lt;container-terminated-reason&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_init_container_status_last_terminated_reason | Gauge | Describes the last reason the init container was in terminated state | | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> reason=&lt;last-terminated-reason&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_init_container_status_last_terminated_exitcode | Gauge | Describes the exit code for the last init container in terminated state. | | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_init_container_status_last_terminated_timestamp | Gauge | Last terminated time for a pod init container in unix timestamp | seconds | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_init_container_status_ready | Gauge | Describes whether the init containers readiness check succeeded | | container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_init_container_status_restarts_total | Counter | The number of restarts for the init container | integer | container=&lt;container-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> pod=&lt;pod-name&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_init_container_resource_limits | Gauge | The number of CPU cores requested limit by an init container | cpu=&lt;core&gt; <br> memory=&lt;bytes&gt; | resource=&lt;resource-name&gt; <br> unit=&lt;resource-unit&gt; <br> container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> node=&lt; node-name&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_init_container_resource_requests | Gauge | The number of CPU cores requested by an init container | cpu=&lt;core&gt; <br> memory=&lt;bytes&gt; | resource=&lt;resource-name&gt; <br> unit=&lt;resource-unit&gt; <br> container=&lt;container-name&gt; <br> pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> node=&lt; node-name&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_spec_volumes_persistentvolumeclaims_info | Gauge | Information about persistentvolumeclaim and ephemeral volumes in a pod. For ephemeral="true", the persistentvolumeclaim label is the generated claim name <pod-name>-<volume-name>; non-ephemeral volumes retain their declared claim name. | | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> volume=&lt;volume-name&gt; <br> persistentvolumeclaim=&lt;persistentvolumeclaim-claimname&gt; <br> ephemeral=&lt;true\|false&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_spec_volumes_persistentvolumeclaims_readonly | Gauge | Describes whether a persistentvolumeclaim is mounted read only. Ephemeral volumes always report 0 since the ephemeral volume source does not support a read-only flag. For ephemeral="true", the persistentvolumeclaim label is the generated claim name <pod-name>-<volume-name>; non-ephemeral volumes retain their declared claim name. | bool | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> volume=&lt;volume-name&gt; <br> persistentvolumeclaim=&lt;persistentvolumeclaim-claimname&gt; <br> ephemeral=&lt;true\|false&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_status_reason | Gauge | The pod status reasons. Emitted only for the reason that is actually set; a missing series does not mean the reason is false. An unrecognized pod.status.reason is reported as Other; conditions and container-terminated reasons outside this list are not reported. | | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> reason=&lt;Evicted\|NodeAffinity\|NodeLost\|PreemptionByScheduler\|SchedulingGated\|Shutdown\|TerminationByKubelet\|UnexpectedAdmissionError\|Other&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_status_disruption_reason | Gauge | The pod disruption condition reason. Emitted only when a DisruptionTarget condition is present; a missing series does not mean the reason is false. An unrecognized reason is reported as Other. kube_pod_status_reason remains available separately and existing queries against it should not be replaced with this metric. | | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> reason=&lt;PreemptionByScheduler\|DeletionByTaintManager\|EvictionByEvictionAPI\|DeletionByPodGC\|TerminationByKubelet\|Other&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_status_scheduled_time | Gauge | Unix timestamp when pod moved into scheduled status | seconds | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_status_unschedulable | Gauge | Describes the unschedulable status for the pod | | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_status_unscheduled_time | Gauge | Unix timestamp when pod moved into unscheduled status | seconds | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_tolerations | Gauge | Information about the pod tolerations | | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; <br> key=&lt;toleration-key&gt; <br> operator=&lt;toleration-operator&gt; <br> value=&lt;toleration-value&gt; <br> effect=&lt;toleration-effect&gt; toleration_seconds=&lt;toleration-seconds&gt; | EXPERIMENTAL | - |
| kube_pod_service_account | Gauge | The service account for a pod | | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; <br> service_account=&lt;service_account&gt; | EXPERIMENTAL | - |
| kube_pod_scheduler | Gauge | The scheduler for a pod | | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; <br> name=&lt;scheduler-name&gt; | EXPERIMENTAL | - |
| kube_pod_resourceclaim_info | Gauge | Information about a DRA ResourceClaim referenced by a pod, one series per pod.spec.resourceClaims entry | | pod=&lt;pod-name&gt; <br> namespace=&lt;pod-namespace&gt; <br> uid=&lt;pod-uid&gt; <br> claim_name=&lt;pod-local-claim-name&gt; <br> resourceclaim_name=&lt;resolved-resourceclaim-name&gt; <br> resourceclaim_template_name=&lt;resourceclaimtemplate-name&gt; | EXPERIMENTAL | - |

Useful metrics queries

How to retrieve non-standard Pod state

It is not straightforward to get the Pod states for certain cases like "Terminating" and "Unknown" since it is not stored behind a field in the Pod.Status.

So to mimic the logic used by the kubectl command line, you will need to compose multiple metrics.

For example:

To get the list of pods that are in the Unknown state, you can run the following PromQL query: sum(kube_pod_status_phase{phase="Unknown"}) by (namespace, pod) or (count(kube_pod_deletion_timestamp) by (namespace, pod) sum(kube_pod_status_reason{reason="NodeLost"}) by(namespace, pod))

* For Pods in Terminating state: count(kube_pod_deletion_timestamp) by (namespace, pod) unless count(kube_pod_status_reason{reason="NodeLost"}) by (namespace, pod)

Here is an example of a Prometheus rule that can be used to alert on a Pod that has been in the Terminating state for more than 5m.

yaml
groups:
- name: Pod state
rules:
- alert: PodsBlockedInTerminatingState
expr: count(kube_pod_deletion_timestamp) by (namespace, pod) unless count(kube_pod_status_reason{reason="NodeLost"}) by (namespace, pod)
for: 5m
labels:
severity: page
annotations:
summary: Pod {{$labels.namespace}}/{{$labels.pod}} blocked in Terminating state.

---

Metrics/Workload/Replicaset Metrics

ReplicaSet metrics

| Metric name | Metric type | Description | Labels/tags | Status |
| --------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| kube_replicaset_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via --metric-annotations-allowlist | replicaset=&lt;replicaset-name&gt; <br> namespace=&lt;replicaset-namespace&gt; <br> annotation_REPLICASET_ANNOTATION=&lt;REPLICASET_ANNOTATION&gt; | EXPERIMENTAL |
| kube_replicaset_status_replicas | Gauge | | replicaset=&lt;replicaset-name&gt; <br> namespace=&lt;replicaset-namespace&gt; | STABLE |
| kube_replicaset_status_fully_labeled_replicas | Gauge | | replicaset=&lt;replicaset-name&gt; <br> namespace=&lt;replicaset-namespace&gt; | STABLE |
| kube_replicaset_status_ready_replicas | Gauge | | replicaset=&lt;replicaset-name&gt; <br> namespace=&lt;replicaset-namespace&gt; | STABLE |
| kube_replicaset_status_terminating_replicas | Gauge | The number of terminating replicas per ReplicaSet. | replicaset=&lt;replicaset-name&gt; <br> namespace=&lt;replicaset-namespace&gt; | ALPHA |
| kube_replicaset_status_observed_generation | Gauge | | replicaset=&lt;replicaset-name&gt; <br> namespace=&lt;replicaset-namespace&gt; | STABLE |
| kube_replicaset_spec_replicas | Gauge | | replicaset=&lt;replicaset-name&gt; <br> namespace=&lt;replicaset-namespace&gt; | STABLE |
| kube_replicaset_metadata_generation | Gauge | | replicaset=&lt;replicaset-name&gt; <br> namespace=&lt;replicaset-namespace&gt; | STABLE |
| kube_replicaset_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | replicaset=&lt;replicaset-name&gt; <br> namespace=&lt;replicaset-namespace&gt; <br> label_REPLICASET_LABEL=&lt;REPLICASET_LABEL&gt; | STABLE |
| kube_replicaset_created | Gauge | | replicaset=&lt;replicaset-name&gt; <br> namespace=&lt;replicaset-namespace&gt; | STABLE |
| kube_replicaset_owner | Gauge | | replicaset=&lt;replicaset-name&gt; <br> namespace=&lt;replicaset-namespace&gt; <br> owner_kind=&lt;owner kind&gt; <br> owner_name=&lt;owner name&gt; <br> owner_is_controller=&lt;whether owner is controller&gt; | STABLE |

---

Metrics/Workload/Replicationcontroller Metrics

ReplicationController metrics

| Metric name | Metric type | Description | Labels/tags | Status |
| -------------------------------------------------------- | ----------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------ |
| kube_replicationcontroller_status_replicas | Gauge | | replicationcontroller=&lt;replicationcontroller-name&gt; <br> namespace=&lt;replicationcontroller-namespace&gt; | STABLE |
| kube_replicationcontroller_status_fully_labeled_replicas | Gauge | | replicationcontroller=&lt;replicationcontroller-name&gt; <br> namespace=&lt;replicationcontroller-namespace&gt; | STABLE |
| kube_replicationcontroller_status_ready_replicas | Gauge | | replicationcontroller=&lt;replicationcontroller-name&gt; <br> namespace=&lt;replicationcontroller-namespace&gt; | STABLE |
| kube_replicationcontroller_status_available_replicas | Gauge | | replicationcontroller=&lt;replicationcontroller-name&gt; <br> namespace=&lt;replicationcontroller-namespace&gt; | STABLE |
| kube_replicationcontroller_status_observed_generation | Gauge | | replicationcontroller=&lt;replicationcontroller-name&gt; <br> namespace=&lt;replicationcontroller-namespace&gt; | STABLE |
| kube_replicationcontroller_spec_replicas | Gauge | | replicationcontroller=&lt;replicationcontroller-name&gt; <br> namespace=&lt;replicationcontroller-namespace&gt; | STABLE |
| kube_replicationcontroller_metadata_generation | Gauge | | replicationcontroller=&lt;replicationcontroller-name&gt; <br> namespace=&lt;replicationcontroller-namespace&gt; | STABLE |
| kube_replicationcontroller_created | Gauge | | replicationcontroller=&lt;replicationcontroller-name&gt; <br> namespace=&lt;replicationcontroller-namespace&gt; | STABLE |
| kube_replicationcontroller_owner | Gauge | | replicationcontroller=&lt;replicationcontroller-name&gt; <br> namespace=&lt;replicationcontroller-namespace&gt; <br> owner_kind=&lt;owner kind&gt; <br> owner_name=&lt;owner name&gt; <br> owner_is_controller=&lt;whether owner is controller&gt; | EXPERIMENTAL |

---

Metrics/Workload/Statefulset Metrics

Stateful Set Metrics

| Metric name | Metric type | Description | Labels/tags | Status |
| ------------------------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| kube_statefulset_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via --metric-annotations-allowlist | statefulset=&lt;statefulset-name&gt; <br> namespace=&lt;statefulset-namespace&gt; <br> annotation_STATEFULSET_ANNOTATION=&lt;STATEFULSET_ANNOTATION&gt; | STABLE |
| kube_statefulset_status_replicas | Gauge | | statefulset=&lt;statefulset-name&gt; <br> namespace=&lt;statefulset-namespace&gt; | STABLE |
| kube_statefulset_status_replicas_current | Gauge | | statefulset=&lt;statefulset-name&gt; <br> namespace=&lt;statefulset-namespace&gt; | STABLE |
| kube_statefulset_status_replicas_ready | Gauge | | statefulset=&lt;statefulset-name&gt; <br> namespace=&lt;statefulset-namespace&gt; | STABLE |
| kube_statefulset_status_replicas_available | Gauge | | statefulset=&lt;statefulset-name&gt; <br> namespace=&lt;statefulset-namespace&gt; | STABLE |
| kube_statefulset_status_replicas_updated | Gauge | | statefulset=&lt;statefulset-name&gt; <br> namespace=&lt;statefulset-namespace&gt; | STABLE |
| kube_statefulset_status_observed_generation | Gauge | | statefulset=&lt;statefulset-name&gt; <br> namespace=&lt;statefulset-namespace&gt; | STABLE |
| kube_statefulset_replicas | Gauge | | statefulset=&lt;statefulset-name&gt; <br> namespace=&lt;statefulset-namespace&gt; | STABLE |
| kube_statefulset_ordinals_start | Gauge | | statefulset=&lt;statefulset-name&gt; <br> namespace=&lt;statefulset-namespace&gt; | STABLE |
| kube_statefulset_metadata_generation | Gauge | | statefulset=&lt;statefulset-name&gt; <br> namespace=&lt;statefulset-namespace&gt; | STABLE |
| kube_statefulset_persistentvolumeclaim_retention_policy | Gauge | | statefulset=&lt;statefulset-name&gt; <br> namespace=&lt;statefulset-namespace&gt; <br> when_deleted=&lt;statefulset-when-deleted-pvc-policy&gt; <br> when_scaled=&lt;statefulset-when-scaled-pvc-policy&gt; | STABLE |
| kube_statefulset_created | Gauge | | statefulset=&lt;statefulset-name&gt; <br> namespace=&lt;statefulset-namespace&gt; | STABLE |
| kube_statefulset_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | statefulset=&lt;statefulset-name&gt; <br> namespace=&lt;statefulset-namespace&gt; <br> label_STATEFULSET_LABEL=&lt;STATEFULSET_LABEL&gt; | STABLE |
| kube_statefulset_status_current_revision | Gauge | | statefulset=&lt;statefulset-name&gt; <br> namespace=&lt;statefulset-namespace&gt; <br> revision=&lt;statefulset-current-revision&gt; | STABLE |
| kube_statefulset_status_update_revision | Gauge | | statefulset=&lt;statefulset-name&gt; <br> namespace=&lt;statefulset-namespace&gt; <br> revision=&lt;statefulset-update-revision&gt; | STABLE |
| kube_statefulset_deletion_timestamp | Gauge | Unix deletion timestamp | statefulset=&lt;statefulset-name&gt; <br> namespace=&lt;statefulset-namespace&gt; | STABLE |

---

Metrics/Storage/Configmap Metrics

ConfigMap Metrics

| Metric name | Metric type | Description | Labels/tags | Status |
| ---------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| kube_configmap_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via --metric-annotations-allowlist | configmap=&lt;configmap-name&gt; <br> namespace=&lt;configmap-namespace&gt; <br> annotation_CONFIGMAP_ANNOTATION=&lt;CONFIGMAP_ANNOTATION&gt; | EXPERIMENTAL |
| kube_configmap_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | configmap=&lt;configmap-name&gt; <br> namespace=&lt;configmap-namespace&gt; <br> label_CONFIGMAP_LABEL=&lt;CONFIGMAP_LABEL&gt; | STABLE |
| kube_configmap_info | Gauge | | configmap=&lt;configmap-name&gt; <br> namespace=&lt;configmap-namespace&gt; | STABLE |
| kube_configmap_created | Gauge | | configmap=&lt;configmap-name&gt; <br> namespace=&lt;configmap-namespace&gt; | STABLE |
| kube_configmap_metadata_resource_version | Gauge | | configmap=&lt;configmap-name&gt; <br> namespace=&lt;configmap-namespace&gt; | EXPERIMENTAL |

---

Metrics/Storage/Persistentvolume Metrics

PersistentVolume Metrics

| Metric name | Metric type | Description | Unit (where applicable) | Labels/tags | Status |
|------------------------------------------|-------------|---------------------------------------------------------------------------------------------------------------------------|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|
| kube_persistentvolume_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via --metric-annotations-allowlist | | persistentvolume=&lt;persistentvolume-name&gt; <br> annotation_PERSISTENTVOLUME_ANNOTATION=&lt;PERSISTENTVOLUME_ANNOTATION&gt; | EXPERIMENTAL |
| kube_persistentvolume_capacity_bytes | Gauge | | | persistentvolume=&lt;pv-name&gt; | STABLE |
| kube_persistentvolume_status_phase | Gauge | | | persistentvolume=&lt;pv-name&gt; <br>phase=&lt;Bound\|Failed\|Pending\|Available\|Released&gt; | STABLE |
| kube_persistentvolume_claim_ref | Gauge | | | persistentvolume=&lt;pv-name&gt; <br>claim_namespace=<namespace>; <br>name=<name>; | STABLE |
| kube_persistentvolume_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | | persistentvolume=&lt;persistentvolume-name&gt; <br> label_PERSISTENTVOLUME_LABEL=&lt;PERSISTENTVOLUME_LABEL&gt; | STABLE |
| kube_persistentvolume_info | Gauge | Information about Persistent Volumes | | persistentvolume=&lt;pv-name&gt; <br> storageclass=&lt;storageclass-name&gt; <br> gce_persistent_disk_name=&lt;pd-name&gt; <br> host_path=&lt;path-of-a-host-volume&gt; <br> host_path_type=&lt;host-mount-type&gt; <br> ebs_volume_id=&lt;ebs-volume-id&gt; <br> azure_disk_name=&lt;azure-disk-name&gt; <br> fc_wwids=&lt;fc-wwids-comma-separated&gt; <br> fc_lun=&lt;fc-lun&gt; <br> fc_target_wwns=&lt;fc-target-wwns-comma-separated&gt; <br> iscsi_target_portal=&lt;iscsi-target-portal&gt; <br> iscsi_iqn=&lt;iscsi-iqn&gt; <br> iscsi_lun=&lt;iscsi-lun&gt; <br> iscsi_initiator_name=&lt;iscsi-initiator-name&gt; <br> local_path=&lt;path-of-a-local-volume&gt; <br> local_fs=&lt;local-volume-fs-type&gt; <br> nfs_server=&lt;nfs-server&gt; <br> nfs_path=&lt;nfs-path&gt; <br> csi_driver=&lt;csi-driver&gt; <br> csi_volume_handle=&lt;csi-volume-handle&gt; <br> reclaim_policy=&lt;reclaim-policy&gt; | STABLE |
| kube_persistentvolume_created | Gauge | Unix creation timestamp | seconds | persistentvolume=&lt;persistentvolume-name&gt; <br> | EXPERIMENTAL |
| kube_persistentvolume_deletion_timestamp | Gauge | Unix deletion timestamp | seconds | persistentvolume=&lt;persistentvolume-name&gt; <br> | EXPERIMENTAL |
| kube_persistentvolume_csi_attributes | Gauge | CSI attributes of the Persistent Volume, disabled by default, manage with --metric-opt-in-list) | | persistentvolume=&lt;persistentvolume-name&gt; <br> csi_mounter=&lt;csi-mounter&gt; <br> csi_map_options=&lt;csi-map-options&gt; | EXPERIMENTAL |
| kube_persistentvolume_volume_mode | Gauge | Volume Mode information for the PersistentVolume. | | persistentvolume=&lt;persistentvolume-name&gt; <br>volumemode=&lt;volumemode&gt; | EXPERIMENTAL |
| kube_persistentvolume_access_mode | Gauge | Access modes of the PersistentVolume. | | persistentvolume=&lt;persistentvolume-name&gt; <br>access_mode=&lt;ReadWriteOnce \| ReadOnlyMany \| ReadWriteMany \| ReadWriteOncePod&gt; | EXPERIMENTAL |

Useful metrics queries

How to retrieve non-standard PV state

It is not straightforward to get the PV states for certain cases like "Terminating" since it is not stored behind a field in the PersistentVolume.Status.

So to mimic the logic used by the kubectl command line, you will need to compose multiple metrics.

Here is an example of a Prometheus rule that can be used to alert on a PV that has been in the Terminating state for more than 5m.

yaml
groups:
- name: PV state
rules:
- alert: PVBlockedInTerminatingState
expr: kube_persistentvolume_deletion_timestamp * on(persistentvolume) group_left() (kube_persistentvolume_status_phase{phase="Bound"} == 1) > 0
for: 5m
labels:
severity: warning
annotations:
summary: PV {{$labels.persistentvolume}} blocked in Terminating state.

---

Metrics/Storage/Persistentvolumeclaim Metrics

PersistentVolumeClaim Metrics

| Metric name | Metric type | Description | Unit (where applicable) | Labels/tags | Status |
| ---------------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------ |
| kube_persistentvolumeclaim_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via --metric-annotations-allowlist | | persistentvolumeclaim=&lt;persistentvolumeclaim-name&gt; <br> namespace=&lt;persistentvolumeclaim-namespace&gt; <br> annotation_PERSISTENTVOLUMECLAIM_ANNOTATION=&lt;PERSISTENTVOLUMECLAIM_ANNOATION&gt; | EXPERIMENTAL |
| kube_persistentvolumeclaim_access_mode | Gauge | | | access_mode=&lt;persistentvolumeclaim-access-mode&gt; <br>namespace=&lt;persistentvolumeclaim-namespace&gt; <br> persistentvolumeclaim=&lt;persistentvolumeclaim-name&gt; | STABLE |
| kube_persistentvolumeclaim_info | Gauge | | | namespace=&lt;persistentvolumeclaim-namespace&gt; <br> persistentvolumeclaim=&lt;persistentvolumeclaim-name&gt; <br> storageclass=&lt;persistentvolumeclaim-storageclassname&gt;<br>volumename=&lt;volumename&gt;<br>volumemode=&lt;volumemode&gt; | STABLE |
| kube_persistentvolumeclaim_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | | persistentvolumeclaim=&lt;persistentvolumeclaim-name&gt; <br> namespace=&lt;persistentvolumeclaim-namespace&gt; <br> label_PERSISTENTVOLUMECLAIM_LABEL=&lt;PERSISTENTVOLUMECLAIM_LABEL&gt; | STABLE |
| kube_persistentvolumeclaim_resource_requests_storage_bytes | Gauge | | | namespace=&lt;persistentvolumeclaim-namespace&gt; <br> persistentvolumeclaim=&lt;persistentvolumeclaim-name&gt; | STABLE |
| kube_persistentvolumeclaim_status_condition | Gauge | | | namespace =&lt;persistentvolumeclaim-namespace&gt; <br> persistentvolumeclaim=&lt;persistentvolumeclaim-name&gt; <br> type=&lt;persistentvolumeclaim-condition-type&gt; <br> status=&lt;true\false\unknown&gt; | EXPERIMENTAL |
| kube_persistentvolumeclaim_status_phase | Gauge | | | namespace=&lt;persistentvolumeclaim-namespace&gt; <br> persistentvolumeclaim=&lt;persistentvolumeclaim-name&gt; <br> phase=&lt;Pending\Bound\Lost&gt; | STABLE |
| kube_persistentvolumeclaim_created | Gauge | Unix creation timestamp | seconds | namespace=&lt;persistentvolumeclaim-namespace&gt; <br> persistentvolumeclaim=&lt;persistentvolumeclaim-name&gt; | EXPERIMENTAL |
| kube_persistentvolumeclaim_deletion_timestamp | Gauge | Unix deletion timestamp | seconds | namespace=&lt;persistentvolumeclaim-namespace&gt; <br> persistentvolumeclaim=&lt;persistentvolumeclaim-name&gt; | EXPERIMENTAL |

Note:

* An empty string will be used if PVC has no storage class.

Useful metrics queries

How to retrieve non-standard PVC state

It is not straightforward to get the PVC states for certain cases like "Terminating" since it is not stored behind a field in the PersistentVolumeClaim.Status.

So to mimic the logic used by the kubectl command line, you will need to compose multiple metrics.

Here is an example of a Prometheus rule that can be used to alert on a PVC that has been in the Terminating state for more than 5m.

yaml
groups:
- name: PVC state
rules:
- alert: PVCBlockedInTerminatingState
expr: kube_persistentvolumeclaim_deletion_timestamp * on(namespace, persistentvolumeclaim) group_left() (kube_persistentvolumeclaim_status_phase{phase="Bound"} == 1) > 0
for: 5m
labels:
severity: warning
annotations:
summary: PVC {{$labels.namespace}}/{{$labels.persistentvolumeclaim}} blocked in Terminating state.

---

Metrics/Storage/Secret Metrics

Secret Metrics

| Metric name | Metric type | Description | Labels/tags | Status |
| ------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| kube_secret_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via --metric-annotations-allowlist | secret=&lt;secret-name&gt; <br> namespace=&lt;secret-namespace&gt; <br> annotations_SECRET_ANNOTATION=&lt;SECRET_ANNOTATION&gt; | EXPERIMENTAL |
| kube_secret_info | Gauge | | secret=&lt;secret-name&gt; <br> namespace=&lt;secret-namespace&gt; | STABLE |
| kube_secret_type | Gauge | | secret=&lt;secret-name&gt; <br> namespace=&lt;secret-namespace&gt; <br> type=&lt;secret-type&gt; | STABLE |
| kube_secret_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | secret=&lt;secret-name&gt; <br> namespace=&lt;secret-namespace&gt; <br> label_SECRET_LABEL=&lt;SECRET_LABEL&gt; | STABLE |
| kube_secret_created | Gauge | | secret=&lt;secret-name&gt; <br> namespace=&lt;secret-namespace&gt; | STABLE |
| kube_secret_metadata_resource_version | Gauge | | secret=&lt;secret-name&gt; <br> namespace=&lt;secret-namespace&gt; | EXPERIMENTAL |
| kube_secret_owner | Gauge | | secret=&lt;secret-name&gt; <br> namespace=&lt;secret-namespace&gt; <br> owner_kind=&lt;owner kind&gt; <br> owner_name=&lt;owner name&gt; <br> owner_is_controller=&lt;whether owner is controller&gt; | EXPERIMENTAL |

---

Metrics/Storage/Storageclass Metrics

StorageClass Metrics

| Metric name | Metric type | Description | Labels/tags | Status |
| ----------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| kube_storageclass_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via --metric-annotations-allowlist | storageclass=&lt;storageclass-name&gt; <br> annotation_STORAGECLASS_ANNOTATION=&lt;STORAGECLASS_ANNOTATION&gt; | EXPERIMENTAL |
| kube_storageclass_info | Gauge | | storageclass=&lt;storageclass-name&gt; <br> provisioner=&lt;storageclass-provisioner&gt; <br> reclaim_policy=&lt;storageclass-reclaimPolicy&gt; <br> volume_binding_mode=&lt;storageclass-volumeBindingMode&gt; | STABLE |
| kube_storageclass_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | storageclass=&lt;storageclass-name&gt; <br> label_STORAGECLASS_LABEL=&lt;STORAGECLASS_LABEL&gt; | STABLE |
| kube_storageclass_created | Gauge | | storageclass=&lt;storageclass-name&gt; | STABLE |

---

Metrics/Storage/Volumeattachment Metrics

VolumeAttachment Metrics

| Metric name | Metric type | Description | Labels/tags | Status |
| -------------------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------ |
| kube_volumeattachment_info | Gauge | | volumeattachment=&lt;volumeattachment-name&gt; <br> attacher=&lt;attacher-name&gt; <br> node=&lt;node-name&gt; | EXPERIMENTAL |
| kube_volumeattachment_created | Gauge | | volumeattachment=&lt;volumeattachment-name&gt; | EXPERIMENTAL |
| kube_volumeattachment_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | volumeattachment=&lt;volumeattachment-name&gt; <br> label_VOLUMEATTACHMENT_LABEL=&lt;VOLUMEATTACHMENT_LABEL&gt; | EXPERIMENTAL |
| kube_volumeattachment_spec_source_persistentvolume | Gauge | | volumeattachment=&lt;volumeattachment-name&gt; <br> volumename=&lt;persistentvolume-name&gt; | EXPERIMENTAL |
| kube_volumeattachment_status_attached | Gauge | | volumeattachment=&lt;volumeattachment-name&gt; | EXPERIMENTAL |
| kube_volumeattachment_status_attachment_metadata | Gauge | | volumeattachment=&lt;volumeattachment-name&gt; <br> metadata_METADATA_KEY=&lt;METADATA_VALUE&gt; | EXPERIMENTAL |

---

Metrics/Service/Endpoint Metrics

Endpoint Metrics

| Metric name | Metric type | Description | Labels/tags | Status |
| ------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| kube_endpoint_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via --metric-annotations-allowlist | endpoint=&lt;endpoint-name&gt; <br> namespace=&lt;endpoint-namespace&gt; <br> annotation_ENDPOINT_ANNOTATION=&lt;ENDPOINT_ANNOTATION&gt; | EXPERIMENTAL |
| kube_endpoint_info | Gauge | | endpoint=&lt;endpoint-name&gt; <br> namespace=&lt;endpoint-namespace&gt; | STABLE |
| kube_endpoint_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | endpoint=&lt;endpoint-name&gt; <br> namespace=&lt;endpoint-namespace&gt; <br> label_ENDPOINT_LABEL=&lt;ENDPOINT_LABEL&gt; | STABLE |
| kube_endpoint_created | Gauge | | endpoint=&lt;endpoint-name&gt; <br> namespace=&lt;endpoint-namespace&gt; | STABLE |
| kube_endpoint_ports | Gauge | | endpoint=&lt;endpoint-name&gt; <br> namespace=&lt;endpoint-namespace&gt; <br> port_name=&lt;endpoint-port-name&gt; <br> port_protocol=&lt;endpoint-port-protocol&gt; <br> port_number=&lt;endpoint-port-number&gt; | STABLE (Deprecated from 2.14.0) |
| kube_endpoint_address | Gauge | | endpoint=&lt;endpoint-name&gt; <br> namespace=&lt;endpoint-namespace&gt; <br> ip=&lt;endpoint-ip&gt; <br> port_name=&lt;endpoint-port-name&gt; <br> port_protocol=&lt;endpoint-port-protocol&gt; <br> port_number=&lt;endpoint-port-number&gt;ready=&lt;true if available, false if unavailalbe&gt; | STABLE |

---

Metrics/Service/Endpointslice Metrics

Endpoint Metrics

| Metric name | Metric type | Description | Labels/tags | Status |
| ------------------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| kube_endpointslice_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via --metric-annotations-allowlist | endpointslice=&lt;endpointslice-name&gt; <br> namespace=&lt;endpointslice-namespace&gt; <br> annotation_ENDPOINTSLICE_ANNOTATION=&lt;ENDPOINTSLICE_ANNOTATION&gt; | EXPERIMENTAL |
| kube_endpointslice_info | Gauge | | endpointslice=&lt;endpointslice-name&gt; <br> namespace=&lt;endpointslice-namespace&gt; <br> addresstype=&lt;endpointslice-addresstype&gt; | EXPERIMENTAL |
| kube_endpointslice_ports | Gauge | | endpointslice=&lt;endpointslice-name&gt; <br> namespace=&lt;endpointslice-namespace&gt; <br> port_name=&lt;endpointslice-port-name&gt; <br> port_protocol=&lt;endpointslice-port-protocol&gt; <br> port_number=&lt;endpointslice-port-number&gt; | EXPERIMENTAL |
| kube_endpointslice_endpoints | Gauge | | endpointslice=&lt;endpointslice-name&gt; <br> namespace=&lt;endpointslice-namespace&gt; <br> address=&lt;endpointslice-address&gt; <br> ready=&lt;endpointslice-ready&gt; <br> serving=&lt;endpointslice-serving&gt; <br> terminating=&lt;endpointslice-terminating&gt; <br> hostname=&lt;endpointslice-hostname&gt; <br> targetref_kind=&lt;endpointslice-targetref-kind&gt; <br> targetref_name=&lt;endpointslice-targetref-name&gt; <br> targetref_namespace=&lt;endpointslice-targetref-namespace&gt; <br> nodename=&lt;endpointslice-nodename&gt; <br> endpoint_zone=&lt;endpointslice-zone&gt; | EXPERIMENTAL |
| kube_endpointslice_endpoints_hints | Gauge | Each line is a hint applied to an endpoint-slice | endpointslice=&lt;endpointslice-name&gt; <br> namespace=&lt;endpointslice-namespace&gt; <br> address=&lt;endpointslice-address[0]&gt; <br> for_zone=&lt;endpointslice-hint&gt; | EXPERIMENTAL |
| kube_endpointslice_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | endpointslice=&lt;endpointslice-name&gt; <br> namespace=&lt;endpointslice-namespace&gt; <br> label_ENDPOINTSLICE_LABEL=&lt;ENDPOINTSLICE_LABEL&gt; | EXPERIMENTAL |
| kube_endpointslice_created | Gauge | | endpointslice=&lt;endpointslice-name&gt; <br> namespace=&lt;endpointslice-namespace&gt; | EXPERIMENTAL |

---

Metrics/Service/Ingress Metrics

Ingress Metrics

| Metric name | Metric type | Description | Labels/tags | Status |
| -------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| ------------ |
| kube_ingress_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via --metric-annotations-allowlist | ingress=&lt;ingress-name&gt; <br> namespace=&lt;ingress-namespace&gt; <br> annotation_INGRESS_ANNOTATION=&lt;ANNOTATION_LABEL&gt; | EXPERIMENTAL |
| kube_ingress_info | Gauge | | ingress=&lt;ingress-name&gt; <br> namespace=&lt;ingress-namespace&gt; <br> ingressclass=&lt;ingress-class&gt; or _default if not set | STABLE |
| kube_ingress_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | ingress=&lt;ingress-name&gt; <br> namespace=&lt;ingress-namespace&gt; <br> label_INGRESS_LABEL=&lt;INGRESS_LABEL&gt; | STABLE |
| kube_ingress_created | Gauge | | ingress=&lt;ingress-name&gt; <br> namespace=&lt;ingress-namespace&gt; | STABLE |
| kube_ingress_metadata_resource_version | Gauge | | ingress=&lt;ingress-name&gt; <br> namespace=&lt;ingress-namespace&gt; | EXPERIMENTAL |
| kube_ingress_path | Gauge | | ingress=&lt;ingress-name&gt; <br> namespace=&lt;ingress-namespace&gt; <br> host=&lt;ingress-host&gt; <br> path=&lt;ingress-path&gt; <br> path_type=&lt;ingress-path type&gt; <br> If path served by Service Backend <br> service_name=&lt;service name for the path&gt; <br> service_port=&lt;service port for the path&gt; <br> If path served by Resource Backend <br> resource_api_group=&lt;resource backend api group&gt; <br> resource_kind=&lt;resource backend kind&gt; <br> resource_name=&lt;resource backend name&gt; | STABLE |
| kube_ingress_tls | Gauge | | ingress=&lt;ingress-name&gt; <br> namespace=&lt;ingress-namespace&gt; <br> tls_host=&lt;tls hostname&gt; <br> secret=&lt;tls secret name&gt; | STABLE |

---

Metrics/Service/Ingressclass Metrics

IngressClass Metrics

| Metric name | Metric type | Description | Labels/tags | Status |
| ----------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------ |
| kube_ingressclass_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via --metric-annotations-allowlist | ingressclass=&lt;ingressclass-name&gt; <br> annotation_INGRESSCLASS_ANNOTATION=&lt;INGRESSCLASS_ANNOTATION&gt; | EXPERIMENTAL |
| kube_ingressclass_info | Gauge | | ingressclass=&lt;ingressclass-name&gt; <br> controller=&lt;ingress-controller-name&gt; <br> | EXPERIMENTAL |
| kube_ingressclass_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | ingressclass=&lt;ingressclass-name&gt; <br> label_INGRESSCLASS_LABEL=&lt;INGRESSCLASS_LABEL&gt; | EXPERIMENTAL |
| kube_ingressclass_created | Gauge | | ingressclass=&lt;ingressclass-name&gt; | EXPERIMENTAL |

---

Metrics/Service/Service Metrics

Service Metrics

| Metric name | Metric type | Description | Unit (where applicable) | Labels/tags | Status |
| ----------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| kube_service_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via --metric-annotations-allowlist | | service=&lt;service-name&gt; <br> namespace=&lt;service-namespace&gt; <br> uid=&lt;service-uid&gt; <br> annotation_SERVICE_ANNOTATION=&lt;SERVICE_ANNOTATION&gt; | EXPERIMENTAL |
| kube_service_info | Gauge | Information about service | | service=&lt;service-name&gt; <br> namespace=&lt;service-namespace&gt; <br> uid=&lt;service-uid&gt; <br> cluster_ip=&lt;service cluster ip&gt; <br> external_name=&lt;service external name&gt; <br> external_traffic_policy=&lt;service external traffic policy&gt; <br> load_balancer_ip=&lt;service load balancer ip&gt; | STABLE |
| kube_service_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | | service=&lt;service-name&gt; <br> namespace=&lt;service-namespace&gt; <br> uid=&lt;service-uid&gt; <br> label_SERVICE_LABEL=&lt;SERVICE_LABEL&gt; | STABLE |
| kube_service_created | Gauge | Unix creation timestamp | seconds | service=&lt;service-name&gt; <br> namespace=&lt;service-namespace&gt; <br> uid=&lt;service-uid&gt; | STABLE |
| kube_service_spec_type | Gauge | Type about service | | service=&lt;service-name&gt; <br> namespace=&lt;service-namespace&gt; <br> uid=&lt;service-uid&gt; <br> type=&lt;ClusterIP\|NodePort\|LoadBalancer\|ExternalName&gt; | STABLE |
| kube_service_spec_external_ip | Gauge | Service external ips. One series for each ip | | service=&lt;service-name&gt; <br> namespace=&lt;service-namespace&gt; <br> uid=&lt;service-uid&gt; <br> external_ip=&lt;external-ip&gt; | STABLE |
| kube_service_status_load_balancer_ingress | Gauge | Service load balancer ingress status | | service=&lt;service-name&gt; <br> namespace=&lt;service-namespace&gt; <br> uid=&lt;service-uid&gt; <br> ip=&lt;load-balancer-ingress-ip&gt; <br> hostname=&lt;load-balancer-ingress-hostname&gt; | STABLE |
| kube_service_deletion_timestamp | Gauge | Unix deletion timestamp | seconds | service=&lt;service-name&gt; <br> namespace=&lt;service-namespace&gt; <br> uid=&lt;service-uid&gt; | EXPERIMENTAL |

---

Metrics/Policy/Limitrange Metrics

LimitRange Metrics

| Metric name | Metric type | Description | Labels/tags | Status |
| ----------------------- | ----------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ |
| kube_limitrange | Gauge | | limitrange=&lt;limitrange-name&gt; <br> namespace=&lt;namespace&gt; <br> resource=&lt;ResourceName&gt; <br> type=&lt;Pod\|Container\|PersistentVolumeClaim&gt; <br> constraint=&lt;constraint&gt; | STABLE |
| kube_limitrange_created | Gauge | | limitrange=&lt;limitrange-name&gt; <br> namespace=&lt;namespace&gt; | STABLE |

---

Metrics/Policy/Networkpolicy Metrics

Network Policy Metrics

| Metric name | Metric type | Description | Labels/tags | Status |
| ------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------------ |
| kube_networkpolicy_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via --metric-annotations-allowlist | namespace=&lt;namespace name&gt; networkpolicy=&lt;networkpolicy name&gt; | EXPERIMENTAL |
| kube_networkpolicy_created | Gauge | | namespace=&lt;namespace name&gt; networkpolicy=&lt;networkpolicy name&gt; | EXPERIMENTAL |
| kube_networkpolicy_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | namespace=&lt;namespace name&gt; networkpolicy=&lt;networkpolicy name&gt; | EXPERIMENTAL |
| kube_networkpolicy_spec_egress_rules | Gauge | | namespace=&lt;namespace name&gt; networkpolicy=&lt;networkpolicy name&gt; | EXPERIMENTAL |
| kube_networkpolicy_spec_ingress_rules | Gauge | | namespace=&lt;namespace name&gt; networkpolicy=&lt;networkpolicy name&gt; | EXPERIMENTAL |

---

Metrics/Policy/Poddisruptionbudget Metrics

PodDisruptionBudget Metrics

| Metric name | Metric type | Description | Labels/tags | Status |
| ------------------------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| kube_poddisruptionbudget_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via --metric-annotations-allowlist | poddisruptionbudget=&lt;poddisruptionbudget-name&gt; <br> namespace=&lt;poddisruptionbudget-namespace&gt; <br> annotation_PODDISRUPTIONBUDGET_ANNOTATION=&lt;PODDISRUPTIONBUDGET_ANNOATION&gt; | EXPERIMENTAL |
| kube_poddisruptionbudget_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | poddisruptionbudget=&lt;poddisruptionbudget-name&gt; <br> namespace=&lt;poddisruptionbudget-namespace&gt; <br> label_PODDISRUPTIONBUDGET_LABEL=&lt;PODDISRUPTIONBUDGET_ANNOATION&gt; | EXPERIMENTAL |
| kube_poddisruptionbudget_created | Gauge | | poddisruptionbudget=&lt;pdb-name&gt; <br> namespace=&lt;pdb-namespace&gt; | STABLE |
| kube_poddisruptionbudget_status_current_healthy | Gauge | | poddisruptionbudget=&lt;pdb-name&gt; <br> namespace=&lt;pdb-namespace&gt; | STABLE |
| kube_poddisruptionbudget_status_desired_healthy | Gauge | | poddisruptionbudget=&lt;pdb-name&gt; <br> namespace=&lt;pdb-namespace&gt; | STABLE |
| kube_poddisruptionbudget_status_pod_disruptions_allowed | Gauge | | poddisruptionbudget=&lt;pdb-name&gt; <br> namespace=&lt;pdb-namespace&gt; | STABLE |
| kube_poddisruptionbudget_status_expected_pods | Gauge | | poddisruptionbudget=&lt;pdb-name&gt; <br> namespace=&lt;pdb-namespace&gt; | STABLE |
| kube_poddisruptionbudget_status_observed_generation | Gauge | | poddisruptionbudget=&lt;pdb-name&gt; <br> namespace=&lt;pdb-namespace&gt; | STABLE |
| kube_poddisruptionbudget_deletion_timestamp | Gauge | | poddisruptionbudget=&lt;pdb-name&gt; <br> namespace=&lt;pdb-namespace&gt; | EXPERIMENTAL |

---

Metrics/Policy/Resourcequota Metrics

ResourceQuota Metrics

| Metric name | Metric type | Description | Labels/tags | Status |
| ------------------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| kube_resourcequota | Gauge | | resourcequota=&lt;quota-name&gt; <br> namespace=&lt;namespace&gt; <br> resource=&lt;ResourceName&gt; <br> type=&lt;quota-type&gt; | STABLE |
| kube_resourcequota_created | Gauge | | resourcequota=&lt;quota-name&gt; <br> namespace=&lt;namespace&gt; | STABLE |
| kube_resourcequota_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via --metric-annotations-allowlist | resourcequota=&lt;quota-name&gt; <br> namespace=&lt;namespace&gt; <br> annotation_RESOURCE_QUOTA_ANNOTATION=&lt;RESOURCE_QUOTA_ANNOTATION&gt; | EXPERIMENTAL |
| kube_resourcequota_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via --metric-labels-allowlist | resourcequota=&lt;quota-name&gt; <br> namespace=&lt;namespace&gt; <br> label_RESOURCE_QUOTA_LABEL=&lt;RESOURCE_QUOTA_LABEL&gt; | EXPERIMENTAL |

---

Metrics/Extend/Customresourcestate Metrics

Custom Resource State Metrics

NOTE

custom-resource-state is feature-frozen in favor of resource-state-metrics. Once resource-state-metrics is stable, custom-resource-state will be deprecated.

This section describes how to add metrics based on the state of a custom resource without writing a custom resource
registry and running your own build of KSM.

Configuration

A YAML configuration file described below is required to define your custom resources and the fields to turn into metrics.

Two flags can be used:

* --custom-resource-state-config "inline yaml (see example)" or
* --custom-resource-state-config-file /path/to/config.yaml

When using a --config file, the equivalent YAML key is custom_resource_state_config_file. The pre-v2.17 key custom_resource_config_file is still honored as a deprecated alias and will be removed in a future release; please migrate to custom_resource_state_config_file.

If both flags are provided, the inline configuration will take precedence.
When multiple entries for the same resource exist, kube-state-metrics will exit with an error.
This includes configuration which refers to a different API version.

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: kube-state-metrics
namespace: kube-system
spec:
template:
spec:
containers:
- name: kube-state-metrics
args:
- --custom-resource-state-config
# in YAML files, | allows a multi-line string to be passed as a flag value
# see https://yaml-multiline.info
- |
kind: CustomResourceStateMetrics
spec:
resources:
- groupVersionKind:
group: myteam.io
version: "v1"
kind: Foo
metrics:
- name: active_count
help: "Count of active Foo"
each:
type: Gauge
...

It's also possible to configure kube-state-metrics to run in a custom-resource-mode only. In addition to specifying one of --custom-resource-state-config* flags, you could set --custom-resource-state-only to true.
With this configuration only the known custom resources configured in --custom-resource-state-config* will be taken into account by kube-state-metrics.

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: kube-state-metrics
namespace: kube-system
spec:
template:
spec:
containers:
- name: kube-state-metrics
args:
- --custom-resource-state-config
# in YAML files, | allows a multi-line string to be passed as a flag value
# see https://yaml-multiline.info
- |
kind: CustomResourceStateMetrics
spec:
resources:
- groupVersionKind:
group: myteam.io
version: "v1"
kind: Foo
metrics:
- name: active_count
help: "Count of active Foo"
each:
type: Gauge
...
- --custom-resource-state-only=true

NOTE: The customresource_group, customresource_version, and customresource_kind common labels are reserved, and will be overwritten by the values from the groupVersionKind field.

RBAC-enabled Clusters

Please be aware that kube-state-metrics needs list and watch permissions granted to customresourcedefinitions.apiextensions.k8s.io as well as to the resources you want to gather metrics from.

Examples

The examples in this section will use the following custom resource:

yaml
kind: Foo
apiVersion: myteam.io/vl
metadata:
annotations:
bar: baz
qux: quxx
labels:
foo: bar
name: foo
spec:
version: v1.2.3
order:
- id: 1
value: true
- id: 3
value: false
replicas: 1
refs:
- my_other_foo
- foo_2
- foo_with_extensions
status:
phase: Pending
active:
type-a: 1
type-b: 3
conditions:
- name: a
value: 45
- name: b
value: 66
sub:
type-a:
active: 1
ready: 2
type-b:
active: 3
ready: 4
uptime: 43.21

#### Single Values

The config:

yaml
kind: CustomResourceStateMetrics
spec:
resources:
- groupVersionKind:
group: myteam.io
kind: "Foo"
version: "v1"
metrics:
- name: "uptime"
help: "Foo uptime"
each:
type: Gauge
gauge:
path: [status, uptime]

Produces the metric:

prometheus
kube_customresource_uptime{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1"} 43.21

#### Multiple Metrics/Kitchen Sink

text
/ Detailed source-code truncated for AI context efficiency. /

Produces the following metrics:

prometheus
kube_customresource_ready_count{customresource_group="myteam.io", customresource_kind="Foo", 
customresource_version="v1", active="1",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-a",
lorem_bar="baz",lorem_qux="quxx",} 2
kube_customresource_ready_count{customresource_group="myteam.io", customresource_kind="Foo",
customresource_version="v1", active="3",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-b",
lorem_bar="baz",lorem_qux="quxx",} 4

#### Non-map Arrays

yaml
kind: CustomResourceStateMetrics
spec:
resources:
- groupVersionKind:
group: myteam.io
kind: "Foo"
version: "v1"
labelsFromPath:
name: [metadata, name]
metrics:
- name: "ref_info"
help: "Reference to other Foo"
each:
type: Info
info:
# targeting an array will produce a metric for each element
# labelsFromPath and value are relative to this path
path: [spec, refs]

# if path targets a list of values (e.g. strings or numbers, not objects or maps), individual values can
# referenced by a label using this syntax
labelsFromPath:
ref: []

Produces the following metrics:

prometheus
kube_customresource_ref_info{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1", name="foo",ref="my_other_foo"} 1
kube_customresource_ref_info{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1", name="foo",ref="foo_2"} 1
kube_customresource_ref_info{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1", name="foo",ref="foo_with_extensions"} 1

#### Same Metrics with Different Labels

yaml
recommendation:
containerRecommendations:
- containerName: consumer
lowerBound:
cpu: 100m
memory: 262144k

For example in VPA we have above attributes and we want to have a same metrics for both CPU and Memory, you can use below config:

text
/ Detailed source-code truncated for AI context efficiency. /

Produces the following metrics:

prometheus

HELP kube_customresource_verticalpodautoscaler_status_recommendation_containerrecommendations_lowerbound Minimum memory resources the container can use before the VerticalPodAutoscaler updater evicts it.


TYPE kube_customresource_verticalpodautoscaler_status_recommendation_containerrecommendations_lowerbound gauge


kube_customresource_verticalpodautoscaler_status_recommendation_containerrecommendations_lowerbound{container="consumer",customresource_group="autoscaling.k8s.io",customresource_kind="VerticalPodAutoscaler",customresource_version="v1",namespace="namespace-example",resource="memory",target_api_version="apps/v1",target_kind="Deployment",target_name="target-name-example",unit="byte",verticalpodautoscaler="vpa-example"} 123456

HELP kube_customresource_verticalpodautoscaler_status_recommendation_containerrecommendations_lowerbound Minimum cpu resources the container can use before the VerticalPodAutoscaler updater evicts it.


TYPE kube_customresource_verticalpodautoscaler_status_recommendation_containerrecommendations_lowerbound gauge


kube_customresource_verticalpodautoscaler_status_recommendation_containerrecommendations_lowerbound{container="consumer",customresource_group="autoscaling.k8s.io",customresource_kind="VerticalPodAutoscaler",customresource_version="v1",namespace="namespace-example",resource="cpu",target_api_version="apps/v1",target_kind="Deployment",target_name="target-name-example",unit="core",verticalpodautoscaler="vpa-example"} 0.1

#### VerticalPodAutoscaler

In v2.9.0 the vericalpodautoscalers resource was removed from the list of default resources. In order to generate metrics for verticalpodautoscalers, you can use the following Custom Resource State config:

text
/ Detailed source-code truncated for AI context efficiency. /

The above configuration was tested on this VPA configuration, with an added annotation (foo: 123).

#### All VerticalPodAutoscaler Metrics

As an addition for the above configuration, here's the complete CustomResourceStateMetrics spec to re-enable all of the VPA metrics which are removed from the list of the default resources:

<details>

<summary>VPA CustomResourceStateMetrics</summary>

text
/ Detailed source-code truncated for AI context efficiency. /

</details>

Metric types

The configuration supports three kind of metrics from the OpenMetrics specification.

The metric type is specified by the type field and its specific configuration at the types specific struct.

#### Gauge

Gauges are current measurements, such as bytes of memory currently used or the number of items in a queue. For gauges the absolute value is what is of interest to a user. [[0]](https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#gauge)

Example:

yaml
kind: CustomResourceStateMetrics
spec:
resources:
- groupVersionKind:
group: myteam.io
kind: "Foo"
version: "v1"
metrics:
- name: "uptime"
help: "Foo uptime"
each:
type: Gauge
gauge:
path: [status, uptime]

Produces the metric:

prometheus
kube_customresource_uptime{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1"} 43.21

##### Type conversion and special handling

Gauges produce values of type float64 but custom resources can be of all kinds of types.
Kube-state-metrics performs implicit type conversions for a lot of type.
Supported types are:

* (u)int32/64, int, float32 and byte are cast to float64
* nil is generally mapped to 0.0 if NilIsZero is true, otherwise it will throw an error
* for bool true is mapped to 1.0 and false is mapped to 0.0
* for string the following logic applies
* "true" and "yes" are mapped to 1.0, "false", "no" and "unknown" are mapped to 0.0 (all case-insensitive)
* RFC3339 times are parsed to float timestamp
* Quantities like "250m" or "512Gi" are parsed to float using <https://github.com/kubernetes/apimachinery/blob/master/pkg/api/resource/quantity.go>
* Percentages ending with a "%" are parsed to float
* finally the string is parsed to float using <https://pkg.go.dev/strconv#ParseFloat> which should support all common number formats. If that fails an error is yielded

##### Example for status conditions on Kubernetes Controllers

yaml
kind: CustomResourceStateMetrics
spec:
resources:
- groupVersionKind:
group: myteam.io
kind: "Foo"
version: "v1"
labelsFromPath:
name:
- metadata
- name
namespace:
- metadata
- namespace
metrics:
- name: "foo_status"
help: "status condition "
each:
type: Gauge
gauge:
path: [status, conditions]
labelsFromPath:
type: ["type"]
valueFrom: ["status"]

This will work for kubernetes controller CRs which expose status conditions according to the kubernetes api (<https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#Condition>):

yaml
status:
conditions:
- lastTransitionTime: "2019-10-22T16:29:31Z"
status: "True"
type: Ready

kube_customresource_foo_status{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1", type="Ready"} 1.0

#### StateSet

StateSets represent a series of related boolean values, also called a bitset. If ENUMs need to be encoded this MAY be done via StateSet. [[1]](https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#stateset)

yaml
kind: CustomResourceStateMetrics
spec:
resources:
- groupVersionKind:
group: myteam.io
kind: "Foo"
version: "v1"
metrics:
- name: "status_phase"
help: "Foo status_phase"
each:
type: StateSet
stateSet:
labelName: phase
path: [status, phase]
list: [Pending, Bar, Baz]

Metrics of type StateSet will generate a metric for each value defined in list for each resource.
The value will be 1, if the value matches the one in list.

If path (or valueFrom, if set) does not resolve, for example because the status field is not populated yet,
no metrics are produced for that resource and no error is logged. Once the field is set, the metrics appear.
A value that resolves to a non-string type is reported as an error.

Produces the metric:

prometheus
kube_customresource_status_phase{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1", phase="Pending"} 1
kube_customresource_status_phase{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1", phase="Bar"} 0
kube_customresource_status_phase{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1", phase="Baz"} 0

#### Info

Info metrics are used to expose textual information which SHOULD NOT change during process lifetime. Common examples are an application's version, revision control commit, and the version of a compiler. [[2]](https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#info)

Metrics of type Info will always have a value of 1.

yaml
kind: CustomResourceStateMetrics
spec:
resources:
- groupVersionKind:
group: myteam.io
kind: "Foo"
version: "v1"
metrics:
- name: "version"
help: "Foo version"
each:
type: Info
info:
labelsFromPath:
version: [spec, version]

Produces the metric:

prometheus
kube_customresource_version{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1", version="v1.2.3"} 1

Naming

The default metric names are prefixed to avoid collisions with other metrics.
By default, a metric prefix of kube_ concatenated with your custom resource's group+version+kind is used.
You can override this behavior with the metricNamePrefix field.

yaml
kind: CustomResourceStateMetrics
spec:
resources:
- groupVersionKind: ...
metricNamePrefix: myteam_foos
metrics:
- name: uptime
# ...

Produces:

prometheus
myteam_foos_uptime{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1"} 43.21

To omit namespace and/or subsystem altogether, set them to the empty string:

yaml
kind: CustomResourceStateMetrics
spec:
resources:
- groupVersionKind: ...
metricNamePrefix: ""
metrics:
- name: uptime
# ...

Produces:

prometheus
uptime{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1"} 43.21

Logging

If a metric path is registered but not found on a custom resource, an error will be logged. For some resources,
this may produce a lot of noise. The error log [verbosity][vlog] for a metric or resource can be set with errorLogV on
the resource or metric:

yaml
kind: CustomResourceStateMetrics
spec:
resources:
- groupVersionKind: ...
errorLogV: 0 # 0 = default for errors
metrics:
- name: uptime
errorLogV: 10 # only log at high verbosity

[vlog]: https://github.com/go-logr/logr#why-v-levels

Path Syntax

Paths are specified as a list of strings. Each string is a path segment, resolved dynamically against the data of the custom resource.
If any part of a path is missing, the result is nil.

Examples:

yaml

simple path lookup


[spec, replicas] # spec.replicas == 1

indexing an array


[spec, order, "0", value] # spec.order[0].value = true

finding an element in a list by key=value


[status, conditions, "[name=a]", value] # status.conditions[0].value = 45

if the value to be matched is a number or boolean, the value is compared as a number or boolean


[status, conditions, "[value=66]", name] # status.conditions[1].name = "b"

For generally matching against a field in an object schema, use the following syntax:


[metadata, "name=foo"] # if v, ok := metadata[name]; ok && v == "foo" { return v; } else { / ignore / }

Wildcard matching of version and kind fields

The Custom Resource State (CRS hereon) configuration also allows you to monitor all versions and/or kinds that come under a group. It watches
the installed CRDs for this purpose. Taking the aforementioned Foo object as reference, the configuration below allows
you to monitor all objects under all versions and all kinds that come under the myteam.io group.

yaml
kind: CustomResourceStateMetrics
spec:
resources:
- groupVersionKind:
group: "myteam.io"
version: "*" # Set to v1 to monitor all kinds under myteam.io/v1. Wildcard matches all installed versions that come under this group.
kind: "*" # Set to
Foo to monitor all Foo objects under the myteam.io group (under all versions). Wildcard matches all installed kinds that come under this group (and version, if specified).
metrics:
- name: "myobject_info"
help: "Foo Bar Baz"
each:
type: Info
info:
path: [metadata]
labelsFromPath:
object: [name]
namespace: [namespace]

The configuration above produces these metrics.

yaml
kube_customresource_myobject_info{customresource_group="myteam.io",customresource_kind="Foo",customresource_version="v1",namespace="ns",object="foo"} 1
kube_customresource_myobject_info{customresource_group="myteam.io",customresource_kind="Bar",customresource_version="v1",namespace="ns",object="bar"} 1

#### Note

* Only versions that the API server actually serves (served: true in the CRD's spec.versions) are discovered. A version that is still declared in the CRD but no longer served cannot be listed or watched, so the wildcard will not resolve to it, and pinning it explicitly will not generate any metrics. Such skipped versions are logged at verbosity level 1 (-v=1).
For cases where the GVKs defined in a CRD have multiple versions under a single group for the same kind, as expected, the wildcard value will resolve to all* versions, but a query for any specific version will return all resources under all versions, in that versions' representation. This basically means that for two such versions
A and B, if a resource exists under B, it will reflect in the metrics generated for A as well, in addition to any resources of itself, and vice-versa. This logic is based on the current list`ing behavior of the client-go library.
* The introduction of this feature further discourages (and discontinues) the use of native objects in the CRS featureset, since these do not have an explicit CRD associated with them, and conflict with internal stores defined specifically for such native resources. Please consider opening an issue or raising a PR if you'd like to expand on the current metric labelsets for them. Also, any such configuration will be ignored, and no metrics will be generated for the same.

---