KubeStateMetrics Documentation v2.13
kube-state-metrics (KSM) is a simple service that listens to the Kubernetes API server and generates metrics about the state of objects — it is not focused on the health of individual Kubernetes components, but rather on the health of various objects inside, such as deployments, nodes, and pods.
Quick Start
The fastest way to get KSM running is via Helm:
helm repo add prometheus-community \
https://prometheus-community.github.io/helm-charts
helm repo update helm install kube-state-metrics \
prometheus-community/kube-state-metrics \
--namespace monitoring \
--create-namespace kubectl rollout status deployment/kube-state-metrics \
-n monitoring
# deployment "kube-state-metrics" successfully rolled out kubectl port-forward svc/kube-state-metrics 8080:8080 -n monitoring
curl http://localhost:8080/metrics | head -50 Requirements
| Component | Minimum Version | Notes |
|---|---|---|
| Kubernetes | 1.26+ | Uses apps/v1, batch/v1 APIs |
| Prometheus | 2.0+ | For OpenMetrics use 2.44+ |
| Helm | 3.0+ | Only for Helm installation method |
| CPU (idle) | 5m cores | Scales with cluster object count |
| Memory (idle) | 100Mi | Scales with cluster object count |
Helm Chart Installation
The Helm chart is the recommended installation method for production clusters. It handles RBAC, ServiceAccount, Service, and Deployment configuration automatically.
helm install kube-state-metrics \
prometheus-community/kube-state-metrics \
--namespace monitoring \
--create-namespace \
--set replicaCount=2 \
--set autosharding.enabled=true \
--set resources.requests.cpu=50m \
--set resources.requests.memory=128Mi \
--set resources.limits.cpu=250m \
--set resources.limits.memory=256Mi Key Helm Values
| Parameter | Default | Description |
|---|---|---|
replicaCount | 1 | Number of KSM replicas. Use ≥2 for HA. |
autosharding.enabled | false | Enable automatic metric sharding across replicas. |
metricLabelsAllowlist | [] | Kubernetes label keys to include in metrics. |
collectors | all | List of resource types to collect metrics for. |
namespaces | "" (all) | Comma-separated namespace filter. |
selfMonitor.enabled | false | Expose KSM's own Prometheus metrics. |
Direct kubectl Installation
kubectl apply -f \
https://github.com/kubernetes/kube-state-metrics/releases/latest/download/kube-state-metrics.yaml kube-system with cluster-wide RBAC. For namespace-scoped deployments, use the Helm chart with custom namespace values.Configuration Flags
| Flag | Description |
|---|---|
--resources | Comma-separated list of resources to enable. Default: all |
--namespaces | Comma-separated list of namespaces to monitor. Default: all |
--metric-labels-allowlist | Kubernetes object labels to include in the exposed metrics |
--metric-denylist | Regex-based metric denylist to reduce cardinality |
--metric-allowlist | Regex-based metric allowlist (exclusive with denylist) |
--shard | The shard index for horizontal sharding (0-indexed) |
--total-shards | Total number of shards for horizontal sharding |
--use-apiserver-cache | Use API server's watch cache for reduced load |
--tls-config | Path to TLS configuration file |
RBAC Configuration
KSM requires read access to all Kubernetes objects it monitors. Below is the minimal ClusterRole:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kube-state-metrics
rules:
- apiGroups: [""]
resources: [configmaps, secrets, nodes, pods, services,
serviceaccounts, resourcequotas, replicationcontrollers,
limitranges, persistentvolumeclaims, persistentvolumes,
namespaces, endpoints]
verbs: ["list", "watch"]
- apiGroups: ["apps"]
resources: [statefulsets, daemonsets, deployments, replicasets]
verbs: ["list", "watch"]
- apiGroups: ["batch"]
resources: [cronjobs, jobs]
verbs: ["list", "watch"]
- apiGroups: ["autoscaling"]
resources: [horizontalpodautoscalers]
verbs: ["list", "watch"]
- apiGroups: ["networking.k8s.io"]
resources: [ingresses, networkpolicies]
verbs: ["list", "watch"]
- apiGroups: ["storage.k8s.io"]
resources: [storageclasses, volumeattachments]
verbs: ["list", "watch"] --namespaces and a Role instead of ClusterRole to restrict KSM to specific namespaces for compliance or multi-tenant environments.Allow & Deny Lists
# Only expose specific metrics (allowlist)
--metric-allowlist=kube_pod_status_phase,kube_deployment_.*,kube_node_.*
# Exclude specific metrics (denylist)
--metric-denylist=kube_secret_.*,kube_configmap_.*
# Include specific Kubernetes labels as metric labels
--metric-labels-allowlist=pods=[app,version,tier],deployments=[app] Horizontal Sharding
For large clusters (>5,000 nodes or >50,000 pods), distribute the KSM workload across multiple instances:
# Shard 0 of 4
./kube-state-metrics \
--resources=pods,deployments \
--shard=0 \
--total-shards=4 With AutoSharding enabled in the Helm chart, KSM automatically assigns shards based on the StatefulSet ordinal:
helm upgrade kube-state-metrics prometheus-community/kube-state-metrics \
--set replicaCount=4 \
--set autosharding.enabled=true Custom Resource Support
Expose metrics from your own CRDs without writing any code:
kind: CustomResourceStateMetrics
spec:
resources:
- groupVersionKind:
group: mycompany.io
version: v1alpha1
kind: MyApp
labelsFromPath:
app_name: [metadata, name]
namespace: [metadata, namespace]
metrics:
- name: myapp_ready
help: "Whether the MyApp resource is ready"
each:
type: Gauge
gauge:
path: [status, ready] Prometheus Integration
scrape_configs:
- job_name: kube-state-metrics
honor_labels: true
static_configs:
- targets:
- kube-state-metrics.monitoring.svc.cluster.local:8080 With Prometheus Operator, use a ServiceMonitor:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: kube-state-metrics
namespace: monitoring
spec:
selector:
matchLabels:
app.kubernetes.io/name: kube-state-metrics
endpoints:
- port: http
interval: 30s
honorLabels: true Grafana Dashboards
| Dashboard | Grafana ID | Description |
|---|---|---|
| Kubernetes Cluster Overview | 6417 | Node, pod, and resource summary |
| Kubernetes Deployments | 8588 | Rollout status and replica health |
| Kubernetes PVCs | 13646 | Storage binding and capacity |
| Kubernetes HPA | 10257 | Autoscaler current vs desired |
| Kubernetes Nodes | 11074 | Node conditions and capacity |
Alert Rules
groups:
- name: kubernetes-apps
rules:
- alert: KubePodCrashLooping
expr: increase(kube_pod_container_status_restarts_total[15m]) > 0
for: 15m
labels: {severity: warning}
annotations:
summary: "Pod {{ $labels.pod }} is crash looping"
- alert: KubeDeploymentReplicasMismatch
expr: |
kube_deployment_spec_replicas !=
kube_deployment_status_replicas_available
for: 15m
labels: {severity: warning}
- alert: KubeNodeNotReady
expr: kube_node_status_condition{condition="Ready",status="true"} == 0
for: 15m
labels: {severity: critical}
- alert: KubePVCPending
expr: kube_persistentvolumeclaim_status_phase{phase="Pending"} == 1
for: 5m
labels: {severity: warning}
- alert: KubeHPAMaxedOut
expr: |
kube_horizontalpodautoscaler_status_current_replicas ==
kube_horizontalpodautoscaler_spec_max_replicas
for: 30m
labels: {severity: warning}