Convert CPU seconds into CPU utilization with PromQL
Convert cumulative CPU time into cores used, host utilization, and container-limit percentages without assuming a fixed CPU quota period.
Apply rate to a cumulative CPU-seconds counter. The result is CPU seconds consumed per second: a value of 1 means one CPU core's worth of execution. Multiply by 100 for a percentage of one core, or divide by the relevant capacity first for a capacity-relative percentage.
Host CPU utilization
With Node Exporter:
100 - 100 * avg by (instance) (
rate(node_cpu_seconds_total{mode="idle"}[5m])
)
Each logical CPU has its own mode counters. The idle rate is a fraction for that CPU; averaging across CPUs produces the host's idle fraction. Subtracting it from one gives non-idle time. This includes modes such as I/O wait, so interpret it as non-idle utilization rather than proof that useful application code was executing.
To show user-mode time alone:
100 * avg by (instance) (
rate(node_cpu_seconds_total{mode="user"}[5m])
)
Retain a cluster or job label in the grouping if instance is not unique in your data.
Container CPU usage
For kubelet/cAdvisor metrics, start with cores used:
sum without (cpu) (
rate(container_cpu_usage_seconds_total{container!="",container!="POD"}[5m])
)
Where cAdvisor exposes both CPU quota and period, the configured limit in cores is container_spec_cpu_quota / container_spec_cpu_period. Both are durations in microseconds; the period is not universally 100000.
Some cAdvisor versions expose usage with cpu="total", while others expose per-CPU values; deployments may also omit the cpu label. The sum without (cpu) above combines per-CPU counters or removes the extra label from a total. Use one representation per container: do not sum total and per-CPU series together or combine duplicate scrapes.
For a scrape where the remaining labels match the quota and period metrics:
100 * sum without (cpu) (
rate(container_cpu_usage_seconds_total{container!="",container!="POD"}[5m])
)
/
(
(container_spec_cpu_quota{container!="",container!="POD"} > 0)
/ container_spec_cpu_period{container!="",container!="POD"}
)
The positive-quota filter excludes unlimited configurations. Inspect the actual label sets before choosing a matching rule; duplicate scrapes or extra labels can otherwise produce missing results or many-to-many errors. Some environments do not expose these quota metrics, so use an appropriate documented limit metric from your Kubernetes monitoring stack instead.
Check the units
A rate of 0.5 is half a core. That is 50% of one core, 25% of a two-core host, or 100% of a container limit of half a core. These are different denominators describing the same consumption.
FAQ
Should I use rate or irate? rate uses a window and is generally suitable for trends and alerts. irate uses the last two samples and can show sharper changes, but is more sensitive to sampling.
Why is the value above 100%? A workload using two cores consumes 200% of one core. Normalize by host capacity or a valid container limit when that is the question you want to answer.
What happens when a counter resets? rate adjusts for observed resets. Missing samples and coarse scrape intervals still limit what it can infer; it cannot reconstruct unseen execution exactly.
Sources
This guide is based on the documentation below; the examples have not been tested against a live deployment.
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan