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.

Best practices
Metrics monitoring and troubleshooting

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.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting